NAV Navbar
Logo

Overview

This page describes the logical and technical usage of the getOptimum API.

This API has the purpose to solve real-world routing tasks that involve multiple vehicles and multiple destinations. A typical use case is the dispatch of goods to several customers by a hauler. Various constraints like maximum load of vehicles and time windows are supported to allow the solution of realistic scenarios.

Features

getOptimum can solve routing tasks that consist of any number of given locations where certain freight has to be delivered or picked up (these are called orders). These orders are satisfied by any number of given vehicles with certain properties that can transport freight. The goal of the routing algorithm is to minimize the aggregate traveling time of all vehicles.

Basic features

The routing algorithm ensures that all constraints arising from the following properties are satisfied.

Freight types

Each vehicle can be assigned a set of allowed freight types that can be transported, and in turn a type can be assigned to each freight instance. This feature allows the handling of e.g. hazardous or chilled goods that can only be transported by certain specialized vehicles.

Time windows for orders

For each order, any number of time windows can be configured. If at least one time window exists, the routing will ensure that loading and unloading of goods for this order is only done during one of these windows. Otherwise, there is no such restriction applied.

Custom time/distance matrices

For increased flexibility, it is possible to provide matrices that define traveling times/distances between locations. If a time/distance matrix is present in a request, it is used to determine the traveling times/distances instead of actual map data.

With this feature, it is possible to use the routing algorithm to solve a wider class of routing tasks, e.g. managing workers inside a warehouse.

A simple example task

HTTP/1.1 200 OK
Access-Control-Allow-Origin: /routeplan/{id}/output
Vary: Origin
Access-Control-Allow-Credentials: true
Content-Type: application/json;charset=UTF-8
Content-Length: 1619

{
  "id" : "e6ccc82a-6a1d-4f4d-af64-6b83d7ea8c35",
  "status" : "OPTIMIZED",
  "routes" : [ {
    "totalTimeInSeconds" : 44280.0,
    "startFreight" : {
      "weight" : 4.0,
      "load" : 4.0
    },
    "vehicle" : {
      "ident" : "vehicle 1",
      "startLocation" : {
        "ident" : "Regensburg",
        "latitude" : 49.314623,
        "longitude" : 12.178348
      },
      "endLocation" : {
        "ident" : "Regensburg",
        "latitude" : 49.314623,
        "longitude" : 12.178348
      },
      "startTime" : "2017-11-10T08:00:00Z",
      "endTime" : "2017-11-10T21:00:00Z",
      "freightLimitation" : {
        "maxWeight" : 4.0,
        "maxLoad" : 4.0
      }
    },
    "orders" : [ {
      "location" : {
        "ident" : "Regensburg",
        "latitude" : 49.314623,
        "longitude" : 12.178348
      },
      "arrival" : "2017-11-10T08:00:00Z",
      "startLoadingTime" : "2017-11-10T08:00:00Z"
    }, {
      "location" : {
        "ident" : "Dortmund",
        "latitude" : 49.01343,
        "longitude" : 7.465298
      },
      "arrival" : "2017-11-10T14:00:00Z",
      "startLoadingTime" : "2017-11-10T14:00:00Z"
    }, {
      "location" : {
        "ident" : "Schwandorf",
        "latitude" : 49.319888,
        "longitude" : 12.109135
      },
      "arrival" : "2017-11-10T19:48:00Z",
      "startLoadingTime" : "2017-11-10T19:48:00Z"
    }, {
      "location" : {
        "ident" : "Regensburg",
        "latitude" : 49.314623,
        "longitude" : 12.178348
      },
      "arrival" : "2017-11-10T20:18:00Z",
      "startLoadingTime" : "2017-11-10T20:18:00Z"
    } ]
  } ]
}

We consider a routing task that consists of only two orders and one vehicle in the following. The main intention is to give an idea about the kind of tasks the routing algorithm can solve and the structure of the solution. However, the complexity of the example task is way below typical use cases of getOptimum.

