为什么内核在设置有容量的车辆路由问题CVRP中的初始节点时似乎已死Google OR Tools

问题描述

我正在研究一个有能力的车辆路线问题(参考 Google OR 工具)。

我的代码

dist = distanceMetric.get_metric('haversine')

def create_data_model_cap_con(df_user,no_fos):
    """Stores the data for the problem."""
    data = {}
    data['distance_matrix'] = dist.pairwise(df_user [['lat','lon']].to_numpy())*6373
    
    #a = dist.pairwise(df_user_org[['lat','lon']])
    #a[:,0] = 0 
    #a[0,:] = 0 
    #data['starts'] = [2,5]
    #data['ends'] = [0,0]
    #assert(len(data['starts']) == len(data['ends']))
    #assert(data['num_vehicles'] == len(data['starts']))
    
    #A = dist.pairwise(df_user [['lat','lon']].to_numpy())*6373
    #x = np.c_[np.zeros(len(A[0])),A ] 
    #y = np.vstack([np.zeros(len(x[0])),x])
    
    #data['distance_matrix']=a
    
    data['num_vehicles'] = no_fos
    data['starts'] = [2,5,9,12]
    data['ends'] = [0,0]
    data['demands'] = df_user["no_cases"].to_list()
    data['vehicle_capacities'] = [75]*no_fos
    return data

def print_solution_cap_con(data,manager,routing,assignment):
    """Prints assignment on console."""
    # display dropped nodes.
    dropped_nodes = 'Dropped nodes:'
    for node in range(routing.Size()):
        if routing.Isstart(node) or routing.IsEnd(node):
            continue
        if assignment.Value(routing.Nextvar(node)) == node:
            dropped_nodes += ' {}'.format(manager.IndexToNode(node))
    print(dropped_nodes)
    # display routes
    total_distance = 0
    total_load = 0
    for vehicle_id in range(data['num_vehicles']):
        index = routing.Start(vehicle_id)
        plan_output = 'Route for vehicle {}:\n'.format(vehicle_id)
        route_distance = 0
        route_load = 0
        while not routing.IsEnd(index):
            node_index = manager.IndexToNode(index)
            route_load += data['demands'][node_index]
            plan_output += ' {0} Load({1}) -> '.format(node_index,route_load)
            prevIoUs_index = index
            index = assignment.Value(routing.Nextvar(index))
            route_distance += routing.GetArcCostForVehicle(
                prevIoUs_index,index,vehicle_id)
        plan_output += ' {0} Load({1})\n'.format(manager.IndexToNode(index),route_load)
        plan_output += 'distance of the route: {}m\n'.format(route_distance)
        plan_output += 'Load of the route: {}\n'.format(route_load)
        print(plan_output)
        total_distance += route_distance
        total_load += route_load
    print('Total distance of all routes: {}m'.format(total_distance))
    print('Total Load of all routes: {}'.format(total_load))


def distance_cap_con(x,y,data):
    dis = data['distance_matrix'][x][y]
    return dis

def get_routes_cap_con(solution,df_user,data):
  """Get vehicle routes from a solution and store them in an array."""
  # Get vehicle routes and store them in a two dimensional array whose
  # i,j entry is the jth location visited by vehicle i along its route.
  routes = []
  #routes_dist = []  
  for route_nbr in range(routing.vehicles()):
    index = routing.Start(route_nbr)
    route = [manager.IndexToNode(index)]
    
    while not routing.IsEnd(index):
      index = solution.Value(routing.Nextvar(index))
      route.append(manager.IndexToNode(index))
    routes.append(route)
    #routes = get_routes(solution,manager)
    routes_t = pd.DataFrame(routes).T
    col_to_iter = routes_t.columns
    routes_t['route_info'] = routes_t.index
    routes_t = pd.melt(routes_t,id_vars=['route_info'],value_vars=col_to_iter)
    routes_t = routes_t.drop_duplicates(subset='value',keep="first")

    df_user['value'] = df_user.index
    df_user_out = pd.merge(df_user,routes_t,on="value")
    
    df_user_out = df_user_out.sort_values(by=['variable','route_info'])
    df_user_out['route_lag'] = df_user_out.groupby('variable')['value'].shift(-1).fillna(0)
    df_user_out['route_lag'] = df_user_out['route_lag'].astype(np.int64)
    df_user_out['route_info'] = df_user_out['route_info'].astype(np.int64)
    df_user_out['dist'] = df_user_out.apply(lambda row: distance_cap_con(row['route_lag'],row['value'],data),axis=1)
    
  return df_user_out

