• Optimization
  • Navigation
  • Tracking
  • Maps
  • Places

Soft Constraints

The Soft Constraints feature enables users to complete more tasks by treating specific time-related limitations as flexible. NextBillion.ai’s Route Optimization Flexible API currently allows vehicle shift timings and task time windows to be made flexible up to a configurable degree. This functionality is useful in commercial scenarios where job completion ratio is the most crucial measure and time constraints are not strict. Let’s build an example to understand how these constraints work.

Setup

Jobs

We will start by defining 6 jobs. For these tasks we will add:

  • A unique identifier for each task

  • Location indexes for each task

  • Specify the schedule of tasks. This is done by adding time windows within which a task must be completed.

  • The actual time taken to complete the tasks once the driver/vehicle is at the task’s location i.e. the service time for each task.

Let’s take a look at the jobs JSON after the above properties are configured:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
{
  "jobs": [
    {
      "id": 1,
      "location_index": 0,
      "service": 180,
      "time_windows": [[1693388747, 1693389047]]
    },
    {
      "id": 2,
      "location_index": 1,
      "service": 120,
      "time_windows": [[1693387800, 1693388100]]
    },
    {
      "id": 3,
      "location_index": 2,
      "service": 120,
      "time_windows": [[1693387800, 1693388000]]
    },
    {
      "id": 4,
      "location_index": 3,
      "service": 120,
      "time_windows": [[1693389947, 1693390247]]
    },
    {
      "id": 5,
      "location_index": 4,
      "service": 60,
      "time_windows": [[1693391147, 1693391447]]
    },
    {
      "id": 6,
      "location_index": 5,
      "service": 120,
      "time_windows": [[1693392347, 1693392647]]
    }
  ]
}

Vehicles

Next, we add 2 vehicles that will be responsible for fulfilling the tasks within the defined constraints. To describe the vehicles and their properties we add:

  • A unique ID for each vehicle

  • Vehicle shift time or the time window

  • Start_index to denote the point from where the vehicle would start.

  • Costs for all vehicles. We have specified only fixed cost for the sake of simplicity, readers can choose any type of cost.

Once the vehicle and their properties are defined, the resulting vehicles JSON is:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
{
  "vehicles": [
    {
      "id": 1,
      "start_index": 6,
      "costs": {
        "fixed": 1000
      },
      "time_window": [1693384200, 1693390200]
    },
    {
      "id": 2,
      "start_index": 7,
      "costs": {
        "fixed": 3000
      },
      "time_window": [1693383300, 1693392300]
    }
  ]
}

Locations

Next, we define the locations object and add all the locations used in the problem along with a valid id. The locations object with all the points used in this example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
  "locations": {
    "id": 1,
    "location": [
      "34.083950,-118.318640",
      "34.054927,-118.323726",
      "34.075525,-118.361588",
      "34.076350,-118.338519",
      "34.090425,-118.338933",
      "34.037925,-118.459842",
      "34.016137,-118.253523",
      "33.940407,-118.265196"
    ]
  }
}

Options

And lastly, we configure the degree up to which the job time windows and vehicle shift timings can be treated as flexible. For our example, we allow:

  • Vehicles to extend their shift timings by 30 mins (~1800 seconds)

  • Tasks to be assigned even if the vehicle is late by 5 minutes (~300 seconds) beyond the given schedule.

Once the constraint properties are defined, the resulting options JSON is:

1
2
3
4
5
6
7
8
{
  "options": {
    "constraint": {
      "max_visit_lateness": 300,
      "max_vehicle_overtime": 1800
    }
  }
}

Optimization POST Request