The starting point of the vehicle is the depot in Regensburg, and freight has to be delivered to Schwandorf and Dortmund. Both destinations need goods with weight and load equal to 2, and the vehicle has a maximum transported weight and load of 4. The vehicle can transport all the needed goods at once, so the only degree of freedom for the routing algorithm is the choice which location to go first. The vehicle starts in Regensburg at 8 AM.

The optimized route determined by the algorithm is shown on the right hand side, represented by a JSON object contained in a HTTP response (this is a real response of the getOptimum API). The most important informations can be explained without going into too much detail (see this chapter for a complete description of the solution fields).

The solution contains a field called routes, which represents the optimized routes per vehicle. In our case, there is only one vehicle and consequently just one route. In the routes, there is a field called orders, which represents the locations the vehicle has to visit in the given sequence. As can be seen, the routing algorithm firstly sends the vehicle from Regensburg to Dortmund, where it arrives at 2 PM. From there, it drives to Schwandorf and finally back to Regensburg, where it ends its route at 8:18 PM.

Note that for this simple task, the other possible routing path (first Schwandorf, then Dortmund) is equally optimal, so the algorithm just chooses one possibility at random.

Route plan tasks

This REST resource is used to create route plan tasks and retrieve their solution from the server. The full workflow to solve a routing request is depicted in the diagram below.

The specific REST interfaces used in this workflow are described in the following.

Creating a task

curl https://api.getoptimum.de/v1/routeplan -i -X POST -H "Content-Type: application/json;charset=UTF-8" -H "x-api-key: MY-API-KEY-12345" -d "{ \"fleet\" : { \"vehicles\" : [ { \"ident\" : \"vehicle 1\", \"startLocation\" : { \"ident\" : \"Regensburg\" }, \"endLocation\" : { \"ident\" : \"Regensburg\" }, \"startTime\" : \"2017-11-10T10:13:04.932Z\", \"endTime\" : \"2017-11-10T18:13:04.931Z\", \"freightLimitation\" : { \"maxWeight\" : 3.0, \"maxLoad\" : 3.0, \"allowedTypes\" : [ \"HAZMAT\" ] } } ] }, \"orders\" : [ { \"location\" : { \"ident\" : \"Dortmund\", \"latitude\" : 49.01343, \"longitude\" : 7.465298 }, \"loadTimeInSeconds\" : 0, \"deliver\" : { \"weight\" : 2.0, \"load\" : 2.0, \"type\" : \"HAZMAT\" }, \"pickup\" : { \"weight\" : 1.0, \"load\" : 1.0 }, \"timeWindows\" : [ { \"startTime\" : \"2017-11-10T12:12:04.932Z\", \"endTime\" : \"2017-11-10T16:13:04.931Z\" } ] } ], \"timeMatrix\" : { \"locationIdents\" : [ \"Regensburg\", \"Dortmund\" ], \"entries\" : [ [ 0, 15000.0 ], [ 15000.0, 0 ] ] }, \"distanceMatrix\" : { \"locationIdents\" : [ \"Regensburg\", \"Dortmund\" ], \"entries\" : [ [ 0, 1 ], [ 1, 0 ] ] } }"

Beautified:

$ curl https://api.getoptimum.de/v1/routeplan -i -X POST 
    -H 'Content-Type: application/json;charset=UTF-8' 
    -H 'x-api-key: MY-API-KEY-12345' 
  -d '{
  "fleet" : {
    "vehicles" : [ {
      "ident" : "vehicle 1",
      "startLocation" : {
        "ident" : "Regensburg"
      },
      "endLocation" : {
        "ident" : "Regensburg"
      },
      "startTime" : "2017-11-10T10:13:04.932Z",
      "endTime" : "2017-11-10T18:13:04.931Z",
      "freightLimitation" : {
        "maxWeight" : 3.0,
        "maxLoad" : 3.0,
        "allowedTypes" : [ "HAZMAT" ]
      }
    } ]
  },
  "orders" : [ {
    "location" : {
      "ident" : "Dortmund",
      "latitude" : 49.01343,
      "longitude" : 7.465298
    },
    "loadTimeInSeconds" : 0,
    "deliver" : {
      "weight" : 2.0,
      "load" : 2.0,
      "type" : "HAZMAT"
    },
    "pickup" : {
      "weight" : 1.0,
      "load" : 1.0
    },
    "timeWindows" : [ {
      "startTime" : "2017-11-10T12:12:04.932Z",
      "endTime" : "2017-11-10T16:13:04.931Z"
    } ]
  } ],
  "timeMatrix" : {
    "locationIdents" : [ "Regensburg", "Dortmund" ],
    "entries" : [ [ 0, 15000.0 ], [ 15000.0, 0 ] ]
  },
  "distanceMatrix" : {
    "locationIdents" : [ "Regensburg", "Dortmund" ],
    "entries" : [ [ 0, 1 ], [ 1, 0 ] ]
  }
}'

