Convex Optimization C API Examples#
LP Example With Data#
This example demonstrates how to use the LP solver in C. More details on the API can be found in C API.
The example code is available at examples/cuopt-c/lp/simple_lp_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 LP C API Example
7 *
8 * This example demonstrates how to use the cuOpt C API for linear programming.
9 *
10 * Problem:
11 * Minimize: -0.2*x1 + 0.1*x2
12 * Subject to:
13 * 3.0*x1 + 4.0*x2 <= 5.4
14 * 2.7*x1 + 10.1*x2 <= 4.9
15 * x1, x2 >= 0
16 *
17 * Expected Output:
18 * Termination status: Optimal (1)
19 * Solve time: 0.000013 seconds
20 * Objective value: -0.360000
21 * x1 = 1.800000
22 * x2 = 0.000000
23 *
24 * Build:
25 * gcc -I $INCLUDE_PATH -L $LIBCUOPT_LIBRARY_PATH -o simple_lp_example simple_lp_example.c -lcuopt
26 *
27 * Run:
28 * ./simple_lp_example
29 */
30
31// Include the cuOpt linear programming solver header
32#include <cuopt/linear_programming/cuopt_c.h>
33#include <stdio.h>
34#include <stdlib.h>
35
36// Convert termination status to string
37const char* termination_status_to_string(cuopt_int_t termination_status)
38{
39 switch (termination_status) {
40 case CUOPT_TERMINATION_STATUS_OPTIMAL:
41 return "Optimal";
42 case CUOPT_TERMINATION_STATUS_INFEASIBLE:
43 return "Infeasible";
44 case CUOPT_TERMINATION_STATUS_UNBOUNDED:
45 return "Unbounded";
46 case CUOPT_TERMINATION_STATUS_ITERATION_LIMIT:
47 return "Iteration limit";
48 case CUOPT_TERMINATION_STATUS_TIME_LIMIT:
49 return "Time limit";
50 case CUOPT_TERMINATION_STATUS_NUMERICAL_ERROR:
51 return "Numerical error";
52 case CUOPT_TERMINATION_STATUS_PRIMAL_FEASIBLE:
53 return "Primal feasible";
54 case CUOPT_TERMINATION_STATUS_FEASIBLE_FOUND:
55 return "Feasible found";
56 default:
57 return "Unknown";
58 }
59}
60
61// Test simple LP problem
62cuopt_int_t test_simple_lp()
63{
64 cuOptOptimizationProblem problem = NULL;
65 cuOptSolverSettings settings = NULL;
66 cuOptSolution solution = NULL;
67
68 /* Solve the following LP:
69 minimize -0.2*x1 + 0.1*x2
70 subject to:
71 3.0*x1 + 4.0*x2 <= 5.4
72 2.7*x1 + 10.1*x2 <= 4.9
73 x1, x2 >= 0
74 */
75
76 cuopt_int_t num_variables = 2;
77 cuopt_int_t num_constraints = 2;
78 cuopt_int_t nnz = 4;
79
80 // CSR format constraint matrix
81 // https://docs.nvidia.com/nvpl/latest/sparse/storage_format/sparse_matrix.html#compressed-sparse-row-csr
82 // From the constraints:
83 // 3.0*x1 + 4.0*x2 <= 5.4
84 // 2.7*x1 + 10.1*x2 <= 4.9
85 cuopt_int_t row_offsets[] = {0, 2, 4};
86 cuopt_int_t column_indices[] = {0, 1, 0, 1};
87 cuopt_float_t values[] = {3.0, 4.0, 2.7, 10.1};
88
89 // Objective coefficients
90 // From the objective function: minimize -0.2*x1 + 0.1*x2
91 // -0.2 is the coefficient of x1
92 // 0.1 is the coefficient of x2
93 cuopt_float_t objective_coefficients[] = {-0.2, 0.1};
94
95 // Constraint bounds
96 // From the constraints:
97 // 3.0*x1 + 4.0*x2 <= 5.4
98 // 2.7*x1 + 10.1*x2 <= 4.9
99 cuopt_float_t constraint_upper_bounds[] = {5.4, 4.9};
100 cuopt_float_t constraint_lower_bounds[] = {-CUOPT_INFINITY, -CUOPT_INFINITY};
101
102 // Variable bounds
103 // From the constraints:
104 // x1, x2 >= 0
105 cuopt_float_t var_lower_bounds[] = {0.0, 0.0};
106 cuopt_float_t var_upper_bounds[] = {CUOPT_INFINITY, CUOPT_INFINITY};
107
108 // Variable types (continuous)
109 // From the constraints:
110 // x1, x2 >= 0
111 char variable_types[] = {CUOPT_CONTINUOUS, CUOPT_CONTINUOUS};
112
113 cuopt_int_t status;
114 cuopt_float_t time;
115 cuopt_int_t termination_status;
116 cuopt_float_t objective_value;
117
118 printf("Creating and solving simple LP problem...\n");
119
120 // Create the problem
121 status = cuOptCreateRangedProblem(num_constraints,
122 num_variables,
123 CUOPT_MINIMIZE,
124 0.0, // objective offset
125 objective_coefficients,
126 row_offsets,
127 column_indices,
128 values,
129 constraint_lower_bounds,
130 constraint_upper_bounds,
131 var_lower_bounds,
132 var_upper_bounds,
133 variable_types,
134 &problem);
135 if (status != CUOPT_SUCCESS) {
136 printf("Error creating problem: %d\n", status);
137 goto DONE;
138 }
139
140 // Create solver settings
141 status = cuOptCreateSolverSettings(&settings);
142 if (status != CUOPT_SUCCESS) {
143 printf("Error creating solver settings: %d\n", status);
144 goto DONE;
145 }
146
147 // Set solver parameters
148 status = cuOptSetFloatParameter(settings, CUOPT_ABSOLUTE_PRIMAL_TOLERANCE, 0.0001);
149 if (status != CUOPT_SUCCESS) {
150 printf("Error setting optimality tolerance: %d\n", status);
151 goto DONE;
152 }
153
154 // Solve the problem
155 status = cuOptSolve(problem, settings, &solution);
156 if (status != CUOPT_SUCCESS) {
157 printf("Error solving problem: %d\n", status);
158 goto DONE;
159 }
160
161 // Get solution information
162 status = cuOptGetSolveTime(solution, &time);
163 if (status != CUOPT_SUCCESS) {
164 printf("Error getting solve time: %d\n", status);
165 goto DONE;
166 }
167
168 status = cuOptGetTerminationStatus(solution, &termination_status);
169 if (status != CUOPT_SUCCESS) {
170 printf("Error getting termination status: %d\n", status);
171 goto DONE;
172 }
173
174 status = cuOptGetObjectiveValue(solution, &objective_value);
175 if (status != CUOPT_SUCCESS) {
176 printf("Error getting objective value: %d\n", status);
177 goto DONE;
178 }
179
180 // Print results
181 printf("\nResults:\n");
182 printf("--------\n");
183 printf("Termination status: %s (%d)\n",
184 termination_status_to_string(termination_status),
185 termination_status);
186 printf("Solve time: %f seconds\n", time);
187 printf("Objective value: %f\n", objective_value);
188
189 // Get and print solution variables
190 cuopt_float_t* solution_values = (cuopt_float_t*)malloc(num_variables * sizeof(cuopt_float_t));
191 if (solution_values == NULL) {
192 printf("Error allocating solution values\n");
193 goto DONE;
194 }
195 status = cuOptGetPrimalSolution(solution, solution_values);
196 if (status != CUOPT_SUCCESS) {
197 printf("Error getting solution values: %d\n", status);
198 free(solution_values);
199 goto DONE;
200 }
201
202 printf("\nPrimal Solution: Solution variables \n");
203 for (cuopt_int_t i = 0; i < num_variables; i++) {
204 printf("x%d = %f\n", i + 1, solution_values[i]);
205 }
206 free(solution_values);
207
208DONE:
209 cuOptDestroyProblem(&problem);
210 cuOptDestroySolverSettings(&settings);
211 cuOptDestroySolution(&solution);
212
213 return status;
214}
215
216int main()
217{
218 // Run the test
219 cuopt_int_t status = test_simple_lp();
220
221 if (status == CUOPT_SUCCESS) {
222 printf("\nTest completed successfully!\n");
223 return 0;
224 } else {
225 printf("\nTest failed with status: %d\n", status);
226 return 1;
227 }
228}
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_lp_example simple_lp_example.c -lcuopt
./simple_lp_example
You should see the following output:
Creating and solving simple LP problem...
Solving a problem with 2 constraints 2 variables (0 integers) and 4 nonzeros
Objective offset 0.000000 scaling_factor 1.000000
Running concurrent
Dual simplex finished in 0.00 seconds
Iter Primal Obj. Dual Obj. Gap Primal Res. Dual Res. Time
0 +0.00000000e+00 +0.00000000e+00 0.00e+00 0.00e+00 2.00e-01 0.011s
PDLP finished
Concurrent time: 0.013s
Solved with dual simplex
Status: Optimal Objective: -3.60000000e-01 Iterations: 1 Time: 0.013s
Results:
--------
Termination status: Optimal (1)
Solve time: 0.000013 seconds
Objective value: -0.360000
Primal Solution: Solution variables
x1 = 1.800000
x2 = 0.000000
Test completed successfully!
LP Example With MPS File#
This example demonstrates how to use the cuOpt linear programming solver in C to solve an MPS file.
The same cuOptReadProblem call also accepts LP format files. The
format is dispatched from the filename extension (case-insensitive):
.lp / .lp.gz / .lp.bz2 → LP parser; .mps / .qps and
their .gz / .bz2 variants → MPS parser. Unknown extensions are
rejected. See LP Example With LP File for an LP counterpart.
The example code is available at examples/cuopt-c/lp/mps_file_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 * MPS File C API Example (LP / QP / QCQP / SOCP)
7 *
8 * This example reads any problem from an MPS file and solves it with the cuOpt C
9 * API. The same program handles problems with
10 * - linear objectives (LP),
11 * - quadratic objectives (QP via a QUADOBJ section), and
12 * - quadratic constraints (QCQP/SOCP via QCMATRIX sections).
13 *
14 *
15 * Example LP problem (from sample.mps):
16 * Minimize: -0.2*VAR1 + 0.1*VAR2
17 * Subject to:
18 * 3*VAR1 + 4*VAR2 <= 5.4
19 * 2.7*VAR1 + 10.1*VAR2 <= 4.9
20 * VAR1, VAR2 >= 0
21 *
22 * Expected Output (sample.mps):
23 * Number of variables: 2
24 * Termination status: Optimal (1)
25 * Solve time: 0.000014 seconds
26 * Objective value: -0.360000
27 * x1 = 1.800000
28 * x2 = 0.000000
29 *
30 * See qp_sample.mps (quadratic objective) and socp_sample.mps (standard and
31 * rotated second-order cone constraints) for QP and SOCP inputs to this same
32 * program.
33 *
34 * Build:
35 * gcc -I $INCLUDE_PATH -L $LIBCUOPT_LIBRARY_PATH -o mps_file_example mps_file_example.c -lcuopt
36 *
37 * Run:
38 * ./mps_file_example sample.mps
39 */
40
41#include <cuopt/linear_programming/cuopt_c.h>
42#include <stdio.h>
43#include <stdlib.h>
44
45const char* termination_status_to_string(cuopt_int_t termination_status)
46{
47 switch (termination_status) {
48 case CUOPT_TERMINATION_STATUS_OPTIMAL:
49 return "Optimal";
50 case CUOPT_TERMINATION_STATUS_INFEASIBLE:
51 return "Infeasible";
52 case CUOPT_TERMINATION_STATUS_UNBOUNDED:
53 return "Unbounded";
54 case CUOPT_TERMINATION_STATUS_ITERATION_LIMIT:
55 return "Iteration limit";
56 case CUOPT_TERMINATION_STATUS_TIME_LIMIT:
57 return "Time limit";
58 case CUOPT_TERMINATION_STATUS_NUMERICAL_ERROR:
59 return "Numerical error";
60 case CUOPT_TERMINATION_STATUS_PRIMAL_FEASIBLE:
61 return "Primal feasible";
62 case CUOPT_TERMINATION_STATUS_FEASIBLE_FOUND:
63 return "Feasible found";
64 default:
65 return "Unknown";
66 }
67}
68
69cuopt_int_t solve_mps_file(const char* filename)
70{
71 cuOptOptimizationProblem problem = NULL;
72 cuOptSolverSettings settings = NULL;
73 cuOptSolution solution = NULL;
74 cuopt_int_t status;
75 cuopt_float_t time;
76 cuopt_int_t termination_status;
77 cuopt_float_t objective_value;
78 cuopt_int_t num_variables;
79 cuopt_float_t* solution_values = NULL;
80
81 printf("Reading and solving MPS file: %s\n", filename);
82
83 // Create the problem from MPS file
84 status = cuOptReadProblem(filename, &problem);
85 if (status != CUOPT_SUCCESS) {
86 printf("Error creating problem from MPS file: %d\n", status);
87 goto DONE;
88 }
89
90 // Get problem size
91 status = cuOptGetNumVariables(problem, &num_variables);
92 if (status != CUOPT_SUCCESS) {
93 printf("Error getting number of variables: %d\n", status);
94 goto DONE;
95 }
96
97 // Create solver settings
98 status = cuOptCreateSolverSettings(&settings);
99 if (status != CUOPT_SUCCESS) {
100 printf("Error creating solver settings: %d\n", status);
101 goto DONE;
102 }
103
104 // Set solver parameters
105 status = cuOptSetFloatParameter(settings, CUOPT_ABSOLUTE_PRIMAL_TOLERANCE, 0.0001);
106 if (status != CUOPT_SUCCESS) {
107 printf("Error setting optimality tolerance: %d\n", status);
108 goto DONE;
109 }
110
111 // Solve the problem
112 status = cuOptSolve(problem, settings, &solution);
113 if (status != CUOPT_SUCCESS) {
114 printf("Error solving problem: %d\n", status);
115 goto DONE;
116 }
117
118 // Get solution information
119 status = cuOptGetSolveTime(solution, &time);
120 if (status != CUOPT_SUCCESS) {
121 printf("Error getting solve time: %d\n", status);
122 goto DONE;
123 }
124
125 status = cuOptGetTerminationStatus(solution, &termination_status);
126 if (status != CUOPT_SUCCESS) {
127 printf("Error getting termination status: %d\n", status);
128 goto DONE;
129 }
130
131 status = cuOptGetObjectiveValue(solution, &objective_value);
132 if (status != CUOPT_SUCCESS) {
133 printf("Error getting objective value: %d\n", status);
134 goto DONE;
135 }
136
137 // Print results
138 printf("\nResults:\n");
139 printf("--------\n");
140 printf("Number of variables: %d\n", num_variables);
141 printf("Termination status: %s (%d)\n",
142 termination_status_to_string(termination_status),
143 termination_status);
144 printf("Solve time: %f seconds\n", time);
145 printf("Objective value: %f\n", objective_value);
146
147 // Get and print solution variables
148 solution_values = (cuopt_float_t*)malloc(num_variables * sizeof(cuopt_float_t));
149 status = cuOptGetPrimalSolution(solution, solution_values);
150 if (status != CUOPT_SUCCESS) {
151 printf("Error getting solution values: %d\n", status);
152 goto DONE;
153 }
154
155 printf("\nPrimal Solution: First 10 solution variables (or fewer if less exist):\n");
156 for (cuopt_int_t i = 0; i < (num_variables < 10 ? num_variables : 10); i++) {
157 printf("x%d = %f\n", i + 1, solution_values[i]);
158 }
159 if (num_variables > 10) {
160 printf("... (showing only first 10 of %d variables)\n", num_variables);
161 }
162
163DONE:
164 free(solution_values);
165 cuOptDestroyProblem(&problem);
166 cuOptDestroySolverSettings(&settings);
167 cuOptDestroySolution(&solution);
168
169 return status;
170}
171
172int main(int argc, char* argv[])
173{
174 if (argc != 2) {
175 printf("Usage: %s <mps_file_path>\n", argv[0]);
176 return 1;
177 }
178
179 // Run the solver
180 cuopt_int_t status = solve_mps_file(argv[1]);
181
182 if (status == CUOPT_SUCCESS) {
183 printf("\nSolver completed successfully!\n");
184 return 0;
185 } else {
186 printf("\nSolver failed with status: %d\n", status);
187 return 1;
188 }
189}
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 MPS file (download sample.mps):
1NAME good-1
2ROWS
3 N COST
4 L ROW1
5 L ROW2
6COLUMNS
7 VAR1 COST -0.2
8 VAR1 ROW1 3 ROW2 2.7
9 VAR2 COST 0.1
10 VAR2 ROW1 4 ROW2 10.1
11RHS
12 RHS1 ROW1 5.4 ROW2 4.9
13ENDATA
Build and run the example
# Build and run the example
gcc -I $INCLUDE_PATH -L $LIBCUOPT_LIBRARY_PATH -o mps_file_example mps_file_example.c -lcuopt
./mps_file_example sample.mps
You should see the following output:
Reading and solving MPS file: sample.mps
Solving a problem with 2 constraints 2 variables (0 integers) and 4 nonzeros
Objective offset 0.000000 scaling_factor 1.000000
Running concurrent
Dual simplex finished in 0.00 seconds
Iter Primal Obj. Dual Obj. Gap Primal Res. Dual Res. Time
0 +0.00000000e+00 +0.00000000e+00 0.00e+00 0.00e+00 2.00e-01 0.012s
PDLP finished
Concurrent time: 0.014s
Solved with dual simplex
Status: Optimal Objective: -3.60000000e-01 Iterations: 1 Time: 0.014s
Results:
--------
Number of variables: 2
Termination status: Optimal (1)
Solve time: 0.000014 seconds
Objective value: -0.360000
Primal Solution: First 10 solution variables (or fewer if less exist):
x1 = 1.800000
x2 = 0.000000
Solver completed successfully!
LP Example With LP File#
cuOptReadProblem also accepts LP format files. The same function is
used — it dispatches on the file extension (case-insensitive):
.lp / .lp.gz / .lp.bz2 → LP parser; .mps / .qps and
their .gz / .bz2 variants → MPS parser; unknown extensions are
rejected. See the read_lp declaration in
cuopt/linear_programming/io/parser.hpp for the supported subset of
the LP format.
The example code is available at examples/cuopt-c/lp/lp_file_example.c (download):
1/*
2 * SPDX-FileCopyrightText: Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3 * SPDX-License-Identifier: Apache-2.0
4 */
5/*
6 * LP File C API Example
7 *
8 * This example demonstrates how to solve an LP problem from an LP format
9 * file using the cuOpt C API. The same ``cuOptReadProblem`` call handles
10 * both MPS and LP inputs — the format is dispatched automatically by the
11 * file extension (case-insensitive): ``.lp`` / ``.lp.gz`` / ``.lp.bz2``
12 * go to the LP parser; ``.mps`` / ``.qps`` and their ``.gz`` / ``.bz2``
13 * variants go to the MPS parser.
14 *
15 * Problem (from LP file):
16 * Minimize: -0.2*VAR1 + 0.1*VAR2
17 * Subject to:
18 * 3*VAR1 + 4*VAR2 <= 5.4
19 * 2.7*VAR1 + 10.1*VAR2 <= 4.9
20 * VAR1, VAR2 >= 0
21 *
22 * Expected Output:
23 * Number of variables: 2
24 * Termination status: Optimal (1)
25 * Objective value: -0.360000
26 * x1 = 1.800000
27 * x2 = 0.000000
28 *
29 * Build:
30 * gcc -I $INCLUDE_PATH -L $LIBCUOPT_LIBRARY_PATH -o lp_file_example lp_file_example.c -lcuopt
31 *
32 * Run:
33 * ./lp_file_example sample.lp
34 */
35
36#include <cuopt/linear_programming/cuopt_c.h>
37#include <stdio.h>
38#include <stdlib.h>
39
40const char* termination_status_to_string(cuopt_int_t termination_status)
41{
42 switch (termination_status) {
43 case CUOPT_TERMINATION_STATUS_OPTIMAL:
44 return "Optimal";
45 case CUOPT_TERMINATION_STATUS_INFEASIBLE:
46 return "Infeasible";
47 case CUOPT_TERMINATION_STATUS_UNBOUNDED:
48 return "Unbounded";
49 case CUOPT_TERMINATION_STATUS_ITERATION_LIMIT:
50 return "Iteration limit";
51 case CUOPT_TERMINATION_STATUS_TIME_LIMIT:
52 return "Time limit";
53 case CUOPT_TERMINATION_STATUS_NUMERICAL_ERROR:
54 return "Numerical error";
55 case CUOPT_TERMINATION_STATUS_PRIMAL_FEASIBLE:
56 return "Primal feasible";
57 case CUOPT_TERMINATION_STATUS_FEASIBLE_FOUND:
58 return "Feasible found";
59 default:
60 return "Unknown";
61 }
62}
63
64cuopt_int_t solve_lp_file(const char* filename)
65{
66 cuOptOptimizationProblem problem = NULL;
67 cuOptSolverSettings settings = NULL;
68 cuOptSolution solution = NULL;
69 cuopt_int_t status;
70 cuopt_float_t time;
71 cuopt_int_t termination_status;
72 cuopt_float_t objective_value;
73 cuopt_int_t num_variables;
74 cuopt_float_t* solution_values = NULL;
75
76 printf("Reading and solving input file: %s\n", filename);
77
78 // Create the problem from the input file. cuOptReadProblem dispatches on
79 // the file extension (case-insensitive): ``.lp`` / ``.lp.gz`` / ``.lp.bz2``
80 // go to the LP parser; ``.mps`` / ``.qps`` and their ``.gz`` / ``.bz2``
81 // variants go to the MPS parser.
82 status = cuOptReadProblem(filename, &problem);
83 if (status != CUOPT_SUCCESS) {
84 printf("Error creating problem from input file: %d\n", status);
85 goto DONE;
86 }
87
88 status = cuOptGetNumVariables(problem, &num_variables);
89 if (status != CUOPT_SUCCESS) {
90 printf("Error getting number of variables: %d\n", status);
91 goto DONE;
92 }
93
94 status = cuOptCreateSolverSettings(&settings);
95 if (status != CUOPT_SUCCESS) {
96 printf("Error creating solver settings: %d\n", status);
97 goto DONE;
98 }
99
100 status = cuOptSetFloatParameter(settings, CUOPT_ABSOLUTE_PRIMAL_TOLERANCE, 0.0001);
101 if (status != CUOPT_SUCCESS) {
102 printf("Error setting optimality tolerance: %d\n", status);
103 goto DONE;
104 }
105
106 status = cuOptSolve(problem, settings, &solution);
107 if (status != CUOPT_SUCCESS) {
108 printf("Error solving problem: %d\n", status);
109 goto DONE;
110 }
111
112 status = cuOptGetSolveTime(solution, &time);
113 if (status != CUOPT_SUCCESS) {
114 printf("Error getting solve time: %d\n", status);
115 goto DONE;
116 }
117
118 status = cuOptGetTerminationStatus(solution, &termination_status);
119 if (status != CUOPT_SUCCESS) {
120 printf("Error getting termination status: %d\n", status);
121 goto DONE;
122 }
123
124 status = cuOptGetObjectiveValue(solution, &objective_value);
125 if (status != CUOPT_SUCCESS) {
126 printf("Error getting objective value: %d\n", status);
127 goto DONE;
128 }
129
130 printf("\nResults:\n");
131 printf("--------\n");
132 printf("Number of variables: %d\n", num_variables);
133 printf("Termination status: %s (%d)\n",
134 termination_status_to_string(termination_status),
135 termination_status);
136 printf("Solve time: %f seconds\n", time);
137 printf("Objective value: %f\n", objective_value);
138
139 solution_values = (cuopt_float_t*)malloc(num_variables * sizeof(cuopt_float_t));
140 status = cuOptGetPrimalSolution(solution, solution_values);
141 if (status != CUOPT_SUCCESS) {
142 printf("Error getting solution values: %d\n", status);
143 goto DONE;
144 }
145
146 printf("\nPrimal Solution: First 10 solution variables (or fewer if less exist):\n");
147 for (cuopt_int_t i = 0; i < (num_variables < 10 ? num_variables : 10); i++) {
148 printf("x%d = %f\n", i + 1, solution_values[i]);
149 }
150 if (num_variables > 10) {
151 printf("... (showing only first 10 of %d variables)\n", num_variables);
152 }
153
154DONE:
155 free(solution_values);
156 cuOptDestroyProblem(&problem);
157 cuOptDestroySolverSettings(&settings);
158 cuOptDestroySolution(&solution);
159
160 return status;
161}
162
163int main(int argc, char* argv[])
164{
165 if (argc != 2) {
166 printf("Usage: %s <lp_or_mps_file_path>\n", argv[0]);
167 return 1;
168 }
169
170 cuopt_int_t status = solve_lp_file(argv[1]);
171
172 if (status == CUOPT_SUCCESS) {
173 printf("\nSolver completed successfully!\n");
174 return 0;
175 } else {
176 printf("\nSolver failed with status: %d\n", status);
177 return 1;
178 }
179}
A sample LP file (download sample.lp),
equivalent to the MPS sample above:
1\ Problem name: good-1
2\ Equivalent to sample.mps in this directory.
3
4Minimize
5 COST: - 0.2 VAR1 + 0.1 VAR2
6Subject To
7 ROW1: 3 VAR1 + 4 VAR2 <= 5.4
8 ROW2: 2.7 VAR1 + 10.1 VAR2 <= 4.9
9End
Build and run the example
gcc -I $INCLUDE_PATH -L $LIBCUOPT_LIBRARY_PATH -o lp_file_example lp_file_example.c -lcuopt
./lp_file_example sample.lp
The output matches the MPS example above (same problem, same objective = -0.36).
Simple Quadratic Programming Example#
This example demonstrates how to use the cuOpt C API for quadratic programming.
The example code is available at examples/cuopt-c/lp/simple_qp_example.c (download):
1/*
2 * SPDX-FileCopyrightText: Copyright (c) 2025-2026, NVIDIA CORPORATION & AFFILIATES. All rights
3 * reserved. SPDX-License-Identifier: Apache-2.0
4 */
5/*
6 * Simple QP C API Example
7 *
8 * This example demonstrates how to use the cuOpt C API for quadratic programming.
9 *
10 * Problem:
11 * Minimize: x^2 + y^2
12 * Subject to:
13 * x + y >= 1
14 * x, y >= 0
15 *
16 *
17 * Build:
18 * gcc -I $INCLUDE_PATH -L $LIBCUOPT_LIBRARY_PATH -o simple_qp_example simple_qp_example.c -lcuopt
19 *
20 * Run:
21 * ./simple_qp_example
22 */
23
24// Include the cuOpt linear programming solver header
25#include <cuopt/linear_programming/cuopt_c.h>
26#include <stdio.h>
27#include <stdlib.h>
28
29// Convert termination status to string
30const char* termination_status_to_string(cuopt_int_t termination_status)
31{
32 switch (termination_status) {
33 case CUOPT_TERMINATION_STATUS_OPTIMAL:
34 return "Optimal";
35 case CUOPT_TERMINATION_STATUS_INFEASIBLE:
36 return "Infeasible";
37 case CUOPT_TERMINATION_STATUS_UNBOUNDED:
38 return "Unbounded";
39 case CUOPT_TERMINATION_STATUS_ITERATION_LIMIT:
40 return "Iteration limit";
41 case CUOPT_TERMINATION_STATUS_TIME_LIMIT:
42 return "Time limit";
43 case CUOPT_TERMINATION_STATUS_NUMERICAL_ERROR:
44 return "Numerical error";
45 case CUOPT_TERMINATION_STATUS_PRIMAL_FEASIBLE:
46 return "Primal feasible";
47 case CUOPT_TERMINATION_STATUS_FEASIBLE_FOUND:
48 return "Feasible found";
49 case CUOPT_TERMINATION_STATUS_UNBOUNDED_OR_INFEASIBLE:
50 return "Unbounded or infeasible";
51 default:
52 return "Unknown";
53 }
54}
55
56// Test simple QP problem
57cuopt_int_t test_simple_qp()
58{
59 cuOptOptimizationProblem problem = NULL;
60 cuOptSolverSettings settings = NULL;
61 cuOptSolution solution = NULL;
62
63 /* Solve the following QP:
64 minimize x^2 + y^2
65 subject to:
66 x + y >= 1
67 x, y >= 0
68 */
69
70 cuopt_int_t num_variables = 2;
71 cuopt_int_t num_constraints = 1;
72 cuopt_int_t nnz = 2;
73
74 // CSR format constraint matrix
75 // https://docs.nvidia.com/nvpl/latest/sparse/storage_format/sparse_matrix.html#compressed-sparse-row-csr
76 cuopt_int_t row_offsets[] = {0, 2};
77 cuopt_int_t column_indices[] = {0, 1};
78 cuopt_float_t values[] = {1.0, 1.0};
79
80 // Objective coefficients
81 // From the objective function: minimize x^2 + y^2
82 // 0 is the coefficient of the linear term on x
83 // 0 is the coefficient of the linear term on y
84 cuopt_float_t linear_objective_coefficients[] = {0.0, 0.0};
85
86 // Quadratic objective matrix
87 // From the objective function: minimize x^2 + y^2
88 // 1 is the coefficient of the quadratic term on x^2
89 // 1 is the coefficient of the quadratic term on y^2
90 cuopt_float_t quadratic_objective_matrix_values[] = {1.0, 1.0};
91 cuopt_int_t quadratic_objective_matrix_row_offsets[] = {0, 1, 2};
92 cuopt_int_t quadratic_objective_matrix_column_indices[] = {0, 1};
93
94 // Constraint bounds
95 // From the constraints:
96 // x + y >= 1
97 cuopt_float_t constraint_rhs[] = {1.0};
98 char constraint_sense[] = {CUOPT_GREATER_THAN};
99
100 // Variable bounds
101 // From the constraints:
102 // x1, x2 >= 0
103 cuopt_float_t var_lower_bounds[] = {0.0, 0.0};
104 cuopt_float_t var_upper_bounds[] = {CUOPT_INFINITY, CUOPT_INFINITY};
105
106 // Variable types (continuous)
107 // From the constraints:
108 // x1, x2 >= 0
109 char variable_types[] = {CUOPT_CONTINUOUS, CUOPT_CONTINUOUS};
110
111 cuopt_int_t status;
112 cuopt_float_t time;
113 cuopt_int_t termination_status;
114 cuopt_float_t objective_value;
115
116 printf("Creating and solving simple QP problem...\n");
117
118 // Create the problem
119 status = cuOptCreateQuadraticProblem(num_constraints,
120 num_variables,
121 CUOPT_MINIMIZE,
122 0.0, // objective offset
123 linear_objective_coefficients,
124 quadratic_objective_matrix_row_offsets,
125 quadratic_objective_matrix_column_indices,
126 quadratic_objective_matrix_values,
127 row_offsets,
128 column_indices,
129 values,
130 constraint_sense,
131 constraint_rhs,
132 var_lower_bounds,
133 var_upper_bounds,
134 &problem);
135 if (status != CUOPT_SUCCESS) {
136 printf("Error creating problem: %d\n", status);
137 goto DONE;
138 }
139
140 // Create solver settings
141 status = cuOptCreateSolverSettings(&settings);
142 if (status != CUOPT_SUCCESS) {
143 printf("Error creating solver settings: %d\n", status);
144 goto DONE;
145 }
146
147 // Solve the problem
148 status = cuOptSolve(problem, settings, &solution);
149 if (status != CUOPT_SUCCESS) {
150 printf("Error solving problem: %d\n", status);
151 goto DONE;
152 }
153
154 // Get solution information
155 status = cuOptGetSolveTime(solution, &time);
156 if (status != CUOPT_SUCCESS) {
157 printf("Error getting solve time: %d\n", status);
158 goto DONE;
159 }
160
161 status = cuOptGetTerminationStatus(solution, &termination_status);
162 if (status != CUOPT_SUCCESS) {
163 printf("Error getting termination status: %d\n", status);
164 goto DONE;
165 }
166
167 status = cuOptGetObjectiveValue(solution, &objective_value);
168 if (status != CUOPT_SUCCESS) {
169 printf("Error getting objective value: %d\n", status);
170 goto DONE;
171 }
172
173 // Print results
174 printf("\nResults:\n");
175 printf("--------\n");
176 printf("Termination status: %s (%d)\n",
177 termination_status_to_string(termination_status),
178 termination_status);
179 printf("Solve time: %f seconds\n", time);
180 printf("Objective value: %f\n", objective_value);
181
182 // Get and print solution variables
183 cuopt_float_t* solution_values = (cuopt_float_t*)malloc(num_variables * sizeof(cuopt_float_t));
184 if (solution_values == NULL) {
185 printf("Error allocating solution values\n");
186 goto DONE;
187 }
188 status = cuOptGetPrimalSolution(solution, solution_values);
189 if (status != CUOPT_SUCCESS) {
190 printf("Error getting solution values: %d\n", status);
191 free(solution_values);
192 goto DONE;
193 }
194
195 printf("\nPrimal Solution: Solution variables \n");
196 for (cuopt_int_t i = 0; i < num_variables; i++) {
197 printf("x%d = %f\n", i + 1, solution_values[i]);
198 }
199 free(solution_values);
200
201DONE:
202 cuOptDestroyProblem(&problem);
203 cuOptDestroySolverSettings(&settings);
204 cuOptDestroySolution(&solution);
205
206 return status;
207}
208
209int main()
210{
211 // Run the test
212 cuopt_int_t status = test_simple_qp();
213
214 if (status == CUOPT_SUCCESS) {
215 printf("\nTest completed successfully!\n");
216 return 0;
217 } else {
218 printf("\nTest failed with status: %d\n", status);
219 return 1;
220 }
221}
Build and run the example
# Build and run the example
gcc -I $INCLUDE_PATH -L $LIBCUOPT_LIBRARY_PATH -o simple_qp_example simple_qp_example.c -lcuopt
./simple_qp_example
You should see the following output:
Creating and solving simple QP problem...
Results:
--------
Termination status: Optimal (1)
Objective value: 0.500000
Primal Solution: Solution variables
x1 = 0.500000
x2 = 0.500000
Test completed successfully!
Simple Second-Order Cone Programming Example#
This example builds an SOCP directly with the C API: a linear problem is created with cuOptCreateProblem(), then a second-order cone constraint is added with cuOptAddQuadraticConstraint(). It minimizes x3 subject to x1 + x2 >= 2 and the cone ||(x1, x2)||_2 <= x3, written as the quadratic inequality x1^2 + x2^2 - x3^2 <= 0. cuOpt detects the second-order cone structure and solves with the barrier method.
The example code is available at examples/cuopt-c/lp/simple_socp_example.c (download):
1/*
2 * SPDX-FileCopyrightText: Copyright (c) 2025-2026, NVIDIA CORPORATION & AFFILIATES. All rights
3 * reserved. SPDX-License-Identifier: Apache-2.0
4 */
5/*
6 * Simple SOCP C API Example
7 *
8 * Demonstrates building a second-order cone program (SOCP) with the cuOpt C API:
9 * a linear problem is created with cuOptCreateProblem, then a quadratic
10 * constraint is added with cuOptAddQuadraticConstraint. cuOpt detects the
11 * second-order cone structure of the quadratic constraint and solves with the
12 * barrier method.
13 *
14 * Problem:
15 * minimize x3
16 * subject to x1 + x2 >= 2
17 * x1^2 + x2^2 - x3^2 <= 0 (i.e. ||(x1, x2)||_2 <= x3)
18 * x3 >= 0, x1, x2 free
19 *
20 * Optimal: x1 = x2 = 1, x3 = sqrt(2) ~= 1.414214, objective ~= 1.414214.
21 *
22 * Build:
23 * gcc -I $INCLUDE_PATH -L $LIBCUOPT_LIBRARY_PATH -o simple_socp_example simple_socp_example.c -lcuopt
24 *
25 * Run:
26 * ./simple_socp_example
27 */
28
29#include <cuopt/linear_programming/cuopt_c.h>
30#include <stdio.h>
31#include <stdlib.h>
32
33// Convert termination status to string
34const char* termination_status_to_string(cuopt_int_t termination_status)
35{
36 switch (termination_status) {
37 case CUOPT_TERMINATION_STATUS_OPTIMAL:
38 return "Optimal";
39 case CUOPT_TERMINATION_STATUS_INFEASIBLE:
40 return "Infeasible";
41 case CUOPT_TERMINATION_STATUS_UNBOUNDED:
42 return "Unbounded";
43 case CUOPT_TERMINATION_STATUS_ITERATION_LIMIT:
44 return "Iteration limit";
45 case CUOPT_TERMINATION_STATUS_TIME_LIMIT:
46 return "Time limit";
47 case CUOPT_TERMINATION_STATUS_NUMERICAL_ERROR:
48 return "Numerical error";
49 default:
50 return "Unknown";
51 }
52}
53
54cuopt_int_t test_simple_socp()
55{
56 cuOptOptimizationProblem problem = NULL;
57 cuOptSolverSettings settings = NULL;
58 cuOptSolution solution = NULL;
59
60 cuopt_int_t num_variables = 3; // x1, x2, x3
61 cuopt_int_t num_constraints = 1; // linear: x1 + x2 >= 2 (the cone is added separately)
62
63 // Linear objective: minimize x3
64 cuopt_float_t objective_coefficients[] = {0.0, 0.0, 1.0};
65
66 // Linear constraint matrix in CSR: row 0 is x1 + x2
67 cuopt_int_t row_offsets[] = {0, 2};
68 cuopt_int_t column_indices[] = {0, 1};
69 cuopt_float_t values[] = {1.0, 1.0};
70 char constraint_sense[] = {CUOPT_GREATER_THAN};
71 cuopt_float_t rhs[] = {2.0};
72
73 // Variable bounds: x1, x2 free; x3 (the cone head) >= 0
74 cuopt_float_t var_lower_bounds[] = {-CUOPT_INFINITY, -CUOPT_INFINITY, 0.0};
75 cuopt_float_t var_upper_bounds[] = {CUOPT_INFINITY, CUOPT_INFINITY, CUOPT_INFINITY};
76 char variable_types[] = {CUOPT_CONTINUOUS, CUOPT_CONTINUOUS, CUOPT_CONTINUOUS};
77
78 // Second-order cone constraint x1^2 + x2^2 - x3^2 <= 0, supplied as the
79 // quadratic matrix Q in coordinate (triplet) form. There is no linear part
80 // and the right-hand side must be 0.
81 cuopt_int_t q_row_index[] = {0, 1, 2};
82 cuopt_int_t q_col_index[] = {0, 1, 2};
83 cuopt_float_t q_coeff[] = {1.0, 1.0, -1.0};
84
85 cuopt_int_t status;
86 cuopt_float_t time;
87 cuopt_int_t termination_status;
88 cuopt_float_t objective_value;
89 cuopt_float_t* solution_values = NULL;
90
91 printf("Creating and solving simple SOCP problem...\n");
92
93 // Create the linear part of the problem
94 status = cuOptCreateProblem(num_constraints,
95 num_variables,
96 CUOPT_MINIMIZE,
97 0.0, // objective offset
98 objective_coefficients,
99 row_offsets,
100 column_indices,
101 values,
102 constraint_sense,
103 rhs,
104 var_lower_bounds,
105 var_upper_bounds,
106 variable_types,
107 &problem);
108 if (status != CUOPT_SUCCESS) {
109 printf("Error creating problem: %d\n", status);
110 goto DONE;
111 }
112
113 // Add the second-order cone constraint (no linear term, rhs = 0)
114 status = cuOptAddQuadraticConstraint(problem,
115 3, // number of quadratic entries
116 q_row_index,
117 q_col_index,
118 q_coeff,
119 0, // number of linear entries
120 NULL, // linear indices
121 NULL, // linear coefficients
122 CUOPT_LESS_THAN,
123 0.0);
124 if (status != CUOPT_SUCCESS) {
125 printf("Error adding quadratic constraint: %d\n", status);
126 goto DONE;
127 }
128
129 status = cuOptCreateSolverSettings(&settings);
130 if (status != CUOPT_SUCCESS) {
131 printf("Error creating solver settings: %d\n", status);
132 goto DONE;
133 }
134
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 status = cuOptGetSolveTime(solution, &time);
142 if (status != CUOPT_SUCCESS) {
143 printf("Error getting solve time: %d\n", status);
144 goto DONE;
145 }
146
147 status = cuOptGetTerminationStatus(solution, &termination_status);
148 if (status != CUOPT_SUCCESS) {
149 printf("Error getting termination status: %d\n", status);
150 goto DONE;
151 }
152
153 status = cuOptGetObjectiveValue(solution, &objective_value);
154 if (status != CUOPT_SUCCESS) {
155 printf("Error getting objective value: %d\n", status);
156 goto DONE;
157 }
158
159 printf("\nResults:\n");
160 printf("--------\n");
161 printf("Termination status: %s (%d)\n",
162 termination_status_to_string(termination_status),
163 termination_status);
164 printf("Solve time: %f seconds\n", time);
165 printf("Objective value: %f\n", objective_value);
166
167 solution_values = (cuopt_float_t*)malloc(num_variables * sizeof(cuopt_float_t));
168 if (solution_values == NULL) {
169 printf("Error allocating solution values\n");
170 goto DONE;
171 }
172 status = cuOptGetPrimalSolution(solution, solution_values);
173 if (status != CUOPT_SUCCESS) {
174 printf("Error getting solution values: %d\n", status);
175 free(solution_values);
176 goto DONE;
177 }
178
179 printf("\nPrimal Solution: Solution variables \n");
180 for (cuopt_int_t i = 0; i < num_variables; i++) {
181 printf("x%d = %f\n", i + 1, solution_values[i]);
182 }
183 free(solution_values);
184
185DONE:
186 cuOptDestroyProblem(&problem);
187 cuOptDestroySolverSettings(&settings);
188 cuOptDestroySolution(&solution);
189
190 return status;
191}
192
193int main()
194{
195 cuopt_int_t status = test_simple_socp();
196
197 if (status == CUOPT_SUCCESS) {
198 printf("\nTest completed successfully!\n");
199 return 0;
200 } else {
201 printf("\nTest failed with status: %d\n", status);
202 return 1;
203 }
204}
Build and run the example
# Build and run the example
gcc -I $INCLUDE_PATH -L $LIBCUOPT_LIBRARY_PATH -o simple_socp_example simple_socp_example.c -lcuopt
./simple_socp_example
The optimum is x1 = x2 = 1 and x3 = sqrt(2):
Creating and solving simple SOCP problem...
Results:
--------
Termination status: Optimal (1)
Objective value: 1.414214
Primal Solution: Solution variables
x1 = 1.000000
x2 = 1.000000
x3 = 1.414214
Test completed successfully!
Note that dual variables are not currently returned for problems with quadratic constraints.
Rotated Second-Order Cone Example#
This example adds a rotated cone with cuOptAddQuadraticConstraint(). The
quadratic matrix Q must be supplied symmetrically, so the cross term of
x1^2 + x2^2 <= x3*x4 is given as the two equal off-diagonal entries
Q[x3, x4] = Q[x4, x3] = -0.5 (triplets (2, 3, -0.5) and (3, 2, -0.5)).
It minimizes x3 + x4 subject to x1 + x2 >= 2 and the rotated cone.
The example code is available at examples/cuopt-c/lp/rotated_socp_example.c (download):
1/*
2 * SPDX-FileCopyrightText: Copyright (c) 2025-2026, NVIDIA CORPORATION & AFFILIATES. All rights
3 * reserved. SPDX-License-Identifier: Apache-2.0
4 */
5/*
6 * Rotated SOCP C API Example
7 *
8 * Demonstrates a rotated second-order cone with the cuOpt C API. A linear
9 * problem is created with cuOptCreateProblem, then a rotated cone is added with
10 * cuOptAddQuadraticConstraint.
11 *
12 * The quadratic matrix Q must be supplied symmetrically: the cross term of a
13 * rotated cone is given as the two equal off-diagonal entries
14 * Q[x3, x4] = Q[x4, x3] = -0.5, so that x^T Q x contributes -x3*x4.
15 *
16 * Problem:
17 * minimize x3 + x4
18 * subject to x1 + x2 >= 2
19 * x1^2 + x2^2 - x3*x4 <= 0
20 * x3 >= 0, x4 >= 0, x1, x2 free
21 *
22 * Optimal: x1 = x2 = 1, x3 = x4 = sqrt(2) ~= 1.414214, objective = 2*sqrt(2) ~= 2.828427.
23 *
24 * Build:
25 * gcc -I $INCLUDE_PATH -L $LIBCUOPT_LIBRARY_PATH -o rotated_socp_example rotated_socp_example.c -lcuopt
26 *
27 * Run:
28 * ./rotated_socp_example
29 */
30
31#include <cuopt/linear_programming/cuopt_c.h>
32#include <stdio.h>
33#include <stdlib.h>
34
35// Convert termination status to string
36const char* termination_status_to_string(cuopt_int_t termination_status)
37{
38 switch (termination_status) {
39 case CUOPT_TERMINATION_STATUS_OPTIMAL:
40 return "Optimal";
41 case CUOPT_TERMINATION_STATUS_INFEASIBLE:
42 return "Infeasible";
43 case CUOPT_TERMINATION_STATUS_UNBOUNDED:
44 return "Unbounded";
45 case CUOPT_TERMINATION_STATUS_ITERATION_LIMIT:
46 return "Iteration limit";
47 case CUOPT_TERMINATION_STATUS_TIME_LIMIT:
48 return "Time limit";
49 case CUOPT_TERMINATION_STATUS_NUMERICAL_ERROR:
50 return "Numerical error";
51 default:
52 return "Unknown";
53 }
54}
55
56cuopt_int_t test_rotated_socp()
57{
58 cuOptOptimizationProblem problem = NULL;
59 cuOptSolverSettings settings = NULL;
60 cuOptSolution solution = NULL;
61
62 cuopt_int_t num_variables = 4; // x1, x2, x3, x4
63 cuopt_int_t num_constraints = 1; // linear: x1 + x2 >= 2 (the cone is added separately)
64
65 // Linear objective: minimize x3 + x4
66 cuopt_float_t objective_coefficients[] = {0.0, 0.0, 1.0, 1.0};
67
68 // Linear constraint matrix in CSR: row 0 is x1 + x2
69 cuopt_int_t row_offsets[] = {0, 2};
70 cuopt_int_t column_indices[] = {0, 1};
71 cuopt_float_t values[] = {1.0, 1.0};
72 char constraint_sense[] = {CUOPT_GREATER_THAN};
73 cuopt_float_t rhs[] = {2.0};
74
75 // Variable bounds: x1, x2 free; x3, x4 (the cone heads) >= 0
76 cuopt_float_t var_lower_bounds[] = {-CUOPT_INFINITY, -CUOPT_INFINITY, 0.0, 0.0};
77 cuopt_float_t var_upper_bounds[] = {
78 CUOPT_INFINITY, CUOPT_INFINITY, CUOPT_INFINITY, CUOPT_INFINITY};
79 char variable_types[] = {
80 CUOPT_CONTINUOUS, CUOPT_CONTINUOUS, CUOPT_CONTINUOUS, CUOPT_CONTINUOUS};
81
82 // Rotated cone x1^2 + x2^2 - x3*x4 <= 0, supplied as a symmetric quadratic
83 // matrix Q in coordinate (triplet) form. The cross term is split into the two
84 // equal off-diagonal entries Q[x3, x4] = Q[x4, x3] = -0.5. rhs must be 0.
85 cuopt_int_t q_row_index[] = {0, 1, 2, 3};
86 cuopt_int_t q_col_index[] = {0, 1, 3, 2};
87 cuopt_float_t q_coeff[] = {1.0, 1.0, -0.5, -0.5};
88
89 cuopt_int_t status;
90 cuopt_float_t time;
91 cuopt_int_t termination_status;
92 cuopt_float_t objective_value;
93 cuopt_float_t* solution_values = NULL;
94
95 printf("Creating and solving rotated SOCP problem...\n");
96
97 // Create the linear part of the problem
98 status = cuOptCreateProblem(num_constraints,
99 num_variables,
100 CUOPT_MINIMIZE,
101 0.0, // objective offset
102 objective_coefficients,
103 row_offsets,
104 column_indices,
105 values,
106 constraint_sense,
107 rhs,
108 var_lower_bounds,
109 var_upper_bounds,
110 variable_types,
111 &problem);
112 if (status != CUOPT_SUCCESS) {
113 printf("Error creating problem: %d\n", status);
114 goto DONE;
115 }
116
117 // Add the rotated second-order cone constraint (no linear term, rhs = 0)
118 status = cuOptAddQuadraticConstraint(problem,
119 4, // number of quadratic entries
120 q_row_index,
121 q_col_index,
122 q_coeff,
123 0, // number of linear entries
124 NULL, // linear indices
125 NULL, // linear coefficients
126 CUOPT_LESS_THAN,
127 0.0);
128 if (status != CUOPT_SUCCESS) {
129 printf("Error adding quadratic constraint: %d\n", status);
130 goto DONE;
131 }
132
133 status = cuOptCreateSolverSettings(&settings);
134 if (status != CUOPT_SUCCESS) {
135 printf("Error creating solver settings: %d\n", status);
136 goto DONE;
137 }
138
139 status = cuOptSolve(problem, settings, &solution);
140 if (status != CUOPT_SUCCESS) {
141 printf("Error solving problem: %d\n", status);
142 goto DONE;
143 }
144
145 status = cuOptGetSolveTime(solution, &time);
146 if (status != CUOPT_SUCCESS) {
147 printf("Error getting solve time: %d\n", status);
148 goto DONE;
149 }
150
151 status = cuOptGetTerminationStatus(solution, &termination_status);
152 if (status != CUOPT_SUCCESS) {
153 printf("Error getting termination status: %d\n", status);
154 goto DONE;
155 }
156
157 status = cuOptGetObjectiveValue(solution, &objective_value);
158 if (status != CUOPT_SUCCESS) {
159 printf("Error getting objective value: %d\n", status);
160 goto DONE;
161 }
162
163 printf("\nResults:\n");
164 printf("--------\n");
165 printf("Termination status: %s (%d)\n",
166 termination_status_to_string(termination_status),
167 termination_status);
168 printf("Solve time: %f seconds\n", time);
169 printf("Objective value: %f\n", objective_value);
170
171 solution_values = (cuopt_float_t*)malloc(num_variables * sizeof(cuopt_float_t));
172 if (solution_values == NULL) {
173 printf("Error allocating solution values\n");
174 goto DONE;
175 }
176 status = cuOptGetPrimalSolution(solution, solution_values);
177 if (status != CUOPT_SUCCESS) {
178 printf("Error getting solution values: %d\n", status);
179 free(solution_values);
180 goto DONE;
181 }
182
183 printf("\nPrimal Solution: Solution variables \n");
184 for (cuopt_int_t i = 0; i < num_variables; i++) {
185 printf("x%d = %f\n", i + 1, solution_values[i]);
186 }
187 free(solution_values);
188
189DONE:
190 cuOptDestroyProblem(&problem);
191 cuOptDestroySolverSettings(&settings);
192 cuOptDestroySolution(&solution);
193
194 return status;
195}
196
197int main()
198{
199 cuopt_int_t status = test_rotated_socp();
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}
Build and run the example
# Build and run the example
gcc -I $INCLUDE_PATH -L $LIBCUOPT_LIBRARY_PATH -o rotated_socp_example rotated_socp_example.c -lcuopt
./rotated_socp_example
The optimum is x1 = x2 = 1 and x3 = x4 = sqrt(2):
Creating and solving rotated SOCP problem...
Results:
--------
Termination status: Optimal (1)
Objective value: 2.828427
Primal Solution: Solution variables
x1 = 1.000000
x2 = 1.000000
x3 = 1.414214
x4 = 1.414214
Test completed successfully!
Note that dual variables are not currently returned for problems with quadratic constraints.
General Convex Quadratic Constraint Example#
This example adds a general convex quadratic constraint with
cuOptAddQuadraticConstraint(). Here we add the convex quadratic constraint
2*x^2 + 2*x*y + 2*y^2 <= 6. Note that the quadratic matrix Q that encodes this
constraint need no be symmetric. Here the term 2*x*y is supplied as a single entry Q[0,1] = 2.
The example code is available at examples/cuopt-c/lp/general_quadratic_example.c (download):
1/*
2 * SPDX-FileCopyrightText: Copyright (c) 2025-2026, NVIDIA CORPORATION & AFFILIATES. All rights
3 * reserved. SPDX-License-Identifier: Apache-2.0
4 */
5/*
6 * General Convex Quadratic Constraint C API Example
7 *
8 * Demonstrates a general convex quadratic constraint x^T Q x + d^T x <= alpha
9 * with the cuOpt C API. A linear problem is created with cuOptCreateProblem,
10 * then the quadratic constraint is added with cuOptAddQuadraticConstraint.
11 *
12 * Q may be any matrix whose symmetric part (Q + Q^T)/2 is positive semidefinite.
13 * Note that Q need not be supplied symmetrically: here the cross term 2*x*y is
14 * given as the single off-diagonal entry Q[0,1] = 2; cuOpt symmetrizes Q
15 * internally automatically.
16 *
17 * Problem:
18 * minimize x + y
19 * subject to x + y >= -5
20 * 2*x^2 + 2*x*y + 2*y^2 <= 6 (general convex quadratic)
21 *
22 * Optimal: x = y = -1, objective = -2.
23 *
24 * Build:
25 * gcc -I $INCLUDE_PATH -L $LIBCUOPT_LIBRARY_PATH -o general_quadratic_example general_quadratic_example.c -lcuopt
26 *
27 * Run:
28 * ./general_quadratic_example
29 */
30
31#include <cuopt/linear_programming/cuopt_c.h>
32#include <stdio.h>
33#include <stdlib.h>
34
35// Convert termination status to string
36const char* termination_status_to_string(cuopt_int_t termination_status)
37{
38 switch (termination_status) {
39 case CUOPT_TERMINATION_STATUS_OPTIMAL:
40 return "Optimal";
41 case CUOPT_TERMINATION_STATUS_INFEASIBLE:
42 return "Infeasible";
43 case CUOPT_TERMINATION_STATUS_UNBOUNDED:
44 return "Unbounded";
45 case CUOPT_TERMINATION_STATUS_ITERATION_LIMIT:
46 return "Iteration limit";
47 case CUOPT_TERMINATION_STATUS_TIME_LIMIT:
48 return "Time limit";
49 case CUOPT_TERMINATION_STATUS_NUMERICAL_ERROR:
50 return "Numerical error";
51 default:
52 return "Unknown";
53 }
54}
55
56cuopt_int_t test_general_quadratic()
57{
58 cuOptOptimizationProblem problem = NULL;
59 cuOptSolverSettings settings = NULL;
60 cuOptSolution solution = NULL;
61
62 cuopt_int_t num_variables = 2; // x, y
63 cuopt_int_t num_constraints = 1; // linear: x + y >= -5 (the quadratic is added separately)
64
65 // Linear objective: minimize x + y
66 cuopt_float_t objective_coefficients[] = {1.0, 1.0};
67
68 // Linear constraint matrix in CSR: row 0 is x + y
69 cuopt_int_t row_offsets[] = {0, 2};
70 cuopt_int_t column_indices[] = {0, 1};
71 cuopt_float_t values[] = {1.0, 1.0};
72 char constraint_sense[] = {CUOPT_GREATER_THAN};
73 cuopt_float_t rhs[] = {-5.0};
74
75 // Variables are free
76 cuopt_float_t var_lower_bounds[] = {-CUOPT_INFINITY, -CUOPT_INFINITY};
77 cuopt_float_t var_upper_bounds[] = {CUOPT_INFINITY, CUOPT_INFINITY};
78 char variable_types[] = {CUOPT_CONTINUOUS, CUOPT_CONTINUOUS};
79
80 // General convex quadratic constraint 2*x^2 + 2*x*y + 2*y^2 <= 6, given as the
81 // quadratic matrix Q in coordinate (triplet) form. The cross term 2*x*y is
82 // supplied as the single entry Q[0,1] = 2 (Q need not be symmetric; cuOpt
83 // symmetrizes it internally).
84 cuopt_int_t q_row_index[] = {0, 1, 0};
85 cuopt_int_t q_col_index[] = {0, 1, 1};
86 cuopt_float_t q_coeff[] = {2.0, 2.0, 2.0};
87
88 cuopt_int_t status;
89 cuopt_float_t time;
90 cuopt_int_t termination_status;
91 cuopt_float_t objective_value;
92 cuopt_float_t* solution_values = NULL;
93
94 printf("Creating and solving general convex quadratic problem...\n");
95
96 // Create the linear part of the problem
97 status = cuOptCreateProblem(num_constraints,
98 num_variables,
99 CUOPT_MINIMIZE,
100 0.0, // objective offset
101 objective_coefficients,
102 row_offsets,
103 column_indices,
104 values,
105 constraint_sense,
106 rhs,
107 var_lower_bounds,
108 var_upper_bounds,
109 variable_types,
110 &problem);
111 if (status != CUOPT_SUCCESS) {
112 printf("Error creating problem: %d\n", status);
113 goto DONE;
114 }
115
116 // Add the general convex quadratic constraint (no linear term, rhs = 6)
117 status = cuOptAddQuadraticConstraint(problem,
118 3, // number of quadratic entries
119 q_row_index,
120 q_col_index,
121 q_coeff,
122 0, // number of linear entries
123 NULL, // linear indices
124 NULL, // linear coefficients
125 CUOPT_LESS_THAN,
126 6.0);
127 if (status != CUOPT_SUCCESS) {
128 printf("Error adding quadratic constraint: %d\n", status);
129 goto DONE;
130 }
131
132 status = cuOptCreateSolverSettings(&settings);
133 if (status != CUOPT_SUCCESS) {
134 printf("Error creating solver settings: %d\n", status);
135 goto DONE;
136 }
137
138 status = cuOptSolve(problem, settings, &solution);
139 if (status != CUOPT_SUCCESS) {
140 printf("Error solving problem: %d\n", status);
141 goto DONE;
142 }
143
144 status = cuOptGetSolveTime(solution, &time);
145 if (status != CUOPT_SUCCESS) {
146 printf("Error getting solve time: %d\n", status);
147 goto DONE;
148 }
149
150 status = cuOptGetTerminationStatus(solution, &termination_status);
151 if (status != CUOPT_SUCCESS) {
152 printf("Error getting termination status: %d\n", status);
153 goto DONE;
154 }
155
156 status = cuOptGetObjectiveValue(solution, &objective_value);
157 if (status != CUOPT_SUCCESS) {
158 printf("Error getting objective value: %d\n", status);
159 goto DONE;
160 }
161
162 printf("\nResults:\n");
163 printf("--------\n");
164 printf("Termination status: %s (%d)\n",
165 termination_status_to_string(termination_status),
166 termination_status);
167 printf("Solve time: %f seconds\n", time);
168 printf("Objective value: %f\n", objective_value);
169
170 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("\nPrimal Solution: Solution variables \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 cuopt_int_t status = test_general_quadratic();
199
200 if (status == CUOPT_SUCCESS) {
201 printf("\nTest completed successfully!\n");
202 return 0;
203 } else {
204 printf("\nTest failed with status: %d\n", status);
205 return 1;
206 }
207}
Build and run the example
# Build and run the example
gcc -I $INCLUDE_PATH -L $LIBCUOPT_LIBRARY_PATH -o general_quadratic_example general_quadratic_example.c -lcuopt
./general_quadratic_example
The optimum is x = y = -1:
Creating and solving general convex quadratic problem...
Results:
--------
Termination status: Optimal (1)
Objective value: -2.000000
Primal Solution: Solution variables
x1 = -1.000000
x2 = -1.000000
Test completed successfully!
QP Example With MPS File#
The same mps_file_example.c program also solves quadratic-objective (QP)
problems. A quadratic objective is supplied through a QUADOBJ section, which
holds the (upper-triangular) entries of the objective matrix Q using the
MPS 1/2 * x^T Q x convention.
A sample QP file (download qp_sample.mps),
which minimizes x^2 + y^2 subject to x + y >= 1:
1NAME QPSAMPLE
2ROWS
3 N OBJ
4 G C1
5COLUMNS
6 X C1 1.0
7 Y C1 1.0
8RHS
9 RHS C1 1.0
10QUADOBJ
11 X X 2.0
12 Y Y 2.0
13ENDATA
Run it with the same binary:
./mps_file_example qp_sample.mps
cuOpt detects the quadratic objective and solves with the barrier method. The
optimum is x = y = 0.5 with objective 0.5:
Reading and solving MPS file: qp_sample.mps
Problem has a quadratic objective. Solving with barrier.
Barrier solver: 1 constraints, 3 variables, 3 nonzeros
Quadratic objective matrix : 2 nonzeros
...
Optimal solution found in 11 iterations and 0.188s
Objective +5.00000008e-01
Barrier finished in 0.19 seconds
Results:
--------
Number of variables: 2
Termination status: Optimal (1)
Solve time: 0.190449 seconds
Objective value: 0.500000
Primal Solution: First 10 solution variables (or fewer if less exist):
x1 = 0.500000
x2 = 0.500000
Solver completed successfully!
SOCP Example With MPS File#
Second-order cone (SOCP) constraints are expressed through QCMATRIX sections
— one per quadratic constraint — each holding the full, symmetric entries of
that constraint’s quadratic matrix with a zero right-hand side. Both standard and
rotated cones are supported; see the SOCP section of
LP/QP/QCQP/SOCP Features for the cone forms.
A sample SOCP file (download socp_sample.mps)
minimizes s + p + q subject to a + b >= 2 and two cones:
standard cone
||(a, b)||_2 <= s(rowQCSTD, writtena^2 + b^2 - s^2 <= 0, s >= 0)rotated cone
a^2 + b^2 <= p * q, p >= 0, q >= 0(rowQCROT)
1NAME SOCPSAMPLE
2ROWS
3 N OBJ
4 G C1
5 L QCSTD
6 L QCROT
7COLUMNS
8 A C1 1.0
9 B C1 1.0
10 S OBJ 1.0
11 P OBJ 1.0
12 Q OBJ 1.0
13RHS
14 RHS C1 2.0
15BOUNDS
16 FR BND A
17 FR BND B
18QCMATRIX QCSTD
19 A A 1.0
20 B B 1.0
21 S S -1.0
22QCMATRIX QCROT
23 A A 1.0
24 B B 1.0
25 P Q -0.5
26 Q P -0.5
27ENDATA
The rotated cone’s cross term is given symmetrically as the two half-entries
P Q -0.5 and Q P -0.5 (so that x^T Q x contributes -p*q). Run it
with the same binary:
./mps_file_example socp_sample.mps
cuOpt detects the quadratic constraints, converts them to second-order cones, and
solves with the barrier method. The optimum is a = b = 1 and
s = p = q = sqrt(2) ≈ 1.414214 with objective 3*sqrt(2) ≈ 4.242641. In the
output below, x1..x5 are a, b, s, p, q in column order:
Reading and solving MPS file: socp_sample.mps
Problem has 2 quadratic constraints. Converting to second-order cones and solving with barrier.
Barrier solver: 5 constraints, 10 variables, 13 nonzeros
Second-order cones : 2
...
Optimal solution found in 9 iterations and 0.126s
Objective +4.24264071e+00
Barrier finished in 0.13 seconds
Results:
--------
Number of variables: 5
Termination status: Optimal (1)
Solve time: 0.128689 seconds
Objective value: 4.242641
Primal Solution: First 10 solution variables (or fewer if less exist):
x1 = 1.000000
x2 = 1.000000
x3 = 1.414214
x4 = 1.414214
x5 = 1.414214
Solver completed successfully!