Routing Python Examples#
The following example showcases how to use the CuOptServiceSelfHostClient
to solve a simple routing problem.
The OpenAPI specification for the server is available in open-api spec. The example data is structured as per the OpenAPI specification for the server, please refer OptimizeRoutingData under schema section.
Generic Example#
1from cuopt_sh_client import CuOptServiceSelfHostClient
2import json
3import time
4
5# Example data for routing problem
6# The data is structured as per the OpenAPI specification for the server, please refer /cuopt/request -> schema -> OptimizeRoutingData
7data = {"cost_matrix_data": {"data": {"0": [[0,1],[1,0]]}},
8 "task_data": {"task_locations": [0,1]},
9 "fleet_data": {"vehicle_locations": [[0,0],[0,0]]}}
10
11# If cuOpt is not running on localhost:5000, edit ip and port parameters
12cuopt_service_client = CuOptServiceSelfHostClient(
13 ip="localhost",
14 port=5000,
15 polling_timeout=25,
16 timeout_exception=False
17)
18
19def repoll(solution, repoll_tries):
20 # If solver is still busy solving, the job will be assigned a request id and response is sent back in the
21 # following format {"reqId": <REQUEST-ID>}.
22 # Solver needs to be re-polled for response using this <REQUEST-ID>.
23
24 if "reqId" in solution and "response" not in solution:
25 req_id = solution["reqId"]
26 for i in range(repoll_tries):
27 solution = cuopt_service_client.repoll(req_id, response_type="dict")
28 if "reqId" in solution and "response" in solution:
29 break;
30
31 # Sleep for a second before requesting
32 time.sleep(1)
33
34 return solution
35
36solution = cuopt_service_client.get_optimized_routes(data)
37
38# Number of repoll requests to be carried out for a successful response
39repoll_tries = 500
40
41solution = repoll(solution, repoll_tries)
42
43print(json.dumps(solution, indent=4))
The response would be as follows:
1{ 2"response": { 3 "solver_response": { 4 "status": 0, 5 "num_vehicles": 1, 6 "solution_cost": 2.0, 7 "objective_values": { 8 "cost": 2.0 9 }, 10 "vehicle_data": { 11 "0": { 12 "task_id": [ 13 "Depot", 14 "0", 15 "1", 16 "Depot" 17 ], 18 "arrival_stamp": [ 19 0.0, 20 0.0, 21 0.0, 22 0.0 23 ], 24 "type": [ 25 "Depot", 26 "Delivery", 27 "Delivery", 28 "Depot" 29 ], 30 "route": [ 31 0, 32 0, 33 1, 34 0 35 ] 36 } 37 }, 38 "initial_solutions": [], 39 "dropped_tasks": { 40 "task_id": [], 41 "task_index": [] 42 } 43 }, 44 "total_solve_time": 0.1120915412902832 45}, 46"reqId": "ebd378a3-c02a-47f3-b0a1-adec81be7cdd" 47}
Initial Solution#
Previously run solutions or uploaded solutions can be used as the initial solution for new requests using previously run reqIds as follows:
1from cuopt_sh_client import CuOptServiceSelfHostClient
2import json
3import time
4
5data = {"cost_matrix_data": {"data": {"0": [[0,1],[1,0]]}},
6 "task_data": {"task_locations": [0,1]},
7 "fleet_data": {"vehicle_locations": [[0,0],[0,0]]}}
8
9# If cuOpt is not running on localhost:5000, edit ip and port parameters
10cuopt_service_client = CuOptServiceSelfHostClient(
11 ip="localhost",
12 port=5000,
13 timeout_exception=False
14)
15
16# Get initial solution
17# Set delete_solution to false so it can be used in next request
18initial_solution = cuopt_service_client.get_optimized_routes(
19 data, delete_solution=False
20)
21
22
23# Upload a solution returned/saved from previous request as initial solution
24initial_solution_3 = cuopt_service_client.upload_solution(initial_solution)
25
26# Use previous solution saved in server as initial solution to this request.
27# That solution is referenced with previous request id.
28solution = cuopt_service_client.get_optimized_routes(
29 data,
30 initial_ids=[
31 initial_solution["reqId"],
32 initial_solution_3["reqId"]
33 ]
34)
35
36print(json.dumps(solution, indent=4))
37
38# Delete saved solution if not required to save space
39cuopt_service_client.delete(initial_solution["reqId"])
40cuopt_service_client.delete(initial_solution_3["reqId"])
41
42# Another option is to add a solution that was generated
43# to data model option as follows
44initial_solution_2 = [
45 {
46 "0": {
47 "task_id": ["Depot", "0", "1", "Depot"],
48 "type": ["Depot", "Delivery", "Delivery", "Depot"]
49 }
50 }
51]
52
53data["initial_solution"] = initial_solution_2
54solution = cuopt_service_client.get_optimized_routes(data)
55
56print(json.dumps(solution, indent=4))
The initial solution in the response is not accepted
, because the problem is too small, and the optimal solution is found even before cuOpt could use an initial solution.
The response would be as follows:
1{ 2"response": { 3 "solver_response": { 4 "status": 0, 5 "num_vehicles": 1, 6 "solution_cost": 2.0, 7 "objective_values": { 8 "cost": 2.0 9 }, 10 "vehicle_data": { 11 "0": { 12 "task_id": [ 13 "Depot", 14 "0", 15 "1", 16 "Depot" 17 ], 18 "arrival_stamp": [ 19 0.0, 20 0.0, 21 0.0, 22 0.0 23 ], 24 "type": [ 25 "Depot", 26 "Delivery", 27 "Delivery", 28 "Depot" 29 ], 30 "route": [ 31 0, 32 0, 33 1, 34 0 35 ] 36 } 37 }, 38 "initial_solutions": [ 39 "not accepted", 40 ], 41 "dropped_tasks": { 42 "task_id": [], 43 "task_index": [] 44 } 45 }, 46 "total_solve_time": 0.06160402297973633 47}, 48"reqId": "ebd378a3-c02a-47f3-b0a1-adec81be7cdd" 49}
The data
argument to get_optimized_routes
may be a dictionary of the format shown in Get Routes Open-API spec.
It may also be the path of a file containing such a dictionary as JSON or written using the Python msgpack module.
A JSON file may optionally be compressed with zlib. More details on the responses can be found under the responses schema under request and solution API spec.
To enable HTTPS:
In the case of the server using public certificates, simply enable https.
1from cuopt_sh_client import CuOptServiceSelfHostClient 2 3data = {"cost_matrix_data": {"data": {"0": [[0,1],[1,0]]}}, 4 "task_data": {"task_locations": [0,1]}, 5 "fleet_data": {"vehicle_locations": [[0,0],[0,0]]}} 6 7# If cuOpt is not running on localhost:5000, edit ip and port parameters 8cuopt_service_client = CuOptServiceSelfHostClient( 9 ip="localhost", 10 port=5000, 11 use_https=True 12)
In the case of a self-signed certificate, provide the complete path to the certificate.
1from cuopt_sh_client import CuOptServiceSelfHostClient 2 3data = {"cost_matrix_data": {"data": {"0": [[0,1],[1,0]]}}, 4 "task_data": {"task_locations": [0,1]}, 5 "fleet_data": {"vehicle_locations": [[0,0],[0,0]]}} 6 7# If cuOpt is not running on localhost:5000, edit ip and port parameters 8cuopt_service_client = CuOptServiceSelfHostClient( 9 ip="localhost", 10 port=5000, 11 use_https=True, 12 self_signed_cert=/complete/path/to/certificate 13)
You can generate a self-signed certificate easily as follows:
openssl genrsa -out ca.key 2048 openssl req -new -x509 -days 365 -key ca.key -subj "/C=CN/ST=GD/L=SZ/O=Acme, Inc./CN=Acme Root CA" -out ca.crt openssl req -newkey rsa:2048 -nodes -keyout server.key -subj "/C=CN/ST=GD/L=SZ/O=Acme, Inc./CN=*.example.com" -out server.csr openssl x509 -req -extfile <(printf "subjectAltName=DNS:example.com,DNS:www.example.com") -days 365 -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt
server.crt
andserver.key
are meant for server,ca.crt
is meant for client.
More examples are available in the Examples Notebooks Repository.
Aborting a Running Job in Thin Client#
Please refer to the MILP Example on Aborting a Running Job in Thin Client for more details.
Routing CLI Examples#
Create a data.json
file containing this sample data:
Routing Example#
echo '{"cost_matrix_data": {"data": {"0": [[0, 1], [1, 0]]}},
"task_data": {"task_locations": [0, 1]},
"fleet_data": {"vehicle_locations": [[0, 0], [0, 0]]}}' > data.json
Invoke the CLI.
# client's default ip address for cuOpt is localhost:5000 if ip/port are not specified
export ip="localhost"
export port=5000
cuopt_sh data.json -i $ip -p $port
Initial Solution in CLI#
To use a previous solution as an initial solution for a new request ID, you are required to save the previous solution, which can be accomplished use option -k
. Use the previous reqId in the next request as follows:
# Please update ip and port if the server is running on a different IP address or port
export ip="localhost"
export port=5000
reqId=$(cuopt_sh data.json -i $ip -p $port -k | sed "s/'/\"/g" | jq -r '.reqId')
cuopt_sh data.json -i $ip -p $port -id $reqId
# delete previous saved solutions using follwing command
cuopt_sh -i $ip -p $port -d $reqId
Uploading a Solution#
Users can also upload a solution which might have been saved for later runs.
# Please update ip and port if the server is running on a different IP address or port
export ip="localhost"
export port=5000
# Save solution to a file
cuopt_sh data.json -i $ip -p $port | sed "s/'/\"/g" > solution.json
# Upload the solution and get request-id generated for that
reqId=$(cuopt_sh solution.json -us -i $ip -p $port | sed "s/'/\"/g" | jq -r '.reqId')
# Use this request id for initial solution
cuopt_sh data.json -i $ip -p $port -id $reqId
# delete previous saved solutions using follwing command
cuopt_sh -i $ip -p $port -ds $reqId
Aborting a Running Job In CLI#
Please refer to the MILP Example for more details.
Note
Please use solver settings while using .mps files.
To enable HTTPS#
In the case of the server using public certificates, simply enable https.
cuopt_sh data.json -s -i $ip -p $port
In the case of a self-signed certificate, provide the complete path to the certificate.
cuopt_sh data.json -s -c /complete/path/to/certificate -i $ip -p $port