Multiple trips

These examples demonstrate how to use vehicle reload feature which is designed to overcome vehicle capacity limitation in order to perform multiple trips (tours).

Essentially, reload is a place where vehicle can unload static pickups and load new static deliveries. Here, static correspond to static demand concept which is defined via standalone pickup or delivery jobs, not by single pickup and delivery job.

Same location reload

In this scenario, once some jobs are delivered, the vehicle returns to the original depot to load next goods.

Problem

{
  "plan": {
    "jobs": [
      {
        "id": "job1",
        "deliveries": [
          {
            "places": [
              {
                "location": {
                  "lat": 52.52599,
                  "lng": 13.45413
                },
                "duration": 300.0
              }
            ],
            "demand": [
              1
            ]
          }
        ]
      },
      {
        "id": "job2",
        "deliveries": [
          {
            "places": [
              {
                "location": {
                  "lat": 52.5225,
                  "lng": 13.4095
                },
                "duration": 240.0
              }
            ],
            "demand": [
              1
            ]
          }
        ]
      },
      {
        "id": "job3",
        "deliveries": [
          {
            "places": [
              {
                "location": {
                  "lat": 52.5165,
                  "lng": 13.3808
                },
                "duration": 300.0
              }
            ],
            "demand": [
              1
            ]
          }
        ]
      },
      {
        "id": "job4",
        "deliveries": [
          {
            "places": [
              {
                "location": {
                  "lat": 52.5145,
                  "lng": 13.3513
                },
                "duration": 300.0
              }
            ],
            "demand": [
              1
            ]
          }
        ]
      }
    ]
  },
  "fleet": {
    "vehicles": [
      {
        "typeId": "vehicle",
        "vehicleIds": [
          "vehicle_1"
        ],
        "profile": {
          "matrix": "normal_car"
        },
        "costs": {
          "fixed": 22.0,
          "distance": 0.0002,
          "time": 0.004806
        },
        "shifts": [
          {
            "start": {
              "earliest": "2019-07-04T09:00:00Z",
              "location": {
                "lat": 52.5316,
                "lng": 13.3884
              }
            },
            "end": {
              "latest": "2019-07-04T18:00:00Z",
              "location": {
                "lat": 52.5316,
                "lng": 13.3884
              }
            },
            "reloads": [
              {
                "location": {
                  "lat": 52.5316,
                  "lng": 13.3884
                },
                "duration": 600.0
              }
            ]
          }
        ],
        "capacity": [
          2
        ]
      }
    ],
    "profiles": [
      {
        "name": "normal_car"
      }
    ]
  }
}

Solution

{
  "statistic": {
    "cost": 52.651224000000006,
    "distance": 20995,
    "duration": 5504,
    "times": {
      "driving": 3764,
      "serving": 1740,
      "waiting": 0,
      "break": 0
    }
  },
  "tours": [
    {
      "vehicleId": "vehicle_1",
      "typeId": "vehicle",
      "shiftIndex": 0,
      "stops": [
        {
          "location": {
            "lat": 52.5316,
            "lng": 13.3884
          },
          "time": {
            "arrival": "2019-07-04T09:00:00Z",
            "departure": "2019-07-04T09:00:00Z"
          },
          "distance": 0,
          "load": [
            2
          ],
          "activities": [
            {
              "jobId": "departure",
              "type": "departure"
            }
          ]
        },
        {
          "location": {
            "lat": 52.52599,
            "lng": 13.45413
          },
          "time": {
            "arrival": "2019-07-04T09:14:49Z",
            "departure": "2019-07-04T09:19:49Z"
          },
          "distance": 5090,
          "load": [
            1
          ],
          "activities": [
            {
              "jobId": "job1",
              "type": "delivery"
            }
          ]
        },
        {
          "location": {
            "lat": 52.5225,
            "lng": 13.4095
          },
          "time": {
            "arrival": "2019-07-04T09:31:22Z",
            "departure": "2019-07-04T09:35:22Z"
          },
          "distance": 8930,
          "load": [
            0
          ],
          "activities": [
            {
              "jobId": "job2",
              "type": "delivery"
            }
          ]
        },
        {
          "location": {
            "lat": 52.5316,
            "lng": 13.3884
          },
          "time": {
            "arrival": "2019-07-04T09:45:02Z",
            "departure": "2019-07-04T09:55:02Z"
          },
          "distance": 12156,
          "load": [
            2
          ],
          "activities": [
            {
              "jobId": "reload",
              "type": "reload"
            }
          ]
        },
        {
          "location": {
            "lat": 52.5165,
            "lng": 13.3808
          },
          "time": {
            "arrival": "2019-07-04T10:02:31Z",
            "departure": "2019-07-04T10:07:31Z"
          },
          "distance": 14308,
          "load": [
            1
          ],
          "activities": [
            {
              "jobId": "job3",
              "type": "delivery"
            }
          ]
        },
        {
          "location": {
            "lat": 52.5145,
            "lng": 13.3513
          },
          "time": {
            "arrival": "2019-07-04T10:15:03Z",
            "departure": "2019-07-04T10:20:03Z"
          },
          "distance": 17092,
          "load": [
            0
          ],
          "activities": [
            {
              "jobId": "job4",
              "type": "delivery"
            }
          ]
        },
        {
          "location": {
            "lat": 52.5316,
            "lng": 13.3884
          },
          "time": {
            "arrival": "2019-07-04T10:31:44Z",
            "departure": "2019-07-04T10:31:44Z"
          },
          "distance": 20995,
          "load": [
            0
          ],
          "activities": [
            {
              "jobId": "arrival",
              "type": "arrival"
            }
          ]
        }
      ],
      "statistic": {
        "cost": 52.651224000000006,
        "distance": 20995,
        "duration": 5504,
        "times": {
          "driving": 3764,
          "serving": 1740,
          "waiting": 0,
          "break": 0
        }
      }
    }
  ],
  "unassigned": []
}

