OR-工具 bad_alloc 异常

问题描述 投票:0回答:1

我正在尝试使用 python 中的 OR-tools 库解决车辆路径问题

3.10.12

使用所使用的设置,求解器崩溃。我不明白问题是什么,如果我只使用一辆车就不会发生这种情况。

我已经阅读了这个问题(https://github.com/google/or-tools/issues/3975),即使使用此命令:

search_parameters.local_search_operators.use_shortest_path_swap_active = "BOOL_FALSE"
这不起作用。

或工具版本:

此问题仅存在于高于

9.4.1874
的版本。

抛出错误

terminate called after throwing an instance of 'std::bad_alloc' what():  std::bad_alloc Aborted


from typing import List
from google.protobuf import duration_pb2
from ortools.constraint_solver import routing_enums_pb2
from ortools.constraint_solver import pywrapcp
from datetime import time

class Location:
    def __init__(self, id) -> None:
        self.id = id

    def isDepot(self) -> bool:
        return False  # Default implementation returns False
    def isStep(self) -> bool:
        return False  # Default implementation returns False

class Magazzino(Location):
    def __init__(self,  id) -> None:
        super().__init__( 0) 

    def isDepot(self) -> bool:
        return True

class Step(Location):
    def __init__(self, id ,  type, seq_ordine) -> None:
        super().__init__(id )
        self.id_step = id #  step.id_step
        self.id_ordine = 1 # step.id_ordine
        self.tipo_step = type # step.tipo_step
        self.seq_ordine =  seq_ordine # step.seq_ordine
    
    def isStep(self) -> bool:
        return True


class VRPSolver:

    def __init__(self,  steps : List[Step], depots : List[Magazzino] ):
        self.steps = steps

        combined_locations = depots + steps  

        self.step_id_to_index = { loc.id: idx for idx, loc in enumerate(combined_locations) if loc.isStep()}  # Map custom IDs to indices
        self.index_to_obj = {idx: obj for idx , obj in enumerate(combined_locations)}  # Reverse map

        print("STEP_ID_TO_INDEX:" , self.step_id_to_index)

        self.data = {
            'distance_matrix': [[  0,  21, 209, 106, 132, 121],
       [ 21,   0, 220, 127, 122, 128],
       [209, 220,   0, 214, 341, 311],
       [106, 127, 214,   0, 188, 116],
       [132, 122, 341, 188,   0,  94],
       [121, 128, 311, 116,  94,   0]],
            'time_matrix':  [[  0,  19, 193,  98, 122, 112],
       [ 19,   0, 203, 117, 113, 118],
       [193, 203,   0, 198, 315, 287],
       [ 98, 117, 198,   0, 174, 107],
       [122, 113, 315, 174,   0,  87],
       [112, 118, 287, 107,  87,   0]],
            'num_vehicles': 4,
            'depot': 0,
            'vehicle_capacities': [ 100 ] * 4,
            'pickups_deliveries': [],
            'vehicle_constraints' : {}
        }
        # self.vehicle_constraint() # RIMOSSO PERCHé CHIAMATO DAL LOGIC
        self.consequential_constraint()
        print(self.data)

    def consequential_constraint(self):
        order_steps = {}
        for s in self.steps:
            if s.id_ordine not in order_steps:
                order_steps[s.id_ordine] = []
            order_steps[s.id_ordine].append(s)
        
        print("ORDER_STEP",order_steps)
        # Determine pickup and delivery pairs
        for order in order_steps.values():
            pickups = {s for s in order if s.tipo_step == 'R'}
            deliveries = {s for s in order if s.tipo_step == 'C'}
            
            for p in pickups:
                for d in deliveries:
                    if d.seq_ordine  > p.seq_ordine :
                        self.add_pickup_delivery(p.id, d.id)
                        print("PICKUP  : " + str(p.id) + " C : " + str(d.id)) 

    def add_pickup_delivery(self, pickup_id, delivery_id):
        pickup_index =    self.step_id_to_index[pickup_id]
        delivery_index =   self.step_id_to_index[delivery_id]
        self.data['pickups_deliveries'].append([pickup_index, delivery_index])
    
    def solve(self):
        manager = pywrapcp.RoutingIndexManager(
            len(self.data['distance_matrix']), self.data['num_vehicles'], self.data['depot']
        )
        routing = pywrapcp.RoutingModel(manager)

        ##### TIME ######
        def time_callback(from_index, to_index):
            from_node = manager.IndexToNode(from_index)
            to_node = manager.IndexToNode(to_index)
            return self.data['time_matrix'][from_node][to_node]

        time_callback_index = routing.RegisterTransitCallback(time_callback)

        # Add Time Dimension
        routing.AddDimension(
            time_callback_index,
            60,  # Allow for some waiting time
            30000,  # Large enough to not overly restrict route maximum time
            False,  # Don't force start cumul to zero. This doesn't force the vehicle to start right at the time at the depot
            'Time'
        )
        time_dimension = routing.GetDimensionOrDie('Time')
        time_dimension.SetGlobalSpanCostCoefficient(1)  # Adjust this to give time some influence but less than distance

        ###### DISTANCE ######
        def distance_callback(from_index, to_index):
            from_node = manager.IndexToNode(from_index)
            to_node = manager.IndexToNode(to_index)
            return self.data['distance_matrix'][from_node][to_node]

        transit_callback_index = routing.RegisterTransitCallback(distance_callback)
        routing.SetArcCostEvaluatorOfAllVehicles(transit_callback_index)


        # Add distance dimension
        routing.AddDimension(
            transit_callback_index, 0, 10000, True, 'Distance'
        )
        distance_dimension = routing.GetDimensionOrDie('Distance')
        distance_dimension.SetGlobalSpanCostCoefficient(1)
            
        # Add pickup and delivery
        for request in self.data['pickups_deliveries']:
            pickup_index = manager.NodeToIndex(request[0])
            delivery_index = manager.NodeToIndex(request[1])
            routing.AddPickupAndDelivery(pickup_index, delivery_index)
            routing.solver().Add(
                routing.VehicleVar(pickup_index) == routing.VehicleVar(delivery_index)
            )
            routing.solver().Add(
                distance_dimension.CumulVar(pickup_index) <= distance_dimension.CumulVar(delivery_index)
            )

        search_parameters = pywrapcp.DefaultRoutingSearchParameters()
        search_parameters.first_solution_strategy = (
            routing_enums_pb2.FirstSolutionStrategy.PATH_CHEAPEST_ARC  # Less intensive strategy
        )
        search_parameters.local_search_metaheuristic = (
            routing_enums_pb2.LocalSearchMetaheuristic.TABU_SEARCH    # Change the metaheuristic
        )
        search_parameters.local_search_operators.use_shortest_path_swap_active = "BOOL_FALSE"

        search_parameters.time_limit.seconds = 1  # Limit the search time
        search_parameters.log_search = True  # Enable logging

        solution = routing.SolveWithParameters(search_parameters)
        if solution:
            return solution

def main():
    all_magazzini = [ Magazzino(id=0),
                      Magazzino(id=1 )  ]

    all_step = []
    all_step.append(Step(1, 'C', 4))       
    all_step.append(Step(2, 'R', 1))       
    all_step.append(Step(3, 'C', 3))       
    all_step.append(Step(4, 'R', 2))       

    solver = VRPSolver( steps= all_step, depots = all_magazzini  )#  , vehicles = vehicles,   depot=0,  locations=locations)
    sol = solver.solve()
    print(sol)
    pass

if __name__ == "__main__":
    main()

我尝试过使用9.4以上的所有版本,但都不起作用。

我也尝试了建议的解决方案

search_parameters.local_search_operators.use_shortest_path_swap_active = "BOOL_FALSE"

但什么都没有改变。

元启发式

我尝试过不同的 local_search_metaheuristic。

  • TABU_搜索
  • 贪婪_下降
  • 模拟退火
python-3.x optimization linear-programming or-tools vehicle-routing
1个回答
0
投票

该错误是由于为同一个提货输入了不同的交货而引起的。 通过这样做,最新版本无法解决问题,引发上述异常。

出于某种我不知道的原因,9.4 版本能够解决该问题,尽管该解决方案不是最佳的。

为了克服这个问题,需要复制节点,以便每个节点仅位于 1 个 P&D 对中

© www.soinside.com 2019 - 2024. All rights reserved.