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-2026, 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_TERMINATION_STATUS_OPTIMAL:
19 return "Optimal";
20 case CUOPT_TERMINATION_STATUS_INFEASIBLE:
21 return "Infeasible";
22 case CUOPT_TERMINATION_STATUS_UNBOUNDED:
23 return "Unbounded";
24 case CUOPT_TERMINATION_STATUS_ITERATION_LIMIT:
25 return "Iteration limit";
26 case CUOPT_TERMINATION_STATUS_TIME_LIMIT:
27 return "Time limit";
28 case CUOPT_TERMINATION_STATUS_NUMERICAL_ERROR:
29 return "Numerical error";
30 case CUOPT_TERMINATION_STATUS_PRIMAL_FEASIBLE:
31 return "Primal feasible";
32 case CUOPT_TERMINATION_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",
164 termination_status_to_string(termination_status),
165 termination_status);
166 printf("Solve time: %f seconds\n", time);
167 printf("Objective value: %f\n", objective_value);
168
169 // Get and print solution variables
170 cuopt_float_t* solution_values = (cuopt_float_t*)malloc(num_variables * sizeof(cuopt_float_t));
171 if (solution_values == NULL) {
172 printf("Error allocating solution values\n");
173 goto DONE;
174 }
175 status = cuOptGetPrimalSolution(solution, solution_values);
176 if (status != CUOPT_SUCCESS) {
177 printf("Error getting solution values: %d\n", status);
178 free(solution_values);
179 goto DONE;
180 }
181
182 printf("\nSolution: \n");
183 for (cuopt_int_t i = 0; i < num_variables; i++) {
184 printf("x%d = %f\n", i + 1, solution_values[i]);
185 }
186 free(solution_values);
187
188DONE:
189 cuOptDestroyProblem(&problem);
190 cuOptDestroySolverSettings(&settings);
191 cuOptDestroySolution(&solution);
192
193 return status;
194}
195
196int main()
197{
198 // Run the test
199 cuopt_int_t status = test_simple_milp();
200
201 if (status == CUOPT_SUCCESS) {
202 printf("\nTest completed successfully!\n");
203 return 0;
204 } else {
205 printf("\nTest failed with status: %d\n", status);
206 return 1;
207 }
208}
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-2026, 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_TERMINATION_STATUS_OPTIMAL:
17 return "Optimal";
18 case CUOPT_TERMINATION_STATUS_INFEASIBLE:
19 return "Infeasible";
20 case CUOPT_TERMINATION_STATUS_UNBOUNDED:
21 return "Unbounded";
22 case CUOPT_TERMINATION_STATUS_ITERATION_LIMIT:
23 return "Iteration limit";
24 case CUOPT_TERMINATION_STATUS_TIME_LIMIT:
25 return "Time limit";
26 case CUOPT_TERMINATION_STATUS_NUMERICAL_ERROR:
27 return "Numerical error";
28 case CUOPT_TERMINATION_STATUS_PRIMAL_FEASIBLE:
29 return "Primal feasible";
30 case CUOPT_TERMINATION_STATUS_FEASIBLE_FOUND:
31 return "Feasible found";
32 case CUOPT_TERMINATION_STATUS_UNBOUNDED_OR_INFEASIBLE:
33 return "Unbounded or infeasible";
34 default:
35 return "Unknown";
36 }
37}
38
39cuopt_int_t solve_mps_file(const char* filename)
40{
41 cuOptOptimizationProblem problem = NULL;
42 cuOptSolverSettings settings = NULL;
43 cuOptSolution solution = NULL;
44 cuopt_int_t status;
45 cuopt_float_t time;
46 cuopt_int_t termination_status;
47 cuopt_float_t objective_value;
48 cuopt_int_t num_variables;
49 cuopt_float_t* solution_values = NULL;
50
51 printf("Reading and solving MPS file: %s\n", filename);
52
53 // Create the problem from MPS file
54 status = cuOptReadProblem(filename, &problem);
55 if (status != CUOPT_SUCCESS) {
56 printf("Error creating problem from MPS file: %d\n", status);
57 goto DONE;
58 }
59
60 // Get problem size
61 status = cuOptGetNumVariables(problem, &num_variables);
62 if (status != CUOPT_SUCCESS) {
63 printf("Error getting number of variables: %d\n", status);
64 goto DONE;
65 }
66
67 // Create solver settings
68 status = cuOptCreateSolverSettings(&settings);
69 if (status != CUOPT_SUCCESS) {
70 printf("Error creating solver settings: %d\n", status);
71 goto DONE;
72 }
73
74 // Set solver parameters
75 status = cuOptSetFloatParameter(settings, CUOPT_ABSOLUTE_PRIMAL_TOLERANCE, 0.0001);
76 if (status != CUOPT_SUCCESS) {
77 printf("Error setting optimality tolerance: %d\n", status);
78 goto DONE;
79 }
80
81 // Solve the problem
82 status = cuOptSolve(problem, settings, &solution);
83 if (status != CUOPT_SUCCESS) {
84 printf("Error solving problem: %d\n", status);
85 goto DONE;
86 }
87
88 // Get solution information
89 status = cuOptGetSolveTime(solution, &time);
90 if (status != CUOPT_SUCCESS) {
91 printf("Error getting solve time: %d\n", status);
92 goto DONE;
93 }
94
95 status = cuOptGetTerminationStatus(solution, &termination_status);
96 if (status != CUOPT_SUCCESS) {
97 printf("Error getting termination status: %d\n", status);
98 goto DONE;
99 }
100
101 const int has_primal_solution =
102 termination_status == CUOPT_TERMINATION_STATUS_OPTIMAL ||
103 termination_status == CUOPT_TERMINATION_STATUS_PRIMAL_FEASIBLE ||
104 termination_status == CUOPT_TERMINATION_STATUS_FEASIBLE_FOUND;
105
106 if (has_primal_solution) {
107 status = cuOptGetObjectiveValue(solution, &objective_value);
108 if (status != CUOPT_SUCCESS) {
109 printf("Error getting objective value: %d\n", status);
110 goto DONE;
111 }
112 }
113
114 // Print results
115 printf("\nResults:\n");
116 printf("--------\n");
117 printf("Number of variables: %d\n", num_variables);
118 printf("Termination status: %s (%d)\n",
119 termination_status_to_string(termination_status),
120 termination_status);
121 printf("Solve time: %f seconds\n", time);
122 printf("Objective value: %f\n", objective_value);
123
124 // Get and print solution variables
125 if (has_primal_solution) {
126 solution_values = (cuopt_float_t*)malloc(num_variables * sizeof(cuopt_float_t));
127 status = cuOptGetPrimalSolution(solution, solution_values);
128 if (status != CUOPT_SUCCESS) {
129 printf("Error getting solution values: %d\n", status);
130 goto DONE;
131 }
132 }
133
134 printf("\nSolution: \n");
135 for (cuopt_int_t i = 0; i < num_variables; i++) {
136 printf("x%d = %f\n", i + 1, solution_values[i]);
137 }
138
139DONE:
140 if (solution_values != NULL) {
141 free(solution_values);
142 }
143 cuOptDestroyProblem(&problem);
144 cuOptDestroySolverSettings(&settings);
145 cuOptDestroySolution(&solution);
146
147 return status;
148}
149
150int main(int argc, char* argv[])
151{
152 if (argc != 2) {
153 printf("Usage: %s <mps_file_path>\n", argv[0]);
154 return 1;
155 }
156
157 // Run the solver
158 cuopt_int_t status = solve_mps_file(argv[1]);
159
160 if (status == CUOPT_SUCCESS) {
161 printf("\nSolver completed successfully!\n");
162 return 0;
163 } else {
164 printf("\nSolver failed with status: %d\n", status);
165 return 1;
166 }
167}
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!