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:

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:

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:

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):

Output#
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):

Output#
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:

Output#
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:

Output (barrier iteration log abbreviated)#
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 (row QCSTD, written a^2 + b^2 - s^2 <= 0, s >= 0)

  • rotated cone a^2 + b^2 <= p * q, p >= 0, q >= 0 (row QCROT)

 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:

Output (barrier iteration log abbreviated)#
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!