The above command produces output structured like this:

HTTP/1.1 201 Created
Location: http://localhost:8080/routeplan/10fefad1-6129-4731-820a-812feb0946d5
Content-Type: application/json;charset=UTF-8
Content-Length: 51

{
  "id" : "10fefad1-6129-4731-820a-812feb0946d5"
}

A POST request is used to create a new route plan task. The server will start to solve the task right after it was created. Depending on the complexity of the task, this may take up to a few hours. The following table gives a rough estimation of the solution time for problems with various complexities.

Route plan complexity Time to solve
2 vehicles, 20 orders ≈ 5 seconds
20 vehicles, 200 orders ≈ 40 seconds
100 vehicles, 1000 orders ≈ 5 minutes

HTTP request

POST https://api.getoptimum.de/v1/routeplan

Request fields

Path Type Description Optional Constraints
distanceMatrix -> Location matrix a custom matrix used to calculate travelling distances yes -
fleet -> Fleet the fleet designated to satisfy the given orders no -
orders Array[-> Order] the orders to satisfy no 1 <= size <= 5000
timeMatrix -> Location matrix A custom matrix used to calculate travelling times. The times are measured in seconds. yes -

Additional response headers (basic headers)

Name Description
Location the URI of the created route plan

Response fields

Path Type Description
id String the identifier of the route plan task

Getting the status

curl https://api.getoptimum.de/v1/routeplan/d1f2e69d-3ef4-4da2-8997-9cbd11c3cb79 -i -H "Content-Type: application/json;charset=UTF-8" -H "x-api-key: MY-API-KEY-12345"

Beautified:

$ curl https://api.getoptimum.de/v1/routeplan/d1f2e69d-3ef4-4da2-8997-9cbd11c3cb79 -i 
    -H 'Content-Type: application/json;charset=UTF-8' 
    -H 'x-api-key: MY-API-KEY-12345'

The above command produces output structured like this:

HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Content-Length: 28

{
  "status" : "OPTIMIZED"
}

A GET request is used to get the status of a route plan task. This interface can be used to determine if the task is finished and the solution is available.

HTTP request

GET https://api.getoptimum.de/v1/routeplan/{id}

Path parameters

/routeplan/{id}

Parameter Description
id the identifier of the route plan task

Response fields

Path Type Description
status -> Optimization status contains the current status of the route plan optimization

Getting the solution

curl https://api.getoptimum.de/v1/routeplan/2272ab30-e9db-4a4b-853e-bdd587bc1333/output -i -H "Content-Type: application/json;charset=UTF-8" -H "x-api-key: MY-API-KEY-12345"

Beautified:

$ curl https://api.getoptimum.de/v1/routeplan/2272ab30-e9db-4a4b-853e-bdd587bc1333/output -i 
    -H 'Content-Type: application/json;charset=UTF-8' 
    -H 'x-api-key: MY-API-KEY-12345'

The above command produces output structured like this:

HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Content-Length: 1187