Multiple reloads with different locations

In this scenario, vehicle picks goods and flushes them on two different locations during single tour. This can be used to model waste collection use case.

Problem

{
  "plan": {
    "jobs": [
      {
        "id": "job1",
        "pickups": [
          {
            "places": [
              {
                "location": {
                  "lat": 52.52599,
                  "lng": 13.45413
                },
                "duration": 300.0
              }
            ],
            "demand": [
              1
            ]
          }
        ]
      },
      {
        "id": "job2",
        "pickups": [
          {
            "places": [
              {
                "location": {
                  "lat": 52.5225,
                  "lng": 13.4095
                },
                "duration": 240.0
              }
            ],
            "demand": [
              1
            ]
          }
        ]
      },
      {
        "id": "job3",
        "pickups": [
          {
            "places": [
              {
                "location": {
                  "lat": 52.5165,
                  "lng": 13.3808
                },
                "duration": 300.0
              }
            ],
            "demand": [
              1
            ]
          }
        ]
      },
      {
        "id": "job4",
        "pickups": [
          {
            "places": [
              {
                "location": {
                  "lat": 52.5145,
                  "lng": 13.3513
                },
                "duration": 300.0
              }
            ],
            "demand": [
              1
            ]
          }
        ]
      },
      {
        "id": "job5",
        "pickups": [
          {
            "places": [
              {
                "location": {
                  "lat": 52.4922,
                  "lng": 13.4593
                },
                "duration": 300.0
              }
            ],
            "demand": [
              1
            ]
          }
        ]
      },
      {
        "id": "job6",
        "pickups": [
          {
            "places": [
              {
                "location": {
                  "lat": 52.4989,
                  "lng": 13.3917
                },
                "duration": 300.0
              }
            ],
            "demand": [
              1
            ]
          }
        ]
      }
    ]
  },
  "fleet": {
    "vehicles": [
      {
        "typeId": "vehicle",
        "vehicleIds": [
          "vehicle_1"
        ],
        "profile": {
          "matrix": "normal_car"
        },
        "costs": {
          "fixed": 22.0,
          "distance": 0.0002,
          "time": 0.004806
        },
        "shifts": [
          {
            "start": {
              "earliest": "2019-07-04T09:00:00Z",
              "location": {
                "lat": 52.5316,
                "lng": 13.3884
              }
            },
            "end": {
              "latest": "2019-07-04T18:00:00Z",
              "location": {
                "lat": 52.5316,
                "lng": 13.3884
              }
            },
            "reloads": [
              {
                "location": {
                  "lat": 52.5103,
                  "lng": 13.3898
                },
                "duration": 600.0
              },
              {
                "location": {
                  "lat": 52.5043,
                  "lng": 13.4091
                },
                "duration": 600.0
              }
            ]
          }
        ],
        "capacity": [
          2
        ]
      }
    ],
    "profiles": [
      {
        "name": "normal_car"
      }
    ]
  }
}

