cuOpt Self-Hosted Thin Client API Example#

Routing Example#

 1from cuopt_sh_client import CuOptServiceSelfHostClient
 2import json
 3
 4data = {"cost_matrix_data": {"data": {"0": [[0,1],[1,0]]}},
 5        "task_data": {"task_locations": [0,1]},
 6        "fleet_data": {"vehicle_locations": [[0,0],[0,0]]}}
 7
 8# If cuOpt is not running on localhost:5000, edit ip and port parameters
 9cuopt_service_client = CuOptServiceSelfHostClient(
10    ip="localhost",
11    port=5000
12)
13
14optimized_routes = cuopt_service_client.get_optimized_routes(data)
15print(json.dumps(optimized_routes, indent=4))

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        "dropped_tasks": {
39            "task_id": [],
40            "task_index": []
41        }
42    }
43},
44"reqId": "ebd378a3-c02a-47f3-b0a1-adec81be7cdd"
45}

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 (pickle is deprecated). A JSON file may optionally be compressed with zlib. More details on the response can be found under responses schema in open-api spec or same can be found in redoc as well.

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 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 and server.key are meant for server, ca.crt is meant for client.

LP Example#

Note

Linear Programming (LP) and Mixed Integer Linear Programming (MILP) is an Early Access feature and is currently open to only select customers.

 1from cuopt_sh_client import CuOptServiceSelfHostClient
 2import json
 3
 4data = {
 5    "csr_constraint_matrix": {
 6        "offsets": [0, 2, 4],
 7        "indices": [0, 1, 0, 1],
 8        "values": [3.0, 4.0, 2.7, 10.1]
 9    },
10    "constraint_bounds": {
11        "upper_bounds": [5.4, 4.9],
12        "lower_bounds": ["ninf", "ninf"]
13    },
14    "objective_data": {
15        "coefficients": [0.2, 0.1],
16        "scalability_factor": 1.0,
17        "offset": 0.0
18    },
19    "variable_bounds": {
20        "upper_bounds": ["inf", "inf"],
21        "lower_bounds": [0.0, 0.0]
22    },
23    "maximize": False,
24    "solver_config": {
25        "tolerances": {
26            "optimality": 0.0001
27        }
28    }
29}
30
31# If cuOpt is not running on localhost:5000, edit ip and port parameters
32cuopt_service_client = CuOptServiceSelfHostClient(
33    ip="localhost",
34    port=5000
35)
36
37solution = cuopt_service_client.get_LP_solve(data, response_type="dict")
38
39
40print("---------- Normal mode ---------------  \n", json.dumps(solution, indent=4))
41
42# For batch mode send list of mps/dict/DataModel
43
44solution = cuopt_service_client.get_LP_solve([data, data], response_type="dict")
45
46print("---------- Batch mode -----------------  \n", json.dumps(solution, indent=4))

response would be as follows,

Normal mode response:

 1{
 2"response": {
 3    "solver_response": {
 4        "status": 1,
 5        "solution": {
 6            "primal_solution": [
 7                0.0,
 8                0.0
 9            ],
10            "dual_solution": [
11                0.0,
12                0.0
13            ],
14            "primal_objective": 0.0,
15            "dual_objective": 0.0,
16            "solver_time": 38.0,
17            "vars": {},
18            "lp_statistics": {
19                "primal_residual": 0.0,
20                "dual_residual": 0.0,
21                "gap": 0.0,
22                "reduced_cost": [
23                    0.2,
24                    0.1
25                ]
26            }
27        }
28    }
29},
30"reqId": "39c52105-736d-4383-a101-707390937141"
31}