{
  "id" : "2272ab30-e9db-4a4b-853e-bdd587bc1333",
  "status" : "OPTIMIZED",
  "routes" : [ {
    "totalTimeInSeconds" : 29999.0,
    "startFreight" : {
      "weight" : 2.0,
      "load" : 2.0
    },
    "vehicle" : {
      "ident" : "vehicle 1",
      "startLocation" : {
        "ident" : "Regensburg"
      },
      "endLocation" : {
        "ident" : "Regensburg"
      },
      "startTime" : "2017-11-10T10:13:04.932Z",
      "endTime" : "2017-11-10T18:13:04.931Z",
      "freightLimitation" : {
        "maxWeight" : 3.0,
        "maxLoad" : 3.0,
        "allowedTypes" : [ "HAZMAT" ]
      }
    },
    "orders" : [ {
      "location" : {
        "ident" : "Regensburg"
      },
      "arrival" : "2017-11-10T10:13:04.932Z",
      "startLoadingTime" : "2017-11-10T10:13:04.932Z"
    }, {
      "location" : {
        "ident" : "Dortmund",
        "latitude" : 49.01343,
        "longitude" : 7.465298
      },
      "arrival" : "2017-11-10T14:23:04Z",
      "startLoadingTime" : "2017-11-10T14:23:04Z"
    }, {
      "location" : {
        "ident" : "Regensburg"
      },
      "arrival" : "2017-11-10T18:33:04Z",
      "startLoadingTime" : "2017-11-10T18:33:04Z"
    } ]
  } ]
}

A GET request is used to get the solution of a route plan task. This will only yield a result if the optimization of the task is already finished (otherwise, this request will return not found).

HTTP request

GET https://api.getoptimum.de/v1/routeplan/{id}/output

Path parameters

/routeplan/{id}/output

Parameter Description
id the identifier of the route plan task

Response fields

Path Type Description
id String the identifier of the route plan task
routes Array[-> Route] the optimized routes
status String the status of the optimization

Type definitions

Fleet

Fleet sample

{
  "vehicles" : [ {
    "ident" : "vehicle 1",
    "startLocation" : {
      "ident" : "Regensburg"
    },
    "endLocation" : {
      "ident" : "Regensburg"
    },
    "startTime" : "2017-11-10T10:13:04.932Z",
    "endTime" : "2017-11-10T18:13:04.931Z",
    "freightLimitation" : {
      "maxWeight" : 3.0,
      "maxLoad" : 3.0,
      "allowedTypes" : [ "HAZMAT" ]
    }
  } ]
}

A fleet represents a collections of vehicles.

Fields

Path Type Description Optional Constraints
vehicles Array[-> Vehicle] the vehicles in the fleet no 1 <= size <= 5000

Freight

Freight sample

{
  "weight" : 2.0,
  "load" : 2.0,
  "type" : "HAZMAT"
}

Freight represents goods that have to be transported to or from customers.

The load can represent the amount of space needed by the freight, but it can also be defined to mean something else as long as it is additive and consistent between orders and vehicles. The system will just ensure that the maximum load of each vehicle is not exceeded.

Fields

Path Type Description Optional Constraints
load Number the load of the goods no -
type String the type of the goods yes -
weight Number the weight of the goods no -

Freight limitation

Freight limitation sample

{
  "maxWeight" : 3.0,
  "maxLoad" : 3.0,
  "allowedTypes" : [ "HAZMAT" ]
}

Freight limitation represents restrictions on goods that can be transported by a vehicle.

Fields

Path Type Description Optional Constraints
allowedTypes Array[String] all allowed types of goods that can be transported yes -
maxLoad Number the maximum aggregate load of goods that can be transported at once no -
maxWeight Number the maximum aggregate weight of goods that can be transported at once no -

Instant

Instant sample

"2017-11-10T10:13:04.932Z"

An instant is a point on the time line. The formatting is done as defined in ISO 8601 for combined date and time representations.

Location

Location sample

{
  "ident" : "Dortmund",
  "latitude" : 49.01343,
  "longitude" : 7.465298
}

A location has two different use cases, depending on whether there are custom matrices used in the routing request. If no distance matrix is present in the request, it is defined as a point on the surface of the earth. Otherwise, a location is an abstract entity that has a well-defined distance (via the custom matrix) to every other location. This holds equivalently for a time matrix.

Fields

