API Reference ========================================================== *Tarot Routing - Route Optimisation API* Request ------- RoutingProblem ^^^^^^^^^^^^^^ .. py:data:: RoutingProblem :type: JSON Object A RoutingObject is the body of the request send to the Route Optimisation API endpoint. :param drivers: The :py:data:`Drivers ` to perform the :py:data:`Jobs ` :type drivers: list[:py:data:`Driver`] :param jobs: The :py:data:`Jobs ` to be optimised :type jobs: list[:py:data:`Job`] :param settings: The :py:data:`Settings` under which the optimiser will run :type settings: :py:data:`Settings` Minimal Example .. literalinclude:: _static/ex1.json :language: json Driver ^^^^^^ .. py:data:: Driver :type: JSON Object A :py:data:`Driver` represents a driver, their vehicle, or a theoretical run. :param str uid: A Unique Identifier for this :py:data:`Driver`. No two :py:data:`Drivers ` may have the same UID :param float shift_start: The earliest time this :py:data:`Driver` may begin their shift. Time of day as float (e.g. ``8.5``) in 24h time :param float shift_end: The earliest time this :py:data:`Driver` may begin their shift. Time of day as float (e.g. ``8.5``) in 24h time :param location: Where the :py:data:`Driver` begins their run. :type location: :py:data:`Location` :param end_location: (optional, default= ``driver.location``) Where the :py:data:`Driver` ends their run. :type end_location: :py:data:`Location` :param capacity: (optional) Set the capacity of the vehicle. The algorithm compares the total size of all :py:data:`Jobs ` in this :py:data:`Driver`'s run to the capacity of the vehicle. Simple Capacity can be expressed as an integer. For advanced use cases, see :ref:`Capacity `. :type capacity: int or str :param str spec_type: (optional) A :py:data:`Job` can only be served by a :py:data:`Driver` that has at least one ``spec_type`` in common. Learn how to use :ref:`Types ` :param str territories: (optional) A :py:data:`Job` can only be served by a :py:data:`Driver` with at least one of its ``territories`` in common. Learn how to use :ref:`Territories `. :param float speed_multiplier: (optional, default= ``1``) Adjust the driving speed of this :py:data:`Driver`. A value of ``0.5`` means that this :py:data:`Driver` will drive half as fast as normal. A value of ``1.2`` means that this :py:data:`Driver` will drive 20% faster than normal. :param float lunch_time: (optional) The earliest time that a :py:data:`Driver` can start their lunch break. Time is represented as decimal 24h time. So a lunch break starting at 1:15pm is expressed as ``13.25`` :param float lunch_duration: (optional) The duration in minutes of the :py:data:`Driver`'s lunch break :param float lunch_latest_start: (optional, default= ``lunch_time + lunch_duration/60``) The latest time the :py:data:`Driver`'s lunch break my start. To force an exact lunch time, set ``job.lunch_latest_start = job.lunch_time`` Minimal Example .. code-block:: json { "uid": "unique_driver_id_1", "location": {"lat": -33.867798, "lon": 151.166256}, "shift_start": 9.5, "shift_end": 18.5 } Standard Example .. code-block:: json { "uid": "drvid1", "location": { "lat": -33.84948962, "lon": 151.1274823 }, "shift_start": 9.5, "shift_end": 18.5, "speed_multiplier": 0.8, "lunch_time": 12.5, "lunch_duration": 45, "spec_type": "plumber,electrician", "capacity": 25 } | | | Job ^^^ .. py:data:: Job :type: JSON Object :py:data:`Jobs ` represent tasks, delivery points, customers etc. :param str uid: A Unique Identifier for this :py:data:`Job`. No two :py:data:`Jobs ` may have the same UID :param location: Where the :py:data:`Job` is :type location: :py:data:`Location` :param float duration: The number of minutes the :py:data:`Driver` must spend at this :py:data:`Job`. Include parking, doing the :py:data:`Job`, getting back to the vehicle, etc. Often called the *service time* :param float arrive_after: (optional) The earliest time the :py:data:`Driver` may begin this :py:data:`Job`. Time of day as float (e.g. ``13.75``) in 24h time :param float leave_by: (optional) The latest time the :py:data:`Driver` may finish working on this :py:data:`Job`. Time of day as float (e.g. ``15.5``) in 24h time :param size: (optional) The cumulative ``size`` s of :py:data:`Jobs ` are matched against each :py:data:`Driver`s ``capacity`` to ensure that a :py:data:`Driver`/vehicle does not exceed her vehicle's capacity. Units can be whatever syou wish, but must be consistent between all :py:data:`Job's ` sizes and :py:data:`Driver's ` capacities. If ANY :py:data:`Job` has a size, ALL :py:data:`Drivers ` must have a capacity. For advanced use cases, see :ref:`Capacity `. :type size: float or str :param str spec_type: (optional) A :py:data:`Job` can only be served by a :py:data:`Driver` that has at least one ``spec_type`` in common. Learn how to use :ref:`Types `. :param str territories: (optional) A :py:data:`Job` can only be served by a :py:data:`Driver` with at least one of its ``territories`` in common. Learn how to use :ref:`Territories `. :param bool priority: (optional, default= ``false``) If some :py:data:`Jobs ` are more important than others, mark them as ``priority=true``. In Scenarios where not all :py:data:`Jobs ` can be served by your available :py:data:`Driver`s, these :py:data:`Jobs ` will be served, *even if several others are not*. :param str pickup_from: (optional) This creates a *Pickup and Delivery* constraint by referring to the ``uid`` of another :py:data:`Job`. Learn about :ref:`Pickup Delivery`. :param bool pd_interval_max: (optional) Sets the maximum time in minutes allowed between a :ref:`Pickup Delivery` pair of jobs. It should be set on the **Delivery Job only**. Specifically, it sets a constraint on the Job :ref:`ETAs `, equivalent to ``delivery_job.eta - pickup_job.eta < pd_interval_max`` :param float exclude_period_start: (optional) The start of a *negative* time window. For example, if you don't want to visit a :py:data:`Job` during their lunch break, you could set an ``exclude_period_start`` and ``exclude_period_end`` for it. Time of day as float (e.g. ``13.75``) in 24h time :param float exclude_period_end: (optional) The end of a *negative* time window. For example, if you don't want to visit a :py:data:`Job` during their lunch break, you could set an ``exclude_period_start`` and ``exclude_period_end`` for it. Time of day as float (e.g. ``13.75``) in 24h time :param bool immovable: *beta* (optional, default= ``false``) If you are re-optimising a run in real-time (i.e. after the :py:data:`Driver` has already started performing the route), and this :py:data:`Job` has already been served, you can prevent it from being moved during the optimisation by setting ``job.immovable=true``. This parameter may only be used if initial_runs are provided. Minimal Example .. code-block:: json { "uid": "unique_job_id_1", "duration": 10, "location": {"lat": -33.849489, "lon": 151.127482} } Standard Example .. code-block:: json { "uid": "unique_job_id_2", "duration": 10, "arrive_after": 10, "leave_by": 16.5, "location": { "lat": -33.84948962, "lon": 151.1274823 }, } | | | Location ^^^^^^^^ .. py:data:: Location :type: JSON Object A Location defines the geographical position of a :py:data:`Driver` or :py:data:`Job` :param float lat: Latitude :param float lon: Longitude Example .. code-block:: json { "lat": -33.88066125, "lon": 151.1830961 } | | | Settings ^^^^^^^^ .. py:data:: Settings :type: JSON Object Settings convey parameters which affect the way that the optimisation algorithm runs. :param bool quick_opt: (optional, default= ``true``) Should the algorithm stop once it reaches a local minimum to get a reasonably optimal result quickly? If True: The algorithm will stop fairly quickly once it has found a reasonably good solution. Use ``quick_opt=true`` when it is important to get a solution as fast as possible (e.g. in real time optimisations. If False: The algorithm will run until it reaches the ``improvement_threshold_per_second`` or the ``max_opt_time``, whichever comes first. Use ``quick_opt=false`` when it is important to reach a very optimal solution, but be sure to set ``max_opt_time`` and/or ``improvement_threshold_per_second`` :param int max_opt_time: (optional, default= ``450``) The maximum number of seconds the algorithm is allowed to spend optimising. :param float improvement_threshold_per_second: (optional, default= ``0.00005``) he algorithm periodically measures the percentage improvement in the result vs time. If the improvement is less than this threshold, the result is returned instead of continuing the search. Set it to zero for no improvement threshold :param bool min_time_aboard: (optional, default= ``false``) Only applies to Pickup Delivery problems. If ``min_time_aboard=true``, the optimiser will try to minimise the interval between a Pickup and its related Delivery :param bool first_solution_most_constrained: (optional, default= ``false``) Determines whether the first solution strategy is to create the "most constrained" feasible solution. This is useful if you have a lot of constraints and the algorithm is unable to find a solution otherwise. However, in normal circumstances, you should not use it because it usually creates a worse first solution. Minimal Example .. code-block:: json {} Standard Example .. code-block:: json { "allocate_fairly": true, "quick_opt": false, "max_opt_time": 120, } | | | Response -------- RoutingSolution ^^^^^^^^^^^^^^^ .. py:data:: RoutingSolution :type: JSON Object The API response contains one RoutingSolution. :param runs: A list of :py:data:`Runs ` :type runs: List[:py:data:`Run`] :param unserved_jobs: A list of :py:data:`Jobs ` which the optimiser could not find a way to visit. :type unserved_jobs: List[:py:data:`Job`] Run ^^^ .. py:data:: Run :type: JSON List The first object in each Run is the :py:data:`Driver`. All subsequent objects (if any) are :py:data:`SolutionJobs `. If a Run contains only a Driver, then the optimiser has planned for it not to visit any Jobs. SolutionJob ^^^^^^^^^^^ .. py:data:: SolutionJob :type: JSON Object Each SolutionJob is **identical to the** :py:data:`Job` which you sent to the optimiser, but it has a few extra fields to help communicate the solution to you. :param int run: A 1-based index indicating which run this Job is planned in. Unserved Jobs have ``run=null``. :param int seq: Indicates this Job's sequence within the :py:data:`Run`. Unserved Jobs have ``seq=null``. :param str eta: Indicates the :ref:`Estimated Time of Arrival ` at that Job as a human-readable string ``HH:MM:SS``. E.g. 2:30pm is represented as ``14:30:00``. Unserved Jobs have ``eta=null``. :param float decimal_eta: Indicates the :ref:`Estimated Time of Arrival ` at that Job as a float. E.g. 2:30pm is represented as ``14.5``. Unserved Jobs have ``decimal_eta=null``. :param str etd: Indicates the :ref:`Estimated Time of Departure ` from that Job as a human-readable string ``HH:MM:SS``. E.g. 2:30pm is represented as ``14:30:00``. Unserved Jobs have ``etd=null``. :param float decimal_etd: Indicates the :ref:`Estimated Time of Departure ` from that Job as a float. E.g. 2:30pm is represented as ``14.5``. Unserved Jobs have ``decimal_eta=null``.