Batch mode response:

 1{
 2"response": {
 3    "solver_response": [
 4        {
 5            "status": 1,
 6            "solution": {
 7                "primal_solution": [
 8                    0.0,
 9                    0.0
10                ],
11                "dual_solution": [
12                    0.0,
13                    0.0
14                ],
15                "primal_objective": 0.0,
16                "dual_objective": 0.0,
17                "solver_time": 5.0,
18                "vars": {},
19                "lp_statistics": {
20                    "primal_residual": 0.0,
21                    "dual_residual": 0.0,
22                    "gap": 0.0,
23                    "reduced_cost": [
24                        0.2,
25                        0.1
26                    ]
27                }
28            }
29        },
30        {
31            "status": 1,
32            "solution": {
33                "primal_solution": [
34                    0.0,
35                    0.0
36                ],
37                "dual_solution": [
38                    0.0,
39                    0.0
40                ],
41                "primal_objective": 0.0,
42                "dual_objective": 0.0,
43                "solver_time": 3.0,
44                "vars": {},
45                "lp_statistics": {
46                    "primal_residual": 0.0,
47                    "dual_residual": 0.0,
48                    "gap": 0.0,
49                    "reduced_cost": [
50                        0.2,
51                        0.1
52                    ]
53                }
54            }
55        }
56    ],
57    "total_solve_time": 9.0
58},
59"reqId": "f04a6936-830e-4235-b535-68ad51736ac0"
60}

Example with DataModel is available in the LP example notebook

The data argument to get_LP_solve may be a dictionary of the format shown in LP Open-API spec. More details on the response can be found under responses schema in open-api spec or same can be found in redoc as well.

MILP Example#

Note

Linear Programming (LP) and Mixed Integer Linear Programming (MILP) are Early Access features and are currently open to only select customers.

The major difference between this example and the prior LP example is that some of the variables are integers, so variable_types need to be shared.

 1from cuopt_sh_client import CuOptServiceSelfHostClient
 2import json
 3
 4data = {
 5    "csr_constraint_matrix": {
 6        "offsets": [0, 2],
 7        "indices": [0, 1],
 8        "values": [1.0, 1.0]
 9    },
10    "constraint_bounds": {
11        "upper_bounds": [5000.0],
12        "lower_bounds": [0.0]
13    },
14    "objective_data": {
15        "coefficients": [1.2, 1.7],
16        "scalability_factor": 1.0,
17        "offset": 0.0
18    },
19    "variable_bounds": {
20        "upper_bounds": [3000.0, 5000.0],
21        "lower_bounds": [0.0, 0.0]
22    },
23    "maximize": True,
24    "variable_names": ["x", "y"],
25    "variable_types": ["I", "I"],
26    "solver_config":{
27        "time_limit": 30,
28        "tolerances": {
29            "optimality": 0.0001
30        }
31    }
32}
33
34# If cuOpt is not running on localhost:5000, edit ip and port parameters
35cuopt_service_client = CuOptServiceSelfHostClient(
36    ip="localhost",
37    port=5000
38)
39
40solution = cuopt_service_client.get_LP_solve(data, response_type="dict")
41
42print(json.dumps(solution, indent=4))

response would be as follows,

 1{
 2"response": {
 3    "solver_response": {
 4        "status": 1,
 5        "solution": {
 6            "primal_solution": [
 7                0.0,
 8                0.0
 9            ],
10            "dual_solution": [
11                0.0
12            ],
13            "primal_objective": 0.0,
14            "dual_objective": 0.0,
15            "solver_time": 0.0,
16            "vars": {
17                "x": 0.0,
18                "y": 0.0
19            },
20            "lp_statistics": {
21                "primal_residual": 0.0,
22                "dual_residual": 0.0,
23                "gap": 0.0,
24                "reduced_cost": [
25                    0.0,
26                    0.0
27                ]
28            }
29        }
30    }
31},
32"reqId": "97e61936-e503-423b-b932-709cfac56424"
33}

An example with DataModel is available in the MILP example notebook.

The data argument to get_LP_solve may be a dictionary of the format shown in LP Open-API spec. More details on the response can be found under responses schema in open-api spec or same can be found in redoc as well. The can be of different format as well, please check the documentation.

Aborting a Running Job In Thin Client#

Note