Now let’s put all these components together and create the final POST request that we will submit to the optimizer.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
curl --location 'https://api.nextbillion.io/optimization/v2?key=<your_api_key>' \
--header 'Content-Type: application/json' \
--data '{
"description": "Soft Constraints Example",
   "jobs": [
       {
           "id": 1,
           "location_index":0,
           "service": 180,
           "pickup":[0],
           "time_windows": [
               [
                   1693388747,
                   1693389047
               ]
           ]
       },
       {
           "id": 2,
           "location_index": 1,
           "service": 120,
           "pickup":[0],
           "time_windows": [
               [
                   1693387800,
                   1693388100
               ]
           ]
       },
       {
           "id": 3,
           "location_index": 2,
           "service": 120,
           "pickup":[0],
           "time_windows": [
               [
                   1693387800,
                   1693388000
               ]
           ]
       },
       {
           "id": 4,
           "location_index": 3,
           "service": 120,
           "pickup":[0],
           "time_windows": [
               [
                   1693389947,
                   1693390247
               ]
           ]
       },
       {
           "id": 5,
           "location_index": 4,
           "service": 60,
           "pickup":[0],
           "time_windows": [
               [
                   1693391147,
                   1693391447
               ]
           ]
       },
       {
           "id": 6,
           "location_index": 5,
           "service": 120,
           "pickup":[0],
           "time_windows": [
               [
                   1693392347,
                   1693392647
               ]
           ]
       }
   ],
   "vehicles":
   [
       {
        "id": 1,
        "start_index": 6,
        "capacity":[20],
        "costs":{
            "fixed":1000
        },
        "time_window": [
            1693384200,
            1693390200
        ]
       },
       {
        "id": 2,
        "start_index": 7,
        "capacity":[20],
        "costs":{
            "fixed":3000
        },
        "time_window": [
            1693383300,
            1693392300
            ]
        }
    ],
    "locations":
        {
            "id": 1,
            "location": ["34.083950,-118.318640", "34.054927,-118.323726","34.075525,-118.361588","34.076350,-118.338519","34.090425,-118.338933", "34.037925,-118.459842", "34.016137,-118.253523", "33.940407,-118.265196"]
        },
    "options":{
        "constraint":{
            "max_visit_lateness": 300,
            "max_vehicle_overtime": 1800
            }
        }
}'

Optimization POST Response

Once the request is made, we get a unique ID in the API response:

1
2
3
4
5
{
  "id": "d7bc0660b6deda9eef143bdd2b0856c3",
  "message": "Optimization job created",
  "status": "Ok"
}

Optimization GET Request

We take the ID and use the Optimization GET request to retrieve the result. Here is the GET request:

curl --location 'https://api.nextbillion.io/optimization/v2/result?id=d7bc0660b6deda9eef143bdd2b0856c3&key=<your_api_key>'

Optimization GET Response

