当前位置: 首页 > 知识库问答 >
问题:

Google或Tools VRP-节点被不必要地丢弃

宗政鸿志
2023-03-14

我试图解决一个具有时间窗约束的车辆路径问题,如果没有找到可行的解决方案,则允许解算器删除节点。然而,我发现在添加析取之后,即使施加了很大的惩罚,也会不必要地删除节点。

下面是一个简单的示例程序,以说明该问题。解算器将删除节点1并返回0的解-

我是不是走错了方向?任何帮助都将不胜感激。

from ortools.constraint_solver import routing_enums_pb2
from ortools.constraint_solver import pywrapcp

def create_data_model():
    """Stores the data for the problem."""
    data = {}
    data['time_matrix'] = [
        [0, 3, 2, 1], # depot
        [3, 0, 3, 3],
        [2, 3, 0, 2],
        [1, 3, 2, 0],
    ]
    data['time_windows'] = [
        (0, 0),  # depot
        (0, 3),  
        (0, 6),  
        (0, 9),  
    ]
    data['num_vehicles'] = 1
    data['depot'] = 0

    return data


def print_solution(data, manager, routing, solution):
    """Prints solution on console."""
    # Display dropped nodes.
    dropped_nodes = '\nDropped nodes:'
    for node in range(routing.Size()):
        if routing.IsStart(node) or routing.IsEnd(node):
            continue
        if solution.Value(routing.NextVar(node)) == node:
            dropped_nodes += ' {}'.format(manager.IndexToNode(node))
    print(dropped_nodes + '\n')

    time_dimension = routing.GetDimensionOrDie('Time')
    for vehicle_id in range(data['num_vehicles']):
        index = routing.Start(vehicle_id)
        plan_output = 'Route for vehicle {}:\n'.format(vehicle_id)
        while not routing.IsEnd(index):
            time_var = time_dimension.CumulVar(index)
            plan_output += '{0} Time ({1}, {2}) -> '.format(
                manager.IndexToNode(index), 
                solution.Min(time_var),
                solution.Max(time_var))
            index = solution.Value(routing.NextVar(index))
        time_var = time_dimension.CumulVar(index)
        plan_output += '{0} Time({1},{2})\n'.format(manager.IndexToNode(index),
                                                    solution.Min(time_var),
                                                    solution.Max(time_var))
        plan_output += '\nTime of the route: {}min\n'.format(
            solution.Min(time_var))
        print(plan_output)



def main():
    """Solve the VRP with time windows."""
    # Instantiate the data problem.
    data = create_data_model()

    # Create the routing index manager.
    manager = pywrapcp.RoutingIndexManager(len(data['time_matrix']),
                                           data['num_vehicles'], data['depot'])

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

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

    transit_callback_index = routing.RegisterTransitCallback(time_callback)

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

    # Add Time Windows constraint.
    time = 'Time'
    routing.AddDimension(
        transit_callback_index,
        9999999,  # maximum waiting time
        9999999,  # maximum travel time per vehicle
        False,  # Don't force start cumul to zero.
        time)
    time_dimension = routing.GetDimensionOrDie(time)

    # Add time window constraints for each location except depot.
    for location_idx, time_window in enumerate(data['time_windows']):
        if location_idx == data['depot']:
            continue
        index = manager.NodeToIndex(location_idx)
        time_dimension.CumulVar(index).SetRange(time_window[0], time_window[1])
        
    # Add time window constraints for each vehicle start node.
    depot_idx = data['depot']
    for vehicle_id in range(data['num_vehicles']):
        index = routing.Start(vehicle_id)
        time_dimension.CumulVar(index).SetRange(
            data['time_windows'][depot_idx][0],
            data['time_windows'][depot_idx][1])

    # Instantiate route start and end times to produce feasible times.
    for i in range(data['num_vehicles']):
        routing.AddVariableMinimizedByFinalizer(
            time_dimension.CumulVar(routing.Start(i)))
        routing.AddVariableMinimizedByFinalizer(
            time_dimension.CumulVar(routing.End(i)))

    # Allow to drop nodes.
    penalty = 100000000000
    for node in range(1, len(data['time_matrix'])):
        routing.AddDisjunction([manager.NodeToIndex(node)], penalty)

    # Setting first solution heuristic.
    search_parameters = pywrapcp.DefaultRoutingSearchParameters()
    search_parameters.first_solution_strategy = (
        routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC)
    search_parameters.time_limit.seconds = 10

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

    # Print solution on console.
    if solution:
        print_solution(data, manager, routing, solution)
    else:
        print("\nNo solutions found")