This is only supported in self-hosted

 1from cuopt_sh_client import CuOptServiceSelfHostClient
 2
 3# This is an UUID that is returned by the solver while the solver is trying to find solution so users can come back and check the status or query for results.
 4job_uuid = "<UUID_THAT_WE_GOT>"
 5
 6# If cuOpt is not running on localhost:5000, edit ip and port parameters
 7 cuopt_service_client = CuOptServiceSelfHostClient(
 8     ip="localhost",
 9     port=5000
10 )
11
12 # Delete the job if it is still queued or running
13 response = cuopt_service_client.delete(uuid, running=True, queued=True, cached=False)
14
15 print(response.json())

cuOpt Self-Hosted Thin Client CLI Example#

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
cuopt_sh data.json -i ip -p port

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
    

LP Example#

Note

Linear Programming (LP) and Mixed Integer Linear Programming (MILP) are Early Access features and are currently open to only select customers.

echo '{
    "csr_constraint_matrix": {
        "offsets": [0, 2, 4],
        "indices": [0, 1, 0, 1],
        "values": [3.0, 4.0, 2.7, 10.1]
    },
    "constraint_bounds": {
        "upper_bounds": [5.4, 4.9],
        "lower_bounds": ["ninf", "ninf"]
    },
    "objective_data": {
        "coefficients": [0.2, 0.1],
        "scalability_factor": 1.0,
        "offset": 0.0
    },
    "variable_bounds": {
        "upper_bounds": ["inf", "inf"],
        "lower_bounds": [0.0, 0.0]
    },
    "maximize": "False",
    "solver_config": {
        "tolerances": {
            "optimality": 0.0001
        }
    }
 }' > data.json

Invoke the CLI.

cuopt_sh data.json -t LP -i ip -p port

In the case of batch mode, you can send a bunch of mps files at once, and acquire results. The batch mode works only for mps in the case of CLI.

Note

Batch mode is not available for MILP problems.

 echo "* optimize
*  cost = 0.2 * VAR1 + 0.1 * VAR2
* subject to
*  3 * VAR1 + 4 * VAR2 <= 5.4
*  2.7 * VAR1 + 10.1 * VAR2 <= 4.9
NAME   good-1
ROWS
 N  COST
 L  ROW1
 L  ROW2
COLUMNS
   VAR1      COST      0.2
   VAR1      ROW1      3              ROW2      2.7
   VAR2      COST      0.1
   VAR2      ROW1      4              ROW2      10.1
RHS
   RHS1      ROW1      5.4            ROW2      4.9
ENDATA" > sample.mps

cuopt_sh sample.mps sample.mps sample.mps -t LP -i ip -p port

MILP Example#

The only difference between this example and the prior LP example would be the variable types provided in data.

Note

Linear Programming (LP) and Mixed Integer Linear Programming (MILP) are Early Access features and are currently open to only select customers.

echo '{
   "csr_constraint_matrix": {
       "offsets": [0, 2, 4],
       "indices": [0, 1, 0, 1],
       "values": [3.0, 4.0, 2.7, 10.1]
   },
   "constraint_bounds": {
       "upper_bounds": [5.4, 4.9],
       "lower_bounds": ["ninf", "ninf"]
   },
   "objective_data": {
       "coefficients": [0.2, 0.1],
       "scalability_factor": 1.0,
       "offset": 0.0
   },
   "variable_bounds": {
       "upper_bounds": ["inf", "inf"],
       "lower_bounds": [0.0, 0.0]
   },
   "variable_names": ["x", "y"],
   "variable_types": ["I", "I"],
   "maximize": "False",
   "solver_config": {
       "time_limit": 30,
       "tolerances": {
           "optimality": 0.0001
       }
   }
}' > data.json

Invoke the CLI:

cuopt_sh data.json -t LP -i ip -p port

Note

Batch mode is not supported for MILP.

Aborting a Running Job In CLI#

Note

This is only supported in self-hosted

UUID that is returned by the solver while the solver is trying to find solution so users can come back and check the status or query for results.

This aborts a job with UUID if it’s in running state.

cuopt_sh -d -r -q <UUID>