Route Optimization Flexible API
Introduction
Nextbillion.ai's Route Optimization Flexible API is a powerful tool that helps businesses optimize their delivery routes to maximize efficiency, save time, and reduce costs. It is designed to solve both Single and/or Multi Vehicle Routing Problem (VRP), which is a classic optimization problem in operations research that involves finding the optimal set of routes for a fleet of vehicles to visit a set of locations while satisfying various constraints such as time windows, capacity, and vehicle availability.
The Route Optimization Flexible API consists of two main components - the input data and the optimization engine. The input data includes information about the jobs (stops/places to visit), vehicles (delivery trucks, vans, etc.), and shipments (pickup and delivery tasks), while the optimization engine uses this data to find the most efficient set of routes for the vehicles to follow.
With the ability to handle complex constraints and variables such as capacity, time windows, and vehicle availability, our API can be customized to meet specific needs of your business.
There are two components to API
-
Optimization Post
- Use this method to submit input for your VRP. -
Optimization GET
- Retrieve the status of a submitted VRP using a unique reference ID.
Optimization POST Method
https://api.nextbillion.io/optimization/v2?key={your_api_key}
Use this method to configure the constraints and properties of the optimization problem that you need to solve. Use the fundamental objects - vehicles
, jobs
, locations
and shipments
to emulate the scenario that your business needs to optimize. You can choose to use either one of jobs
and shipments
or use both of them.
Define the objective of your optimization, soft-constraints and routing preferences in the options
object. You can also use advanced features like re-optimization and order sequencing using the solutions
and relations
object respectively.
Once an Optimization POST request is successfully submitted, the API will return a unique task ID in the acknowledgement response. Use this unique ID to retrieve the actual solution using the Optimization GET Method.
Request Parameter
Loading..Request Body
Loading..Response Schema
Loading..Example
Let us build a basic flexible route optimization request using a sample scenario which has:
-
2
vehicles
with properties like capacity, time_window, start_index, end_index and skills set. -
6
jobs
and 1shipments
with their id, locations, pickup/delivery amounts, time_windows and service time set.
Request
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
curl --location 'https://api.nextbillion.io/optimization/v2?key=<your_api_key>' --request POST \ --header 'Content-Type: application/json' \ --data-raw '{ "description": "Los Angeles Sample Optimization", "locations": { "id": 2, "location": ["34.06675919,-118.30620984", "34.04268850,-118.28191077", "34.03434239,-118.28358834", "34.04238041,-118.23817754", "34.08431954,-118.25597762", "34.06892275,-118.29156827", "34.01103011,-118.19238067", "34.08659806,-118.17526366", "34.06624918,-118.11066669", "34.05221370,-118.28427087"] }, "jobs": [ { "id": 8, "location_index": 0, "service": 300, "pickup": [ 1 ], "time_windows": [ [ 1688112000, 1688119200 ] ] }, { "id": 9, "location_index": 1, "service": 300, "pickup": [ 1 ], "time_windows": [ [ 1688112000, 1688119200 ] ] }, { "id": 100, "location_index": 3, "service": 300, "pickup": [ 1 ], "time_windows": [ [ 1688119200, 1688122800 ] ] }, { "id": 18, "location_index": 6, "service": 300, "delivery": [ 1 ], "time_windows": [ [ 1688126400, 1688130000 ] ] }, { "id": 28, "location_index": 7, "service": 300, "delivery": [ 1 ], "time_windows": [ [ 1688126400, 1688137200 ] ] }, { "id": 38, "location_index": 4, "service": 300, "delivery": [ 1 ], "time_windows": [ [ 1688126400, 1688137200 ] ] } ], "vehicles": [ { "id": 1, "start_index": 8, "end_index": 8, "capacity": [ 46 ], "time_window": [ 1688110200, 1688140800 ], "skills": [2, 3] }, { "id": 2, "start_index": 9, "end_index": 9, "capacity": [ 46 ], "time_window": [ 1688110200, 1688146200 ] } ], "shipments": [ { "pickup": { "id": 1, "service": 300, "location_index": 2, "time_windows": [[1688122800, 1688126400]] }, "delivery": { "id": 1, "service": 300, "location_index": 5, "time_windows": [[1688126400, 1688130000]] }, "amount": [5], "skills": [2], "priority": 100 } ] }'
The above problem statement would look like the following when visualized on a map. We can see the locations of the 2 vehicles, 6 jobs and a shipment task. We will cover the solution and how it looks on a map in the next section.
Response
1 2 3 4 5
{ "id": "3b14afd6c576690eb1df5c6871090383", "message": "Optimization job created", "status": "Ok" }
Optimization GET Method
https://api.nextbillion.io/optimization/v2/result?{id}&key={your_api_key}
Use this method to retrieve the optimized solution for the optimization tasks created using the Optimization POST Method.
A point worth highlighting here is that the optimizer uses traffic conditions at the time of making the request to prepare a solution. Slight changes in traffic conditions can cause the optimizer to prefer different routes and possibly different sequences in which to fulfill the jobs or shipments. Therefore, different optimization requests made with similar task or constraint configuration are expected to return different optimized solutions.
Request Parameters
Loading..Response Schema
Loading..Example
Let’s retrieve the same job that was created in the example above in the Optimization POST Method section.
Request
curl --location --request GET 'https://api.nextbillion.io/optimization/v2/result?id=3b14afd6c576690eb1df5c6871090383&key=<your_api_key>'
Response
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 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263
{ "description": "Los Angeles Sample Optimization", "result": { "code": 0, "summary": { "cost": 6774, "routes": 2, "unassigned": 0, "setup": 0, "service": 2400, "duration": 6774, "waiting_time": 1696, "priority": 200, "delivery": [ 8 ], "pickup": [ 8 ], "distance": 88544 }, "routes": [ { "vehicle": 1, "cost": 5391, "steps": [ { "type": "start", "arrival": 1688121973, "duration": 0, "service": 0, "waiting_time": 0, "location": [ 34.06624918, -118.11066669 ], "location_index": 8, "load": [ 3 ], "distance": 0 }, { "type": "job", "arrival": 1688122800, "duration": 827, "service": 300, "waiting_time": 0, "location": [ 34.04238041, -118.23817754 ], "location_index": 3, "id": 100, "load": [ 4 ], "distance": 15357 }, { "type": "pickup", "arrival": 1688123729, "duration": 1456, "service": 300, "waiting_time": 0, "location": [ 34.03434239, -118.28358834 ], "location_index": 2, "id": 1, "load": [ 9 ], "distance": 23975 }, { "type": "job", "arrival": 1688124704, "duration": 2131, "service": 300, "waiting_time": 1696, "location": [ 34.08431954, -118.25597762 ], "location_index": 4, "id": 38, "load": [ 8 ], "distance": 32327 }, { "type": "delivery", "arrival": 1688127297, "duration": 2728, "service": 300, "waiting_time": 0, "location": [ 34.06892275, -118.29156827 ], "location_index": 5, "id": 1, "load": [ 3 ], "distance": 38067 }, { "type": "job", "arrival": 1688128555, "duration": 3686, "service": 300, "waiting_time": 0, "location": [ 34.01103011, -118.19238067 ], "location_index": 6, "id": 18, "load": [ 2 ], "distance": 52640 }, { "type": "job", "arrival": 1688129778, "duration": 4609, "service": 300, "waiting_time": 0, "location": [ 34.08659806, -118.17526366 ], "location_index": 7, "id": 28, "load": [ 1 ], "distance": 67654 }, { "type": "end", "arrival": 1688130860, "duration": 5391, "service": 0, "waiting_time": 0, "location": [ 34.06624918, -118.11066669 ], "location_index": 8, "load": [ 1 ], "distance": 78857 } ], "service": 1800, "duration": 5391, "waiting_time": 1696, "priority": 200, "delivery": [ 8 ], "pickup": [ 6 ], "distance": 78857, "geometry": "aq|nEnn{oUF??aB?uC?s@AeA?w@?OA{@m@@Y?K?W?kA?a@@I?Y?a@?M?w@?I?A?K?I?_@?Y?a@@O@M@YBK?QMkAA_@?M?c@A]?S?M?K?O?U?iB?eA?e@@M?M?U?MAK@S?O?K?kCBm@KICIIEICIAK?IBIBIDEFCFCJEl@?j@?ZAL@HDHDDFBHDLBf@BH?H?J?J?F@f@@`@Bj@@D?DR~B@nCFlNBzMDlJ?~@BlHBxE?bB?f@@tC@|A?n@?J@fA?pA?V?Z@x@@dA?l@?`@@bA@`E?`@BnL@V@pB?~@@t@?F?t@?tA?lA@rA?rB@fD?jABnD@xB?r@?b@?T@j@?x@@v@?fB@`@?jB@f@?N@lE@pA@|FBdF?vA?FAjAC~@Ez@IlAQxBIfACv@Ap@?l@@Z@L?FB\\Ff@Hf@Jf@Lf@Pf@JXFN|ChHr@~AHPJV`BvDFJLZ|ArDDFb@dADJt@jBNZHPn@xAP`@xB|Eb@dAtAdDzBdFjAfCp@~ArAbDbAzBbAdCP^n@|AVv@JVt@lCHZLb@JXJVFPHNLXLVHNHJFLHLJLHLJLf@n@X\\TVPPLLJLNNZ^j@|@j@lADJFPBFFPJXFVF\\BLBJHn@@PBL@T@`@@XBV?N@P?PAZ?b@Af@A\\Et@Cb@OtBC\\APKtAGl@GhAGp@E~@Cd@@ZAl@@R?\\@h@Dt@Fx@Ft@@NBR?BBJ?@BLFZJf@FZDTPj@Lb@JXJ\\Nd@Tn@Rj@@BVz@HRL\\d@zAj@bBDJ`B`FPf@Z|@f@vAbAxCNf@Vv@jAnDjAhD~AdEv@vBn@fBl@dBZv@Tj@Nb@DJDJPl@^jALd@Nl@Hb@Hb@BLNdAHn@Hr@F|@D`@?DBZB\\B`ABpAAn@AnBChDC|A?l@AfAC~BAvAC~AAdA?RAnAAh@?f@KpLCvAKjH@`BFhBDdAV~CFf@Fp@Jz@LtANxAH~@V|BX`BJj@Nn@VdANl@r@lCJb@XlARz@Jj@BRBLH|@Db@Dv@Bb@@j@@f@Az@At@?TANAPGt@CZAPGb@CTETG`@SdAYrAKh@Kf@Kn@ENG^Op@ERKf@If@Ib@Mj@Ox@Kf@GZGTGXMv@Mx@Gb@El@Ed@CZA`@C`@ChA?HAJ?^?JAjAA~@?f@?h@?N?n@Ab@?xB?xA@pC?~@@v@?j@?h@@^@R@V@T@ND\\DZFb@F`@FXFXBNHZDJFTHXJZJTFPFLHNFPDHDFDHBFHNLRHLPTJPNRRTLNJJBBFHTTPRNNFFFJDFHHHJHLLPBFFHJRDFHLFNFLFLDLBLFTDN@JBJ@LHx@@PBR?d@?\\GzB?TAlAC`ACj@I~@CXE^CPEd@Gh@Gd@EZALEf@Eb@CTAHAJKtACZEn@KpAEl@I|@_@|AMj@Ih@AJM|@Ib@AHELGPINGHWHI@K?A?E?IAYCK?e@IKIGIEKCG?G?EAG@G@WV]Z_@DEJIJGPGFAHAJ?H?NBJ@J@\\DPBVDXFPBJ@R?N@HAH?d@CRCLCLANCNARAVB@?VBr@Jd@DTDtBVfBPfAL\\Dn@LLFJFJFFHBDDHLZHNJNDBDBHDLDLBXDF@NLd@FH?Z@D?d@@PKL?rAAZAZ@jBEn@@PJF@HBF@D?F?FBB@@@@B@DDHA\\?b@?Z?`@?pA?D?tA?`@@L?LD`@B\\@X@JHz@@HF|@?BFn@DlAPlBDj@BT@L?B@NFXBFLNBBUx@p@AXAb@?d@?l@?D?V?jABX?d@?j@@f@?j@Br@@vADxDHz@B^?zELbBFt@Bz@@t@@X@n@@d@@|DJ`ABZ@t@@d@@n@Bd@@v@BV@@?p@B@IDg@@G@W@W@Q?O@[?O@W@e@LiFNmFBeBB]FeBDyA@u@Bm@@i@?g@@e@jBE`BA|AAdBAbA?vCAvD@`B?dB?CwCb@?j@?l@Cp@Ab@AN?DAP@NFLFHDBBJJFHHPN\\Ph@FNd@hAn@tAh@jBL`@Nd@FPZbAVv@HTHXL\\DLHVV~@`@lA~@nCZfADJrAlEDNHTLb@~@zCL\\`AbDZdAPr@BHHd@Lr@Jr@Hr@Fr@@H@T@\\?X@F?xB?f@ArAEz@C\\C\\Kz@Mx@Ox@Qv@Sv@Ut@Up@[z@GLeGbNMZo@vAO^MTi@nAaAzBINMXCDk@nAg@jAKRO\\a@|@_AvBeA~BQf@gBzD_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@@^M~A@T?V@^?b@@t@H`D@bABdB@v@LlD@P?HB^BRHtA@HLdBFl@@LBRL~@Hp@Hl@DXv@lGJz@Ff@D\\Fb@BXDZ@N?|AA^CdBCVCPENGLIHIHKFMBO?U@E?G?_@@?c@?{@?S?S?k@?U?e@?O?S@Q?M@KD[nBA`@Ab@?j@?X?LAX@TA`@?N?`@AAG@M@Il@iB^eA\\P^Rb@V|@^\\cAzBhARJGRELKNCBCBI?GCKESGCAYOOIk@]}@_@c@W_@S]Q_@dAm@hBAHAL@Fa@@O?a@?a@i@MMKMACEGGKGQEQE_@ESMaAAEQcAIo@Kq@UaBYiAKmACWAIKeBG}@Ek@AYEm@?GAWAUG{AAy@OmIKy@Ei@EgAMwFCo@Ac@Aa@?MCc@As@Cc@CYEWIYAEGQEICGQWOQQOOISKUGUEWCW?UBWDYHYNWVIBIHSPSPUPMHk@b@WRYPWNSHYDO@Q?SCWCk@OcBi@e@M_@Mg@Ie@U[Oc@Wc@WWS[UUOSS[Wc@_@][QSQQ[_@gAyAQUQYk@{@_@m@S]Wc@}@aBYi@]m@AEQ[Ue@S]KSGMWg@Wg@_@u@Q_@_@s@[k@EIGQa@u@S]oFgKIUS_@[o@uAmC[m@GMwBgEUg@]o@ACOWSa@i@aAMWi@cA_@m@o@_AUYY]QSW[QQQSaAaAWU_@Y{DwCUSc@]KGWSKIOQQS_@W_Ay@QQWWq@k@KKu@s@e@c@SQqAsAq@q@MMUUMO[]aAy@e@g@QSa@a@QQSS]_@}B{Cy@eA}@iBS_@KQSYe@q@q@cAoBgCSYaAwAUUWQMIQGYKGAEAGAWCOCI?M?E?]Eo@EWBSBODC@QJMHC@QPOTILILwA`Da@|@yAjCYf@e@fAQX]d@_@d@a@l@_@j@QZ]j@MROVU^_@h@S^QXOXOVOVEJEFO\\Q^Qb@KTOZKVUn@Qh@Up@Sp@W|@YhAAFoA|EUz@WPUt@]fAKRKPKJKJGBMFWJIBYDCHCFk@fBENCFMZOd@o@hBCJCJAHAFAFAJe@@S@I?}@BO?I?S@[Bo@DUBWBUDmC^WBQ?Y?mAGsCIcAEyBGm@EUCQEMCSGs@U[K[MSGQIe@OICy@[qAe@YMa@Oa@MYEKGIOYMIEMOGGMISKQIOIWKsAo@YSQIKIIIW[GGSUMOMKCEGGMIKIIEEACCKCKAIAKA}@GKAIAGCKEECGKCECC}Aw@KEKCIAGAICm@[QAAAA?A?KGcCsAsFsCPi@Ro@?G?CACACECWOVNDB@B@B?B?FSn@Qh@rFrCbCrAM^Sh@GLo@nBi@dB[`AIRCFGFGFOVKP~@BR?PHJDXLtAt@JFJA^RnAn@hDdBbAf@z@d@^RZNLFpAr@|@f@\\N|@b@~@j@HFl@\\^RfAd@v@^LFv@`@h@Xh@X`@T`@R`Af@t@^LH^RRJRJd@VLFLHh@Vd@XTHVLl@ZNHJFPJRJRJTLTLRJhAl@t@\\j@XM`@Qn@W|AYlBO|@ATYdAGn@Kl@w@fCUr@EL_@`Ae@jAMVMZ_@|@Wl@Up@KZWp@GXOh@Sr@Oj@K\\I^K`@IXGZK`@EVKj@Kf@SdAGTShAc@xB{@hEKh@UlAg@fCCJGZWrACN[dBIb@W|Ak@fEOhA_@`CG`@c@|CALEP_@hCIn@EVIl@UjBGh@QxAGh@Iv@KdAMhAOnACRKn@QbAUhAQz@q@`BKVCDc@bAw@bBQZOVQVML]Za@`@WXKNCBAHAFAF?H?Zp@?P?tCAP@FAdA@P?T?Z?P?XAbB?l@@f@Ar@@Z?T?rAAp@?f@?|@AR?T?t@?X?N?z@Az@?lA?~@?P?N?jB?`A?vB?X?nA?lCAV?D?h@@d@?hB?N?XAn@?R?p@?X?Y?q@?S?o@?Y@O?iB?e@?i@AE?W?mC@oA?Y?wB?aA?kB?O?Q?_A?mA?{@?{@@O?Y?u@?U?S?}@@g@?q@?sA@U?[?s@Ag@@AyB?UAe@A]AQAQAOAGCMAIEOI[Oi@K]CKCOCMAQAM?M?EAK@]?g@@O?u@@cBDwDBg@?CBo@IiANiBBYJcALaARuA\\cCPiATcBPoA@KJo@Fa@LaAf@mDVgBLs@Js@FSRsABKN{@TeAHe@RaAJc@VuABOz@mENs@P}@P_ARgANq@Nw@Ji@Jg@Ps@Nm@No@Nk@Rw@\\gATq@HUVu@|@{B|@wBb@kAPi@`@kARs@Vs@Pq@La@DOv@iCn@mBl@gB~DoLL_@L[Z}@Xu@`@oAj@wBBS`@}A\\sAZqANm@Pq@H]HY@G`@aBbAaEZoAXiALi@T}@Ru@R{@Nk@@ERw@Ty@Nm@Pm@Ng@Tk@Ri@To@Vm@Zs@Xm@DIFMJMzAmCr@gA`@s@Zk@|@uAFKT]l@aAzA_CtAqBNWNS\\e@RUv@y@^]TSb@_@`@]f@c@TQDEFGFCLMLKFEZWfA{@jA_A~AqADGBCFGFELKNKb@[\\[ROJKLOPOV]TURUp@s@RYZe@R[LSj@m@v@mAXc@Va@NS~AgCb@u@r@oANWVe@NYHQFIFOTa@NYP[R_@R_@LSLWFMDGDIDGDIxAoCTa@FMZm@BE^s@HOXg@HOtByDBGHOVk@HQHSJUNc@J_@BKZiCBWDe@@Q?Q@u@Bu@AeA?c@Ai@@i@?[BmAHiD@SBk@HyB@W@U@UDm@Do@BW@MD]JqAL{AJqABYBYDo@BS@U@OFm@Bm@@I?I@K@QD_@@IBY@KToBH{@Hw@H_AD_@LaBPu@BMBIHm@DSH]Ni@Ng@Ri@Vk@BGR]Xc@Za@\\_@^]ZWLIJGLILIJGNGLGd@Qh@U|@_@p@WJELGPGFCb@Q^ORIbBo@~@Y|@W`AUHCNCJAREDA~@O`AM`AIB?x@GTAJAb@ApBCp@AL?N?h@?`@?fACfA?t@A^@h@@`@@ZBP@T@\\BZD\\BZDZDbANr@Ll@HvAXl@DZ@pA?t@Af@CRArAID?n@CZAL?n@@v@Bb@DhAJ`@DVBv@Dn@@n@?j@EPAHAp@EPCl@Gd@KDAh@QLE^K`@OBALGJGb@Un@QFCFCPGVMLGp@c@v@g@v@g@TQJIDE\\[HIb@_@f@c@\\]`AsAJSb@y@NWLQBAFILGHALAL@HBH@NBF@LHPJHFHF\\Pl@VHDFBTJ^N^Lb@Tb@Ph@TJB`A`@LDD@D@NGb@Br@?hFVl@B\\BfAFp@BN@n@BZ@zAFT@Z}@Ts@DIFQX_ADK`A{CRo@lCeIRq@Rm@b@oAFSJYNc@^gAb@oAHSbAyCt@uB\\aAfAiDN_@Pe@Vq@^iAX@X?J?Z?ZAP?h@Ah@AZAXCHAHCLEPGPIXMr@_@b@S~Au@ZOPINGPKRMHEHGJIFKHKN[JUJQBGHMBGFOFIHKLKTMLGL@RANAHAT?n@?j@AHALANCXEHCNETINKrAo@XMD[LiA@MHiAFy@NoCJ}ADi@B_@B_@LkBDaAPmDf@cI@IB[?E@QRyDIQHmAFgA^yJHkB@[BYBWD[D[Nu@b@mBtAaGf@sBNq@BIP{@R_AP{@@Al@iCJe@FYPs@f@uBl@iCJc@T_AtB}IPs@^}ATcAZoA`@aBP{@Nm@j@}Bb@kBZqANo@FWFWR{@x@iDn@oCr@wCNq@R{@VcAZsA\\}AlByHLm@XiARy@Pw@Pq@R{@Ja@DQDQLk@Pu@H[FWJi@H]Le@No@Lm@DOBQDUFUPu@Ja@Pu@DSe@SMGiAc@OEMAM?OBMDKHIHINO\\O^KPCDGDMHODQBM@i@?aBFcAGo@Eg@Au@EMAu@?_AAs@?mBAkB@aA@WAkA@M?u@?[?i@?sA?c@?oFCQAwDCeA?o@AY?m@@SBYBYDq@JUBMBSFUJMF_@NUHu@VUFGBQFu@Rw@Rq@Lk@HiBJS@U@M?K@U?S?_@@mABo@@{@Ay@Cy@Ey@Gy@My@O_ASoFgAq@MYGQCa@Kc@E]G}@ISCQAi@EMAs@Cm@Aw@Ae@?uA?mA@c@?W?WA[?k@CG?G?g@Ea@Eg@I[EAAEA]IUEa@MaA[c@Oe@Ow@WICsBs@k@[c@I]KWKy@YUKeA]m@Ua@Qk@Qm@OYGa@ISCEAYEMAIASCIAa@CiAEiAAcA@qB@S?S?O?I?I?I?EAA?U@e@?aC@U?Q?oA?e@@u@?]?U?O?w@?}@@u@?sA?g@?eA?{A@[@K?c@?_F@qD?wA@[Ay@AMASAm@GWCQCKCq@Kq@QMCa@Mq@Wg@UCAm@Ym@_@m@a@EEsB_B[WEEc@]e@a@{@u@uBaBeBsAcA}@eDmCaAw@o@i@q@g@KG_@UKI_@Sm@Yo@Wo@Uq@SICg@Ms@Ks@Ik@Gi@Eq@AcA@{@@q@Dk@FkCl@_@HgAXeA\\a@N_@JqC|@[HMD]HMDQBa@Fq@HaADs@?g@As@E}@KSAmCW{@IKAOC_@EWEM?SCI?mAK_@COA[EO?MAUCE?GAIAG?}@IOAq@Gc@EQCa@EQCOCOCUCa@GWE[ESGSCSGWG]Gq@S}@YWKu@USGYKWKOIWKSIYKOIGC]M_@QyAo@GCoBy@o@YKEe@Qm@Ye@QIEYM[MSKIE_@OEAm@Ym@Wm@WoBw@SGOEOEYIKCk@Mk@KYGUCk@Eq@EkBIwAEa@COAC?Q?[AE?a@@G?_ABu@@C?G@WDR`AL`@FRDNLVLVXj@LTPXj@dAv@xANZHZHVDT@HBR@T@RAX?B?PCVCNKd@Oj@IZUx@WdAOf@I\\Ol@G^Eb@El@?BAd@AFA|@BhA?H@\\@LBXBTLj@Nd@L`@FN~@bCx@xBFLLZ`@bAPVPT?@PR\\`@DFjAzA|ArBl@v@j@r@nBhCzAnBbApAv@`ATXn@v@Z^LLBBB@\\\\HDZVNHHFZVZPPJt@h@l@^VN^Rv@j@LL\\`@PPHLFJFLFLBHPv@Dl@DZHv@?HHp@Fj@DLBLBJDLDRHTHTHTDJHRBDHHb@f@HFFDFFJDPLQFMDI@[@S@I@{@?W?aEFmBDiBDsABW?E?c@@k@@S@yDJcA@U?uCIqBI}@E_AEO?sAG[AcAEqAEo@Cu@?W?G?EA[AKAKAEAWKsBiAOIQKMIcAm@MGIEQMIGKKMKCCQOKMU]OWKSKOGKGIKIIGOKCAGEKGECEAIAAAE?IAOA]A}B?sA?wB?{BBo@?m@?U?M?MAkA?_@?mA?I?_A?oA@k@?g@?cC@K?uDA@IAKEOIWe@wA_@oAK[CE]kAM]K[s@{B_@PUy@Ma@ZSNb@Vx@r@zBJZL\\\\jABDJZ^nAd@vAHVDN@JAHtD@J?bCAf@?j@?nAA~@?H?lA?^?jA?L@L?T?l@?n@?zBCvB?rA?|B?\\@N@H@D?@@H@D@DBJFFDB@NJHFJHFHFJJNJRNVT\\JLPNBBLJJJHFPLHDLFbAl@LHPJNHrBhAVJD@J@J@Z@D@F?V?t@?n@BpADbADZ@rAFN?~@D|@DpBHtCHT?bAAxDKRAj@Ab@AD?V?rAChBElBE`EGV?z@?HARAZAHALEPGQMKEGGGEIGc@g@IICEISEKIUIUIUESEMCKCMEMGk@Iq@?IIw@E[Em@DGBGBEBCFEDCFCB?HAD?NBTPLLf@^j@b@t@h@`@ZfBnAPLPLHDLFLDLBLBRDV@B?N@b@@r@@`@?pB@f@?N?L?N?N@^CHAHCRIPKFENKJILKHMNODGXk@FUHi@@Q?O?Q?a@?c@?E?M?QAU?yA?K?qAAQ?_A?g@?[?}@?aA?m@?W?WBQBQDQHWNOLKHGNIJGHEXSPI^ULGL@BACICIEKCIIWCIw@}BQe@GUI]Ss@Oy@GWEYACAIKw@EYC]Gu@Ew@Cu@Ae@Aa@AQAWAYCc@B]b@}G@YHiAHgABg@@g@@s@?i@?U?G?WA[AQ?KC]C[Gm@Ec@EYG[Ia@U}@Qo@Oa@EOSk@Yq@a@aAm@mAMS[i@Ua@U_@m@}@}@uAm@gAc@aA[m@m@sAaA}BcAcCy@kBcB}DKUu@_BEKk@uAgBaEc@cA}@uB}AqDWm@]w@Wm@Q_@Se@]y@IQKUQc@c@eAg@iACIQ_@g@iAi@oAcB}Dy@oBUi@EGIQYs@KWM]Qk@Om@Ka@Kg@EQAGIe@G_@E[Gm@AUCQASAUA[Cc@A}@?kAAiDCiC?eCCaF?{@AyAAcD?W?I@]AmAAoEAuAAk@AcB?y@?i@?iAAw@?W?s@AsDAcA?e@?OAy@AwIA}CCcE?]CwH?gACsI?e@CaB?_A?sAA}B?I?MAuBAm@?wA?yB?SCaC?i@?i@CcH?{@AkA?qA?]Aa@?e@AsBAmB?sA?_AA{AAsA?kBAiA?u@AcB?cAC{H?_@?U?UHu@H_A@_A@E?KD[BKDGFGHEJCP?b@?`AARAFAJEHGHKL[HMFIJEPGJ@N?L?z@@t@?h@?PIJ?XCLANA`@AX?^?H?J?@?H?v@?L?`@?X?H?`@AjA?V?J?X?l@A@z@?N?v@@dA?r@?tC?`BG?" }, { "vehicle": 2, "cost": 1383, "steps": [ { "type": "start", "arrival": 1688111823, "duration": 0, "service": 0, "waiting_time": 0, "location": [ 34.0522137, -118.28427087 ], "location_index": 9, "load": [ 0 ], "distance": 0 }, { "type": "job", "arrival": 1688112000, "duration": 177, "service": 300, "waiting_time": 0, "location": [ 34.0426885, -118.28191077 ], "location_index": 1, "id": 9, "load": [ 1 ], "distance": 1177 }, { "type": "job", "arrival": 1688112986, "duration": 863, "service": 300, "waiting_time": 0, "location": [ 34.06675919, -118.30620984 ], "location_index": 0, "id": 8, "load": [ 2 ], "distance": 6005 }, { "type": "end", "arrival": 1688113806, "duration": 1383, "service": 0, "waiting_time": 0, "location": [ 34.0522137, -118.28427087 ], "location_index": 9, "load": [ 2 ], "distance": 9687 } ], "service": 600, "duration": 1383, "waiting_time": 0, "priority": 0, "delivery": [ 0 ], "pickup": [ 2 ], "distance": 9687, "geometry": "kyynEfk}pUD?d@AR?ZAN@\\?V?N?V?pAArCAN?d@AvA?l@?hFCh@@L?h@Bb@D\\@L@XBB?F?R?\\At@?t@?L?nAA|@CVAh@Cd@?f@AR?~AAl@ABONk@HWJ]HU^cAPi@Z{@HWp@iBL@B@@@AACAMAq@hBIV[z@Qh@_@bAITK\\IVOj@CNMx@CRE\\_@bCE^U`BCRAFAJAH?J?LAR?LAL?N?B?V@~F@rA?b@?`@?`A?bA?nD?bB?j@@L?V?p@i@?g@?Y?w@?_@?cA@g@?eB?O?s@?W?M?m@?m@?m@?e@?[@cE?[@]A]?yE?i@?q@?W?m@?q@?gA?g@?Y?K?aA?O?Q?s@AQ@M?I?Q@G?{@?aB?G?MLY?q@@Y?SAUCO?MA]@K?]?[?O?K?W?YIAJCTAV?@?t@?N?xB?bC@dB?N@~B?rA?f@@bF?xE?xEAxE@zE@vE@xE?zEoH?w@?mA?gI?g@?}@?C?y@?}A?O?U?K?cA?I?EAIAICGAIAW?c@?c@?u@?K?Q?_@?}B?kD@}D??vF@`C@tB{G@zGAdD@rAAj@?bAAz@@b@?d@?H?nCEl@?H?R@B@D?D@F?H@j@?dIAlECR?v@?l@?hA@AyF?g@@aEA}D?[?eCAsA?c@?i@?wA?s@Am@?mD?i@?yA?uAAw@?gA?wA?qB?_A?g@?gA?Y?a@?aBAuA?c@?U?_A?k@AqA?kB?{@@yBAq@?C?O@y@@y@?u@@kA?Q?G@[?q@?sA?_@?[AgA?c@?q@?c@?a@?Q?g@?GAe@@[?SA]?e@?U?m@?i@?mAAi@?]?w@?Q?aA?Y@q@?S?_@?O@u@|A?d@?j@BdA?X@x@?T?N@t@Ap@?ZAV?J?P?H?R?Z?lDCdAAfA?V?`@?~@AH?L?V?" } ] }, "status": "Ok", "message": "" }
Following is a visual representation of the optimized solution on a map. We can see that the solution suggested by optimizer has 2 routes to cover all the jobs and shipments. Vehicle 1 starts from its start points and covers the location of all jobs within the prescribed time windows for each job. It also takes care of the shipment between completing the jobs as the skills required for shipment are possessed by only this vehicle in the given scenario. Whereas, vehicle 2 is assigned to only 2 jobs which are located near its starting point. We also get the summary
of the overall solution as well as for each of the routes
. We can see the overall waiting time is around 30 mins for vehicle 1 which was caused when it was waiting for the delivery time_window of the shipment to start. We also get the route-wise as well as overall cost
of the optimized solution.
Object Overview
Location Object
Locations object - locations
- is used to describe locations that will be used for route optimization. A maximum of 2k locations can be added to this object.
Index | Location |
---|---|
0 | 51.388997,-0.119022 |
1 | 51.391915,-0.103666 |
2 | 51.369777,-0.10438 |
3 | 51.365014,-0.105654 |
4 | 51.351818,-0.014773 |
With respect to the example above, if in the "vehicles" property, the start_index
parameter is set to 2, then 51.369777,-0.10438 would be considered as the starting coordinates for that vehicle.
Job Object
jobs
object describes a particular job or a task that needs to be completed as part of the overall optimization process. It contains various properties of a job such as the job id
, the index of the location where the job needs to be performed, the service duration, multidimensional quantities for pickup and delivery, available time windows, mandatory skills required, the priority of the job, and a description of the job.
Properties of a jobs
object provide important information to the optimization algorithm, such as time constraints and resource requirements for each job, which helps generate an optimized route plan. It is important to note here that all delivery-related amounts for jobs are loaded at vehicle start, while all pickup-related amounts for jobs are brought back to the last stop of the vehicle. Therefore, the vehicles should have appropriate capacity to handle job pickup and deliveries accordingly.
Vehicle Object
The Vehicle object describes the characteristics and constraints of a vehicle that will be used in a multi-vehicle routing problem. Some points to consider about vehicles
object:
-
The users can also set a start or an end location of their choice as long as it is present in the locations object. The vehicle’s start and end locations can be different from job locations.
-
In order to request a round trip, you can specify both the start_index and end_index with the same location index.
-
capacity
parameter describes the maximum multidimensional quantities a vehicle can carry.
Relations Object
relations
object is used to configure relationships between jobs and shipments that should be honored in the optimized solution. With this object users can customize the algorithm to emulate real-world constraints like control the sequence of certain jobs/shipments in the solution or ensure certain jobs/shipments are covered on the same route. It allows you to specify various types of relations and their corresponding constraints for the steps. However when using the relations
object, please be mindful of the following considerations:
-
time_windows
constraints injobs
andshipments
might be violated for thesteps
mentioned in therelations
object. -
Soft constraints parameters like
max_vehicle_overtime
andmax_visit_lateness
will not be available in input requests when therelations
object is used. -
Hard constraint of
max_activity_waiting time
is effective only within_same_route
type of relation. It is not effective for other relation types. -
If certain relations require multiple steps (e.g., jobs) to be on the same route, the
vehicle
assigned to that route must have enough capacity and the required skills to serve all the jobs on the route. The optimization service would return an error, otherwise. -
If a
relations
input requires adelivery
step to occur before apickup
step for ashipment
, an error message is returned, as it violates the shipment's logical order. -
For
shipments
, both thepickup
anddelivery
steps should exist within the samerelations
. An error message is reported if arelations
contains only oneshipment
step.
Sample Relations Object
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
{ "relations": [ { "type": "in_direct_sequence", "steps": [ { "type": "start" }, { "type": "pickup", "id": 25 }, { "type": "job", "id": 3 }, { "type": "delivery", "id": 25 }, { "type": "end" } ], "vehicle": 1 } ] }
Custom Cost Matrix
This feature enables the optimization algorithm to consider a user-defined cost
of traveling between different locations. Users can set the travel_cost
parameter of objective
property to customized
to ensure that the algorithm considers the custom cost values for each traveling between locations.
To utilize the "cost_matrix" object, you need to provide a 2D array with 'n' rows and 'n' columns where n
represents the total number of locations. Each element of the array represents the cost of traveling from one location to another. The optimization algorithm would prefer the routes with lower relative costs over the routes with higher relative costs. Therefore, the custom cost matrix can be used to influence the optimized route that the algorithm returns. For example, if you have three locations (A, B, C), the cost_matrix would be a 3x3 array:
1 2 3 4 5
`cost_matrix`: [ [0, 10, 5], [10, 0, 8], [5, 8, 0] ]
In this example, the first row represents the cost of traveling from location A to location A,A to B & A to C, the second row represents the cost of traveling to different locations starting from point B to A and so on. Subsequently, for the given example, the cost of traveling from location A to B is 10, from A to C is 5, from B to A is 10, from B to C is 8, and so on.
Few points to consider regarding the use of cost_matrix
:
-
The cost values should always be non-negative integers.
-
The cost values do not have any unit. Users can consider the cost of traveling from one location to another as abstract but relative weights.
-
Please ensure to match the index between
locations
andcost_matrix
objects. This means that the costs associated with coordinates at index i inlocations
object should be added in a row at index i in thecost_matrix
object as well. -
Using custom costs for a subset of total locations is not allowed. Either it should be used for all locations or not used at all. To ignore a particular location and prevent it from being included in the optimization, you can assign a very large value to the corresponding row and column in the
cost_matrix
. This ensures that the optimizer avoids that location in the routing solution. -
When the
travel_cost
is set tocustomized
, the optimization algorithm takes the customized cost matrix into account when calculating the overallcost
of a route. -
max_travel_cost
feature allows you to set a maximum travel cost for a route. When a customized cost matrix is used in the optimization request, the total cost of a route is calculated based on the values provided in the customized cost matrix. Themax_travel_cost
feature ensures that the calculated cost of a route does not exceed a specified value. By combining the customization of thecost_matrix
and themax_travel_cost
feature, you can optimize routes based on your desired cost factors while also ensuring that the routes remain within specific cost constraints.
Sample Cost Matrix Object
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
"cost_matrix": [ [ 0, 4, 22, 9999 ], [ 4, 0, 12, 33 ], [ 22, 12, 0, 45 ], [ 9999, 33, 45, 0 ] ]
Multi-Dimensional Parameters
Capacity
The Capacity parameter in Vehicle Object is used to describe multidimensional quantities of capacity. In this context, multi-dimension refers to the fact that a single vehicle can carry loads defined in different units. For example, a vehicle may have a capacity of 10 cubic meters for volume, 1000 kg for weight, and 6 pallets for a number of items. These are three different dimensions of capacity, and each has its own value. By specifying Capacity as an array of integers, we can provide values for each dimension of capacity that a vehicle possesses. This information is then used by the optimization algorithm to ensure that the total capacity required by all shipments assigned to a vehicle does not exceed its capacity in any of the dimensions.
Example: Let's say a construction company has a fleet of trucks that are used to transport multiple things, such as bricks, cement, and even construction workers. Each truck has a different capacity for weight, volume, and number of persons it can carry.
In this case, the capacity parameter can be used to describe the multidimensional quantities for each truck. For example, a truck may have a capacity of 100 kg weight, 10 cubic meters of volume, and can carry 5 construction workers. The capacity parameter can be defined as [100, 10, 5] to represent these values respectively.
By leveraging the capacity in multiple dimensions, the solver can optimize job/shipment assignment to appropriate vehicles ensuring better customer service and efficient transportation.
Amount
Amount parameter in Shipment Object is used to describe multidimensional quantities of a shipment. The term "multi-dimensional" refers to the fact that a single shipment can have amounts defined in different units. Continuing with our example of the construction company above, let’s say a truck needs to pick up 50 kg of bricks, and 2 cubic meters of cement from a construction material supplier’s location. When defining the shipment we define this input as
“amount”: [50,2,0]
0 for the construction worker dimension. Next, if we have another stop to pick up 3 construction worker, then we can define the amount as
“amount”: [0,0,3]
If the other parameters, like distance, time_windows, location of other trucks etc. are favorable then these 2 pickups can be assigned to the same vehicle with “capacity”: [100,10,5] like in this example.
Amount parameter is useful for optimizing delivery routes and determining the most efficient way to transport goods based on multiple dimensions of quantity.
Skills
Skills parameter in the Vehicles Object describes the skills that a driver or vehicle possesses in different units. The term "multi-dimension" refers to the fact that a single driver or vehicle may have different skills or abilities, each of which could be measured in different units or quantities.
For example, let's say we have a fleet of delivery vehicles. One of these vehicles may have the following skills:
-
Skill ID ‘101’: Capacity to carry 10 large boxes
-
Skill ID ‘102’: Ability to transport goods at a temperature of -10 degrees Celsius
-
Skill ID ‘103’: Ability to transport hazardous materials in a specific type of container
In this case, the Skills parameter would be set as an array of integers, with each element corresponding to a particular skill or ability. For instance, the skills parameter for the vehicle described above might be set as follows:
"skills": [101, 102, 103]
Here, the first element (101) corresponds to the vehicle's capacity to carry 10 large boxes, the second element (102) corresponds to its ability to transport goods at a temperature of -10 degrees Celsius, and the third element (103) corresponds to its ability to transport hazardous materials in a specific type of container.
By including skills
attribute in the optimization API, users can optimize their delivery routes based on specific skills and abilities of their drivers and vehicles, helping to ensure that each delivery is made efficiently and safely.
Skills Restrictions
Use skills to describe a problem where not all tasks can be served by all vehicles. Job skills are mandatory, i.e. a job can only be served by a vehicle that has all its required skills. In other words: job j is eligible for vehicle v if j.skills is included in v.skills. This definition implies in particular that:
-
a task without skills can be served by any vehicle;
-
a vehicle without skills can only serve tasks with no particular need (i.e. without skills as well).
-
a job with multiple skills will be assigned to vehicles matching all the skills. The job will not be assigned to vehicles with partially matching skills.
In order to ease modeling problems with no skills required, not providing the skills key defaults to providing an empty array.
API Query Limits
-
Nextbillion.ai allows a maximum rate limit of 300 queries per minute or 5 queries/second for continuous requests.
Note: We can increase the quota if needed on request. Contact support@nextbillion.ai for more details.
-
At any point the maximum number of pending requests that the queue can hold is 25, for a given API key. New requests for the same key can be submitted once some of the pending requests are resolved.
-
A maximum of 2000 locations can be added to the
locations
object -
A maximum of 2000 tasks can be added in an optimization problem. Number of tasks is calculated as number of jobs + 2 * (number of shipments).
-
Maximum value that can be provided for
truck_weight
is 100,000 kg. -
Maximum dimensions for
truck_size
are 5000 cm for length, 5000 cm for width, 1000 cm for height. -
When using
traffic_timestamp
or truck related parameters in therouting
property ofoptions
attribute, please expect a higher request processing time, especially if the number of locations provided in the request is also high.
API Error Codes
Response Code | Description | Additional Notes |
---|---|---|
200 | Normal success case. | Normal success case. |
400 | Input validation failed. | There is a missing or an invalid parameter or a parameter with an invalid value type is added to the request. |
401 | APIKEY not supplied or invalid. | This error occurs when the wrong API key is passed in the request or the key is missing altogether. |
403 | APIKEY is valid but does not have access to requested resources. | You might be querying for a geographical region which is not valid for your account or requesting a service which is not enabled for you. |
404 | Requested host/path not found. | This error occurs when a malformed hostname is used. |
422 | Could not process the request. | A feasible solution could not be generated for the given set of locations or parameter configuration. |
429 | Too many requests. | QPM reached or API request count quota reached. |
500 | Internal Service error. | There was an internal issue with NextBillion.ai services. You can reach out to support@nextbillion.ai for an explanation. |