Solution

{
  "statistic": {
    "cost": 52.38156800000001,
    "distance": 23876,
    "duration": 5328,
    "times": {
      "driving": 2388,
      "serving": 2940,
      "waiting": 0,
      "break": 0
    }
  },
  "tours": [
    {
      "vehicleId": "vehicle_1",
      "typeId": "vehicle",
      "shiftIndex": 0,
      "stops": [
        {
          "location": {
            "lat": 52.5316,
            "lng": 13.3884
          },
          "time": {
            "arrival": "2019-07-04T09:00:00Z",
            "departure": "2019-07-04T09:00:00Z"
          },
          "distance": 0,
          "load": [
            0
          ],
          "activities": [
            {
              "jobId": "departure",
              "type": "departure"
            }
          ]
        },
        {
          "location": {
            "lat": 52.5225,
            "lng": 13.4095
          },
          "time": {
            "arrival": "2019-07-04T09:02:55Z",
            "departure": "2019-07-04T09:06:55Z"
          },
          "distance": 1752,
          "load": [
            1
          ],
          "activities": [
            {
              "jobId": "job2",
              "type": "pickup"
            }
          ]
        },
        {
          "location": {
            "lat": 52.5165,
            "lng": 13.3808
          },
          "time": {
            "arrival": "2019-07-04T09:10:21Z",
            "departure": "2019-07-04T09:15:21Z"
          },
          "distance": 3808,
          "load": [
            2
          ],
          "activities": [
            {
              "jobId": "job3",
              "type": "pickup"
            }
          ]
        },
        {
          "location": {
            "lat": 52.5103,
            "lng": 13.3898
          },
          "time": {
            "arrival": "2019-07-04T09:16:53Z",
            "departure": "2019-07-04T09:26:53Z"
          },
          "distance": 4729,
          "load": [
            0
          ],
          "activities": [
            {
              "jobId": "reload",
              "type": "reload"
            }
          ]
        },
        {
          "location": {
            "lat": 52.5145,
            "lng": 13.3513
          },
          "time": {
            "arrival": "2019-07-04T09:31:18Z",
            "departure": "2019-07-04T09:36:18Z"
          },
          "distance": 7379,
          "load": [
            1
          ],
          "activities": [
            {
              "jobId": "job4",
              "type": "pickup"
            }
          ]
        },
        {
          "location": {
            "lat": 52.4989,
            "lng": 13.3917
          },
          "time": {
            "arrival": "2019-07-04T09:41:42Z",
            "departure": "2019-07-04T09:46:42Z"
          },
          "distance": 10621,
          "load": [
            2
          ],
          "activities": [
            {
              "jobId": "job6",
              "type": "pickup"
            }
          ]
        },
        {
          "location": {
            "lat": 52.5043,
            "lng": 13.4091
          },
          "time": {
            "arrival": "2019-07-04T09:48:54Z",
            "departure": "2019-07-04T09:58:54Z"
          },
          "distance": 11944,
          "load": [
            0
          ],
          "activities": [
            {
              "jobId": "reload",
              "type": "reload"
            }
          ]
        },
        {
          "location": {
            "lat": 52.4922,
            "lng": 13.4593
          },
          "time": {
            "arrival": "2019-07-04T10:05:00Z",
            "departure": "2019-07-04T10:10:00Z"
          },
          "distance": 15603,
          "load": [
            1
          ],
          "activities": [
            {
              "jobId": "job5",
              "type": "pickup"
            }
          ]
        },
        {
          "location": {
            "lat": 52.52599,
            "lng": 13.45413
          },
          "time": {
            "arrival": "2019-07-04T10:16:18Z",
            "departure": "2019-07-04T10:21:18Z"
          },
          "distance": 19381,
          "load": [
            2
          ],
          "activities": [
            {
              "jobId": "job1",
              "type": "pickup"
            }
          ]
        },
        {
          "location": {
            "lat": 52.5316,
            "lng": 13.3884
          },
          "time": {
            "arrival": "2019-07-04T10:28:48Z",
            "departure": "2019-07-04T10:28:48Z"
          },
          "distance": 23876,
          "load": [
            0
          ],
          "activities": [
            {
              "jobId": "arrival",
              "type": "arrival"
            }
          ]
        }
      ],
      "statistic": {
        "cost": 52.38156800000001,
        "distance": 23876,
        "duration": 5328,
        "times": {
          "driving": 2388,
          "serving": 2940,
          "waiting": 0,
          "break": 0
        }
      }
    }
  ],
  "unassigned": []
}

