def _add_stop_route(self, stop_id: int, route_id: int): # 获取到通过当前站点的公交路线 ID 后,在数据库中查询该公交线路 # 并将站点 ID 更新到 stops 中 route = Route.find_by_id(route_id) if route: print('正在更新 %s 的站点信息' % route.name) Route.add_a_stop(route_id, stop_id)
def _parse_route(self, content: dict, name: str) -> typing.List[Route]: routes = [] # 用于记录在请求中找到的对应的线路信息的次数 flag = 0 for item in content['items']: # 一条公交线路最多有正向和反向,当正反向同时找到时,停止遍历 if flag == 2: break for route in item['routes']: origin = route['origin'] terminal = route['terminal'] for tmp in self.stops_dict[name]: if origin == tmp[0] and terminal == tmp[-1]: flag += 1 route_id = route['routeId'] # 如果获取到的线路的 id 在 route_ids 里面,则跳过,剩下的全部插入到数据库中 if route_id in self.route_ids: continue else: self.route_ids.append(route_id) a_route = Route() a_route.route_id = route_id if 'oppositeId' in route: a_route.opposite_id = route['oppositeId'] if 'amapId' in route: a_route.amap_id = route['amapId'] a_route.name = route['routeName'] a_route.raw_name = name a_route.origin = route['origin'] a_route.terminal = route['terminal'] a_route.has_gps = route['hasGps'] routes.append(a_route) return routes
def single_route_exchange(self, route_id, pick_random=False): """2-edge exchange within a route""" route = self.schedule.get(route_id) # no possible exchange can be made # if none or only 1 store is visited if len(route.path) < 4: return (None, None) old_distance = route.total_distance neighbor = None feasible_neighbors = [] delta_distance = None # go through the stores in the path for i in range(1, len(route.path)): # edges cannot be adjacent to each other for j in range(i + 2, len(route.path)): # reverse the path in the middle candidate = route.path[0:i] + route.path[ i:j][::-1] + route.path[j:len(route.path)] # check if the route is equal to the original route, # a reversed order path is onsidered equal. if not route.is_equal(candidate): new_route = Route() # check if new route is feasible # add 0.01 as minimum distance gained to prevent numerical problem (float problem) if new_route.traverse(candidate, self.maps): if pick_random: feasible_neighbors.append( (new_route.total_distance, (new_route, ))) elif abs(old_distance - new_route.total_distance) > 0.01 and ( neighbor is None or new_route.total_distance < neighbor[0].total_distance): # put inside iterable for consistency neighbor = (new_route, ) if pick_random and len(feasible_neighbors) > 0: delta_distance, neighbor = feasible_neighbors[random.randint( 0, len(feasible_neighbors) - 1)] elif not pick_random and neighbor is not None: delta_distance = old_distance - neighbor[0].total_distance return (delta_distance, neighbor)
def __init__(self, destinations, initial_temperature=1000, cooling_rate=0.003, use_heuristic=True): self.use_heuristic = use_heuristic self.dictionary = {} self.route_controller = destinations self.route = Route(destinations) self.route.generate_route() self.best = self.route self.temperature = initial_temperature self.cooling_rate = cooling_rate self.iterations = 0
def new_route(self): new_route = Route(self.route_controller, self.route) pos1 = random.randint(1, self.route.route_lenght() - 1) pos2 = random.randint(1, self.route.route_lenght() - 1) cord1 = new_route.get_cord(pos1) cord2 = new_route.get_cord(pos2) new_route.set_Coordinate(pos2, cord1) new_route.set_Coordinate(pos1, cord2) actual_energy = self.route.get_distance(self.dictionary, self.use_heuristic) new_energy = new_route.get_distance(self.dictionary, self.use_heuristic) delta = new_energy - actual_energy if self.acceptance_function(delta): self.route = new_route if new_route.get_distance(self.dictionary, self.use_heuristic) < self.best.get_distance( self.dictionary, self.use_heuristic): self.best = new_route print(new_route.get_distance(), self.use_heuristic)
def add_marker_data(): """Gets the marker data and writes them to tables in database """ content = request.form.get('data') my_markers = json.loads(content) trip_code = request.form.get('trip_code') search_trip = Route.query.filter_by(trip_code=trip_code).all() # print search_trip if search_trip: for trip in search_trip: # print trip db.session.delete(trip) db.session.commit() for key in my_markers: # print key lat = my_markers[key]['lat'] lon = my_markers[key]['lng'] desc = my_markers[key].get('marker_description', None) marker = Route(trip_code=trip_code, lon=lon, lat=lat, description=desc) db.session.add(marker) db.session.commit() session['changes'] = session.get('changes', '') + trip_code + ',' print "session is %s" % session return redirect("/trip_detail/"+trip_code)
def get_stop_details(self, queue: dict, lock: threading.RLock): while len(queue): # 保存下来的的公交站点名为 XXX站 # 根据站名查找时需要去掉'站' # routes 为 ('route_name', [[route_stops], [route_stops]]) lock.acquire() if len(queue): routes = queue.popitem() else: lock.release() break lock.release() for route in routes[1]: route_id = Route.get_id_by_raw_name(routes[0], route[0], route[-1]) for stop_name in route: stop_id = Stop.get_id_by_name(stop_name) if not stop_id: print("正在爬取 %s 的详细信息" % stop_name) result = self.find_stop_by_name(stop_name) if len(result): for item in result: item.create() else: self._add_stop_route(stop_id, route_id) # 爬取后再将剩余队列保存到缓存文件 lock.acquire() with open(self.stops_queue, 'w') as f: json.dump(queue, f, ensure_ascii=False) lock.release()
def adds_routes_to_db(stops_routes_agencies_info): """adds all routes info into db""" for route in stops_routes_agencies_info: direction = stops_routes_agencies_info[route]['direction'] route_code = stops_routes_agencies_info[route]['route_code'] stop_list = stops_routes_agencies_info[route]['stop_list'] agency_code = stops_routes_agencies_info[route]['agency_code'] if agency_code != 3: name = route[0], ', ', route[1] route = ''.join(name) else: route_code = ','.join([str(x) for x in route_code]) route = Route( name=str(route), route_code=str(route_code), direction=str(direction), stop_list=str(stop_list), agency_id=agency_code, ) db.session.add(route) db.session.commit() print "Routes Added to DB"
def show_map(): """Show map and directions""" start_location = request.args.get("start_location").title() end_location = request.args.get("end_location").title() user_id = session.get('user_id') if user_id and Route.query.filter(Route.user_id == user_id, Route.start == start_location, Route.end == end_location).first() is None: route = Route(user_id=user_id, start=start_location, end=end_location) db.session.add(route) db.session.commit() my_route = Route.query.filter(Route.start == start_location, Route.end == end_location).first() if my_route: session['route_id'] = my_route.route_id return render_template( "show_directions.html", YOUR_API_KEY=GOOGLE_MAPS, start=start_location, end=end_location, )
def load_routes(): """Loads database with routes from Mountain Project API.""" route_ids = getRouteIds('routes.json') Route.query.delete() for i in range(len(route_ids))[::100]: payload = {'routeIds': ','.join(route_ids[i:i + 100]), 'key': TOKEN} r = requests.get('https://www.mountainproject.com/data/get-routes', params=payload).json() for route in r['routes']: if validates_vgrade(route['rating']): route = Route(name=route['name'], latitude=route['latitude'], longitude=route['longitude'], state=route['location'][0], area=route['location'][1], v_grade=route['rating'][1:2], url=route['url'], img=route['imgSmallMed']) db.session.add(route) db.session.commit()
def optimize_all(self, schedule): # call optimize() for each route for uid in schedule.get_all_route_ids(): curr_route = schedule.get(uid) solution = self.optimize(curr_route) # rotate the route new_path = self.make_cycle(solution.tour) new_route = Route() # make sure the new route is feasible if new_route.traverse(new_path, self.maps): schedule.replace(uid, new_route) # if it is not feasible, use unoptimised route else: print("[INFO] route is no longer valid after ACO: {}".format(new_route))
def create_route(user, trip_description): """Create and return a new route.""" route = Route(user=user, trip_description=trip_description) db.session.add(route) db.session.commit() return route
def route_suggest(): from model import Route options = [] for route in Route.search(request.args.get('term'), request.args.get('area_id')): options.append({'label': route['name'], 'value': route['route_id']}) return json.dumps(options)
def create_route(user, is_completed): """Create and return a new route.""" route = Route( user=user, is_completed=is_completed, ) db.session.add(route) db.session.commit() return route
def addRoute(): """add a route""" new_user = User(name="Imy", email="aa.gmail.com", password="******") new_route = Route( user_id=1, route_name="home", route_start="Hackbright Academy, Sutter Street, San Francisco, CA, USA", route_end="Dolores Park, 19th Street, San Francisco, CA, USA", score=5246.363636363636) db.session.add(new_user) db.session.add(new_route) db.session.commit()
def load_routes(the_file): """Load routes from bouldering_routes2.csv, bouldering_routes_1.csv into db""" # print the_file # print "\n\n" # open file with open(the_file, 'r,') as csvfile: #checks to see if the file has a header has_header = csv.Sniffer().has_header(csvfile.read(1024)) #resets the file back to the start csvfile.seek(0) # read in file my_file = csv.reader(csvfile, delimiter=',') #skips the header if has_header: next(my_file) #skip header row # loop through the file for row in my_file: # unpack each row parent_name, name, difficulty, desc, directions, protection = row parent_name = parent_name.strip() # print parent_name # print name # print difficulty # print desc # print directions # print protection # print "\n\n" # query the db to get the boulder_id of a matching boulder name parent = Boulder.query.filter_by(boulder_name=parent_name).first() # print type(parent) # print parent parent_id = parent.boulder_id # print parent_id # create a new route object route = Route(route_name=name, difficulty_rate=difficulty, route_directions=directions, route_description=desc, route_protection=protection, boulder_id=parent_id) # add it to db db.session.add(route) # commit the db when done. db.session.commit()
def get_routes_by_id(route_ids): """ Takes in a string representing a list of route_ids and returns a list of dictionaries mapping each route to the lat/longs of each stop on that route """ # print "\nroute_ids!! ", route_ids, "\n" routes_to_display = json.loads(route_ids) # Will be a list of dictionaries routes_trips_to_latlongs_dicts = [] for route in routes_to_display: route_lat_longs = Route.get_all_stops_on_route(route) routes_trips_to_latlongs_dicts.append(route_lat_longs) # print routes_trips_to_latlongs_dicts return routes_trips_to_latlongs_dicts
def post_neighborhood(): """add a route to the database and return to the profile Input: name of the route the start and the end addresses, the score of the best route and the list of neighborhoods of that best route. Done: store this information in the database route. The list of neigh is stored as a string (text). check that that route does not exist. if it does not exist then add it to the database add also the neigh_route foe that route. The neigh_route is the link between the route db and the neigh db Output: msg """ route_name = request.form.get("name") route_start = request.form.get("start_address") route_end = request.form.get("end_address") score = request.form.get("score") list_neigh = request.form.get("list_neigh") list_neigh = json.loads(list_neigh) list_neigh = list(set(list_neigh['neigh'])) exist_route = Route.query.filter_by(user_id=session.get("user_id"), route_start=route_start, route_end=route_end).first() if (exist_route is None): new_route = Route(user_id=session.get("user_id"), route_name=route_name, route_start=route_start, route_end=route_end, score=score) db.session.add(new_route) db.session.commit() for n in list_neigh: neigh = Neighborhood.query.filter( Neighborhood.neigh_name == n).first() if (neigh is not None): # add the neigh route new_route.neighborhoods.append(neigh) db.session.commit() return 'The route has been added', 200 return 'The route already exists'
def city_swap(self, route_id1, route_id2, pick_random=False): """city swap in two route""" if route_id1 == route_id2: print("[ERROR] Route IDs must be different for city_swap: {} {}". format(route_id1, route_id2)) route1, route2 = self.schedule.get_multiple([route_id1, route_id2]) old_distance = route1.total_distance + route2.total_distance min_dist = None neighbor = None feasible_neighbors = [] delta_distance = None # go through each store in route 1 except HQ for idx1, store1 in enumerate(route1.path[1:len(route1.path) - 1]): new_path1 = route1.path[:] # go through each store in route 2 except HQ for idx2, store2 in enumerate(route2.path[1:len(route2.path) - 1]): new_path2 = route2.path[:] # swap city between two routes new_path1[idx1 + 1], new_path2[idx2 + 1] = store2, store1 # check if new routes are feasible # add 0.01 as minimum distance gained to prevent numerical problem (float problem) new_route1 = Route() if new_route1.traverse(new_path1, self.maps): new_route2 = Route() if new_route2.traverse(new_path2, self.maps): new_distance = new_route1.total_distance + new_route2.total_distance if pick_random: feasible_neighbors.append( (old_distance - new_distance, (new_route1, new_route2))) # if pick_random is False, # consider the best out of the feasible alternatives in terms of distance. elif (min_dist is None or (new_route1.total_distance + new_route2.total_distance < min_dist)): min_dist = new_distance neighbor = (new_route1, new_route2) if pick_random and len(feasible_neighbors) > 0: delta_distance, neighbor = feasible_neighbors[random.randint( 0, len(feasible_neighbors) - 1)] elif not pick_random and min_dist is not None: delta_distance = old_distance - min_dist return (delta_distance, neighbor)
def load_routes(): """Seed data from routes_seed.psv into the seed table File format: route|route_acronym """ print("routes") Route.query.delete() with open("seed_data/routes_seed.psv") as routes: for row in routes: route, route_acronym = row.strip().split("|") # Checks if seed is empty, if so, inserts a Null cell into the db acronym = None if route_acronym == 'None' else route_acronym route = Route(route=route, route_acronym=acronym) db.session.add(route) db.session.commit()
def solve(self): # get the store list, make sure all stores are visited stores_list = self.maps.get_store_list() visited_stores = [0] schedule = Schedule() # while there is still store to visit # outer loop is to iterate over the routes while (len(stores_list) > 0): route = Route() have_time = True # inner loop is to build a route while have_time and len(stores_list) > 0: curr_store_id = route.get_curr_store() next_store_id = self.maps.get_next_nearest_store( curr_store_id, visited_stores) # check if the closest store is feasible # to be visited have_time = route.add_next_store( next_store_id, self.maps ) # if it is visited if have_time: visited_stores.append(next_store_id) stores_list.remove(next_store_id) # finish route by going back to HQ dist_to_hq = self.maps.get_distance(route.get_curr_store(), 0) route.end_day(dist_to_hq) schedule.add(route) return schedule
def save_route(): """User saves new route, including one stop.""" name = request.form.get('name') start_address = request.form.get('startAddress') stop_address = request.form.get('stopAddress') mode = request.form.get('mode') stop_order = request.form.get('stopOrder') user_id = User.query.get(session['user_id']).user_id # converting JSON to python dictionary stop_address = eval(stop_address) mode = eval(mode) stop_order = eval(stop_order) # grabbing end/final stop = last stop # stop_address keys are strings! max_stop = 0 end_address = stop_address['0'] for stop in stop_address.keys(): stop = int(stop) if stop > max_stop: stop = str(stop) end_address = stop_address[stop] # USE GOOGLE MAPS PLACES API TO GET LAT AND LNG ############## START ################ start_info = gmaps.places(start_address) # list of results, but coordinates is a dictionary of first element at idx 0 start_coord = start_info['results'][0]['geometry']['location'] start_lat = start_coord['lat'] start_lng = start_coord['lng'] ########## FINAL/END DESTINATION ############## end_info = gmaps.places(end_address) # list of results, but coordinates is a dictionary of first element at idx 0 end_coord = end_info['results'][0]['geometry']['location'] end_lat = end_coord['lat'] end_lng = end_coord['lng'] ########## ALL STOPS (no start address) ############# # get all stops INCLUDING final/endstop! stop_coord = {} for stop in stop_address.keys(): curr_address = stop_address[stop] curr_info = gmaps.places(curr_address) curr_coord = curr_info['results'][0]['geometry']['location'] # save into dictionary stop_coord[stop] = curr_coord # store route info in routes table new_route = Route(name=name, start_address=start_address, start_lat=start_lat, start_lng=start_lng, end_address=end_address, end_lat=end_lat, end_lng=end_lng, user_id=user_id) db.session.add(new_route) db.session.commit() # go through stop info and save to segments table for stop in stop_address.keys(): stop = int(stop) seg_start = "" seg_start_lat = "" seg_start_lng = "" seg_stop = "" seg_stop_lat = "" seg_stop_lng = "" # must be an integer! mode_id = 0 order_num = 0 route_id = 0 # for the first segment, start of segment is actual start address if stop == 0: seg_start = start_address seg_start_lat = start_lat seg_start_lng = start_lng else: seg_start = stop_address[str(stop - 1)] seg_start_lat = stop_coord[str(stop - 1)]['lat'] seg_start_lng = stop_coord[str(stop - 1)]['lng'] # grabbing stop addresses seg_stop = stop_address[str(stop)] seg_stop_lat = stop_coord[str(stop)]['lat'] seg_stop_lng = stop_coord[str(stop)]['lng'] # adding mode of this segment to modes table # go through dictionary and save individual modes to table md = Mode(mode=mode[str(stop)]) db.session.add(md) db.session.commit() mode_id = md.mode_id order_num = stop_order[str(stop)] route_id = new_route.route_id # adding each segment into segments table! segment = Segment(order_num=order_num, start_address=seg_start, start_lat=seg_start_lat, start_lng=seg_start_lng, stop_address=seg_stop, stop_lat=seg_stop_lat, stop_lng=seg_stop_lng, route_id=route_id, mode_id=mode_id) db.session.add(segment) db.session.commit() return 'SUCCESS'
def _dict_to_route(route_dict): return Route(route_dict.get('origin', ''), route_dict.get('destination', ''), route_dict.get('departure_time', ''))
test_route('Cuatro Caminos', 'Cuatro Caminos') test_route('Cuatro Caminos', 'Tacuba') test_route('Cuatro Caminos', 'Colegio Militar') test_route('Cuatro Caminos', 'Tasqueña') def functional_test(): test_route('Cuatro Caminos', 'Insurgentes') def geojson_test(begin='Cuatro Caminos', end='Juanacatlan'): network = load_network() router = Router(network) path = router.enroute(network.node(begin), network.node(end)) print Path.as_geojson(path) if __name__ == "__main__": # geojson_test() f = GenericFactory.get_instance() #node = f.create_object('00c17928-b42c-42e6-ba26-20e83799ca4a') #print (node) #route = f.create_object('a213390f-b6ff-44e7-ace7-a920c9051cc2') #print (route) routes = Route.all_routes() print(routes)
def display_results(): email = session['user_email'] user_id = db.session.query(User.user_id).filter_by(email=email).first() start_address = request.form.get('start') route_type = request.form.get('route') lat_1, lon_1 = db.session.query(Address.latitude, Address.longitude).\ filter_by(user_id=user_id).filter_by(label=start_address).first() if route_type == "loop": specified_miles = float(request.form.get('num_miles')) # Instantiate route_info object route_info = RouteMetadata(user_id, "loop", lat_1, lon_1, specified_miles) # Calculate waypoints for route midpoints, elevation_sample_size = route_info.calculate_waypoints() elif route_type == "midpoint": midpoint_address = request.form.get('midpoint') # Instantiate route_info object route_info = RouteMetadata(user_id, "midpoint", lat_1, lon_1, miles=0) # Geocode midpoint address lat_2, lon_2 = geocode_address(midpoint_address) # Define waypoints attribute route_info.waypoints = [(lat_1, lon_1), (lat_2, lon_2)] # Calculate total elevation changes for route ascent, descent = route_info.calculate_elevation() # Calculate total distance and time for route total_miles, total_minutes = route_info.calculate_distance_time() # Add route to routes table route = Route(total_ascent=ascent, total_descent=descent, is_accepted=True, user_id=route_info.user_id, total_miles=route_info.total_miles, total_minutes=route_info.total_minutes) db.session.add(route) db.session.commit() route_waypoints = [] # Format lat/lon pairs for results.html, add to waypoints table for waypoint in route_info.waypoints: lat = waypoint[0] lon = waypoint[1] route_waypoints.append([lat, lon]) lat_lon = Waypoint(route_id=route.route_id, latitude=lat, longitude=lon) db.session.add(lat_lon) db.session.commit() # Calculate midpoint, format for results.html mid_lat, mid_lon = route_info.calculate_midpoint() # Format and pass results to displayResults function results = { "miles": route_info.total_miles, "elevation": route_info.ascent_feet, "minutes": route_info.total_minutes, "waypoints": route_waypoints, "mid_lat": route_info.mid_lat, "mid_lon": route_info.mid_lon } return jsonify(results)
def route_work_save(): from model import RouteWork errors = [] # Validate data # Check for required fields labels = {'area': 'Area', 'route': 'Route', 'work_date': 'Completed On', 'bolts_placed': 'Bolts', 'anchor': 'Anchor', 'info': 'Notes'} for el in ['area', 'route', 'work_date', 'bolts_placed']: if el not in request.form or len(request.form[el]) == 0: errors.append("'{0}' is a required field.".format(labels[el])) # Make sure route id matches route name if len(request.form['route_id']): if request.form['route_id'] == '0': errors.append("There was a problem finding the route that you entered, please try again.") else: from model import Route route = Route.Route(request.form['route_id']) if route.name != request.form['route']: errors.append("There was a problem finding the route that you entered, please try again.") else: # Try to find route based on area name and route name from model import Route if len(request.form['area_id']): routes = Route.search(request.form['route'], request.form['area_id']) else: routes = Route.search(request.form['route']) # If a single route was found, use that if len(routes) == 1: route = Route.Route(routes[0]['route_id']) # Otherewise, error else: errors.append("There was a problem finding the route that you entered, please try typing part of the route name and then selecting from suggested routes.") # Make sure area id matches area name if len(request.form['area_id']): from model import Area area = Area.Area(request.form['area_id']) if (area.name != request.form['area']): errors.append('There was a problem finding the area that you entered, please try again.') # If errors, display form again if len(errors) != 0: return render_template( 'route_work/form.html', error = "<br/>\n".join(errors), area_options = [('1', 'New River Gorge'), ('2', 'Meadow River Gorge')], route = request.form['route'], route_id = request.form['route_id'], area = request.form['area'], area_id = request.form['area_id'], work_date = request.form['work_date'], who = request.form['who'], bolts_placed = request.form['bolts_placed'], anchor_replaced = '1' if request.form['anchor'] == 'replaced' else '', new_anchor = '1' if request.form['anchor'] == 'new' else '', info = request.form['info'] ) # If no errors, save route work work = RouteWork.RouteWork(request.form['route_work_id']) work.route_id = route.route_id work.work_date = __form_to_sql(request.form['work_date']) work.who = request.form['who'] work.bolts_placed = request.form['bolts_placed'] if len(request.form['bolts_placed']) > 0 else '0' if request.form['anchor'] == 'replaced': work.anchor_replaced = 1 else: work.anchor_replaced = 0 if request.form['anchor'] == 'new': work.new_anchor = 1 else: work.new_anchor = 0 work.user_id = session['user_id'] work.info = request.form['info'] work.save() flash('Route work saved') return redirect(url_for('route_list'))
class SimulatedAnnealing: def __init__(self, destinations, initial_temperature=1000, cooling_rate=0.003, use_heuristic=True): self.use_heuristic = use_heuristic self.dictionary = {} self.route_controller = destinations self.route = Route(destinations) self.route.generate_route() self.best = self.route self.temperature = initial_temperature self.cooling_rate = cooling_rate self.iterations = 0 def acceptance_function(self, energy_delta): if energy_delta < 0: return True elif random.random() <= math.exp(-(energy_delta) / self.temperature): return True return False def new_route(self): new_route = Route(self.route_controller, self.route) pos1 = random.randint(1, self.route.route_lenght() - 1) pos2 = random.randint(1, self.route.route_lenght() - 1) cord1 = new_route.get_cord(pos1) cord2 = new_route.get_cord(pos2) new_route.set_Coordinate(pos2, cord1) new_route.set_Coordinate(pos1, cord2) actual_energy = self.route.get_distance(self.dictionary, self.use_heuristic) new_energy = new_route.get_distance(self.dictionary, self.use_heuristic) delta = new_energy - actual_energy if self.acceptance_function(delta): self.route = new_route if new_route.get_distance(self.dictionary, self.use_heuristic) < self.best.get_distance( self.dictionary, self.use_heuristic): self.best = new_route print(new_route.get_distance(), self.use_heuristic) def run(self): print("Corriendo algoritmo") while self.temperature > 1: self.iterations = self.iterations + 1 self.new_route() self.temperature *= 1 - self.cooling_rate print("La cantidad de iteraciones que dio es de : ", self.iterations) self.resetDictionary() print("Termino algoritmo") def resetDictionary(self): self.dictionary = {}
def two_route_exchange(self, route_id1, route_id2, pick_random=False): """2-edge exchange between 2 routes""" if route_id1 == route_id2: print( "[ERROR] Route IDs must be different for two_route_exchange: {} {}" .format(route_id1, route_id2)) min_dist = None neighbor = None feasible_neighbors = [] delta_distance = None route1, route2 = self.schedule.get_multiple((route_id1, route_id2)) old_distance = route1.total_distance + route2.total_distance # go through every possible split of each route for split1 in route1.splits: for split2 in route2.splits: # for every 2-edge exchange, there are 2 alternatives # each alternative consists of possibly 2 routes. # e.g. we want to exchange: # route1 = [ABC][DEF], route2 = [GHI][JKL] candidates = ( # alternative 1: [ABC][JKL], [GHI][DEF] (split1[0] + split2[1], split2[0] + split1[1]), # alternative 2: [ABC][IHG], [LKJ][DEF] (split1[0] + split2[0][::-1], split1[1][::-1] + split2[1])) # check feasibility and find minimum for candidate in candidates: new_route1 = Route() # check if the first candidate route is equal with either route 1 or 2 is_exist1 = route1.is_equal( candidate[0]) or route2.is_equal(candidate[0]) # check if the first candidate route is feasible if not is_exist1 and new_route1.traverse( candidate[0], self.maps): new_route2 = Route() # check if the second candidate route is equal with either route 1 or 2 is_exist2 = route1.is_equal( candidate[1]) or route2.is_equal(candidate[1]) # check if the second route is feasible if not is_exist2 and new_route2.traverse( candidate[1], self.maps): new_distance = new_route1.total_distance + new_route2.total_distance if pick_random: feasible_neighbors.append( (new_distance - old_distance, (new_route1, new_route2))) # if pick_random is False, # consider the best out of the feasible alternatives # in terms of distance. elif (min_dist is None or (new_route1.total_distance + new_route2.total_distance < min_dist)): min_dist = new_distance neighbor = (new_route1, new_route2) # if is_valid2 and (min_dist is None or ( # new_route1.total_distance + new_route2.total_distance < min_dist)): # min_dist = new_route1.total_distance + new_route2.total_distance # min_neighbor = (new_route1, new_route2) if pick_random and len(feasible_neighbors) > 0: delta_distance, neighbor = feasible_neighbors[random.randint( 0, len(feasible_neighbors) - 1)] elif not pick_random and min_dist is not None: delta_distance = old_distance - min_dist return (delta_distance, neighbor)