if __name__ == '__main__':
    main()

共有1个答案

郎鹤龄
2023-03-14

你在添加析取的过程中走的很好,你只是错过了结尾的这一行

    # Setting first solution heuristic.
    search_parameters = pywrapcp.DefaultRoutingSearchParameters()
    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.log_search = True # to get some logs
-    search_parameters.time_limit.seconds = 10
+    search_parameters.time_limit.seconds = 1 # 1s is large enough ;)

一、 e.您忘记启用引导式局部搜索(GLS),因此最终只有第一个解决方案(节点1已删除),并且您没有运行GLS,因此解算器没有机会将其返回到解决方案。。。

 类似资料:
  • 问题内容: 我有一个BaseActivity,其他所有活动都可以对其进行扩展。关键是,每当用户离开活动时,我都会将音乐静音。我也停止听电话。 问题是,只要用户在活动之间进行切换,就会被调用,这意味着该应用程序不必要地静音和停止,即使仅当用户离开该应用程序时该静音也应该停止。 现在说我在和之间切换。即使我只想 在用户离开应用程序时* 被调用,此开关也 不必要 执行。我该怎么办? * 感谢您的专家意见

  • 我有一个基本的统一(5.1)地形(10x10)在我的场景,和一个单点光。如果我在编辑器中播放场景,我会看到我的地形(有简单的草纹理)被光源照亮。然而,一旦我构建到设备(iPhone6),地形就出现了(我只能勉强辨认出它起伏的特征),但却是完全黑暗的,尽管场景中的其他物体被光源点亮了。 我对Unity和lighting非常熟悉,所以它可能很简单,但我已经在Oculus上开发了一年多,从来没有出现过这

  • 问题内容: 在我拥有的一个小程序(尤其是cgo调用)上,go build和go run非常慢。我想缓存二进制文件,以便仅在源文件较新时才重建。我会使用带有%规则的简单Makefile,但是语言设计人员声称go的构建支持不需要Makefile。 我还有其他选择吗?go社区是否愿意使用另一个构建系统(可能是基于哈希的构建系统)来缓存和重用构建产品? 问题答案: 我写了一个工具来解决这个问题。单独不会检

  • 我在用 使用G1垃圾收集器。JVM参数是 然而,我在没有任何明显原因的情况下经历了完整的GC扫描,如何摆脱它们? GC日志,带有前面事件的一些尾部: 其他类似的: 其他类似问题报告: http://grokbase.com/t/openjdk/hotspot-gc-use/1192sy84j5/g1c-strange-full-gc-behaviorhttp://grokbase.com/p/op

  • 我有一个具有必要字段的窗格扩展类。它将是“大门”。 调用控制器从FXML加载节点树,并将其作为子级附加到“gate”对象 然后创建并显示一个以“gate”为根节点的新场景。 新的窗口控制器有一个对FXML根节点(“gate”的直接子节点)的引用,他所需要做的就是在其上使用.getparent()来获取“gate”。 但管他呢!它返回null!我做错了什么?我应该通过FXMLLoader设置一个不同

  • 问题内容: 似乎有人认为,在64位体系结构上不需要使用“拆分堆栈”运行时模型。我说的似乎是,因为我还没有看到任何人真的这么说,只在它周围跳舞: 由于每个线程不需要最坏情况的堆栈大小,因此典型的多线程程序的内存使用量可能会大大减少。在32位地址空间中运行数百万个线程(完整的NPTL线程或协程序)成为可能。- 伊恩·兰斯·泰勒(Ian Lance Taylor) …暗示一个64位地址空间已经可以处理它