Path Type Description Optional Constraints
ident String the unique identifier of the location no length <= 1000
latitude Number the geographical latitude yes -
longitude Number the geographical longitude yes -

Location matrix

Location matrix sample

{
  "locationIdents" : [ "Regensburg", "Dortmund" ],
  "entries" : [ [ 0, 15000.0 ], [ 15000.0, 0 ] ]
}

A location matrix is a mapping of directed connections between two locations onto a number. The number may represent a time or a distance, depending on the use case.

Fields

Path Type Description Optional Constraints
entries Array[Array[Number]] A two-dimensional array containing the numbers explained above. The row index defines the start location, whereas the column index defines the end location. no -
locationIdents Array[String] an array of location identifiers used to map row and column indices (see below) to actual locations no -

Order

Order sample

{
  "location" : {
    "ident" : "Dortmund",
    "latitude" : 49.01343,
    "longitude" : 7.465298
  },
  "loadTimeInSeconds" : 0,
  "deliver" : {
    "weight" : 2.0,
    "load" : 2.0,
    "type" : "HAZMAT"
  },
  "pickup" : {
    "weight" : 1.0,
    "load" : 1.0
  },
  "timeWindows" : [ {
    "startTime" : "2017-11-10T12:12:04.932Z",
    "endTime" : "2017-11-10T16:13:04.931Z"
  } ]
}

An order represents goods that have to be transported to or from a specific location.

Fields

Path Type Description Optional Constraints
deliver -> Freight the goods to deliver from the depot to the location yes -
loadTimeInSeconds Number the time (in seconds) needed for loading and unloading goods no -
location -> Location the specific location no -
pickup -> Freight the goods to pickup from the location and transport to the depot yes -
timeWindows Array[-> Time window] the possible time windows where loading and unloading can take place yes -

Route

Route sample

{
  "totalTimeInSeconds" : 29999.0,
  "startFreight" : {
    "weight" : 2.0,
    "load" : 2.0
  },
  "vehicle" : {
    "ident" : "vehicle 1",
    "startLocation" : {
      "ident" : "Regensburg"
    },
    "endLocation" : {
      "ident" : "Regensburg"
    },
    "startTime" : "2017-11-10T10:13:04.932Z",
    "endTime" : "2017-11-10T18:13:04.931Z",
    "freightLimitation" : {
      "maxWeight" : 3.0,
      "maxLoad" : 3.0,
      "allowedTypes" : [ "HAZMAT" ]
    }
  },
  "orders" : [ {
    "location" : {
      "ident" : "Regensburg"
    },
    "arrival" : "2017-11-10T10:13:04.932Z",
    "startLoadingTime" : "2017-11-10T10:13:04.932Z"
  }, {
    "location" : {
      "ident" : "Dortmund",
      "latitude" : 49.01343,
      "longitude" : 7.465298
    },
    "arrival" : "2017-11-10T14:23:04Z",
    "startLoadingTime" : "2017-11-10T14:23:04Z"
  }, {
    "location" : {
      "ident" : "Regensburg"
    },
    "arrival" : "2017-11-10T18:33:04Z",
    "startLoadingTime" : "2017-11-10T18:33:04Z"
  } ]
}

A route is a list of orders that is fulfilled by a specific vehicle in a specific sequence. It represents the part of the optimized solution of a routing task that is performed by one vehicle.

Fields

Path Type Description
orders Array[-> Scheduled order] the orders in the sequence they have to be performed
startFreight -> Freight the freight that is loaded on the vehicle at the start of the route
totalTimeInSeconds Number the total time the vehicle needs to complete the route
vehicle -> Vehicle the vehicle that drives the route

Scheduled order

Scheduled order sample

{
  "location" : {
    "ident" : "Regensburg"
  },
  "arrival" : "2017-11-10T10:13:04.932Z",
  "startLoadingTime" : "2017-11-10T10:13:04.932Z"
}

A scheduled order is an order that has been planned by the routing algorithm, i.e. it has been determined which vehicle performs the order at which time.

Fields