Shared reload resource

In this scenario, there are two vehicles with limited capacity [2] with reload which has shared resource constraint [1]. The problem has 6 delivery jobs in total.

Problem

{
  "plan": {
    "jobs": [
      {
        "id": "job1",
        "deliveries": [
          {
            "places": [
              {
                "location": {
                  "lat": 52.52599,
                  "lng": 13.45413
                },
                "duration": 300.0
              }
            ],
            "demand": [
              1
            ]
          }
        ]
      },
      {
        "id": "job2",
        "deliveries": [
          {
            "places": [
              {
                "location": {
                  "lat": 52.5225,
                  "lng": 13.4095
                },
                "duration": 240.0
              }
            ],
            "demand": [
              1
            ]
          }
        ]
      },
      {
        "id": "job3",
        "deliveries": [
          {
            "places": [
              {
                "location": {
                  "lat": 52.5165,
                  "lng": 13.3808
                },
                "duration": 300.0
              }
            ],
            "demand": [
              1
            ]
          }
        ]
      },
      {
        "id": "job4",
        "deliveries": [
          {
            "places": [
              {
                "location": {
                  "lat": 52.5145,
                  "lng": 13.3513
                },
                "duration": 300.0
              }
            ],
            "demand": [
              1
            ]
          }
        ]
      },
      {
        "id": "job5",
        "deliveries": [
          {
            "places": [
              {
                "location": {
                  "lat": 52.4922,
                  "lng": 13.4593
                },
                "duration": 300.0
              }
            ],
            "demand": [
              1
            ]
          }
        ]
      },
      {
        "id": "job6",
        "deliveries": [
          {
            "places": [
              {
                "location": {
                  "lat": 52.4989,
                  "lng": 13.3917
                },
                "duration": 300.0
              }
            ],
            "demand": [
              1
            ]
          }
        ]
      }
    ]
  },
  "fleet": {
    "vehicles": [
      {
        "typeId": "vehicle",
        "vehicleIds": [
          "vehicle_1",
          "vehicle_2"
        ],
        "profile": {
          "matrix": "normal_car"
        },
        "costs": {
          "fixed": 22.0,
          "distance": 0.0002,
          "time": 0.004806
        },
        "shifts": [
          {
            "start": {
              "earliest": "2019-07-04T09:00:00Z",
              "location": {
                "lat": 52.5316,
                "lng": 13.3884
              }
            },
            "end": {
              "latest": "2019-07-04T18:00:00Z",
              "location": {
                "lat": 52.5316,
                "lng": 13.3884
              }
            },
            "reloads": [
              {
                "location": {
                  "lat": 52.5103,
                  "lng": 13.3898
                },
                "duration": 600.0,
                "resourceId": "warehouse_a"
              }
            ]
          }
        ],
        "capacity": [
          2
        ]
      }
    ],
    "profiles": [
      {
        "name": "normal_car"
      }
    ],
    "resources": [
      {
        "type": "reload",
        "id": "warehouse_a",
        "capacity": [1]
      }
    ]
  }
}

As result, the solution has 5 jobs assigned and one is unassigned as there is not enough capacity and reload resource constraint doesn't allow to reload more than 1 delivery in total for all vehicles.

Solution

