MILP C API Examples#
Example With Data#
This example demonstrates how to use the MILP solver in C. More details on the API can be found in C API.
The example code is available at ../lp-milp/examples/simple_milp_example.c (download):
1/*
2 * SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3 * SPDX-License-Identifier: Apache-2.0
4 */
5/*
6 * Simple test program for cuOpt MILP solver
7 */
8
9// Include the cuOpt linear programming solver header
10#include <cuopt/linear_programming/cuopt_c.h>
11#include <stdio.h>
12#include <stdlib.h>
13
14// Convert termination status to string
15const char* termination_status_to_string(cuopt_int_t termination_status)
16{
17 switch (termination_status) {
18 case CUOPT_TERIMINATION_STATUS_OPTIMAL:
19 return "Optimal";
20 case CUOPT_TERIMINATION_STATUS_INFEASIBLE:
21 return "Infeasible";
22 case CUOPT_TERIMINATION_STATUS_UNBOUNDED:
23 return "Unbounded";
24 case CUOPT_TERIMINATION_STATUS_ITERATION_LIMIT:
25 return "Iteration limit";
26 case CUOPT_TERIMINATION_STATUS_TIME_LIMIT:
27 return "Time limit";
28 case CUOPT_TERIMINATION_STATUS_NUMERICAL_ERROR:
29 return "Numerical error";
30 case CUOPT_TERIMINATION_STATUS_PRIMAL_FEASIBLE:
31 return "Primal feasible";
32 case CUOPT_TERIMINATION_STATUS_FEASIBLE_FOUND:
33 return "Feasible found";
34 default:
35 return "Unknown";
36 }
37}
38
39// Test simple MILP problem
40cuopt_int_t test_simple_milp()
41{
42 cuOptOptimizationProblem problem = NULL;
43 cuOptSolverSettings settings = NULL;
44 cuOptSolution solution = NULL;
45
46 /* Solve the following MILP:
47 minimize -0.2*x1 + 0.1*x2
48 subject to:
49 3.0*x1 + 4.0*x2 <= 5.4
50 2.7*x1 + 10.1*x2 <= 4.9
51 x1, x2 >= 0
52 x1 is integer
53 x2 is continuous
54 */
55
56 cuopt_int_t num_variables = 2;
57 cuopt_int_t num_constraints = 2;
58 cuopt_int_t nnz = 4;
59
60 // CSR format constraint matrix
61 // https://docs.nvidia.com/nvpl/latest/sparse/storage_format/sparse_matrix.html#compressed-sparse-row-csr
62 // From the constraints:
63 // 3.0*x1 + 4.0*x2 <= 5.4
64 // 2.7*x1 + 10.1*x2 <= 4.9
65 cuopt_int_t row_offsets[] = {0, 2, 4};
66 cuopt_int_t column_indices[] = {0, 1, 0, 1};
67 cuopt_float_t values[] = {3.0, 4.0, 2.7, 10.1};
68
69 // Objective coefficients
70 // From the objective function: minimize -0.2*x1 + 0.1*x2
71 // -0.2 is the coefficient of x1
72 // 0.1 is the coefficient of x2
73 cuopt_float_t objective_coefficients[] = {-0.2, 0.1};
74
75 // Constraint bounds
76 // From the constraints:
77 // 3.0*x1 + 4.0*x2 <= 5.4
78 // 2.7*x1 + 10.1*x2 <= 4.9
79 cuopt_float_t constraint_upper_bounds[] = {5.4, 4.9};
80 cuopt_float_t constraint_lower_bounds[] = {-CUOPT_INFINITY, -CUOPT_INFINITY};
81
82 // Variable bounds
83 // From the constraints:
84 // x1, x2 >= 0
85 cuopt_float_t var_lower_bounds[] = {0.0, 0.0};
86 cuopt_float_t var_upper_bounds[] = {CUOPT_INFINITY, CUOPT_INFINITY};
87
88 // Variable types
89 // x1 is integer
90 // x2 is continuous
91 char variable_types[] = {CUOPT_INTEGER, CUOPT_CONTINUOUS};
92
93 cuopt_int_t status;
94 cuopt_float_t time;
95 cuopt_int_t termination_status;
96 cuopt_float_t objective_value;
97
98 printf("Creating and solving simple MILP problem...\n");
99
100 // Create the problem
101 status = cuOptCreateRangedProblem(num_constraints,
102 num_variables,
103 CUOPT_MINIMIZE,
104 0.0, // objective offset
105 objective_coefficients,
106 row_offsets,
107 column_indices,
108 values,
109 constraint_lower_bounds,
110 constraint_upper_bounds,
111 var_lower_bounds,
112 var_upper_bounds,
113 variable_types,
114 &problem);
115 if (status != CUOPT_SUCCESS) {
116 printf("Error creating problem: %d\n", status);
117 goto DONE;
118 }
119
120 // Create solver settings
121 status = cuOptCreateSolverSettings(&settings);
122 if (status != CUOPT_SUCCESS) {
123 printf("Error creating solver settings: %d\n", status);
124 goto DONE;
125 }
126
127 // Set solver parameters
128 status = cuOptSetFloatParameter(settings, CUOPT_MIP_ABSOLUTE_TOLERANCE, 0.0001);
129 if (status != CUOPT_SUCCESS) {
130 printf("Error setting optimality tolerance: %d\n", status);
131 goto DONE;
132 }
133
134 // Solve the problem
135 status = cuOptSolve(problem, settings, &solution);
136 if (status != CUOPT_SUCCESS) {
137 printf("Error solving problem: %d\n", status);
138 goto DONE;
139 }
140
141 // Get solution information
142 status = cuOptGetSolveTime(solution, &time);
143 if (status != CUOPT_SUCCESS) {
144 printf("Error getting solve time: %d\n", status);
145 goto DONE;
146 }
147
148 status = cuOptGetTerminationStatus(solution, &termination_status);
149 if (status != CUOPT_SUCCESS) {
150 printf("Error getting termination status: %d\n", status);
151 goto DONE;
152 }
153
154 status = cuOptGetObjectiveValue(solution, &objective_value);
155 if (status != CUOPT_SUCCESS) {
156 printf("Error getting objective value: %d\n", status);
157 goto DONE;
158 }
159
160 // Print results
161 printf("\nResults:\n");
162 printf("--------\n");
163 printf("Termination status: %s (%d)\n", termination_status_to_string(termination_status), termination_status);
164 printf("Solve time: %f seconds\n", time);
165 printf("Objective value: %f\n", objective_value);
166
167 // Get and print solution variables
168 cuopt_float_t* solution_values = (cuopt_float_t*)malloc(num_variables * sizeof(cuopt_float_t));
169 if (solution_values == NULL) {
170 printf("Error allocating solution values\n");
171 goto DONE;
172 }
173 status = cuOptGetPrimalSolution(solution, solution_values);
174 if (status != CUOPT_SUCCESS) {
175 printf("Error getting solution values: %d\n", status);
176 free(solution_values);
177 goto DONE;
178 }
179
180 printf("\nSolution: \n");
181 for (cuopt_int_t i = 0; i < num_variables; i++) {
182 printf("x%d = %f\n", i + 1, solution_values[i]);
183 }
184 free(solution_values);
185
186DONE:
187 cuOptDestroyProblem(&problem);
188 cuOptDestroySolverSettings(&settings);
189 cuOptDestroySolution(&solution);
190
191 return status;
192}
193
194int main() {
195 // Run the test
196 cuopt_int_t status = test_simple_milp();
197
198 if (status == CUOPT_SUCCESS) {
199 printf("\nTest completed successfully!\n");
200 return 0;
201 } else {
202 printf("\nTest failed with status: %d\n", status);
203 return 1;
204 }
205}
It is necessary to have the path for include and library dirs ready, if you know the paths, please add them to the path variables directly. Otherwise, run the following commands to find the path and assign it to the path variables. The following commands are for Linux and might fail in cases where the cuopt library is not installed or there are multiple cuopt libraries in the system.
If you have built it locally, libcuopt.so will be in the build directory cpp/build and include directoy would be cpp/include.
# Find the cuopt header file and assign to INCLUDE_PATH
INCLUDE_PATH=$(find / -name "cuopt_c.h" -path "*/linear_programming/*" -printf "%h\n" | sed 's/\/linear_programming//' 2>/dev/null)
# Find the libcuopt library and assign to LIBCUOPT_LIBRARY_PATH
LIBCUOPT_LIBRARY_PATH=$(find / -name "libcuopt.so" 2>/dev/null)
Build and run the example
# Build and run the example
gcc -I $INCLUDE_PATH -L $LIBCUOPT_LIBRARY_PATH -o simple_milp_example simple_milp_example.c -lcuopt
./simple_milp_example
You should see the following output:
Creating and solving simple LP problem...
Solving a problem with 2 constraints 2 variables (1 integers) and 4 nonzeros
Objective offset 0.000000 scaling_factor 1.000000
After trivial presolve updated 2 constraints 2 variables
Running presolve!
After trivial presolve updated 2 constraints 2 variables
Solving LP root relaxation
Scaling matrix. Maximum column norm 1.046542e+00
Dual Simplex Phase 1
Dual feasible solution found.
Dual Simplex Phase 2
Iter Objective Primal Infeas Perturb Time
1 -2.00000000e-01 1.46434160e+00 0.00e+00 0.00
Root relaxation solution found in 2 iterations and 0.00s
Root relaxation objective -2.00000000e-01
Optimal solution found at root node. Objective -2.0000000000000001e-01. Time 0.00.
B&B added a solution to population, solution queue size 0 with objective -0.2
Solution objective: -0.200000 , relative_mip_gap 0.000000 solution_bound -0.200000 presolve_time 0.041144 total_solve_time 0.000000 max constraint violation 0.000000 max int violation 0.000000 max var bounds violation 0.000000 nodes 0 simplex_iterations 0
Results:
--------
Termination status: Optimal (1)
Solve time: 0.000000 seconds
Objective value: -0.200000
Solution:
x1 = 1.000000
x2 = 0.000000
Test completed successfully!
Example With MPS File#
This example demonstrates how to use the cuOpt solver in C to solve an MPS file.
The example code is available at examples/milp_mps_example.c (download):
1/*
2 * SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3 * SPDX-License-Identifier: Apache-2.0
4 */
5/*
6 * Example program for solving MPS files with cuOpt MILP solver
7 */
8
9#include <cuopt/linear_programming/cuopt_c.h>
10#include <stdio.h>
11#include <stdlib.h>
12
13const char* termination_status_to_string(cuopt_int_t termination_status)
14{
15 switch (termination_status) {
16 case CUOPT_TERIMINATION_STATUS_OPTIMAL:
17 return "Optimal";
18 case CUOPT_TERIMINATION_STATUS_INFEASIBLE:
19 return "Infeasible";
20 case CUOPT_TERIMINATION_STATUS_UNBOUNDED:
21 return "Unbounded";
22 case CUOPT_TERIMINATION_STATUS_ITERATION_LIMIT:
23 return "Iteration limit";
24 case CUOPT_TERIMINATION_STATUS_TIME_LIMIT:
25 return "Time limit";
26 case CUOPT_TERIMINATION_STATUS_NUMERICAL_ERROR:
27 return "Numerical error";
28 case CUOPT_TERIMINATION_STATUS_PRIMAL_FEASIBLE:
29 return "Primal feasible";
30 case CUOPT_TERIMINATION_STATUS_FEASIBLE_FOUND:
31 return "Feasible found";
32 default:
33 return "Unknown";
34 }
35}
36
37cuopt_int_t solve_mps_file(const char* filename)
38{
39 cuOptOptimizationProblem problem = NULL;
40 cuOptSolverSettings settings = NULL;
41 cuOptSolution solution = NULL;
42 cuopt_int_t status;
43 cuopt_float_t time;
44 cuopt_int_t termination_status;
45 cuopt_float_t objective_value;
46 cuopt_int_t num_variables;
47 cuopt_float_t* solution_values = NULL;
48
49 printf("Reading and solving MPS file: %s\n", filename);
50
51 // Create the problem from MPS file
52 status = cuOptReadProblem(filename, &problem);
53 if (status != CUOPT_SUCCESS) {
54 printf("Error creating problem from MPS file: %d\n", status);
55 goto DONE;
56 }
57
58 // Get problem size
59 status = cuOptGetNumVariables(problem, &num_variables);
60 if (status != CUOPT_SUCCESS) {
61 printf("Error getting number of variables: %d\n", status);
62 goto DONE;
63 }
64
65 // Create solver settings
66 status = cuOptCreateSolverSettings(&settings);
67 if (status != CUOPT_SUCCESS) {
68 printf("Error creating solver settings: %d\n", status);
69 goto DONE;
70 }
71
72 // Set solver parameters
73 status = cuOptSetFloatParameter(settings, CUOPT_ABSOLUTE_PRIMAL_TOLERANCE, 0.0001);
74 if (status != CUOPT_SUCCESS) {
75 printf("Error setting optimality tolerance: %d\n", status);
76 goto DONE;
77 }
78
79 // Solve the problem
80 status = cuOptSolve(problem, settings, &solution);
81 if (status != CUOPT_SUCCESS) {
82 printf("Error solving problem: %d\n", status);
83 goto DONE;
84 }
85
86 // Get solution information
87 status = cuOptGetSolveTime(solution, &time);
88 if (status != CUOPT_SUCCESS) {
89 printf("Error getting solve time: %d\n", status);
90 goto DONE;
91 }
92
93 status = cuOptGetTerminationStatus(solution, &termination_status);
94 if (status != CUOPT_SUCCESS) {
95 printf("Error getting termination status: %d\n", status);
96 goto DONE;
97 }
98
99 status = cuOptGetObjectiveValue(solution, &objective_value);
100 if (status != CUOPT_SUCCESS) {
101 printf("Error getting objective value: %d\n", status);
102 goto DONE;
103 }
104
105 // Print results
106 printf("\nResults:\n");
107 printf("--------\n");
108 printf("Number of variables: %d\n", num_variables);
109 printf("Termination status: %s (%d)\n", termination_status_to_string(termination_status), termination_status);
110 printf("Solve time: %f seconds\n", time);
111 printf("Objective value: %f\n", objective_value);
112
113 // Get and print solution variables
114 solution_values = (cuopt_float_t*)malloc(num_variables * sizeof(cuopt_float_t));
115 status = cuOptGetPrimalSolution(solution, solution_values);
116 if (status != CUOPT_SUCCESS) {
117 printf("Error getting solution values: %d\n", status);
118 goto DONE;
119 }
120
121 printf("\nSolution: \n");
122 for (cuopt_int_t i = 0; i < num_variables; i++) {
123 printf("x%d = %f\n", i + 1, solution_values[i]);
124 }
125
126DONE:
127 free(solution_values);
128 cuOptDestroyProblem(&problem);
129 cuOptDestroySolverSettings(&settings);
130 cuOptDestroySolution(&solution);
131
132 return status;
133}
134
135int main(int argc, char* argv[]) {
136 if (argc != 2) {
137 printf("Usage: %s <mps_file_path>\n", argv[0]);
138 return 1;
139 }
140
141 // Run the solver
142 cuopt_int_t status = solve_mps_file(argv[1]);
143
144 if (status == CUOPT_SUCCESS) {
145 printf("\nSolver completed successfully!\n");
146 return 0;
147 } else {
148 printf("\nSolver failed with status: %d\n", status);
149 return 1;
150 }
151}
It is necessary to have the path for include and library dirs ready, if you know the paths, please add them to the path variables directly. Otherwise, run the following commands to find the path and assign it to the path variables. The following commands are for Linux and might fail in cases where the cuopt library is not installed or there are multiple cuopt libraries in the system.
If you have built it locally, libcuopt.so will be in the build directory cpp/build and include directoy would be cpp/include.
# Find the cuopt header file and assign to INCLUDE_PATH
INCLUDE_PATH=$(find / -name "cuopt_c.h" -path "*/linear_programming/*" -printf "%h\n" | sed 's/\/linear_programming//' 2>/dev/null)
# Find the libcuopt library and assign to LIBCUOPT_LIBRARY_PATH
LIBCUOPT_LIBRARY_PATH=$(find / -name "libcuopt.so" 2>/dev/null)
A sample MILP MPS file (download mip_sample.mps):
1* Example 2.1 from N & W
2* Optimal solution -28
3NAME EXAMPLE21
4ROWS
5 N OBJ
6 L C1
7 L C2
8 L C3
9COLUMNS
10 MARK0001 'MARKER' 'INTORG'
11 X1 OBJ -7
12 X1 C1 -1
13 X1 C2 5
14 X1 C3 -2
15 X2 OBJ -2
16 X2 C1 2
17 X2 C2 1
18 X2 C3 -2
19 MARK0001 'MARKER' 'INTEND'
20RHS
21 RHS C1 4
22 RHS C2 20
23 RHS C3 -7
24BOUNDS
25 UP BOUND X1 10
26 UP BOUND X2 10
27ENDATA
Build and run the example
# Build and run the example
gcc -I $INCLUDE_PATH -L $LIBCUOPT_LIBRARY_PATH -o milp_mps_example milp_mps_example.c -lcuopt
./milp_mps_example mip_sample.mps
You should see the following output:
Reading and solving MPS file: sample.mps
Solving a problem with 3 constraints 2 variables (2 integers) and 6 nonzeros
Objective offset 0.000000 scaling_factor 1.000000
After trivial presolve updated 3 constraints 2 variables
Running presolve!
After trivial presolve updated 3 constraints 2 variables
Solving LP root relaxation
Scaling matrix. Maximum column norm 1.225464e+00
Dual Simplex Phase 1
Dual feasible solution found.
Dual Simplex Phase 2
Iter Objective Primal Infeas Perturb Time
1 -3.04000000e+01 7.57868205e+00 0.00e+00 0.00
Root relaxation solution found in 3 iterations and 0.00s
Root relaxation objective -3.01818182e+01
Strong branching on 2 fractional variables
| Explored | Unexplored | Objective | Bound | Depth | Iter/Node | Gap | Time
0 1 +inf -3.018182e+01 1 0.0e+00 - 0.00
B 3 1 -2.700000e+01 -2.980000e+01 2 6.7e-01 10.4% 0.00
B&B added a solution to population, solution queue size 0 with objective -27
B 4 0 -2.800000e+01 -2.980000e+01 2 7.5e-01 6.4% 0.00
B&B added a solution to population, solution queue size 1 with objective -28
Explored 4 nodes in 0.00s.
Absolute Gap 0.000000e+00 Objective -2.8000000000000004e+01 Lower Bound -2.8000000000000004e+01
Optimal solution found.
Generated fast solution in 0.136067 seconds with objective -28.000000
Solution objective: -28.000000 , relative_mip_gap 0.000000 solution_bound -28.000000 presolve_time 0.039433 total_solve_time 0.000000 max constraint violation 0.000000 max int violation 0.000000 max var bounds violation 0.000000 nodes 4 simplex_iterations 3
Results:
--------
Number of variables: 2
Termination status: Optimal (1)
Solve time: 0.000000 seconds
Objective value: -28.000000
Solution:
x1 = 4.000000
x2 = 0.000000
Solver completed successfully!