Precedence¶
Info
This feature is configurable via .json input, without the need for code
customization and is available for both the Marketplace app and Platform. You
can find a list of all available features.
| Field name | Required | Data type | SI Unit | Defined on | Example | Configurable via defaults |
|---|---|---|---|---|---|---|
precedes |
No | array of object or array of string or string |
NA | stop |
{"precedes": ["foo", "bar"]} |
➖ |
succeeds |
No | array of object or array of string or string |
NA | stop |
{"succeeds": ["foo", "bar"]} |
➖ |
The precedence constraint is used to indicate that a specific stop must be
visited (pickup) before a different one (dropoff). You can use the precedes
and succeeds fields on the stops of the input to work with precedence
constraints as follows.
precedes: ensures that the pickup is visited before the dropoff. It is applied to the individual stop that must be visited before the stopiddefined in theprecedesfield.succeeds: can be used to model the precedence relation the other way around. Using the same example as above, the opposite would be specified: on the dropoff stop we define that it needs to succeed its pickup counterpart.
Both precedes and succeeds may be specified as:
- a
stringvalue that specifies a relationship with a single stop given by itsid. - an
arrayofstringvalues that specifies a relationship with multiple stops given by theirids. This array is unordered meaning that the order of the stops in the array will not be enforced in the assigned route. - an
arrayofobjectvalues that specifies a relationship with multiple stops given by theirids and an optional fielddirect. Ifdirectis set to true, this means that there can be not stop between the two stops on which the precedence relationship is defined.
Here is an example defining both types of precedence relationships and their types. A sample output obtained after solving the problem is also shown.
{
"stops": [
{
"id": "Fushimi Inari Taisha",
"location": { "lon": 135.772695, "lat": 34.967146 },
"precedes": "Kiyomizu-dera"
},
{
"id": "Kiyomizu-dera",
"location": { "lon": 135.78506, "lat": 34.994857 }
},
{
"id": "Nijō Castle",
"location": { "lon": 135.748134, "lat": 35.014239 },
"succeeds": "Kiyomizu-dera"
},
{
"id": "Kyoto Imperial Palace",
"location": { "lon": 135.762057, "lat": 35.025431 },
"precedes": [
{ "id": "Gionmachi", "direct": true },
{ "id": "Kinkaku-ji", "direct": false }
]
},
{
"id": "Gionmachi",
"location": { "lon": 135.775682, "lat": 35.002457 }
},
{
"id": "Kinkaku-ji",
"location": { "lon": 135.728898, "lat": 35.039705 }
},
{
"id": "Arashiyama Bamboo Forest",
"location": { "lon": 135.672009, "lat": 35.017209 },
"succeeds": ["Gionmachi", "Kinkaku-ji"]
}
],
"vehicles": [
{
"id": "v1",
"speed": 20
}
]
}
{
"options": {
"check": {
"duration": 30000000000,
"verbosity": "off"
},
"format": {
"disable": {
"progression": true
}
},
"model": {
"constraints": {
"disable": {
"attributes": false,
"capacities": null,
"capacity": false,
"distance_limit": false,
"groups": false,
"maximum_duration": false,
"maximum_stops": false,
"maximum_wait_stop": false,
"maximum_wait_vehicle": false,
"mixing_items": false,
"precedence": false,
"start_time_windows": false,
"vehicle_end_time": false,
"vehicle_start_time": false
},
"enable": {
"cluster": false
}
},
"objectives": {
"capacities": "",
"cluster": 0,
"distance": 0,
"early_arrival_penalty": 1,
"late_arrival_penalty": 1,
"min_stops": 1,
"stop_balance": 0,
"travel_duration": 0,
"unplanned_penalty": 1,
"vehicle_activation_penalty": 1,
"vehicles_duration": 1
},
"properties": {
"disable": {
"duration_groups": false,
"durations": false,
"initial_solution": false,
"stop_duration_multipliers": false
},
"maximum_time_horizon": 15552000
},
"validate": {
"disable": {
"resources": false,
"start_time": false
},
"enable": {
"matrix": false,
"matrix_asymmetry_tolerance": 20
}
}
},
"solve": {
"duration": 10000000000,
"iterations": 50,
"parallel_runs": 1,
"plateau": {
"absolute_threshold": -1,
"delay": 0,
"duration": 0,
"iterations": 0,
"relative_threshold": 0
},
"run_deterministically": true,
"solver": {
"plan_group_size": {
"delta": 0,
"delta_after_iterations": 1000000000,
"max_value": 2,
"min_value": 2,
"snap_back_after_improvement": true,
"start_value": 2,
"zigzag": true
},
"unplan_units": {
"delta": 2,
"delta_after_iterations": 125,
"max_value": -1,
"min_value": 2,
"snap_back_after_improvement": true,
"start_value": 2,
"zigzag": true
},
"unplan_weights": "Vehicle:3,Island:1,Location:293"
},
"start_solutions": 1
}
},
"solutions": [
{
"objective": {
"name": "1 * vehicles_duration + 1 * unplanned_penalty",
"objectives": [
{
"base": 1101.3248523907805,
"factor": 1,
"name": "vehicles_duration",
"value": 1101.3248523907805
},
{
"factor": 1,
"name": "unplanned_penalty",
"value": 0
}
],
"value": 1101.3248523907805
},
"unplanned": [],
"vehicles": [
{
"id": "v1",
"route": [
{
"cumulative_travel_duration": 0,
"stop": {
"id": "Fushimi Inari Taisha",
"location": {
"lat": 34.967146,
"lon": 135.772695
}
},
"travel_duration": 0
},
{
"cumulative_travel_distance": 3280,
"cumulative_travel_duration": 164,
"stop": {
"id": "Kiyomizu-dera",
"location": {
"lat": 34.994857,
"lon": 135.78506
}
},
"travel_distance": 3280,
"travel_duration": 164
},
{
"cumulative_travel_distance": 7273,
"cumulative_travel_duration": 363,
"stop": {
"id": "Kyoto Imperial Palace",
"location": {
"lat": 35.025431,
"lon": 135.762057
}
},
"travel_distance": 3993,
"travel_duration": 199
},
{
"cumulative_travel_distance": 10112,
"cumulative_travel_duration": 505,
"stop": {
"id": "Gionmachi",
"location": {
"lat": 35.002457,
"lon": 135.775682
}
},
"travel_distance": 2839,
"travel_duration": 141
},
{
"cumulative_travel_distance": 12942,
"cumulative_travel_duration": 647,
"stop": {
"id": "Nijō Castle",
"location": {
"lat": 35.014239,
"lon": 135.748134
}
},
"travel_distance": 2830,
"travel_duration": 141
},
{
"cumulative_travel_distance": 16271,
"cumulative_travel_duration": 813,
"stop": {
"id": "Kinkaku-ji",
"location": {
"lat": 35.039705,
"lon": 135.728898
}
},
"travel_distance": 3329,
"travel_duration": 166
},
{
"cumulative_travel_distance": 22023,
"cumulative_travel_duration": 1101,
"stop": {
"id": "Arashiyama Bamboo Forest",
"location": {
"lat": 35.017209,
"lon": 135.672009
}
},
"travel_distance": 5752,
"travel_duration": 287
}
],
"route_duration": 1101,
"route_travel_distance": 22023,
"route_travel_duration": 1101
}
]
}
],
"statistics": {
"result": {
"custom": {
"activated_vehicles": 1,
"max_duration": 0.123,
"max_stops_in_vehicle": 7,
"max_travel_duration": 0.123,
"min_duration": 0.123,
"min_stops_in_vehicle": 7,
"min_travel_duration": 0.123,
"unplanned_stops": 0
},
"duration": 0.123,
"value": 0.123
},
"run": {
"duration": 0.123,
"iterations": 50
},
"schema": "v1"
},
"version": {
"sdk": "VERSION"
}
}
Note that all stops that have a precedence relationship that groups them together will be assigned to the same vehicle in the final solution.
Info
Both, precedes and succeeds, can be used in combination to model more
complex precedence relationships.