Path Type Description
arrival -> Instant the time when the vehicle arrives at the location
location -> Location the location of the order
startLoadingTime -> Instant the time when the loading of freight starts

Optimization status

Optimization status sample

"OPTIMIZED"

The possible status values of a route plan optimization are shown in the following table.

Value Meaning
OPTIMIZING the optimization is still running
OPTIMIZED the optimization is finished
ERROR There was a fatal error during the optimization. The optimization will not be finished, but you can post the route plan again. If the retry also fails, please contact the support.

Time window

Time window sample

{
  "startTime" : "2017-11-10T12:12:04.932Z",
  "endTime" : "2017-11-10T16:13:04.931Z"
}

A time window is a time interval between two given points in time.

Fields

Path Type Description Optional Constraints
endTime -> Instant the end time of the interval no -
startTime -> Instant the start time of the interval no -

Vehicle

Vehicle sample

{
  "ident" : "vehicle 1",
  "startLocation" : {
    "ident" : "Regensburg"
  },
  "endLocation" : {
    "ident" : "Regensburg"
  },
  "startTime" : "2017-11-10T10:13:04.932Z",
  "endTime" : "2017-11-10T18:13:04.931Z",
  "freightLimitation" : {
    "maxWeight" : 3.0,
    "maxLoad" : 3.0,
    "allowedTypes" : [ "HAZMAT" ]
  }
}

A vehicle is a device that can transport goods (e.g. a truck).

Fields

Path Type Description Optional Constraints
ident String a unique identifier for the vehicle no length <= 1000
endLocation -> Location the location where the vehicle ends its tour no -
endTime -> Instant the vehicle has to have finished its tour until this time no -
freightLimitation -> Freight limitation the limitations concerning freight the vehicle can transport no -
startLocation -> Location the location where the vehicle starts its tour no -
startTime -> Instant the vehicle is available to starts its tour from this time no -

REST API - General

This chapter contains general technical information concerning the REST API of the getOptimum server.

The current version number is 1.

The API base path is https://api.getoptimum.de/v1/routeplan.

All data received from and sent to this API is in JSON.

HTTP Verbs

This API tries to adhere as closely as possible to standard HTTP and REST conventions in its use of HTTP verbs.

Verb Usage
GET used to retrieve a resource
POST used to create a new resource
PATCH used to update an existing resource, including partial updates
PUT used to replace an existing resource
DELETE used to delete an existing resource

HTTP Status Codes

This API tries to adhere as closely as possible to standard HTTP and REST conventions in its use of HTTP status codes.

Status code Usage
200 OK the request completed successfully
201 Created A new resource has been created successfully. The resource’s URI is available from the response’s Location header.
204 No Content an update to an existing resource has been applied successfully
400 Bad Request The request was malformed. The response body will include an error providing further information.
401 Unauthorized The request contained no or invalid credentials. See chapter authentication.
404 Not Found the requested resource did not exist

Headers

Every request should contain the following header(s):

Name Description
Content-Type the Content-Type of the payload, e.g. ‘application/hal+json’
x-api-key the API key used to authenticate the request

Every response has the following header(s):

Name Description
Content-Type the Content-Type of the payload, e.g. ‘application/hal+json’

Authentication

Authentication is done via an API key that has to be transferred in the header of each rest request. You do not have an API key?

Invalid requests

An invalid request might result in an error message like this:

HTTP/1.1 400 Bad Request
Content-Type: application/json;charset=UTF-8
Content-Length: 389

{
  "message" : "all locations have to be contained in time matrix;
               fleet.vehicles[0].freightLimitation.maxWeight: may not be null;
               orders[1].location: may not be null;
               fleet.vehicles[0].ident: size must be between 0 and 1000;
               fleet.vehicles[0].endLocation.ident: may not be null;
               timeMatrix: size of entries does not match size of locationIdents;
               orders[0].loadTimeInSeconds: may not be null"
}

A request that is invalid because one of the logical constraints described in route plan tasks is not fulfilled results in a response with status code 400 Bad Request. There is an error message contained with all the invalid fields and the respective cause.

Support

If you experience any issues with this API or have questions please contact our support team.