Following is the optimized route plan:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
{
  "description": "Soft Constraints Example",
  "result": {
    "code": 0,
    "summary": {
      "cost": 8169,
      "routes": 2,
      "unassigned": 0,
      "setup": 0,
      "service": 720,
      "duration": 4169,
      "waiting_time": 4363,
      "priority": 0,
      "delivery": [0],
      "pickup": [0],
      "distance": 61255.5
    },
    "routes": [
      {
        "vehicle": 1,
        "cost": 3238,
        "steps": [
          {
            "type": "start",
            "arrival": 1693387108,
            "duration": 0,
            "service": 0,
            "waiting_time": 0,
            "location": [34.016137, -118.253523],
            "location_index": 6,
            "load": [0]
          },
          {
            "type": "job",
            "arrival": 1693388300,
            "duration": 1192,
            "service": 120,
            "waiting_time": 0,
            "location": [34.075525, -118.361588],
            "location_index": 2,
            "id": 3,
            "load": [0],
            "late_by": 300
          },
          {
            "type": "job",
            "arrival": 1693388992,
            "duration": 1764,
            "service": 180,
            "waiting_time": 0,
            "location": [34.08395, -118.31864],
            "location_index": 0,
            "id": 1,
            "load": [0],
            "late_by": 0
          },
          {
            "type": "job",
            "arrival": 1693389510,
            "duration": 2102,
            "service": 120,
            "waiting_time": 437,
            "location": [34.07635, -118.338519],
            "location_index": 3,
            "id": 4,
            "load": [0],
            "late_by": 0
          },
          {
            "type": "job",
            "arrival": 1693390203,
            "duration": 2238,
            "service": 60,
            "waiting_time": 944,
            "location": [34.090425, -118.338933],
            "location_index": 4,
            "id": 5,
            "load": [0],
            "late_by": 0
          },
          {
            "type": "end",
            "arrival": 1693391207,
            "duration": 2238,
            "service": 0,
            "waiting_time": 0,
            "location": [34.090425, -118.338933],
            "location_index": 4,
            "load": [0]
          }
        ],
        "service": 480,
        "duration": 2238,
        "waiting_time": 1381,
        "priority": 0,
        "delivery": [0],
        "pickup": [0],
        "distance": 27138.8,
        "geometry": "uwrnEbkwpUSKkBcAoAq@aB_AeAk@a@SsA{@{A{@g@a@a@_@mAeAmAkAmAgAmAiAoAgAsAgAUS_BoAkAy@w@m@SOGE{BcBwAzC]t@gB~DMVc@`AUQWWm@k@GGIGWU[UQOCCSQKIe@c@_@bAEv@CNKf@Sz@GTMb@Y~@Wx@?@GRO`@O`@Ul@I^]p@Yn@Sb@GVADk@nAq@nBc@tBgBzD_AtBSb@Q`@OZO^KRaAdCUl@e@pAUp@GROd@Md@M`@K^GTGVOj@CJKd@Sx@I`@SdAQv@Ot@S|@Ml@Oj@Kb@K`@St@KXGRITIVMZKXEJIRMZKTGNGNy@dBYn@S`@Ud@MVYn@o@tAO^MV]v@a@|@[v@Q\\g@hACFIPs@zAg@`AMVu@xAILS\\e@t@o@`AINc@r@c@p@]j@[h@MRi@`Aw@tAQ`@Q\\Sb@Qb@Ul@M\\Qd@GRGNK`@Oj@CHCHCLEPKf@CLCNCJAJAJ?DCL?FAJCr@?J?j@@^?bB?NBl@Bl@Br@HxALrFBd@DxAFdBDj@@L@XDp@@JJpAFj@Dd@Hn@@JTdBJv@@HBT@JN~@ZxBZlCJp@Fn@@HBZLjADt@Ft@FtADxABvA?x@?lA?pBAH?|@Aj@?~C?~AAv@AlHArAClF?`CEzE?nA?n@?d@?hAAnA?h@AjC?L?z@AjA?dBApB?VA|B?zB?\\C`EA~D?jC?vAAx@?P?x@?`@?f@?h@AV?jCAn@AtGAd@?H?LAtEAjA?b@?R?LAdC?vA?r@@pDBpD@lADlBHxC?^DdADhAPrDHnAPvCLtB?J?JJdANrC^lELbBZ~CZhEDb@T|CJ|A^vENpBRnCDf@JtBHzADrABzA@L@f@@r@@p@DlCJlFBfBLhH?PDfC@b@F~BJlG@PBrBBhABjBDdD@r@@dAHhF@b@F`DBlA@h@@^@`AB|ABr@@n@?HBpADhB@bABjA@fABbA@V?R@R?T@T@t@B|AD`BDzC@d@HtD@~@@x@B|@@X?FBzAB`AD~BFbDB`A@pAFzB@n@@t@BvBB|B?TAl@PnEBfA?`@@`@B|@DxAD`BBn@DhB@r@@bB?|@?l@?b@Al@?PCv@Al@Cr@Cj@Cv@Gz@Gv@GbAIp@CXs@xCUtAYtAk@rCYrAWnAI^Kb@K\\CJKZCJQf@Sn@CFCHITABIXM`@ENKJA@I^o@Wy@UMEYGMEWGWEUG]C]C]?Q?]BU@a@FSDA?MDMBE@UHQH[Lc@Ro@\\WLSJq@\\k@XWNi@RGBMDYFWDO@O@Q@E?Q?Q?]C[EYGa@MkFgBiA_@oBo@cA_@aFaBYIeA[eAQAAYEUEoAUcCc@}@Q_AO_HoA_AQ}@QqB_@a@IMCQCUCMAA?MAM?I?I@S?U@S@M?I?[AA?MAOASCOCa@K_@MOGi@S[IOIQIm@UUESIWKa@My@]k@UcC{@{@[ICSGu@Y{Ai@oBs@SG[MyBw@_@MQIC?GCo@Wi@SYKa@Oi@U[MCAWKc@Qa@Qq@Yy@[c@OwAm@c@S_@Oe@SSIg@U_@Os@Yc@S_@OMG]MCA[MQIEA[KWGOAKAO?e@?Q?Q?S?S@Q?Q?e@?e@?O?g@?W?Q?g@@e@?U?cA?W?oC?U?mC?w@@c@?a@?O?[@g@?k@?i@?c@?e@?o@?a@@Y?[?Y?U?S?cA?]?U?[A_A@m@?i@?uBAY?_A?g@?g@?u@?Q?{@@U?_@?e@?a@?uB?{@@M?Q?G?U?]?u@??kA?W?_@AS?S?c@?U?M?qA?i@?a@?]AQ?g@?mAAi@?c@?gA?i@?S?_@?sA?g@?c@?m@?y@?c@?Y?MAY?g@?]?[?i@?u@?_@?]?_@?}@?c@?_@Am@?g@?}@?g@?UAa@?a@?e@?c@?qA?a@@i@?oA?U?g@?g@?a@?c@?eA?g@?e@?M?c@?k@?yA?c@?k@?]?_@?gA?e@AaA@a@Aa@?y@?e@?s@?a@?c@?Y?e@?M?w@?q@?u@?w@?U?e@Ao@@yEAgB?}@?o@?s@?uB?o@?m@?a@Ac@?m@?q@?Y?q@?s@?i@?[AoA?y@?e@?uC?y@?e@?e@AiAAs@?O@K?K@O@O@O@Y?_@?_@?oA@_ADK@K@K@Q?W?K?mA?YAy@?c@?k@@U@U@]BYN{ALqA^wDBSDq@@Y?QASGM?UAMAU?C?CEa@I_@AGK]GSIWKWq@KA?OCG?E?Y?M?K?[@c@DE?o@He@Dg@@e@?C?E?u@?S?aC?s@?WAUCmAKq@EwB@c@?yA?gA?O?WAUCOAEAQGOGUKQMUMKGECMEMEOEOCSEUAE?OAOAWA?o@?i@?Y?o@?Q?y@?iBA{A@]?c@?[?u@?m@?W?m@?g@?e@?K?c@?g@?k@?cA?q@?e@?oB?a@?Y?i@AoB?Q?oA?oA?k@?e@?wA?s@_B@A`@@B?@?@?@DDBB@@@B?P?R?N?b@?d@?J?K?e@?c@?O?S?QACAACCEE?A?A?AAC@a@~AA?r@nJCxO?`B?|B?xEAhB??`@?f@?l@?t@?l@?b@?d@?l@@tB?n@?l@?l@@hB?n@?l@?vB?j@A^?T?R?d@?pA?R?bBAf@@T?v@?~@?b@AbC?n@?T?F?F?H@L?DDb@D\\DRDN?BHXJVHVFRJ\\@FH^D`@?B?B@T@L?TENAX?V?LAPCVCVWnC[dDEf@CXCZARAp@?tC@nA?JAN?LA\\DNA~@?nA?^?^AXANANAN?JAJ?N@r@@hA?d@?d@?x@?tC?d@?x@@nA?Z?h@?r@?p@a@?M?Q?{B?iF@iDAY?gEB_IAaFA[@[?_@?i@?{@?[?m@?cB?G?E?QLw@?sA@S?M?W?oA?U?W?aA?]?c@?y@?[?eB?W?S?i@?s@?oA?U?M?eA?U?q@@Y@U???",
        "vehicle_overtime": 1007
      },
      {
        "vehicle": 2,
        "cost": 4931,
        "steps": [
          {
            "type": "start",
            "arrival": 1693387314,
            "duration": 0,
            "service": 0,
            "waiting_time": 0,
            "location": [33.940407, -118.265196],
            "location_index": 7,
            "load": [0]
          },
          {
            "type": "job",
            "arrival": 1693388400,
            "duration": 1086,
            "service": 120,
            "waiting_time": 0,
            "location": [34.054927, -118.323726],
            "location_index": 1,
            "id": 2,
            "load": [0],
            "late_by": 300
          },
          {
            "type": "job",
            "arrival": 1693389365,
            "duration": 1931,
            "service": 120,
            "waiting_time": 2982,
            "location": [34.037925, -118.459842],
            "location_index": 5,
            "id": 6,
            "load": [0],
            "late_by": 0
          },
          {
            "type": "end",
            "arrival": 1693392467,
            "duration": 1931,
            "service": 0,
            "waiting_time": 0,
            "location": [34.037925, -118.459842],
            "location_index": 5,
            "load": [0]
          }
        ],
        "service": 240,
        "duration": 1931,
        "waiting_time": 2982,
        "priority": 0,
        "delivery": [0],
        "pickup": [0],
        "distance": 34116.7,
        "geometry": "q~cnEftypU{B?aC?o@?uA?_@AcA?i@?c@?}@?k@Ag@?_A@Q?M?k@?c@?W?U?[?g@?K?Y??\\?bA?X?^@vA?bE@dH?Z?N?v@Af@@z@Ah@@`@?jH@~E?z@?j@?x@@n@?~@At@?p@@h@?~C?~A@dD?N?V?b@?Z?Z@l@?V?P?H?F?F?X?r@?h@?N?N?\\gDKuBCaAAW@_@@e@@g@Da@BWDUBWBg@Fi@D_@FUFkBf@mANqBXmANSBg@Fm@Fy@JkBTiANo@Hy@J{AP[Dc@Di@D_@Ds@Bm@Bs@@iB?k@AqBAg@?[AyA?sFCwCC[?o@?o@?M?W?o@?w@?uCBO?kJBcA@iB?gB@g@@eA?yH@_A@oB?G?]?yE?Q?aB?yF?S?cD?M?I?e@?{B?y@XoH?g@?gN?]?aF?_C?[A_B?}@?_BAyACcBGaDQG?[CkAEkBImAEuCCuDCq@A[?w@AK?kFE}ECQ?mC?G?Q?_A?_A?Q?mB@_DHk@@aBDE?{B@oB?g@?kF?gA@wA@q@BuBFS@Q@eJ\\mHXy@Dm@Be@@mBHi@BgCHwCDwD?[?S?gCAcB?mBAyICO?M?sA?uICcAAwAAk@A{@Cc@AMA}BEgBC]?i@AkCCw@?[AG?W?IAI?o@AcAEeBKg@GqBm@k@IUE]G}@Ww@WaA_@yAk@aA_@gAe@mFeCIEiAi@}Ay@{A{@i@_@kAm@y@_@iAa@UIa@S_Bo@kDoAy@WOGs@YUKc@Sm@Ww@]o@[OK_@QUMKG}@g@QIm@Yo@Ws@Ss@OYGSEGAi@MOAWE]AY?KAgAAkA@_CFyAD[@c@?S?Q?O@G?_@@i@Ba@@a@ByCFO?g@@m@@w@K_@CaAGgAGwAM}C[e@EUCSCUCKCu@MWGi@Q_ASs@_@YIo@Q]IUCMAS?GAU@I@M@u@JIBI@I@e@DK?U@[?QASA{@[QGIEIEKGKGGIGGEGCIEGAGCGAIAI?I?G?I@K@G@I@GBEBGBIDEBGDEFEFEDCDCFCFADADABAD?FAF?H?F?H@L@F@D@HBJFJDHDFDFFFFFHFHLRBHFR@HBJBZ@J@N@f@@N?X@Z@J?^@J?VBp@HlCDtCRvHFhB?NFpBDbABp@@NFbADv@@TBVDn@Fx@NxAD`B@HBT@JN~@ZxBZlCJp@Fn@@HBZLjADt@Ft@FtADxABvA?x@?lA?pBAH?|@Aj@?~C?~AAv@AlHArAClF?`CEzE?nAOrBCxAEdACj@IrBAT@t@@d@@`@?jCAlAAj@?X?PAPAnC?H?L?N?x@?~@Ap@ItBAbACb@?f@AbB@bB?b@@Z@tA?Z@b@At@G~@Cz@S`GGhBIhCGxBA\\A\\g@@y@B}@BIDI?W?U?i@?iA?W?K?[Aa@?G?m@?Q?[?U@k@?y@?_A?O?Y@g@?c@?Q?_@?e@?w@@y@?]?]?aA?{@?M?I?k@?g@?I?M?iD@iC?q@@yA?[?S?e@?i@?]?Y?yA@cB?mAAkA?eB@sD?uD@i@?]?c@?iAA?x@AhA?d@?l@?x@?f@@hB?hB?n@@p@AtA?f@?LBvA@bA@f@?Z@hBDdB?N?PBpB@n@@T?F?R@r@Cx@AN?HCTABEREVSv@WhAI^a@fB_@vAW`AOh@]nAK^i@lBa@|AGRQr@GRMj@St@EPER_@tACLI^I`@CPAHC\\ARAT_@C^B@U@SB]@IBQHa@ZNPJb@P^NhAh@PHDBTJLFHDx@^hAf@~@b@tCrAVLpClApEpBnF~Bd@RHFNFTJt@\\f@TrAj@@?VLjCjAnD~Ah@TPHRJNFPHn@Xl@VVLTJf@TPHx@^nB|@rAj@dAf@^PZNZLvDbBxAp@FDNFd@Tf@TVJJDh@TVLl@Xd@RzCxAbF~BXLRJZN\\P~@`@LVb@RVNVLVHf@N?R@XBdADjA@b@Bh@B\\@R@RBXBL@J@R@FBZBPFl@HfABp@@HDl@BPBF@FP^DdD@r@@dAHhF@b@F`DBlA@h@@^@`AB|ABr@@n@?HBpADhB@bABjA@fABbA@V?R@R?T@T@t@B|AD`BDzC@d@HtD@~@@x@B|@@X?FBzAB`AD~BFbDB`A@pAFzB@n@@t@BvBB|B?TAl@PnEBfA?`@@`@B|@DxAD`BBn@DhB@r@@bB?|@?l@?b@Al@?PCv@Al@Cr@Cj@Cv@Gz@Gv@GbAIp@CXO`BYvBCLo@|ES|AS`BM`AIn@EZO`ACVETGd@_@hCCRG`@EZ[dCEZGd@Ih@k@lEMdAE^CJCTET]nCi@bE_@zCCNKz@CNM~@OjAKz@Ij@EXEb@ALCTCPAXA`@AXAf@?^?f@@x@@^@`@Bh@Dd@Fr@Df@Hh@DXFb@H`@H\\FTZfAZ~@\\~@^x@v@|AxDxHnAfCnAdCJPHPLVTd@Tb@Rb@P\\Vf@P^Zp@b@z@Xn@Zl@^v@LVZn@Vf@DH?@^r@Zp@DJPZf@`AXp@R\\NZLZHJDHFLLVHLFNFLJRJRVf@JTJTFLHPFLFLFLFLJVHVJR@BFRFNFPDLDLDNDNDLDPDNBLDPFTDTFVDTBRDRDXDZDXBRBRBVBXBT@V@N@L@P@N@XBh@BrA?h@Aj@?TAb@A^A^Cb@AZAZCd@AVSfFOnDGlAAj@QlECf@OlEE~@GtAAJOfD?HATK`CCX?JAJGhBQxDKrCAXAZA\\Cj@CXALCd@KdAC\\EZO`ACNKn@U`AMh@Kd@i@rBg@vBo@nCGZQv@GXKl@ETANEZGp@E\\Eh@Cb@Ch@AZA`@A^Ar@?r@@n@Aj@@j@?b@Al@@\\?R?n@AlA@`A?V?^?`A?jA?rA?R?b@@vA?fA?h@?Z?F@X?l@?\\@^AV@lB@tE?`A?h@?l@?jB@fC@pB?bC@lB?J?`A?l@?hB@bABfABvAB|@@ZBz@F`BHzANdCP|BJrAHlA@L@N@F@FF|@HhAVnD`@rFRhCXtDNvBJ|ATnCLjBf@hGNrAJfAFb@Dd@VxBBJ?DFZHh@BVFZDPBRDPNfALt@FZBJHh@Hf@F\\XzANtCBXLbAJv@LdAJ~@DV@RBPBP@N@J@P?J?LAD?BAHADAFCBEJGHGFSd@OL_@Xo@d@]\\ONILMPQT[b@OPcAlAW\\q@x@}@hAORGF{@`AMRQTWXQTILMN_@d@m@t@W`@W\\]b@[\\MPOPMNOPKLEFo@x@GHOPCDOP[^o@x@gArAeBrBQR[^q@t@s@|@{@hAyAnB}@jA_AhAq@x@KLcAjAEGUc@??",
        "vehicle_overtime": 167
      }
    ]
  },
  "status": "Ok",
  "message": ""
}

