Server Data Construction and Result with Cost/Time Matrix

[9]:
import json

Accumulate Problem Data

[10]:
json_data = {}

Set Cost/Travel Time Matrix


We need to provide square matrices for cost/time matrices which have positve float values.

Cost matrices act as a cost of travel between one location to another. This cost can be accumulated over the result to find best possible solution. By default, this cost is accumulated, and it can be disabled with the objective value set to 0.

The travel time matrix is used to evaluate time window constraints for vehicles and tasks. So if any kind of time window constraint usage or time related constraint, the Time Matrix is a must-have.

Multiple cost and travel time matrices can be provided depending on the types of vehicle supported, and cost and time differs for such vehicles (For example, CAR and BIKE).

[11]:
# Considering cost is half of travel time

# Car
car_cost_matrix = [
    [0, 5, 4, 3, 5],
    [5, 0, 6, 4, 3],
    [4, 8, 0, 4, 2],
    [1, 4, 3, 0, 4],
    [3, 3, 5, 6, 0],
]

car_time_matrix = [
    [ 0, 10,  8,  6, 10],
    [10,  0, 12,  8,  6],
    [ 8, 16,  0,  8,  4],
    [ 2,  8,  6,  0,  8],
    [ 6,  6, 10, 12,  0],
]

# 1 represents car type and 2 represents bike type

# Add cost matrix

json_data["cost_matrix_data"] = {
    "data" : {
        1:car_cost_matrix
    }
}

# Add time matrix

json_data["travel_time_matrix_data"] = {
    "data" : {
        1:car_time_matrix
    }
}

Set Fleet Data


Provide vehicle start and end locations along with vehicle features and capacity.

[12]:
fleet_data = {
    "vehicle_locations": [[0, 0], [0, 0], [0, 0], [0, 0], [0, 0]],
    "vehicle_ids": ["Car-A", "Car-B", "Car-C", "Car-D", "Car-E"],
    "vehicle_types": [1, 1, 1, 1, 1],
    "capacities": [[75, 75, 75, 75, 75]],
    "vehicle_time_windows": [
        [0, 100],
        [0, 100],
        [0, 100],
        [0, 100],
        [0, 100]
    ],
    # Vehicle can take breaks in this time window as per berak duration provided
    "vehicle_break_time_windows":[
        [
            [20, 25],
            [20, 25],
            [20, 25],
            [20, 25],
            [20, 25]
        ]
    ],
    "vehicle_break_durations": [[1, 1, 1, 1, 1]],
    # Maximum cost a vehicle can incur while delivering
    "vehicle_max_costs": [100, 100, 100, 100, 100],
    # Maximum time a vehicle can be working
    "vehicle_max_times": [120, 120, 120, 120, 120]
}

json_data["fleet_data"] = fleet_data

Set Task Data


Provide details on task locations, demand, and time window; there are other options as well.

[13]:
task_data = {
    "task_locations": [1, 2, 3, 4],
    "demand": [[30, 40, 40, 30]],
    "task_time_windows": [
        [3, 20],
        [5, 30],
        [1, 20],
        [4, 40],
    ],
    "service_times": [3, 1, 8, 4],
    "prizes": [50, 50, 100, 50]
}

json_data["task_data"] = task_data

Set Solver Config


Larger problems might require more time.

[14]:
solver_config = {
    "objectives": {
        "cost": 1,
        "travel_time": 1,
        "prize": 2
    }
}

json_data["solver_config"] = solver_config

Solve the Problem


cuOpt endpoints can be triggered as shown in the thin client example.

Use this data and invoke cuOpt endpoint, which would return routes.

If the response status is 0,

then cuOpt found a feasible solution, under dictionary solver_response.

if status is 1,

then it found an infeasible solution by going over constraints. Warnings will list what constraints caused the infeasible solution, which can be analyzed further. Any other state indicating that cuOpt failed may be due to invalid data or some unhandled issue. This will be under dictionary solver_infeasible_response.

{
    'response': {
        'solver_response': {
            'status': 0,
            'num_vehicles': 2,
            'solution_cost': -407.0,
            'vehicle_data': {
                'Car-A': {
                    'task_id': ['Depot', '0', 'Break', '1', 'Depot'],
                    'arrival_stamp': [0.0, 10.0, 25.0, 26.0, 35.0],
                    'route': [0, 1, 2, 2, 0],
                    'type': ['Depot', 'Delivery', 'Break', 'Delivery', 'Depot']
                },
                'Car-B': {
                    'task_id': ['Depot', '2', 'Break', '3', 'Depot'],
                    'arrival_stamp': [6.0, 12.0, 20.0, 29.0, 39.0],
                    'route': [0, 3, 3, 4, 0],
                    'type': ['Depot', 'Delivery', 'Break', 'Delivery', 'Depot']
                }
            },
            'dropped_tasks': {
              'task_id': [],
              'task_index': []
            },
            'msg': ''
        },
        'perf_times': None
    },
    'reqId': '13f4e591-525f-4f22-9f4d-4e3c81f9b0d7'
}

Solution cost is -407.0, this is due to objective value being set for prize, which gets negated from other values.