def flat_varset(self, varset, grouped=False): # pprint(varset) vs = {v: 0 for v in varset} self.graphs = { v0: { self.paths[v0][i]: { self.paths[v0][i + 1]: None } for i in range(len(self.paths[v0]) - 1) } for v0 in self.paths } stop_to_route = {} for v0 in self.graphs: vs[vn('RouteActive', self.data.v_index(v0))] = 1 for v in self.graphs[v0]: vs[vn('Stop', self.data.v_index(v))] = 1 stop_to_route[v] = v0 for v2 in self.graphs[v0][v]: vs[vn('Edge', self.data.v_index(v), self.data.v_index(v2))] = 1 assignment = assign_students_mip(self.data, self.graphs) for s in assignment: v = assignment[s] c = self.data.student_to_stop[s] v0 = stop_to_route[v] if grouped: vs[vn('StopCluster', self.data.v_index(v), sorted(list(map(self.data.v_index, c))))] += 1 else: vs[vn('StopStudent', self.data.v_index(v), self.data.s_index(s))] = 1 vs[vn('StopLoad', self.data.v_index(v))] += 1 for v0 in self.paths: for i in range(1, len(self.paths[v0])): v1 = self.paths[v0][i - 1] v2 = self.paths[v0][i] vs[vn('EdgeLoad', self.data.v_index(v1), self.data.v_index(v2))] = vs[vn('StopLoad', self.data.v_index(v1))] vs[vn('StopLoad', self.data.v_index(v2))] += vs[vn('StopLoad', self.data.v_index(v1))] # pprint(vs) res = [varset, [vs[v] for v in varset]] # exit() return res
def __call__(self): sols = self.get_values() dsol = {variables[i][0]: sols[i] for i in range(len(sols)) if sols[i] > 0.5} gs = {data.v_index(v0): defaultdict(lambda: []) for v0 in data.depots} for vname in dsol: sp = vname.split("_") if sp[0] == 'RoEd': v0, i, j = map(int, sp[1:]) gs[v0][i].append(j) for v0, g in gs.items(): main_tour = bfs(g, v0) loops = set([v for v in g]).difference(main_tour) while len(loops) > 0: loop = bfs(g, loops.pop()) for v00 in data.depots: rhs = len(loop) - 1 sense = 'L' constraint = [ [vn('RoEd', data.v_index(v00), v1, v2) for v1 in loop for v2 in loop if v1 != v2], [1 for v1 in loop for v2 in loop if v1 != v2] ] self.add(constraint=constraint, sense=sense, rhs=rhs) loops.difference_update(loop)
def direct_varset(self, varset, grouped=False): # pprint(varset) vs = {v: 0 for v in varset} self.graphs = { v0: { self.paths[v0][i]: { self.paths[v0][i + 1]: None } for i in range(len(self.paths[v0]) - 1) } for v0 in self.paths } stop_to_route = {} for v0 in self.graphs: vs[vn('RoA', self.data.v_index(v0))] = 1 for v in self.graphs[v0]: vs[vn('RoSto', self.data.v_index(v0), self.data.v_index(v))] = 1 stop_to_route[v] = v0 for v2 in self.graphs[v0][v]: smallpath = self.data.path[v][v2] for j in range(len(smallpath) - 1): vs[vn('RoEd', self.data.v_index(v0), self.data.v_index(smallpath[j]), self.data.v_index(smallpath[j + 1]))] += 1 assignment = assign_students_mip(self.data, self.graphs) for s in assignment: v = assignment[s] c = self.data.student_to_stop[s] v0 = stop_to_route[v] if grouped: vs[vn('RoStoCl', self.data.v_index(v0), self.data.v_index(v), sorted(list(map(self.data.v_index, c))))] += 1 else: vs[vn('RoSoSu', self.data.v_index(v0), self.data.v_index(v), self.data.s_index(s))] = 1 # pprint(vs) res = [varset, [vs[v] for v in varset]] # exit() return res
def __call__(self): global times sols = self.get_values() dsol = {variables[i][0]: sols[i] for i in range(len(sols)) if sols[i] > 0.5} gs = {data.v_index(v0): defaultdict(lambda: []) for v0 in data.depots} for vname in dsol: sp = vname.split("_") if sp[0] == 'RoEd': v0, i, j = map(int, sp[1:]) gs[v0][i].append(j) sloops = [] for v0, g in gs.items(): main_tour = bfs(g, v0) loops = set([v for v in g]).difference(main_tour) while len(loops) > 0: loop = bfs(g, loops.pop()) sloops.append(loop) loops.difference_update(loop) # print(sloops) for loop in sloops: # print(loop) for v in loop: if data.vdictinv[v] not in data.stops: continue for v0 in data.depots: rhs = 0 sense = 'G' constraint = [ [vn('RoEd', data.v_index(v0), v1, data.v_index(v2)) for v1 in loop for v2 in data.original_graph[data.vdictinv[v1]] if data.v_index(v2) not in loop] + [vn('RoSto', data.v_index(v0), v)], [1 for v1 in loop for v2 in data.original_graph[data.vdictinv[v1]] if data.v_index(v2) not in loop] + [-1] ] self.add(constraint=constraint, sense=sense, rhs=rhs)
def insertion_precalc_wrapper(data, vnames): try: heur = InsertionHeuristic(data) except KeyError: return onvars = [] stop_route = {} for p in heur.paths: onvars.append(vn('RouteActive', data.v_index(p[0]))) for i in range(len(p) - 1): onvars.append(vn('RouteEdge', data.v_index(p[0]), data.v_index(p[i]), data.v_index(p[i+1]))) for i in range(len(p)): onvars.append(vn('RouteStop', data.v_index(p[0]), data.v_index(p[i]))) stop_route[p[i]] = p[0] for v in heur.stops: for s in heur.stops[v]: onvars.append(vn('RouteStopStudent', data.v_index(stop_route[v]), data.v_index(v), data.s_index(s))) return (vnames, [1 if v in onvars else 0 for v in vnames])
def __call__(self): # Generamos diccionarios para obtener rapidamente las variables val_dict = {x[0][0]: x[1] for x in zip(variables, self.get_values())} # pprint(val_dict) stop_route = defaultdict(lambda: []) student_stop_route = defaultdict(lambda: []) edges_cost = defaultdict(lambda: defaultdict(lambda: {})) for vname in val_dict: sp = vname.split("_") if sp[0] == 'RoSto': v0, s = map(int, sp[1:]) stop_route[s].append((val_dict[vname], v0)) if sp[0] == 'RoStoStu': v0, s, st = map(int, sp[1:]) student_stop_route[st].append((val_dict[vname], v0, s)) if sp[0] == 'RoEd': v0, s1, s2 = map(int, sp[1:]) edges_cost[v0][s1][s2] = (1 - val_dict[vname]) * \ data.dist[data.vdictinv[s1]][data.vdictinv[s2]] # Shuffleando para no tener sesgo hacia ciertas paradas/estudiantes for s in stop_route: shuffle(stop_route[s]) for st in student_stop_route: shuffle(student_stop_route[st]) # pprint(stop_route) # pprint(student_stop_route) rvars = defaultdict(lambda: 0) stop_route_choice = {} routes = defaultdict(lambda: {}) # De cada parada, elegimos la ruta que tenga mayor de asociación entre # ruta y parada. Si todas son 0, entonces la dejamos afuera. Al mismo # tiempo, activamos las rutas for s in stop_route: highest = 0.0 best = None for val, v0 in stop_route[s]: if val > highest: highest = val best = v0 stop_route_choice[s] = best if best is not None: rvars[vn('RoSto', best, s)] = 1 rvars[vn('RoA', best)] = 1 # Agrego la parada a la ruta, todavía no sabemos como se # conectan routes[best][s] = None # pprint(stop_route_choice) # pprint(rvars) # pprint(routes) # De cada estudiante, nos fijamos que combinación de parada y ruta tiene # mayor valor, y la asignamos ahí load = defaultdict(lambda: 0) student_stop_route_choice = {} for st in student_stop_route: # print(st, student_stop_route[st]) highest = -0.1 for val, v0, s in student_stop_route[st]: # print(val, v0, s) if val > highest and stop_route_choice[s] == v0: highest = val best = (v0, s) # print(best) student_stop_route_choice[st] = best # print(student_stop_route_choice) rvars[vn('RoStoStu', best[0], best[1], st)] = 1 load[best[0]] += 1 if load[best[0]] > data.capacity: return # pprint(student_stop_route_choice) # pprint(onvars) # pprint(route_edges) school = data.v_index(data.school) total_cost = 0 rank = defaultdict(lambda: 0) for v0 in edges_cost: routes[v0][v0] = school # print(routes[v0]) out_of_tour = set(routes[v0].keys()) out_of_tour.difference_update([v0]) # print(out_of_tour) while len(out_of_tour) > 0: best = (float('+inf'), 0, 0) for v in out_of_tour: vi = v0 while vi != school: vnext = routes[v0][vi] new_cost = ( edges_cost[v0][vi][v] + edges_cost[v0][v][vnext] - edges_cost[v0][v][vnext], vi, v) # print(new_cost) best = min(best, new_cost) vi = routes[v0][vi] # print(best) _, vi, v = best vnext = routes[v0][vi] # print("AGREGO", v, "DESPUES DE", vi, "ANTES DE", vnext) routes[v0][v] = vnext routes[v0][vi] = v out_of_tour.remove(v) rvars[vn('Rank', v0, v0)] = 1 v = v0 while v != data.v_index(data.school): rvars[vn("RoEd", v0, v, routes[v0][v])] = 1 rvars[vn('Rank', v0, routes[v0][v]) ] = rvars[vn('Rank', v0, v)] + 1 total_cost += data.dist[data.vdictinv[v] ][data.vdictinv[routes[v0][v]]] if total_cost >= self.get_incumbent_objective_value()-.01: return v = routes[v0][v] # print(v0, routes[v0]) # pprint(rvars) res = [[v[0] for v in variables], [ rvars[v[0]] for v in variables]] print(total_cost, self.get_incumbent_objective_value()) self.set_solution(res, objective_value=total_cost)
parser.add_option("--nodeheur", dest="node_heur", action="store_true") (options, args) = parser.parse_args() # INPUT data = ProblemData(options.in_file) problem = cplex.Cplex() problem.objective.set_sense(problem.objective.sense.minimize) # problem.parameters.dettimelimit.set(1000000) problem.parameters.timelimit.set(3600) problem.parameters.workmem.set(20000) variables = [ (vn('RoEd', data.v_index(v0), data.v_index( v1), data.v_index(v2)), 'B', data.dist[v1][v2]) for v0 in data.depots for v1 in data.stops for v2 in data.stops if v1 != v2] + \ [(vn('RoSto', data.v_index(v0), data.v_index(v1)), 'B', 0) for v0 in data.depots for v1 in data.stops[1:]] + \ [(vn('RoA', data.v_index(v0)), 'B', 0) for v0 in data.depots] if True: variables += [(vn('RoStoCl', data.v_index(v0), data.v_index(v1), sorted(list(map(data.v_index, c)))), 'I', 0) for v0 in data.depots for v1 in data.stops for c in data.stop_to_clusters[v1]] else: variables += [(vn('RoStoStu', data.v_index(v0), data.v_index(v1), data.s_index(s)), 'B', 0) for s in data.students for v0 in data.depots for v1 in data.student_to_stop[s]] if True: variables += [(vn('Rank', data.v_index(v0), data.v_index(v)), 'C', 0) for v0 in data.depots for v in data.stops]
def feasible_aux(self, paths, wont_be_routed): problem = cplex.Cplex() problem.parameters.emphasis.mip.set(1) problem.parameters.mip.display.set(0) problem.set_log_stream(None) problem.set_error_stream(None) problem.set_warning_stream(None) problem.set_results_stream(None) variables = [(vn('RouteStop', self.data.v_index(v0), self.data.v_index(v1)), 'B', 0) for v0 in paths for v1 in self.data.stops[1:]] + \ [(vn('RouteStopCluster', self.data.v_index(v0), self.data.v_index(v1), list(map(self.data.v_index, c))), 'I', 1) for v0 in paths for v1 in self.data.stops for c in self.data.stop_to_clusters[v1]] problem.variables.add(types=[v[1] for v in variables], names=[v[0] for v in variables]) # All stops can be visited at most one time rhs = [1 for v in self.data.stops[1:]] sense = ['L' for v in self.data.stops[1:]] constraint = [[[ vn('RouteStop', self.data.v_index(v0), self.data.v_index(v)) for v0 in paths ], [1 for v0 in paths]] for v in self.data.stops[1:]] problem.linear_constraints.add(lin_expr=constraint, senses=sense, rhs=rhs) # Cluster choices add to cluster size rhs = [self.data.clusters[c] for c in self.data.clusters] sense = ['E' for c in self.data.clusters] constraint = [[[ vn('RouteStopCluster', self.data.v_index(v0), self.data.v_index(v1), list(map(self.data.v_index, c))) for v0 in paths for v1 in c ], [1 for v0 in paths for v1 in c]] for c in self.data.clusters] problem.linear_constraints.add(lin_expr=constraint, senses=sense, rhs=rhs) # If cluster to stop, route is larger than 1, stop,route must be active rhs = [ 0 for v0 in paths for v1 in self.data.stops for c in self.data.stop_to_clusters[v1] ] sense = [ 'L' for v0 in paths for v1 in self.data.stops for c in self.data.stop_to_clusters[v1] ] constraint = [[[ vn('RouteStopCluster', self.data.v_index(v0), self.data.v_index(v1), list(map(self.data.v_index, c))), vn('RouteStop', self.data.v_index(v0), self.data.v_index(v1)) ], [1, -self.data.clusters[c]]] for v0 in paths for v1 in self.data.stops for c in self.data.stop_to_clusters[v1]] problem.linear_constraints.add(lin_expr=constraint, senses=sense, rhs=rhs) # Capacities are kept rhs = [self.data.capacity for v0 in paths] sense = ['L' for v0 in paths] constraint = [[[ vn('RouteStopCluster', self.data.v_index(v0), self.data.v_index(v1), list(map(self.data.v_index, c))) for v1 in self.data.stops for c in self.data.stop_to_clusters[v1] ], [ 1 for v1 in self.data.stops for c in self.data.stop_to_clusters[v1] ]] for v0 in paths] problem.linear_constraints.add(lin_expr=constraint, senses=sense, rhs=rhs) rhs = [] sense = [] constraint = [] for v0 in paths: for v in paths[v0][:-1]: rhs.append(1) sense.append('E') constraint.append([[ vn('RouteStop', self.data.v_index(v0), self.data.v_index(v)) ], [1]]) for v in wont_be_routed: rhs.append(0) sense.append('E') constraint.append([[ vn('RouteStop', self.data.v_index(v0), self.data.v_index(v)) for v0 in paths ], [1 for v0 in paths]]) problem.linear_constraints.add(lin_expr=constraint, senses=sense, rhs=rhs) problem.solve() return problem.solution.is_primal_feasible()
parser.add_option("--of", dest="out_file") parser.add_option("--grouped", dest="grouped", action="store_true") parser.add_option("--optcut", dest="optcut", action="store_true") parser.add_option("--heur", dest="heur", action="store_true") parser.add_option("--flow", dest="flow",action="store_true") (options, args) = parser.parse_args() # INPUT data = ProblemData(options.in_file) problem = cplex.Cplex() problem.objective.set_sense(problem.objective.sense.minimize) # problem.parameters.dettimelimit.set(1000000) problem.parameters.timelimit.set(3600) problem.parameters.workmem.set(20000) variables = [(vn('RoEd', data.v_index(v0), data.v_index(v1), data.v_index(v2)), 'I', data.original_graph[v1][v2][0]) for v0 in data.depots for v1 in data.original_graph for v2 in data.original_graph[v1]] + \ [(vn('RoSto', data.v_index(v0), data.v_index(v1)), 'B', 0) for v0 in data.depots for v1 in data.stops[1:]] + \ [(vn('RoA', data.v_index(v0)), 'B', 0) for v0 in data.depots] if True: variables += [(vn('RoEdFlo', data.v_index(v0), data.v_index(v1), data.v_index(v2)), 'C', 0) for v0 in data.depots for v1 in data.original_graph for v2 in data.original_graph[v1]] if True: variables += [(vn('RoStoCl', data.v_index(v0), data.v_index(v1), sorted(list(map(data.v_index, c)))), 'I', 0) for v0 in data.depots for v1 in data.stops for c in data.stop_to_clusters[v1]] else:
parser.add_option("--if", dest="in_file") parser.add_option("--of", dest="out_file") parser.add_option("--grouped", dest="grouped", action="store_true") parser.add_option("--heur", dest="heur", action="store_true") (options, args) = parser.parse_args() # INPUT data = ProblemData(options.in_file) problem = cplex.Cplex() problem.objective.set_sense(problem.objective.sense.minimize) # problem.parameters.dettimelimit.set(1000000) problem.parameters.timelimit.set(3600) # problem.parameters.mip.display.set(1) variables = [(vn('Edge', data.v_index(v1), data.v_index(v2)), 'B', data.dist[v1][v2]) for v1 in data.stops for v2 in data.stops if v1 != v2] + \ [(vn('EdgeLoad', data.v_index(v1), data.v_index(v2)), 'C', 0) for v1 in data.stops for v2 in data.stops if v1 != v2] + \ [(vn('Stop', data.v_index(v1)), 'B', 0) for v1 in data.stops[1:]] + \ [(vn('StopLoad', data.v_index(v1)), 'C', 0) for v1 in data.stops] + \ [(vn('RouteActive', data.v_index(v0)), 'B', 0) for v0 in data.depots] if options.grouped: variables += [(vn('StopCluster', data.v_index(v1), sorted(list(map(data.v_index, c)))), 'I', 0) for v1 in data.stops for c in data.stop_to_clusters[v1]]
def assign_students_mip(data, gs): vset = set() for v0 in gs: vset.update(gs[v0].keys()) problem = cplex.Cplex() problem.objective.set_sense(problem.objective.sense.minimize) problem.set_log_stream(None) problem.set_error_stream(None) problem.set_warning_stream(None) problem.set_results_stream(None) variables = [(vn('StopStudent', data.v_index(v1), data.s_index(s)), 'B', haversine_dist(s, v1)) for s in data.students for v1 in data.student_to_stop[s] if v1 in vset] problem.variables.add(obj=[v[2] for v in variables], types=[v[1] for v in variables], names=[v[0] for v in variables]) # for s in data.students: # print(data.s_index(s), list(map(data.v_index, data.student_to_stop[s]))) # Choice adds to one rhs = [1 for s in data.students] sense = ['E' for s in data.students] constraint = [[[ vn('StopStudent', data.v_index(v1), data.s_index(s)) for v1 in data.student_to_stop[s] if v1 in vset ], [1 for v1 in data.student_to_stop[s] if v1 in vset]] for s in data.students] # pprint(constraint) names = ['choice_addition_' + str(data.s_index(s)) for s in data.students] problem.linear_constraints.add(lin_expr=constraint, senses=sense, rhs=rhs, names=names) # Capacities are respected rhs = [data.capacity for v0 in gs] sense = ['L' for v0 in gs] constraint = [[[ vn('StopStudent', data.v_index(v), data.s_index(s)) for v in gs[v0] if v in data.stops for s in data.stop_to_students[v] ], [ 1 for v in gs[v0] if v in data.stops for s in data.stop_to_students[v] ]] for v0 in gs] problem.linear_constraints.add(lin_expr=constraint, senses=sense, rhs=rhs) problem.solve() print("BEST STUDENT ASSIGNMENT WALKING DISTANCE: ", problem.solution.get_objective_value()) sol = problem.solution.get_values() dsol = {variables[i][0]: sol[i] for i in range(len(sol)) if sol[i] > 0.5} assignment = {} for vname in dsol: if dsol[vname] < 0.5: continue sp = vname.split("_") if sp[0] == 'StopStudent': v, s = map(int, sp[1:]) assignment[data.students[s]] = data.vdictinv[v] return assignment