def get_sol_cap_con(sub_dist_fil,fos_cnt,state_fil):
    df_user_org_sub = df_user_org[(df_user_org.sub_district == sub_dist_fil) & (df_user_org.State == state_fil) ]
    df_user_org_sub.reset_index( inplace=True,drop=True)
    print(sub_dist_fil," no fos",fos_cnt)

    fos_cnt=fos_cnt

    
    
    data = create_data_model_cap_con(df_user_org_sub,fos_cnt)

    # Create the routing index manager.
    manager = pywrapcp.RoutingIndexManager(len(data['distance_matrix']),data['num_vehicles'],data['starts'],data['ends'])

    # Create Routing Model.
    routing = pywrapcp.RoutingModel(manager)


    # Create and register a transit callback.
    def distance_callback(from_index,to_index):
        """Returns the distance between the two nodes."""
        # Convert from routing variable Index to distance matrix NodeIndex.
        from_node = manager.IndexToNode(from_index)
        to_node = manager.IndexToNode(to_index)
        return data['distance_matrix'][from_node][to_node]

    transit_callback_index = routing.RegisterTransitCallback(distance_callback)

    # Define cost of each arc.
    routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index)


    def demand_callback(from_index):
        """Returns the demand of the node."""
        # Convert from routing variable Index to demands NodeIndex.
        from_node = manager.IndexToNode(from_index)
        return data['demands'][from_node]

    demand_callback_index = routing.RegisterUnaryTransitCallback(
        demand_callback)
    routing.AddDimensionWithVehicleCapacity(
        demand_callback_index,# null capacity slack
        data['vehicle_capacities'],# vehicle maximum capacities
        True,# start cumul to zero
        'Capacity')
    # Allow to drop nodes.
    penalty = 1000
    for node in range(1,len(data['distance_matrix'])):
        routing.Adddisjunction([manager.NodetoIndex(node)],penalty)

    # Setting first solution heuristic.
    search_parameters = pywrapcp.DefaultRoutingSearchParameters()
    search_parameters.time_limit.seconds = 30
    search_parameters.solution_limit = 100
    search_parameters.first_solution_strategy = (
        routing_enums_pb2.FirstSolutionStrategy.PATH_CHEApest_ARC)
    search_parameters.local_search_Metaheuristic = (
        routing_enums_pb2.LocalSearchMetaheuristic.GUIDED_LOCAL_SEARCH)
    #search_parameters.time_limit.FromSeconds(30)


    # Solve the problem.
    solution = routing.solveWithParameters(search_parameters)

    out_df = get_routes_cap_con(solution,df_user_org_sub,data)

    # Print solution on console.
    if solution:
        print_solution_cap_con(data,solution)
    return   out_df  

我的目标是使用这个有能力的车辆路线问题(google OR tools - https://developers.google.com/optimization/routing/routing_tasks),其中我已经指定了车辆可以承载的重量([75] *no_fos)。现在我想设置车辆的初始节点(位置),它将等于我的数据集的索引号(我手动分配 data['starts'] = [2,12] 和数据['结束'] = 0)。但是在运行它时,即使我将时间限制设置为 30 秒,我的内核也会失去连接。它会在几秒钟内丢失/死亡,所以我无法获得任何输出

如何修改上面的代码,以便我添加重量(车辆的容量)并根据我的意愿(索引号)设置车辆的初始节点(位置)而不是零(即我不想要数据['仓库'] = 0)?

我也愿意采用 Google OR 工具以外的任何工具,如果这有助于我解决问题。

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)