When the above result is plotted on the map we can see how all the tasks were covered.

Analyzing the Solution

Looking at the result we can observe some interesting insights:

  • The summary section gives details about the total number of routes, total cost of the solution, distance and duration taken to complete all the assigned jobs.

  • In the routes section:

    • We can see that job 3 was fulfilled even though vehicle 1 arrived at the location 5 mins after the scheduled time window had ended. The late_by field indicates the value by which the vehicle was late to arrive at job 3 location.

    • For job 2, the optimizer uses the relaxations available for time window constraints and assigns job 2 with 5 minutes of acceptable delay.

    • Observe the vehicle_overtime field for vehicle 1 & 2 and we come to know that they operated for around 16 mins and 3 mins beyond their shift to complete all the assigned jobs. This happened as the optimizer was allowed to operate vehicles for 1800 seconds (~30 minutes) beyond their shift end time, if needed.

The above example exhibits how NextBillion.ai’s Route Optimization Flexible API allows and implements the relaxations configured for vehicle shift times and task time windows and suggests the best solution with maximum possible task assignment. We encourage you to go ahead and try out different configurations of soft constraints and explore how the solution changes under different scenarios presented to Route Optimization Flexible API.

Liked the above example? Take a look at a host of advanced use cases that Route Optimization Flexible API can solve for you.