In the routing model, is there a way to get the list of nodes that have been visited by a vehicle in a callback function?

34 views
Skip to first unread message

Charumathi Vasudevan

unread,
Jul 21, 2024, 8:25:26 AM (4 days ago) Jul 21
to or-tools-discuss
I am very new to OR-tools and combinatorial optimization so I am struggling to find a solution for the routing problem at hand. The problem along with minimizing travel time, should also keep track of what unique commodity type have been picked up along the route and once it reaches a maximum limit go back to depot.

For example, imagine there is a cart in the vehicle which has 3 separate compartments and each compartment can hold only one type of  commodity. Now the vehicle can pickup only 3 different commodity (though the capacity of each compartment might be infinite and therefore the qty picked for each category need not be tracked).

I first wrote a unique items callback function that maintains a set of what items are picked up in each location. 
class UniqueItemsCounter:
    def __init__(self, data, manager,vehicle):
        self.data = data
        self.manager = manager
        self.vehicle = vehicle
        self.visited_items = set()

    def __call__(self, from_index):
        vehicle_id = self.vehicle
        from_node = self.manager.IndexToNode(from_index)
        previous_item_type_count = 0
        current_item_type_count = 0
        if from_node == self.data['depot']:
            self.visited_items = set()  # Reset items when at depot
        if from_node != self.data['depot']:
            previous_item_type_count = len(self.visited_items)
            self.visited_items.update(
                self.data['item_type'][from_node])
            current_item_type_count = len(self.visited_items)
        return current_item_type_count-previous_item_type_count
unique_items_callback_indices = []
for vehicle_id in range(data['num_vehicles']):
    unique_items_callback_indices.append(
        routing.RegisterUnaryTransitCallback(
            UniqueItemsCounter(data, manager, vehicle_id)))
routing.AddDimensionWithVehicleTransits(
    unique_items_callback_indices,
    0,  # no slack
    data['cluster_size'],  # vehicle capacity
    True,  # start cumul to zero
    'UniqueItems')
unique_items_dimension = routing.GetDimensionOrDie('UniqueItems')
unique_items_dimension.SetSpanCostCoefficientForAllVehicles(1)

# Add the constraint to return to depot when max unique items limit is reached
# for vehicle_id in range(data['num_vehicles']):
#     unique_items_dimension.CumulVar(routing.End(vehicle_id)).SetMax(data['cluster_size'])
penalty = 1000
for node in range(1, len(data['travel_times'])):
    routing.AddDisjunction([manager.NodeToIndex(node)], penalty)
This did not work - I am guessing because while the set 'visited_items' will be updated with each item picked up, there is no way to remove these items when the solver explores various solution paths.

So my second approach was that I could simulate the compartments as separate vehicles themselves but adding two constraints: that every 3 (one vehicle for each compartment) vehicles in the fleet are dependent on each other - i.e. they should take the same route but pick up a single item type. 
My questions are:
1. Is it possible to make the routes of vehicle A and vehicle B the same? If yes, how can I model that in OR tools?
2. Is it possible to put a constraint on each vehicle that each vehicle will pickup only one particular item?


So how do I enforce this?

I have so far tried two approaches:
One is to create a callback class which keeps track of the item types
Reply all
Reply to author
Forward
0 new messages