{
  "statistic": {
    "cost": 67.17683,
    "distance": 19644,
    "duration": 4005,
    "times": {
      "driving": 1965,
      "serving": 2040,
      "waiting": 0,
      "break": 0,
      "commuting": 0,
      "parking": 0
    }
  },
  "tours": [
    {
      "vehicleId": "vehicle_1",
      "typeId": "vehicle",
      "shiftIndex": 0,
      "stops": [
        {
          "location": {
            "lat": 52.5316,
            "lng": 13.3884
          },
          "time": {
            "arrival": "2019-07-04T09:00:00Z",
            "departure": "2019-07-04T09:00:00Z"
          },
          "distance": 0,
          "load": [
            2
          ],
          "activities": [
            {
              "jobId": "departure",
              "type": "departure"
            }
          ]
        },
        {
          "location": {
            "lat": 52.5145,
            "lng": 13.3513
          },
          "time": {
            "arrival": "2019-07-04T09:05:15Z",
            "departure": "2019-07-04T09:10:15Z"
          },
          "distance": 3152,
          "load": [
            1
          ],
          "activities": [
            {
              "jobId": "job4",
              "type": "delivery"
            }
          ]
        },
        {
          "location": {
            "lat": 52.4989,
            "lng": 13.3917
          },
          "time": {
            "arrival": "2019-07-04T09:15:39Z",
            "departure": "2019-07-04T09:20:39Z"
          },
          "distance": 6394,
          "load": [
            0
          ],
          "activities": [
            {
              "jobId": "job6",
              "type": "delivery"
            }
          ]
        },
        {
          "location": {
            "lat": 52.5103,
            "lng": 13.3898
          },
          "time": {
            "arrival": "2019-07-04T09:22:47Z",
            "departure": "2019-07-04T09:32:47Z"
          },
          "distance": 7670,
          "load": [
            1
          ],
          "activities": [
            {
              "jobId": "reload",
              "type": "reload"
            }
          ]
        },
        {
          "location": {
            "lat": 52.5165,
            "lng": 13.3808
          },
          "time": {
            "arrival": "2019-07-04T09:34:19Z",
            "departure": "2019-07-04T09:39:19Z"
          },
          "distance": 8591,
          "load": [
            0
          ],
          "activities": [
            {
              "jobId": "job3",
              "type": "delivery"
            }
          ]
        },
        {
          "location": {
            "lat": 52.5316,
            "lng": 13.3884
          },
          "time": {
            "arrival": "2019-07-04T09:42:15Z",
            "departure": "2019-07-04T09:42:15Z"
          },
          "distance": 10349,
          "load": [
            0
          ],
          "activities": [
            {
              "jobId": "arrival",
              "type": "arrival"
            }
          ]
        }
      ],
      "statistic": {
        "cost": 36.25301,
        "distance": 10349,
        "duration": 2535,
        "times": {
          "driving": 1035,
          "serving": 1500,
          "waiting": 0,
          "break": 0,
          "commuting": 0,
          "parking": 0
        }
      }
    },
    {
      "vehicleId": "vehicle_2",
      "typeId": "vehicle",
      "shiftIndex": 0,
      "stops": [
        {
          "location": {
            "lat": 52.5316,
            "lng": 13.3884
          },
          "time": {
            "arrival": "2019-07-04T09:00:00Z",
            "departure": "2019-07-04T09:00:00Z"
          },
          "distance": 0,
          "load": [
            2
          ],
          "activities": [
            {
              "jobId": "departure",
              "type": "departure"
            }
          ]
        },
        {
          "location": {
            "lat": 52.52599,
            "lng": 13.45413
          },
          "time": {
            "arrival": "2019-07-04T09:07:30Z",
            "departure": "2019-07-04T09:12:30Z"
          },
          "distance": 4495,
          "load": [
            1
          ],
          "activities": [
            {
              "jobId": "job1",
              "type": "delivery"
            }
          ]
        },
        {
          "location": {
            "lat": 52.5225,
            "lng": 13.4095
          },
          "time": {
            "arrival": "2019-07-04T09:17:35Z",
            "departure": "2019-07-04T09:21:35Z"
          },
          "distance": 7543,
          "load": [
            0
          ],
          "activities": [
            {
              "jobId": "job2",
              "type": "delivery"
            }
          ]
        },
        {
          "location": {
            "lat": 52.5316,
            "lng": 13.3884
          },
          "time": {
            "arrival": "2019-07-04T09:24:30Z",
            "departure": "2019-07-04T09:24:30Z"
          },
          "distance": 9295,
          "load": [
            0
          ],
          "activities": [
            {
              "jobId": "arrival",
              "type": "arrival"
            }
          ]
        }
      ],
      "statistic": {
        "cost": 30.92382,
        "distance": 9295,
        "duration": 1470,
        "times": {
          "driving": 930,
          "serving": 540,
          "waiting": 0,
          "break": 0,
          "commuting": 0,
          "parking": 0
        }
      }
    }
  ],
  "unassigned": [
    {
      "jobId": "job5",
      "reasons": [
        {
          "code": "RELOAD_RESOURCE_CONSTRAINT",
          "description": "cannot be assigned due to reload resource constraint",
          "details": [
            {
              "vehicleId": "vehicle_1",
              "shiftIndex": 0
            }
          ]
        },
        {
          "code": "CAPACITY_CONSTRAINT",
          "description": "does not fit into any vehicle due to capacity",
          "details": [
            {
              "vehicleId": "vehicle_2",
              "shiftIndex": 0
            }
          ]
        }
      ]
    }
  ]
}