Claude Cursor Skill

cuopt-numerical-optimization-api

LP, MILP, and QP (beta) with cuOpt — Python, C, and CLI. Use when the user is solving LP, MILP, or QP with any cuOpt interface.

LLM Mart · 0 points · 0 views 0 listing impressions 0 install-command copies
Virus-scanned Reviewed automatically before listing.

Full trust report

Download nvidia-skills-skills_cuopt-numerical-optimization-api-d8519c5.zip · 53 KB
nvidia/skills 3445 416 forks Apache-2.0 Updated 1d ago
Part of nvidia/skills — 26 skills

Install

skills CLI npx skills add https://github.com/NVIDIA/skills/tree/main/skills/cuopt-numerical-optimization-api
Claude Code claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install nvidia-skills@llmmart
Git git clone https://github.com/NVIDIA/skills.git

The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole nvidia/skills collection as a plugin from our marketplace. Git is the plain clone.

Skill manifest

cuOpt Numerical Optimization API

Model and solve LP, MILP, and QP problems using NVIDIA cuOpt's GPU-accelerated solver.

Interface Selection

Choose the reference for the user's interface:

Interface When to use Reference
Python User is writing Python code references/python_api.md
C / C++ User is embedding in a C/C++ application references/c_api.md
CLI User is solving from MPS files on the command line references/cli_api.md

If the interface is not yet clear, ask before writing any code.

Already using a modeling language? cuOpt also works as a solver backend for third-party modeling tools — AMPL, GAMS / GAMSPy, PuLP, JuMP, Pyomo, and CVXPY — with near-zero code changes (point the model's solver at cuOpt). CVXPY additionally covers convex QP and, in beta, QCQP / SOCP. Prefer this when the user already has a model in one of these tools rather than porting it to the cuOpt API. See Third-Party Modeling Languages.

Choosing LP vs MILP vs QP

Decide from the objective and variables:

If the objective is... And variables are... Use
Linear (sum of c_i * x_i) All continuous LP
Linear Some integer or binary MILP
Has squared (x*x) or cross (x*y) terms Continuous (integer QP not supported) QP (beta)

Prefer LP when the problem allows it. LP solves faster and has stronger optimality guarantees. Use MILP only when the problem logically requires whole numbers or yes/no decisions. Use QP only when the objective is genuinely quadratic (variance, squared error, kinetic energy).

  • Use LP when every quantity can meaningfully be fractional: flows, proportions, rates, dollars, hours, tonnes of material, etc.
  • Use MILP when the problem mentions counts of discrete entities, yes/no choices, or either/or decisions (e.g. open a facility or not, assign a person to a shift, number of trucks).
  • Use QP when the objective minimizes variance, squared error, or any expression with x*x or x*y terms (portfolio optimization, least squares, regularized regression).

Integer vs Continuous from Wording

Problem wording / concept Variable type Examples
Discrete entities (counts) INTEGER Workers, cars, trucks, machines, pilots, facilities, units to manufacture
Yes/no or on/off INTEGER (binary, lb=0 ub=1) Open a facility, run a machine, assign a person to a shift
Amounts that can be fractional CONTINUOUS Tonnes, litres, dollars, hours, kWh, proportion of capacity
Rates or fractions CONTINUOUS Utilization, percentage, share of budget

Rule of thumb: "How many things" → INTEGER. "How much" → CONTINUOUS.

QP Rules (all interfaces)

  • MINIMIZE only — the solver rejects MAXIMIZE for quadratic objectives. To maximize f(x), minimize -f(x) and negate the reported objective value.
  • Continuous variables only — integer QP is not supported.
  • Q should be positive semi-definite for a convex, well-posed problem.
  • Beta — API may evolve; treat as production-capable for typical convex QP.

Dual Values

Duals and reduced costs are available for LP and QP only:

  • MILP — no duals (integer optima are not continuous).
  • Quadratic constraints — duals unavailable even for LP/QP; all values return NaN.
  • PDLP warmstart — LP only; MILP solves do not accept a PDLP warmstart.

Common Issues (all interfaces)

Problem Likely cause Fix
Infeasible Conflicting constraints Check constraint logic and bounds
Unbounded Missing bounds Add variable bounds
Slow solve Large problem Set time limit; increase gap tolerance
QP rejected with MAXIMIZE QP only supports MINIMIZE Negate the objective; negate the result
QP returns non-optimal Q not PSD or badly scaled Check Q is PSD; rescale variables

Solver Settings (concepts)

Setting Purpose
time_limit Stop after N seconds
mip_relative_gap Stop MILP when within X% of optimal
mip_absolute_tolerance Absolute MIP gap stop
log_to_console Enable solver logging

Syntax varies by interface — see the interface reference file.

Files (skills)
  • assets
    • c
      • lp_basic
        • lp_simple.c 3.6 KB · in bundle
        • README.md 466 B
          # Simple LP (C API)
          
          Minimize `-0.2*x1 + 0.1*x2` subject to:
          - `3*x1 + 4*x2 <= 5.4`
          - `2.7*x1 + 10.1*x2 <= 4.9`
          - `x1, x2 >= 0`
          
          **Build:** From repo root or skill dir, with cuOpt on `INCLUDE_PATH` and `LIB_PATH`:
          
          ```bash
          gcc -I${INCLUDE_PATH} -L${LIB_PATH} -o lp_simple lp_simple.c -lcuopt
          LD_LIBRARY_PATH=${LIB_PATH}:$LD_LIBRARY_PATH ./lp_simple
          ```
          
          **See also:** [references/examples.md](../../references/examples.md) for parameter constants and more examples.
          
      • lp_duals
        • lp_duals.c 4 KB · in bundle
        • README.md 500 B
          # LP duals and reduced costs (C API)
          
          Retrieve dual values (shadow prices) and reduced costs after solving an LP.
          
          **Problem:** Minimize 3x + 2y + 5z subject to x + y + z = 4, 2x + y + z = 5, x, y, z ≥ 0.
          
          **Build:** With cuOpt on `INCLUDE_PATH` and `LIB_PATH`:
          
          ```bash
          gcc -I${INCLUDE_PATH} -L${LIB_PATH} -o lp_duals lp_duals.c -lcuopt
          LD_LIBRARY_PATH=${LIB_PATH}:$LD_LIBRARY_PATH ./lp_duals
          ```
          
          **See also:** [references/examples.md](../../references/examples.md) for full parameter reference.
          
      • lp_warmstart
        • README.md 289 B
          # LP PDLP warmstart (C API)
          
          PDLP warmstart: use solution data from a solved LP to solve a similar problem faster. LP only (not MILP).
          
          Warmstart is not demonstrated in these C assets. See repo docs (e.g. `docs/cuopt/source/cuopt-c/lp-qp-milp/`) and headers for C-level warmstart support.
          
      • milp_basic
        • milp_simple.c 3.4 KB · in bundle
        • README.md 405 B
          # Simple MILP (C API)
          
          Same as LP but `x1` is integer. Demonstrates variable types and MIP parameters.
          
          **Build:** With cuOpt on `INCLUDE_PATH` and `LIB_PATH`:
          
          ```bash
          gcc -I${INCLUDE_PATH} -L${LIB_PATH} -o milp_simple milp_simple.c -lcuopt
          LD_LIBRARY_PATH=${LIB_PATH}:$LD_LIBRARY_PATH ./milp_simple
          ```
          
          **See also:** [references/examples.md](../../references/examples.md) for full parameter reference.
          
      • milp_production_planning
        • milp_production.c 3.5 KB · in bundle
        • README.md 459 B
          # Production planning MILP (C API)
          
          Two products (A, B), resource limits (machine time, labor, material), minimum production, maximize profit.
          
          **Build:** With cuOpt on `INCLUDE_PATH` and `LIB_PATH`:
          
          ```bash
          gcc -I${INCLUDE_PATH} -L${LIB_PATH} -o milp_production milp_production.c -lcuopt
          LD_LIBRARY_PATH=${LIB_PATH}:$LD_LIBRARY_PATH ./milp_production
          ```
          
          **See also:** [references/examples.md](../../references/examples.md) for parameters and MIP options.
          
      • mps_solver
        • data
          • sample.mps 490 B · in bundle
        • mps_solver.c 3.4 KB · in bundle
        • README.md 590 B
          # MPS file solver (C API)
          
          Read and solve LP/MILP from a standard MPS file using `cuOptReadProblem`.
          
          **Build:** With cuOpt on `INCLUDE_PATH` and `LIB_PATH`:
          
          ```bash
          gcc -I${INCLUDE_PATH} -L${LIB_PATH} -o mps_solver mps_solver.c -lcuopt
          LD_LIBRARY_PATH=${LIB_PATH}:$LD_LIBRARY_PATH ./mps_solver data/sample.mps
          ```
          
          **Data:** `data/sample.mps` is a small LP (two variables, two constraints). Use any MPS file path as the first argument.
          
          **See also:** [references/examples.md](../../references/examples.md); repo example `docs/cuopt/source/cuopt-c/lp-qp-milp/examples/mps_file_example.c`.
          
      • README.md 1.7 KB
        # Assets — reference C examples
        
        LP/MILP C API reference implementations. Use as reference when building new applications; do not edit in place. Build requires cuOpt installed (include and lib paths set).
        
        | Example | Type | Description |
        |---------|------|-------------|
        | [lp_basic](lp_basic/) | LP | Simple LP: create problem, solve, get solution |
        | [lp_duals](lp_duals/) | LP | Dual values and reduced costs |
        | [lp_warmstart](lp_warmstart/) | LP | PDLP warmstart (see README) |
        | [milp_basic](milp_basic/) | MILP | Simple MILP with integer variable |
        | [milp_production_planning](milp_production_planning/) | MILP | Production planning with resource constraints |
        | [mps_solver](mps_solver/) | LP/MILP | Solve from MPS file via `cuOptReadProblem` |
        
        ## Build and run
        
        Set include and library paths, then build and run.
        
        **Using conda:** Activate your cuOpt env first (`conda activate cuopt`), then:
        
        ```bash
        # Paths from active conda env (CONDA_PREFIX is set when env is activated)
        export INCLUDE_PATH="${CONDA_PREFIX}/include"
        export LIB_PATH="${CONDA_PREFIX}/lib"
        export LD_LIBRARY_PATH="${LIB_PATH}:${LD_LIBRARY_PATH}"
        
        # Build and run (from this assets/ directory) — example: lp_basic
        gcc -I"${INCLUDE_PATH}" -L"${LIB_PATH}" -o lp_basic/lp_simple lp_basic/lp_simple.c -lcuopt
        ./lp_basic/lp_simple
        ```
        
        For the other examples, use the same pattern (e.g. `lp_duals/lp_duals.c` → `lp_duals/lp_duals`). `mps_solver` takes an MPS file path: `./mps_solver mps_solver/data/sample.mps`.
        
        Without conda, set `INCLUDE_PATH` and `LIB_PATH` to your cuOpt include and lib directories, then use the same `gcc` and `LD_LIBRARY_PATH` as above. Each subdirectory README has a one-line build/run for that example.
        
    • cli
      • lp_production
        • production.mps 375 B · in bundle
        • README.md 192 B
          # Production LP (MPS)
          
          Production planning: maximize 40*chairs + 30*tables subject to wood and labor limits.
          
          **Run:** `cuopt_cli production.mps` or `cuopt_cli production.mps --time-limit 30`
          
      • lp_simple
        • README.md 191 B
          # Minimal LP (MPS)
          
          Maximize 40*PROD_X + 30*PROD_Y subject to resource constraints. Two variables, two constraints.
          
          **Run:** `cuopt_cli sample.mps` or `cuopt_cli sample.mps --time-limit 30`
          
        • sample.mps 490 B · in bundle
      • milp_facility
        • facility.mps 694 B · in bundle
        • README.md 199 B
          # Facility location MILP (MPS)
          
          Facility location with binary open/close variables. Integer markers: INTORG / INTEND.
          
          **Run:** `cuopt_cli facility.mps --time-limit 60 --mip-relative-tolerance 0.01`
          
      • README.md 856 B
        # Assets — sample MPS files
        
        Sample MPS files for use with `cuopt_cli`. Use as reference; do not edit in place.
        
        | File | Type | Description |
        |------|------|-------------|
        | [lp_production](lp_production/) | LP | Production planning: chairs + tables, wood/labor |
        | [milp_facility](milp_facility/) | MILP | Facility location with binary open/close |
        | [lp_simple](lp_simple/) | LP | Minimal LP (PROD_X, PROD_Y, two constraints) |
        
        **Run:** From each subdir or with path: `cuopt_cli lp_simple/sample.mps` (or `cuopt_cli production.mps`, etc.). See the skill for options (`--time-limit`, `--mip-relative-tolerance`, etc.).
        
        ## Test CLI
        
        With conda env `cuopt` activated, from this `assets/` directory:
        
        ```bash
        cuopt_cli lp_simple/sample.mps --time-limit 10
        ```
        
        Use the same pattern for the other MPS files; for MILP, add e.g. `--mip-relative-gap 0.01`.
        
    • python
      • least_squares
        • model.py 831 B
          # SPDX-FileCopyrightText: Copyright (c) 2025-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
          # SPDX-License-Identifier: Apache-2.0
          
          """
          Least squares: minimize (x-3)² + (y-4)². Solution should be x=3, y=4.
          """
          
          from cuopt.linear_programming.problem import Problem, CONTINUOUS, MINIMIZE
          from cuopt.linear_programming.solver_settings import SolverSettings
          
          problem = Problem("LeastSquares")
          
          x = problem.addVariable(lb=-100, ub=100, vtype=CONTINUOUS, name="x")
          y = problem.addVariable(lb=-100, ub=100, vtype=CONTINUOUS, name="y")
          
          problem.setObjective(x * x + y * y - 6 * x - 8 * y + 25, sense=MINIMIZE)
          
          problem.solve(SolverSettings())
          
          if problem.Status.name in ["Optimal", "PrimalFeasible"]:
              print(f"x = {x.getValue():.4f}")
              print(f"y = {y.getValue():.4f}")
          else:
              print(f"Status: {problem.Status.name}")
          
        • README.md 136 B
          # Least squares (QP)
          
          Minimize (x-3)² + (y-4)² — find point closest to (3, 4). Unconstrained quadratic.
          
          **Run:** `python model.py`
          
      • lp_basic
        • model.py 1.1 KB
          # SPDX-FileCopyrightText: Copyright (c) 2025-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
          # SPDX-License-Identifier: Apache-2.0
          
          """
          Minimal LP: variables, constraints, objective, solve.
          
          Problem:
              Maximize: x + y
              Subject to: x + y <= 10, x - y >= 0, x, y >= 0
          """
          
          from cuopt.linear_programming.problem import Problem, CONTINUOUS, MAXIMIZE
          from cuopt.linear_programming.solver_settings import SolverSettings
          
          
          def main():
              problem = Problem("Simple LP")
              x = problem.addVariable(lb=0, vtype=CONTINUOUS, name="x")
              y = problem.addVariable(lb=0, vtype=CONTINUOUS, name="y")
              problem.addConstraint(x + y <= 10, name="c1")
              problem.addConstraint(x - y >= 0, name="c2")
              problem.setObjective(x + y, sense=MAXIMIZE)
          
              settings = SolverSettings()
              settings.set_parameter("time_limit", 60)
              problem.solve(settings)
          
              if problem.Status.name in ["Optimal", "PrimalFeasible"]:
                  print(f"Objective: {problem.ObjValue}")
                  print(f"x = {x.getValue()}, y = {y.getValue()}")
              else:
                  print(f"Status: {problem.Status.name}")
          
          
          if __name__ == "__main__":
              main()
          
        • README.md 207 B
          # Minimal LP
          
          Basic linear program: continuous variables, linear constraints, maximize objective.
          
          **Problem:** Maximize x + y subject to x + y ≤ 10, x − y ≥ 0, x, y ≥ 0.
          
          **Run:** `python model.py`
          
      • lp_duals
        • model.py 1.2 KB
          # SPDX-FileCopyrightText: Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
          # SPDX-License-Identifier: Apache-2.0
          
          """
          LP with dual values and reduced costs.
          
          Problem:
              Minimize: 3x + 2y + 5z
              Subject to: x + y + z = 4, 2x + y + z = 5, x, y, z >= 0
          """
          
          from cuopt.linear_programming.problem import Problem, MINIMIZE
          
          
          def main():
              problem = Problem("min_dual_rc")
              x = problem.addVariable(lb=0.0, name="x")
              y = problem.addVariable(lb=0.0, name="y")
              z = problem.addVariable(lb=0.0, name="z")
              problem.addConstraint(x + y + z == 4.0, name="c1")
              problem.addConstraint(2.0 * x + y + z == 5.0, name="c2")
              problem.setObjective(3.0 * x + 2.0 * y + 5.0 * z, sense=MINIMIZE)
              problem.solve()
          
              if problem.Status.name in ["Optimal", "PrimalFeasible"]:
                  print(f"Objective: {problem.ObjValue}")
                  for v in problem.getVariables():
                      print(
                          f"{v.VariableName} = {v.Value}, ReducedCost = {v.ReducedCost}"
                      )
                  for c in problem.getConstraints():
                      print(f"{c.ConstraintName} DualValue = {c.DualValue}")
              else:
                  print(f"Status: {problem.Status.name}")
          
          
          if __name__ == "__main__":
              main()
          
        • README.md 227 B
          # LP Duals and Reduced Costs
          
          Retrieve dual values (shadow prices) and reduced costs after solving an LP.
          
          **Problem:** Minimize 3x + 2y + 5z subject to x + y + z = 4, 2x + y + z = 5, x, y, z ≥ 0.
          
          **Run:** `python model.py`
          
      • lp_warmstart
        • model.py 1.8 KB
          # SPDX-FileCopyrightText: Copyright (c) 2025-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
          # SPDX-License-Identifier: Apache-2.0
          
          """
          PDLP warmstart: solve a similar LP faster by reusing solution context.
          
          Warmstart is for LP only, not MILP.
          """
          
          from cuopt.linear_programming.problem import Problem, CONTINUOUS, MAXIMIZE
          from cuopt.linear_programming.solver.solver_parameters import (
              CUOPT_METHOD,
              CUOPT_PDLP_SOLVER_MODE,
          )
          from cuopt.linear_programming.solver_settings import (
              SolverSettings,
              SolverMethod,
              PDLPSolverMode,
          )
          
          
          def main():
              print("=== Problem 1 ===")
              problem = Problem("LP1")
              x = problem.addVariable(lb=0, vtype=CONTINUOUS, name="x")
              y = problem.addVariable(lb=0, vtype=CONTINUOUS, name="y")
              problem.addConstraint(4 * x + 10 * y <= 130, name="c1")
              problem.addConstraint(8 * x - 3 * y >= 40, name="c2")
              problem.setObjective(2 * x + y, sense=MAXIMIZE)
          
              settings = SolverSettings()
              settings.set_parameter(CUOPT_METHOD, SolverMethod.PDLP)
              settings.set_parameter(CUOPT_PDLP_SOLVER_MODE, PDLPSolverMode.Stable2)
              problem.solve(settings)
              print(f"Objective: {problem.ObjValue}")
          
              warmstart_data = problem.getWarmstartData()
              print("\n=== Problem 2 (with warmstart) ===")
              new_problem = Problem("LP2")
              x = new_problem.addVariable(lb=0, vtype=CONTINUOUS, name="x")
              y = new_problem.addVariable(lb=0, vtype=CONTINUOUS, name="y")
              new_problem.addConstraint(4 * x + 10 * y <= 100, name="c1")
              new_problem.addConstraint(8 * x - 3 * y >= 50, name="c2")
              new_problem.setObjective(2 * x + y, sense=MAXIMIZE)
              settings.set_pdlp_warm_start_data(warmstart_data)
              new_problem.solve(settings)
              if new_problem.Status.name in ["Optimal", "PrimalFeasible"]:
                  print(f"Objective: {new_problem.ObjValue}")
          
          
          if __name__ == "__main__":
              main()
          
        • README.md 140 B
          # LP PDLP Warmstart
          
          Use warmstart data from a solved LP to solve a similar problem faster. LP only (not MILP).
          
          **Run:** `python model.py`
          
      • maximization_workaround
        • model.py 736 B
          # SPDX-FileCopyrightText: Copyright (c) 2025-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
          # SPDX-License-Identifier: Apache-2.0
          
          """
          Maximize -x² + 4x (max at x=2) by minimizing x² - 4x; then report -objective.
          """
          
          from cuopt.linear_programming.problem import Problem, CONTINUOUS, MINIMIZE
          
          problem = Problem("MaxWorkaround")
          
          x = problem.addVariable(lb=0, ub=10, vtype=CONTINUOUS, name="x")
          problem.setObjective(x * x - 4 * x, sense=MINIMIZE)
          
          problem.solve()
          
          if problem.Status.name in ["Optimal", "PrimalFeasible"]:
              print(f"x = {x.getValue():.4f}")
              print(f"Minimized value = {problem.ObjValue:.4f}")
              print(f"Original maximum = {-problem.ObjValue:.4f}")
          else:
              print(f"Status: {problem.Status.name}")
          
        • README.md 152 B
          # Maximization workaround (QP)
          
          QP supports MINIMIZE only. To maximize f(x), minimize -f(x); then negate the optimal value.
          
          **Run:** `python model.py`
          
      • milp_basic
        • incumbent_callback.py 1.8 KB
          # SPDX-FileCopyrightText: Copyright (c) 2025-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
          # SPDX-License-Identifier: Apache-2.0
          
          """
          Same MILP as model.py but with a callback to receive incumbent (intermediate) solutions.
          MILP only; not for LP.
          """
          
          from cuopt.linear_programming.problem import Problem, INTEGER, MAXIMIZE
          from cuopt.linear_programming.solver_settings import SolverSettings
          from cuopt.linear_programming.solver.solver_parameters import CUOPT_TIME_LIMIT
          from cuopt.linear_programming.internals import GetSolutionCallback
          
          
          class IncumbentCallback(GetSolutionCallback):
              def __init__(self, problem, variables, user_data):
                  super().__init__()
                  self.problem = problem
                  self.variables = variables
                  self.n_callbacks = 0
                  self.user_data = user_data
          
              def get_solution(self, solution, solution_cost, solution_bound, user_data):
                  self.n_callbacks += 1
                  values = self.problem.getIncumbentValues(solution, self.variables)
                  cost = float(solution_cost[0])
                  vals_str = ", ".join(f"{float(v)}" for v in values)
                  print(f"Incumbent {self.n_callbacks}: [{vals_str}], cost: {cost:.2f}")
          
          
          def main():
              problem = Problem("Incumbent Example")
              x = problem.addVariable(vtype=INTEGER)
              y = problem.addVariable(vtype=INTEGER)
              problem.addConstraint(2 * x + 4 * y >= 230)
              problem.addConstraint(3 * x + 2 * y <= 190)
              problem.setObjective(5 * x + 3 * y, sense=MAXIMIZE)
          
              user_data = {"source": "incumbent_callback"}
              settings = SolverSettings()
              callback = IncumbentCallback(problem, [x, y], user_data)
              settings.set_mip_callback(callback, user_data)
              settings.set_parameter(CUOPT_TIME_LIMIT, 30)
              problem.solve(settings)
          
              print(f"Status: {problem.Status.name}, Objective: {problem.ObjValue}")
          
          
          if __name__ == "__main__":
              main()
          
        • model.py 1.2 KB
          # SPDX-FileCopyrightText: Copyright (c) 2025-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
          # SPDX-License-Identifier: Apache-2.0
          
          """
          Minimal MILP: integer variables with bounds, linear constraints.
          
          Problem:
              Maximize: 5x + 3y
              Subject to: 2x + 4y >= 230, 3x + 2y <= 190, 10 <= y <= 50, x, y integer
          """
          
          from cuopt.linear_programming.problem import Problem, INTEGER, MAXIMIZE
          from cuopt.linear_programming.solver_settings import SolverSettings
          
          
          def main():
              problem = Problem("Simple MIP")
              x = problem.addVariable(vtype=INTEGER, name="V_x")
              y = problem.addVariable(lb=10, ub=50, vtype=INTEGER, name="V_y")
              problem.addConstraint(2 * x + 4 * y >= 230, name="C1")
              problem.addConstraint(3 * x + 2 * y <= 190, name="C2")
              problem.setObjective(5 * x + 3 * y, sense=MAXIMIZE)
          
              settings = SolverSettings()
              settings.set_parameter("time_limit", 60)
              problem.solve(settings)
          
              if problem.Status.name in ["Optimal", "FeasibleFound"]:
                  print(f"Objective: {problem.ObjValue}")
                  print(f"x = {x.getValue()}, y = {y.getValue()}")
              else:
                  print(f"Status: {problem.Status.name}")
          
          
          if __name__ == "__main__":
              main()
          
        • README.md 433 B
          # Minimal MILP
          
          Basic mixed-integer program: integer variables with bounds, linear constraints.
          
          **Problem:** Maximize 5x + 3y subject to 2x + 4y ≥ 230, 3x + 2y ≤ 190, 10 ≤ y ≤ 50, x, y integer.
          
          - **model.py** — solve and print solution.
          - **incumbent_callback.py** — same problem with a callback that prints intermediate (incumbent) solutions during solve.
          
          **Run:** `python model.py` or `python incumbent_callback.py`
          
      • milp_production_planning
        • model.py 1.2 KB
          # SPDX-FileCopyrightText: Copyright (c) 2025-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
          # SPDX-License-Identifier: Apache-2.0
          
          """
          Production planning: two products, resource limits (machine, labor, material), maximize profit.
          """
          
          from cuopt.linear_programming.problem import Problem, INTEGER, MAXIMIZE
          from cuopt.linear_programming.solver_settings import SolverSettings
          
          
          def main():
              problem = Problem("Production Planning")
              x1 = problem.addVariable(lb=10, vtype=INTEGER, name="Product_A")
              x2 = problem.addVariable(lb=15, vtype=INTEGER, name="Product_B")
              problem.addConstraint(2 * x1 + x2 <= 100, name="Machine_Time")
              problem.addConstraint(x1 + 3 * x2 <= 120, name="Labor_Hours")
              problem.addConstraint(4 * x1 + 2 * x2 <= 200, name="Material")
              problem.setObjective(50 * x1 + 30 * x2, sense=MAXIMIZE)
          
              settings = SolverSettings()
              settings.set_parameter("time_limit", 30)
              problem.solve(settings)
          
              if problem.Status.name in ["Optimal", "FeasibleFound"]:
                  print(f"Product A: {x1.getValue()}, Product B: {x2.getValue()}")
                  print(f"Total profit: {problem.ObjValue}")
              else:
                  print(f"Status: {problem.Status.name}")
          
          
          if __name__ == "__main__":
              main()
          
        • README.md 165 B
          # Production Planning (MILP)
          
          Two products (A, B), resource limits (machine time, labor, material), minimum production, maximize profit.
          
          **Run:** `python model.py`
          
      • mps_solver
        • data
          • README.md 2 KB
            # MPS Solver Data
            
            This directory contains MPS files for testing.
            
            ## Included Files
            
            ### air05.mps (MIPLIB Benchmark)
            
            An airline crew scheduling problem from the MIPLIB benchmark library.
            
            | Property | Value |
            |----------|-------|
            | Type | Binary Integer Program |
            | Variables | 7,195 (all binary) |
            | Constraints | 426 |
            | Non-zeros | 52,121 |
            | Known Optimal | 26,374 |
            
            **Source**: https://miplib.zib.de/instance_details_air05.html
            
            **Problem**: Given flight legs and possible crew pairings, find the minimum-cost
            set of pairings that covers all flight legs (set covering problem).
            
            ## MPS File Format
            
            MPS (Mathematical Programming System) is a standard format for LP/MILP problems.
            
            ### Sections
            
            | Section | Purpose |
            |---------|---------|
            | NAME | Problem name |
            | ROWS | Constraint and objective definitions |
            | COLUMNS | Variable coefficients in each row |
            | RHS | Right-hand side values for constraints |
            | BOUNDS | Variable bounds and types |
            | ENDATA | End of file marker |
            
            ### Row Types
            
            | Type | Meaning |
            |------|---------|
            | N | Objective function (no constraint) |
            | L | Less than or equal (≤) |
            | G | Greater than or equal (≥) |
            | E | Equality (=) |
            
            ### Bound Types
            
            | Type | Meaning |
            |------|---------|
            | LO | Lower bound |
            | UP | Upper bound |
            | FX | Fixed value (lb = ub) |
            | FR | Free variable (-∞ to +∞) |
            | BV | Binary variable (0 or 1) |
            | UI | Upper bound, integer |
            | LI | Lower bound, integer |
            
            ## Adding Custom MPS Files
            
            ```bash
            python model.py --file path/to/your/problem.mps
            ```
            
            ## Standard Test Problem Sources
            
            - [MIPLIB](https://miplib.zib.de/) - Mixed Integer Programming Library
            - [Netlib LP](https://www.netlib.org/lp/) - Classic LP test problems
            - [NEOS](https://neos-server.org/neos/) - Network-Enabled Optimization System
            
            ## Creating MPS Files
            
            cuOpt can export problems to MPS format:
            
            ```python
            from cuopt.linear_programming.problem import Problem
            
            problem = Problem("MyProblem")
            # ... define variables, constraints, objective ...
            problem.writeMPS("output.mps")
            ```
            
          • sample.mps 490 B · in bundle
        • model.py 8.2 KB
          # SPDX-FileCopyrightText: Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
          # SPDX-License-Identifier: Apache-2.0
          
          """
          MPS File Solver using cuOpt Python API
          
          Read and solve LP/MILP problems from standard MPS files using
          cuOpt's built-in readMPS method.
          
          Default benchmark: air05.mps (airline crew scheduling from MIPLIB)
          - Best known optimal: 26,374
          """
          
          import os
          import gzip
          import urllib.request
          from typing import Optional
          
          from cuopt.linear_programming.problem import Problem
          from cuopt.linear_programming.solver_settings import SolverSettings
          
          
          # MIPLIB benchmark URL
          AIR05_URL = "https://miplib.zib.de/WebData/instances/air05.mps.gz"
          AIR05_OPTIMAL = 26374  # Best known optimal solution
          
          
          def download_air05(data_dir: str) -> str:
              """Download air05.mps from MIPLIB if not present."""
              mps_file = os.path.join(data_dir, "air05.mps")
          
              if os.path.exists(mps_file):
                  return mps_file
          
              os.makedirs(data_dir, exist_ok=True)
              gz_file = os.path.join(data_dir, "air05.mps.gz")
          
              print("Downloading air05.mps from MIPLIB...")
              urllib.request.urlretrieve(AIR05_URL, gz_file)
          
              # Decompress
              print("Decompressing...")
              with gzip.open(gz_file, "rb") as f_in:
                  with open(mps_file, "wb") as f_out:
                      f_out.write(f_in.read())
          
              # Clean up
              os.remove(gz_file)
              print(f"Downloaded: {mps_file}")
          
              return mps_file
          
          
          def solve_mps(
              filepath: str,
              time_limit: float = 60.0,
              mip_gap: float = 0.01,
              verbose: bool = True,
          ) -> tuple:
              """
              Solve an LP/MILP problem from an MPS file.
          
              Parameters
              ----------
              filepath : str
                  Path to the MPS file
              time_limit : float
                  Solver time limit in seconds
              mip_gap : float
                  MIP relative gap tolerance
              verbose : bool
                  Print solver output
          
              Returns
              -------
              tuple
                  (problem, solution_dict) or (problem, None) if no solution
              """
          
              # Read MPS file directly (static method returns Problem object)
              problem = Problem.readMPS(filepath)
          
              print(f"Loaded MPS file: {filepath}")
              print(f"Variables: {problem.NumVariables}")
              print(f"Constraints: {problem.NumConstraints}")
              print(f"Is MIP: {problem.IsMIP}")
          
              # Solver settings
              settings = SolverSettings()
              settings.set_parameter("time_limit", time_limit)
              settings.set_parameter("log_to_console", verbose)
              settings.set_parameter("mip_relative_gap", mip_gap)
          
              # Solve
              print("\nSolving...")
              problem.solve(settings)
          
              # Extract solution
              status = problem.Status.name
              print(f"\nStatus: {status}")
          
              if status in ["Optimal", "FeasibleFound", "PrimalFeasible"]:
                  solution = {
                      "status": status,
                      "objective": problem.ObjValue,
                      "num_variables": problem.NumVariables,
                      "num_constraints": problem.NumConstraints,
                      "is_mip": problem.IsMIP,
                      "mip_gap": mip_gap,
                  }
          
                  # Get variable values (use getVariables() for MPS-loaded problems)
                  var_values = {}
                  try:
                      variables = problem.getVariables()
                      for var in variables:
                          val = var.getValue()
                          if abs(val) > 1e-6:  # Only include non-zero values
                              var_values[var.Name] = val
                  except (AttributeError, Exception):
                      # For MPS problems, variable access may be limited
                      pass
          
                  solution["variables"] = var_values
                  return problem, solution
              else:
                  return problem, None
          
          
          def compare_gaps(
              filepath: str,
              time_limit: float = 120.0,
              known_optimal: Optional[float] = None,
          ) -> dict:
              """
              Compare solutions at different MIP gap tolerances.
          
              Parameters
              ----------
              filepath : str
                  Path to the MPS file
              time_limit : float
                  Solver time limit per run
              known_optimal : float, optional
                  Known optimal objective value. If provided, results include
                  "gap_to_optimal" (percent above optimal). Omit for generic MPS files.
          
              Returns
              -------
              dict
                  Results for each gap tolerance
              """
              gaps = [0.01, 0.001]  # 1% and 0.1%
              results = {}
          
              for gap in gaps:
                  print(f"\n{'=' * 60}")
                  print(f"Solving with MIP gap = {gap * 100}%")
                  print(f"{'=' * 60}")
          
                  problem, solution = solve_mps(
                      filepath=filepath, time_limit=time_limit, mip_gap=gap, verbose=True
                  )
          
                  if solution:
                      results[gap] = {
                          "objective": solution["objective"],
                          "status": solution["status"],
                      }
                      if known_optimal is not None:
                          results[gap]["gap_to_optimal"] = (
                              (solution["objective"] - known_optimal)
                              / known_optimal
                              * 100
                          )
                  else:
                      results[gap] = {"objective": None, "status": "No solution"}
          
              return results
          
          
          if __name__ == "__main__":
              import argparse
          
              parser = argparse.ArgumentParser(description="Solve LP/MILP from MPS file")
              parser.add_argument(
                  "--file", type=str, default=None, help="Path to MPS file"
              )
              parser.add_argument(
                  "--time-limit", type=float, default=60.0, help="Solver time limit"
              )
              parser.add_argument(
                  "--mip-gap", type=float, default=0.01, help="MIP gap tolerance"
              )
              parser.add_argument(
                  "--compare", action="store_true", help="Compare 1%% vs 0.1%% gap"
              )
              parser.add_argument(
                  "--known-optimal",
                  type=float,
                  default=None,
                  help="Known optimal objective value (enables gap-to-optimal reporting)",
              )
              args = parser.parse_args()
          
              print("=" * 60)
              print("MPS File Solver using cuOpt")
              print("=" * 60)
          
              # Determine MPS file to use
              script_dir = os.path.dirname(os.path.abspath(__file__))
              data_dir = os.path.join(script_dir, "data")
          
              if args.file:
                  mps_file = args.file
              else:
                  # Download air05.mps if not present
                  mps_file = download_air05(data_dir)
          
              # Use known optimal only when explicitly set or when using default air05
              known_optimal = args.known_optimal
              if known_optimal is None and mps_file.endswith("air05.mps"):
                  known_optimal = AIR05_OPTIMAL
          
              if args.compare:
                  # Compare different gap tolerances
                  print(f"\nComparing MIP gap tolerances on: {mps_file}")
                  if known_optimal is not None:
                      print(f"Best known optimal: {known_optimal}")
          
                  results = compare_gaps(
                      mps_file, time_limit=args.time_limit, known_optimal=known_optimal
                  )
          
                  print()
                  print("=" * 60)
                  print("COMPARISON SUMMARY")
                  print("=" * 60)
                  if known_optimal is not None:
                      print(f"Best known optimal: {known_optimal}")
                  print()
                  header = f"{'Gap Tolerance':<15} {'Objective':<15}"
                  if known_optimal is not None:
                      header += f" {'Gap to Optimal':<15}"
                  print(header)
                  print("-" * (45 if known_optimal is None else 60))
          
                  for gap, result in sorted(results.items()):
                      if result["objective"] is not None:
                          line = f"{gap * 100:.1f}%{'':<12} {result['objective']:<15.0f}"
                          if known_optimal is not None:
                              line += f" {result['gap_to_optimal']:.2f}%"
                          print(line)
                      else:
                          print(f"{gap * 100:.1f}%{'':<12} {'No solution':<15}")
              else:
                  # Single solve
                  print(f"\nMPS File: {mps_file}")
                  print(f"Time Limit: {args.time_limit}s")
                  print(f"MIP Gap: {args.mip_gap * 100}%")
                  print()
          
                  problem, solution = solve_mps(
                      filepath=mps_file,
                      time_limit=args.time_limit,
                      mip_gap=args.mip_gap,
                      verbose=True,
                  )
          
                  if solution:
                      print()
                      print("=" * 60)
                      print("SOLUTION")
                      print("=" * 60)
                      print(f"Status: {solution['status']}")
                      print(f"Objective Value: {solution['objective']:.0f}")
                      if known_optimal is not None:
                          print(f"Best Known Optimal: {known_optimal}")
                          print(
                              f"Gap to Optimal: {(solution['objective'] - known_optimal) / known_optimal * 100:.2f}%"
                          )
                  else:
                      print("\nNo feasible solution found.")
          
        • README.md 2.2 KB
          # MPS File Solver
          
          Read and solve LP/MILP problems from standard MPS files using cuOpt.
          
          ## Problem Description
          
          MPS (Mathematical Programming System) is a standard file format for representing linear and mixed-integer programming problems. This model demonstrates how to:
          
          1. Load an MPS file using `Problem.readMPS()` (static method)
          2. Solve the problem using cuOpt's GPU-accelerated solver
          3. Extract and display the solution
          
          This is useful when you have optimization problems in standard MPS format from other solvers, modeling tools, or benchmark libraries like MIPLIB.
          
          ## MPS File Format
          
          MPS is a column-oriented format with sections:
          
          ```
          NAME          problem_name
          ROWS
           N  OBJ                    (objective row)
           L  CON1                   (≤ constraint)
           G  CON2                   (≥ constraint)
           E  CON3                   (= constraint)
          COLUMNS
              X1        OBJ        1.0
              X1        CON1       2.0
              X2        OBJ        2.0
              X2        CON1       3.0
          RHS
              RHS       CON1       10.0
          BOUNDS
           LO BND       X1         0.0
           UP BND       X1         5.0
          ENDATA
          ```
          
          ## Usage
          
          ```bash
          # Solve the sample problem
          python model.py
          
          # Solve a custom MPS file
          python model.py --file path/to/problem.mps
          
          # With time limit
          python model.py --file problem.mps --time-limit 120
          ```
          
          ## Model Characteristics
          
          - **Type**: LP or MILP (detected from MPS file)
          - **Input**: Standard MPS file format
          - **Output**: Solution values, objective, status
          
          ## Sample Problem
          
          The included `data/air05.mps` is a MIPLIB benchmark (airline crew scheduling):
          
          - **Variables**: 7,195 (binary)
          - **Constraints**: 426
          - **Known optimal**: 26,374
          - **Typical solve time**: ~2 seconds
          
          ## Key API Usage
          
          ```python
          from cuopt.linear_programming.problem import Problem
          from cuopt.linear_programming.solver_settings import SolverSettings
          
          # Load MPS file (static method - returns Problem object)
          problem = Problem.readMPS("path/to/problem.mps")
          
          # Configure and solve
          settings = SolverSettings()
          settings.set_parameter("time_limit", 60)
          problem.solve(settings)
          
          # Check solution
          if problem.Status.name in ["Optimal", "FeasibleFound"]:
              print(f"Objective: {problem.ObjValue}")
          ```
          
          ## Source
          
          Based on cuOpt's built-in MPS support via `Problem.readMPS()`.
          
        • results.md 2.5 KB
          # MPS Solver Results
          
          ## Problem: air05.mps (MIPLIB benchmark)
          
          **Description:** Airline crew scheduling - set partitioning problem
          
          ### Problem Characteristics
          - **Variables:** 7195 (all binary)
          - **Constraints:** 426
          - **Nonzeros:** 52121
          - **Best Known Optimal:** 26374
          
          ---
          
          ## Gap Tolerance Comparison
          
          Comparing different MIP relative gap tolerances to show trade-off between solution quality and solve time.
          
          ### Run Configuration
          - **Time Limit:** 60 seconds
          - **cuOpt Version:** 26.2.0
          - **Device:** Quadro RTX 8000 (47.24 GiB VRAM)
          - **CPU:** AMD Ryzen Threadripper PRO 3975WX (32 cores)
          
          ### Results Summary
          
          | Gap Tolerance | Objective | Gap to Optimal | Solve Time | Nodes Explored |
          |--------------|-----------|----------------|------------|----------------|
          | 0.1% | **26374** | 0.00% | 8.42s | 386 |
          | 1.0% | 26491 | 0.44% | 3.23s | 328 |
          
          ### Key Observations
          
          1. **Tighter gap finds optimal**: The 0.1% gap tolerance found the exact best-known optimal solution (26374)
          2. **Trade-off**: The looser 1.0% gap converged faster (3.2s vs 8.4s) but with 0.44% suboptimality
          3. **Both are fast**: cuOpt solved this 7195-variable MILP in under 10 seconds
          
          ---
          
          ## Detailed Solver Output (0.1% gap)
          
          ```
          Solving a problem with 426 constraints, 7195 variables (7195 integers), and 52121 nonzeros
          
          Presolve removed: 90 constraints, 1116 variables, 16171 nonzeros
          Presolved problem: 336 constraints, 6079 variables, 35950 nonzeros
          
          Root relaxation objective +2.58776093e+04
          
          Strong branching using 7 threads and 222 fractional variables
          Explored 386 nodes in 7.73s.
          
          Optimal solution found within relative MIP gap tolerance (1.0e-03)
          Solution objective: 26374.000000
          relative_mip_gap 0.000992
          total_solve_time 8.421934
          ```
          
          ---
          
          ## Detailed Solver Output (1.0% gap)
          
          ```
          Solving a problem with 426 constraints, 7195 variables (7195 integers), and 52121 nonzeros
          
          Presolve removed: 90 constraints, 1116 variables, 16171 nonzeros
          Presolved problem: 336 constraints, 6079 variables, 35950 nonzeros
          
          Root relaxation objective +2.58776093e+04
          
          Strong branching using 63 threads and 222 fractional variables
          Explored 328 nodes in 1.09s.
          
          Optimal solution found within relative MIP gap tolerance (1.0e-02)
          Solution objective: 26491.000000
          relative_mip_gap 0.009669
          total_solve_time 3.233650
          ```
          
          ---
          
          ## Usage
          
          ```bash
          # Default: download air05.mps and solve with comparison
          python model.py --compare --time-limit 60
          
          # Solve custom MPS file
          python model.py --file path/to/problem.mps --time-limit 300 --mip-gap 0.001
          ```
          
      • portfolio
        • model.py 1.6 KB
          # SPDX-FileCopyrightText: Copyright (c) 2025-2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
          # SPDX-License-Identifier: Apache-2.0
          
          """
          Portfolio: minimize variance x'Qx subject to sum(x)=1, r'x >= target, x >= 0.
          QP is beta; MUST use MINIMIZE.
          """
          
          from cuopt.linear_programming.problem import Problem, CONTINUOUS, MINIMIZE
          from cuopt.linear_programming.solver_settings import SolverSettings
          
          problem = Problem("Portfolio")
          
          x1 = problem.addVariable(lb=0, ub=1, vtype=CONTINUOUS, name="stock_a")
          x2 = problem.addVariable(lb=0, ub=1, vtype=CONTINUOUS, name="stock_b")
          x3 = problem.addVariable(lb=0, ub=1, vtype=CONTINUOUS, name="stock_c")
          
          r1, r2, r3 = 0.12, 0.08, 0.05
          target_return = 0.08
          
          problem.setObjective(
              0.04 * x1 * x1
              + 0.02 * x2 * x2
              + 0.01 * x3 * x3
              + 0.02 * x1 * x2
              + 0.01 * x1 * x3
              + 0.016 * x2 * x3,
              sense=MINIMIZE,
          )
          problem.addConstraint(x1 + x2 + x3 == 1, name="budget")
          problem.addConstraint(
              r1 * x1 + r2 * x2 + r3 * x3 >= target_return, name="min_return"
          )
          
          settings = SolverSettings()
          settings.set_parameter("time_limit", 60)
          problem.solve(settings)
          
          if problem.Status.name in ["Optimal", "PrimalFeasible"]:
              print(f"Portfolio variance: {problem.ObjValue:.6f}")
              print(f"Std dev: {problem.ObjValue**0.5:.4f}")
              print(f"  Stock A: {x1.getValue() * 100:.2f}%")
              print(f"  Stock B: {x2.getValue() * 100:.2f}%")
              print(f"  Stock C: {x3.getValue() * 100:.2f}%")
              print(
                  f"Expected return: {(r1 * x1.getValue() + r2 * x2.getValue() + r3 * x3.getValue()) * 100:.2f}%"
              )
          else:
              print(f"Status: {problem.Status.name}")
          
        • README.md 232 B
          # Portfolio optimization (QP)
          
          Minimize portfolio variance (risk) subject to fully invested (sum x = 1) and minimum return. Three assets; Q must be PSD.
          
          **Run:** `python model.py`
          
          **Note:** QP is beta; objective must be MINIMIZE.
          
      • README.md 581 B
        # Assets — reference models
        
        LP, MILP, and QP reference implementations. Use as reference when building new applications; do not edit in place.
        
        | Model | Type |
        |-------|------|
        | lp_basic | LP |
        | lp_duals | LP |
        | lp_warmstart | LP |
        | milp_basic | MILP |
        | milp_production_planning | MILP |
        | mps_solver | LP/MILP |
        | portfolio | QP |
        | least_squares | QP |
        | maximization_workaround | QP |
        
        **Run:** From each subdir, `python model.py`. QP is **beta** and supports **MINIMIZE** only. See [references/qp_examples.md](../references/qp_examples.md) for additional QP examples.
        
  • evals
    • evals.json 13.7 KB
      [
        {
          "id": "numopt-py-eval-001-lp-api-call-sequence",
          "question": "I want to solve a small LP (continuous variables only, maximize a linear objective with linear constraints) using the cuOpt Python API. List the API calls in order \u2014 name each method, one line per method, no full runnable script.",
          "expected_skill": "cuopt-numerical-optimization-api",
          "expected_script": null,
          "ground_truth": "The agent produces an ordered list of API calls without a runnable script. The list, in order: (1) Import Problem, CONTINUOUS, and MAXIMIZE from cuopt.linear_programming.problem, and SolverSettings from cuopt.linear_programming.solver_settings. (2) Construct Problem('name'). (3) For each decision variable, call problem.addVariable(lb=..., vtype=CONTINUOUS, name=...). (4) For each constraint, call problem.addConstraint(<linear expression> <= or >= or == <rhs>, name=...). (5) Call problem.setObjective(<linear expression>, sense=MAXIMIZE). (6) Construct SolverSettings(); call set_parameter('time_limit', ...) for time budget. (7) Call problem.solve(settings). (8) Check problem.Status.name in ['Optimal', 'PrimalFeasible'] (PascalCase status names \u2014 case-sensitive). (9) Read problem.ObjValue for the objective, and each variable's .getValue() for its optimal value. The agent uses LP (not MILP / QP) because all variables are continuous and the objective is linear. Mentions that status names are PascalCase (Optimal, not OPTIMAL or optimal) \u2014 case sensitivity matters.",
          "expected_behavior": [
            "Selects LP (not MILP or QP) given continuous variables and a linear objective",
            "Lists the API calls in order without producing a full runnable script",
            "Names Problem, addVariable (with vtype=CONTINUOUS), addConstraint, setObjective (sense=MAXIMIZE)",
            "Names SolverSettings, set_parameter('time_limit', ...), and problem.solve(settings)",
            "Names problem.Status.name and the PascalCase status values (Optimal / PrimalFeasible / FeasibleFound)",
            "Names problem.ObjValue and variable.getValue() for reading results",
            "Mentions that status names are case-sensitive (PascalCase)",
            "Does not invent method names that are not in the skill"
          ]
        },
        {
          "id": "numopt-py-eval-002-status-case-sensitivity",
          "question": "My cuOpt Python LP solve runs without error but the result block never executes. Here is the check I wrote: if problem.Status.name == 'OPTIMAL': print(problem.ObjValue). What is wrong and how do I fix it?",
          "expected_skill": "cuopt-numerical-optimization-api",
          "expected_script": null,
          "ground_truth": "The check silently fails because cuOpt status names use PascalCase, not ALL_CAPS. The string 'OPTIMAL' never matches. The correct LP status values to check are 'Optimal' and 'PrimalFeasible'. The fixed check is: if problem.Status.name in ['Optimal', 'PrimalFeasible']: print(problem.ObjValue). For MILP the correct values are 'Optimal' and 'FeasibleFound'. This is a common silent bug \u2014 the solve completes successfully but the code path that reads results is skipped because the string comparison always returns False.",
          "expected_behavior": [
            "Identifies the bug as a case mismatch \u2014 'OPTIMAL' is wrong, 'Optimal' is correct",
            "States that cuOpt status names are PascalCase, not ALL_CAPS",
            "Gives the correct LP check: problem.Status.name in ['Optimal', 'PrimalFeasible']",
            "Notes that for MILP the passing status is 'FeasibleFound' not 'FEASIBLE_FOUND' or 'FEASIBLEFOUND'",
            "Explains why this is a silent failure \u2014 no exception is raised, the block just never executes"
          ]
        },
        {
          "id": "numopt-py-eval-003-integer-vs-continuous-workers",
          "question": "I am modeling a staffing problem where I need to decide how many nurses to assign to each ward. Should the nurse count variables be INTEGER or CONTINUOUS in the cuOpt Python API, and what vtype constant do I use for each?",
          "expected_skill": "cuopt-numerical-optimization-api",
          "expected_script": null,
          "ground_truth": "Nurse counts should be INTEGER because nurses are discrete countable entities \u2014 you cannot assign 2.7 nurses to a ward. The vtype constant is INTEGER (imported from cuopt.linear_programming.problem). The addVariable call would be: problem.addVariable(lb=0, vtype=INTEGER, name='ward_a_nurses'). This makes the problem a MILP, not an LP. CONTINUOUS would be wrong here because it allows fractional values, which are meaningless for headcounts. The rule is: 'how many things' (people, vehicles, machines) \u2192 INTEGER; 'how much of something' (hours, tonnes, dollars) \u2192 CONTINUOUS.",
          "expected_behavior": [
            "States nurse counts must be INTEGER because nurses are discrete countable entities",
            "Names the correct vtype constant: INTEGER (imported from cuopt.linear_programming.problem)",
            "Shows or describes the addVariable call with vtype=INTEGER",
            "States this makes the problem MILP, not LP",
            "Explains why CONTINUOUS is wrong \u2014 it allows fractional nurse counts",
            "States the rule: countable things \u2192 INTEGER, measurable amounts \u2192 CONTINUOUS"
          ]
        },
        {
          "id": "numopt-py-eval-004-qp-maximize-workaround",
          "question": "I want to maximize a quadratic objective using the cuOpt Python QP API. When I pass sense=MAXIMIZE to setObjective, I get an error. What is the correct approach?",
          "expected_skill": "cuopt-numerical-optimization-api",
          "expected_script": null,
          "ground_truth": "The cuOpt QP solver only supports MINIMIZE \u2014 MAXIMIZE is rejected for quadratic objectives. The correct workaround is to negate all coefficients in the objective and minimize the negated expression. For example, to maximize -0.04*x1*x1 - 0.02*x2*x2 (a concave quadratic with NSD Q), minimize 0.04*x1*x1 + 0.02*x2*x2 with sense=MINIMIZE. The resulting problem.ObjValue will be the negated maximum; multiply by -1 to recover the true maximum. All variables must remain CONTINUOUS \u2014 integer QP is not supported. The Q matrix of the original maximization problem must be negative semi-definite (NSD) for the problem to be concave and have a finite maximum; after negation it becomes PSD, which is what the solver expects. Maximizing a convex quadratic (positive coefficients) is unbounded and not a meaningful use case.",
          "expected_behavior": [
            "States QP only supports MINIMIZE \u2014 MAXIMIZE is rejected",
            "Gives the correct workaround: negate all objective coefficients and use sense=MINIMIZE",
            "Notes that problem.ObjValue will be negated and must be multiplied by -1 to get the true maximum",
            "Reminds that all variables must be CONTINUOUS \u2014 integer QP is not supported",
            "Does not suggest a non-existent MAXIMIZE_QP or similar invented API"
          ]
        },
        {
          "id": "numopt-c-eval-001-milp-api-call-sequence",
          "question": "I want to solve a small MILP (some integer variables, linear objective, linear constraints) with the cuOpt C API. List the C functions and structs I need in order \u2014 names only, one line each, no full source.",
          "expected_skill": "cuopt-numerical-optimization-api",
          "expected_script": null,
          "ground_truth": "The agent produces an ordered list of C API entry points without writing a full source file: include cuopt/mathematical_optimization/cuopt_c.h, then call cuOptCreateRangedProblem with sense CUOPT_MINIMIZE or CUOPT_MAXIMIZE, then cuOptSolve(problem, settings, &solution), then cuOptGetObjectiveValue.",
          "expected_behavior": [
            "Lists C API call sequence without writing a complete source file",
            "Names cuOptCreateRangedProblem, cuOptSolve, cuOptGetObjectiveValue in order"
          ]
        },
        {
          "id": "numopt-c-eval-002-parameter-function-wrong-name",
          "question": "I am setting a time limit on my cuOpt C API solver with this call: cuOptSetIntParameter(settings, CUOPT_TIME_LIMIT, 60.0). My colleague says the function name is wrong. What is the correct function, and what other parameter-setting functions does the C API provide?",
          "expected_skill": "cuopt-numerical-optimization-api",
          "expected_script": null,
          "ground_truth": "The function name cuOptSetIntParameter does not exist in the cuOpt C API \u2014 it is a common mistake. The correct function for float parameters (including CUOPT_TIME_LIMIT, tolerances) is cuOptSetFloatParameter. The C API provides three parameter-setting functions: cuOptSetFloatParameter for float params such as time limits and tolerances, cuOptSetIntegerParameter (not cuOptSetIntParameter) for integer params such as CUOPT_LOG_TO_CONSOLE and method selection, and cuOptSetParameter for string params. CUOPT_TIME_LIMIT is a float parameter so the correct call is cuOptSetFloatParameter(settings, CUOPT_TIME_LIMIT, 60.0).",
          "expected_behavior": [
            "Identifies cuOptSetIntParameter as a non-existent function \u2014 the correct name is cuOptSetIntegerParameter",
            "States CUOPT_TIME_LIMIT is a float parameter requiring cuOptSetFloatParameter, not cuOptSetIntegerParameter",
            "Names all three parameter functions: cuOptSetFloatParameter, cuOptSetIntegerParameter, cuOptSetParameter",
            "Does not produce a full source file \u2014 answers the question about function names only"
          ]
        },
        {
          "id": "numopt-c-eval-003-csr-constraint-matrix",
          "question": "I am building the constraint matrix for a cuOpt C LP. The problem has 2 constraints and 2 variables. Constraint 1: 3x1 + 4x2 <= 5.4. Constraint 2: 2.7x1 + 10.1x2 <= 4.9. Show me the row_offsets, col_indices, and values arrays for the CSR representation, and explain what each array means.",
          "expected_skill": "cuopt-numerical-optimization-api",
          "expected_script": null,
          "ground_truth": "The CSR (Compressed Sparse Row) format uses three arrays. row_offsets has length num_constraints+1 = 3: {0, 2, 4}. Element i gives the starting index in col_indices/values for row i; the last element is the total number of nonzeros (4 here). col_indices = {0, 1, 0, 1}: the column index of each nonzero, ordered by row. values = {3.0, 4.0, 2.7, 10.1}: the nonzero values in the same order. Constraint upper bounds are {5.4, 4.9} and lower bounds are {-CUOPT_INFINITY, -CUOPT_INFINITY} since both constraints are <=. These arrays are passed to cuOptCreateRangedProblem.",
          "expected_behavior": [
            "Gives row_offsets = {0, 2, 4} and explains it as start indices per row plus total nnz at the end",
            "Gives col_indices = {0, 1, 0, 1} matching the column of each nonzero by row",
            "Gives values = {3.0, 4.0, 2.7, 10.1} in row-major order",
            "Explains that constraint_lower_bounds should be -CUOPT_INFINITY for <= constraints",
            "Names cuOptCreateRangedProblem as the function that receives these arrays"
          ]
        },
        {
          "id": "numopt-c-eval-004-qp-restrictions",
          "question": "I want to solve a QP with integer variables using the cuOpt C API. A colleague says this is not supported. Is that correct, and what are the restrictions for QP in the cuOpt C API?",
          "expected_skill": "cuopt-numerical-optimization-api",
          "expected_script": null,
          "ground_truth": "The colleague is correct \u2014 integer QP is not supported in the cuOpt C API. The QP restrictions are: (1) minimization only \u2014 CUOPT_MINIMIZE is required; to maximize a quadratic objective, negate all objective coefficients and Q matrix entries; (2) continuous variables only \u2014 all variables must use CUOPT_CONTINUOUS, integer variables are not supported for QP; (3) the Q matrix should be positive semi-definite (PSD) for a convex, well-posed problem. The same library, include paths, and build pattern as LP/MILP are used; only the problem-creation call differs for QP.",
          "expected_behavior": [
            "Confirms integer QP is not supported \u2014 all QP variables must be CUOPT_CONTINUOUS",
            "States QP only supports CUOPT_MINIMIZE, not CUOPT_MAXIMIZE",
            "Explains how to maximize: negate objective coefficients and Q entries",
            "Mentions Q should be positive semi-definite (PSD) for a convex problem",
            "Notes the same library/headers/build pattern as LP/MILP \u2014 only the problem creation call differs"
          ]
        },
        {
          "id": "numopt-cli-eval-001-mps-sections-and-cli-command",
          "question": "I have an LP problem I want to solve with cuopt_cli from an MPS file, with a 60-second time limit and 1% MIP gap (in case I add integers later). List the MPS sections in required order, and the cuopt_cli command line.",
          "expected_skill": "cuopt-numerical-optimization-api",
          "expected_script": null,
          "ground_truth": "The agent lists the MPS sections in the required order: NAME, ROWS (N row for the objective, L/G/E rows for constraints), COLUMNS (variable-name, row-name, coefficient triples), RHS (right-hand-side values), BOUNDS (optional \u2014 LO/UP/FX/BV/LI/UI), ENDATA. For integer variables, integer markers are 'MARKER' 'INTORG' before and 'MARKER' 'INTEND' after the integer columns. The cuopt_cli invocation is: cuopt_cli problem.mps --time-limit 60 --mip-relative-tolerance 0.01. The agent mentions cuopt_cli --help as the canonical source for all flags. Does not invent flags like --max-time or --gap that are not in the skill. Notes that cuopt_cli ships with the cuopt Python package (install via pip or conda first if not present).",
          "expected_behavior": [
            "Lists MPS sections in required order: NAME, ROWS, COLUMNS, RHS, [BOUNDS], ENDATA",
            "Mentions N row for objective and L/G/E for constraint types",
            "Mentions integer markers ('MARKER' 'INTORG' / 'INTEND') for integer columns",
            "Gives the cuopt_cli command with --time-limit 60 and --mip-relative-tolerance 0.01",
            "References cuopt_cli --help as the canonical flag source",
            "Does not invent flag names that are not in the skill (e.g. --max-time, --gap)",
            "Mentions that cuopt_cli ships with the cuopt Python package"
          ]
        }
      ]
      
  • references
    • cli_api.md 5.5 KB
      # cuOpt Numerical Optimization — CLI
      
      Solve LP, MILP, and QP problems from MPS or LP files via `cuopt_cli`. The same command and options apply across all three; QP is supported in both MPS (QPS) and LP files.
      
      Confirm problem type and formulation (variables, objective, constraints, variable types) before coding.
      
      The CLI is included with the `cuopt` Python package — install via pip or conda, then verify with `cuopt_cli --help`.
      
      ## Basic Usage
      
      ```bash
      cuopt_cli <problem-file> [options]
      ```
      
      The first positional argument is the input file. The format is chosen automatically from the extension — MPS, QPS, and LP files are all accepted (including `.gz` / `.bz2` compressed variants); run `cuopt_cli --help` for the exact list of supported extensions.
      
      ## Options
      
      **`cuopt_cli --help` is the authoritative list — don't work from a hard-coded subset.** The CLI exposes every solver setting as a flag, generated from the parameter list at runtime: take any parameter documented in the cuOpt settings reference and replace underscores with hyphens (`time_limit` → `--time-limit`, `mip_relative_gap` → `--mip-relative-gap`). So if a parameter is documented, the flag exists; `--help` and the [solver-settings docs](https://docs.nvidia.com/cuopt/user-guide/latest/) are the sources of truth for names, meanings, and defaults.
      
      A few options are CLI-specific (not solver parameters) and worth knowing because you wouldn't derive them from a parameter name:
      
      - `--params-file <file>` — supply many parameters from a `key = value` config file instead of repeating flags.
      - `--relaxation` — solve the continuous relaxation of a MILP (drop integrality).
      - `--initial-solution <file>` — warm-start from a solution file.
      
      Run `cuopt_cli --help` for the complete, current set.
      
      ## Authoring input files
      
      MPS, QPS, and LP are precise, externally-specified file formats. Don't hand-author them from memory or from a partial recollection of the layout — column-position rules, marker conventions, the quadratic-objective encoding, and sign/scaling conventions are easy to get subtly wrong, and a malformed file either fails to parse or **silently encodes a different model than intended**.
      
      If you're building a model from data (rather than solving a file you already have), **define the problem through the cuOpt Python API or your preferred modeling interface — don't generate an MPS or LP file by hand to feed the CLI.** These interfaces take coefficients, bounds, and variable types as native data structures, so there's no text format to get wrong. The cuOpt Python API solves and returns the solution in the same program (see [python_api.md](python_api.md)); a separate modeling library (e.g. PuLP, Pyomo, JuMP) can export a valid file for the CLI or call its own solver. Reach for `cuopt_cli` when you *already* have a model file — e.g. a benchmark instance or a file exported by one of these tools.
      
      When a file is genuinely the right artifact, still generate it programmatically rather than by hand:
      
      - **From cuOpt's Python API** — build the model, then export it with `model.writeMPS("problem.mps")` (emits a valid MPS file, including the quadratic objective for QP) and solve with `cuopt_cli problem.mps`.
      - **From another modeling tool** — most LP/MILP modeling libraries and solvers can export standard MPS or LP files; pass the exported file straight to `cuopt_cli`.
      
      If you must read or write these formats by hand anyway, work from the format's full specification (and the cuOpt repo docs at `docs/cuopt/source/cuopt-cli/` for cuOpt-specific conventions such as the quadratic-objective encoding) — not from an example alone.
      
      Either way, **validate before trusting the result**: `cuopt_cli` logs `Read file ...` on a successful parse, and reports the variable/constraint counts and objective — sanity-check those against your intended model.
      
      ## MPS Format (required sections, in order)
      
      1. **NAME** — problem name
      2. **ROWS** — `N` (objective), `L`/`G`/`E` (constraints)
      3. **COLUMNS** — variable names, row names, coefficients
      4. **RHS** — right-hand side values
      5. **BOUNDS** (optional) — `LO`, `UP`, `FX`, `BV`, `LI`, `UI`
      6. **ENDATA**
      
      Integer variables: wrap columns with `'MARKER' 'INTORG'` before and `'MARKER' 'INTEND'` after.
      
      ## QP via CLI (beta)
      
      Quadratic objectives are **MINIMIZE only** (for maximization, negate the objective, including the quadratic terms) and require **continuous variables only** (no integer variables mixed with a quadratic objective). Quadratic objectives use the standard MPS quadratic-objective (QPS) extension and are also supported in LP files. Check `cuopt_cli --help` for QP-specific flags; see `docs/cuopt/source/cuopt-cli/` for the format.
      
      ## Troubleshooting
      
      - **Parsing input file failed** — Confirm the extension matches the format (`.lp` vs `.mps`/`.qps`); an unrecognized extension is rejected before parsing. The parser error names the offending line — fix it against the format spec, or (more reliably) regenerate the file from a modeling tool rather than patching it by hand. Also check `ENDATA`, section order, and integer markers.
      - **Infeasible** — Re-check the model against your intended formulation: constraint directions (`L`/`G`/`E`), right-hand sides, and variable bounds.
      
      ## Reference Models
      
      | Model | Type | Location |
      |-------|------|----------|
      | Minimal LP | LP | [assets/cli/lp_simple/](../assets/cli/lp_simple/) |
      | Production planning | LP | [assets/cli/lp_production/](../assets/cli/lp_production/) |
      | Facility location | MILP | [assets/cli/milp_facility/](../assets/cli/milp_facility/) |
      
    • c_api.md 4.7 KB
      # cuOpt Numerical Optimization — C API
      
      ## Required Headers
      
      ```c
      #include <cuopt/mathematical_optimization/cuopt_c.h>   // Core API
      #include <cuopt/mathematical_optimization/constants.h> // Parameter name macros
      ```
      
      ## API Call Sequence
      
      ```
      cuOptCreateRangedProblem(...)   // build CSR constraint matrix + variable types
      cuOptCreateSolverSettings(...)
      cuOptSetFloatParameter(...)     // time_limit, tolerances
      cuOptSetIntegerParameter(...)   // log_to_console, method
      cuOptSolve(problem, settings, &solution)
      cuOptGetObjectiveValue(solution, &obj)
      cuOptGetPrimalSolution(solution, values)
      cuOptGetDualSolution(...)       // LP/QP only
      // cleanup
      cuOptDestroyProblem(...)
      cuOptDestroySolverSettings(...)
      cuOptDestroySolution(...)
      ```
      
      ## Parameter Setting Functions
      
      | Function | Use for |
      |----------|---------|
      | `cuOptSetFloatParameter` | `time_limit`, tolerances |
      | `cuOptSetIntegerParameter` | `log_to_console`, `method`, `presolve` |
      
      **Common mistake:** `cuOptSetIntParameter` does not exist — use `cuOptSetIntegerParameter`.
      
      ## LP Example
      
      ```c
      #include <cuopt/mathematical_optimization/cuopt_c.h>
      #include <cuopt/mathematical_optimization/constants.h>
      #include <stdio.h>
      #include <stdlib.h>
      
      int main() {
          cuOptOptimizationProblem problem = NULL;
          cuOptSolverSettings settings = NULL;
          cuOptSolution solution = NULL;
      
          cuopt_int_t num_variables = 2, num_constraints = 2;
      
          // Constraint matrix in CSR format
          cuopt_int_t row_offsets[] = {0, 2, 4};
          cuopt_int_t col_indices[] = {0, 1, 0, 1};
          cuopt_float_t values[] = {3.0, 4.0, 2.7, 10.1};
      
          cuopt_float_t obj_coeffs[] = {-0.2, 0.1};
          cuopt_float_t con_lb[] = {-CUOPT_INFINITY, -CUOPT_INFINITY};
          cuopt_float_t con_ub[] = {5.4, 4.9};
          cuopt_float_t var_lb[] = {0.0, 0.0};
          cuopt_float_t var_ub[] = {CUOPT_INFINITY, CUOPT_INFINITY};
          char var_types[] = {CUOPT_CONTINUOUS, CUOPT_CONTINUOUS};
      
          cuopt_int_t status = cuOptCreateRangedProblem(
              num_constraints, num_variables, CUOPT_MINIMIZE, 0.0,
              obj_coeffs, row_offsets, col_indices, values,
              con_lb, con_ub, var_lb, var_ub, var_types, &problem
          );
          if (status != CUOPT_SUCCESS) { return 1; }
      
          cuOptCreateSolverSettings(&settings);
          cuOptSetFloatParameter(settings, CUOPT_TIME_LIMIT, 60.0);
      
          status = cuOptSolve(problem, settings, &solution);
      
          cuopt_float_t obj;
          cuOptGetObjectiveValue(solution, &obj);
          printf("Objective: %f\n", obj);
      
          cuopt_float_t* sol = malloc(num_variables * sizeof(cuopt_float_t));
          cuOptGetPrimalSolution(solution, sol);
          printf("x1=%f x2=%f\n", sol[0], sol[1]);
          free(sol);
      
          cuOptDestroyProblem(&problem);
          cuOptDestroySolverSettings(&settings);
          cuOptDestroySolution(&solution);
          return 0;
      }
      ```
      
      For MILP, set `var_types[i] = CUOPT_INTEGER` for integer variables and use `CUOPT_MIP_RELATIVE_GAP` / `CUOPT_MIP_ABSOLUTE_TOLERANCE` settings.
      
      ## QP via C API (beta)
      
      QP uses the same library, headers, and build pattern — only the problem-creation call differs (it accepts a quadratic objective). See `cpp/include/cuopt/mathematical_optimization/` for QP-specific creation calls and `docs/cuopt/source/cuopt-c/lp-qp-milp/` for end-to-end QP examples.
      
      **QP rules:** MINIMIZE only (`CUOPT_MINIMIZE`); continuous variables only (`CUOPT_CONTINUOUS`); Q should be PSD.
      
      ## Dual Values (LP / QP)
      
      `cuOptGetDualSolution` and `cuOptGetReducedCosts` return duals for LP and QP. They return `NaN` arrays when the model has quadratic constraints. Not available for MILP.
      
      See [assets/c/lp_duals/](../assets/c/lp_duals/) for the call sequence.
      
      ## Constants Reference
      
      ```c
      CUOPT_MINIMIZE / CUOPT_MAXIMIZE
      CUOPT_CONTINUOUS / CUOPT_INTEGER
      CUOPT_INFINITY / -CUOPT_INFINITY
      CUOPT_SUCCESS  // 0
      
      // Float parameters
      CUOPT_TIME_LIMIT
      CUOPT_ABSOLUTE_PRIMAL_TOLERANCE
      CUOPT_MIP_RELATIVE_GAP
      CUOPT_MIP_ABSOLUTE_TOLERANCE
      CUOPT_MIP_RELATIVE_TOLERANCE
      
      // Integer parameters
      CUOPT_LOG_TO_CONSOLE
      CUOPT_METHOD        // CUOPT_METHOD_CONCURRENT(0), PDLP(1), DUAL_SIMPLEX(2), BARRIER(3)
      CUOPT_PRESOLVE
      ```
      
      Full list: `cpp/include/cuopt/mathematical_optimization/constants.h`
      
      ## Build
      
      See [assets/c/README.md](../assets/c/README.md) for the conda-env include/library/`LD_LIBRARY_PATH` setup and `gcc` build command.
      
      ## Reference Models
      
      | Model | Type | Location |
      |-------|------|----------|
      | Simple LP | LP | [assets/c/lp_basic/](../assets/c/lp_basic/) |
      | Dual values | LP | [assets/c/lp_duals/](../assets/c/lp_duals/) |
      | PDLP warmstart | LP | [assets/c/lp_warmstart/](../assets/c/lp_warmstart/) |
      | Integer variable | MILP | [assets/c/milp_basic/](../assets/c/milp_basic/) |
      | Production planning | MILP | [assets/c/milp_production_planning/](../assets/c/milp_production_planning/) |
      | MPS file solver | LP/MILP | [assets/c/mps_solver/](../assets/c/mps_solver/) |
      
    • python_api.md 4.7 KB
      # cuOpt Numerical Optimization — Python API
      
      ## Quick Reference
      
      ```python
      from cuopt.linear_programming.problem import Problem, CONTINUOUS, INTEGER, MINIMIZE, MAXIMIZE
      from cuopt.linear_programming.solver_settings import SolverSettings
      ```
      
      ## LP Example
      
      ```python
      problem = Problem("MyLP")
      
      x = problem.addVariable(lb=0, vtype=CONTINUOUS, name="x")
      y = problem.addVariable(lb=0, vtype=CONTINUOUS, name="y")
      
      problem.addConstraint(2*x + 3*y <= 120, name="resource_a")
      problem.addConstraint(4*x + 2*y <= 100, name="resource_b")
      problem.setObjective(40*x + 30*y, sense=MAXIMIZE)
      
      settings = SolverSettings()
      settings.set_parameter("time_limit", 60)
      problem.solve(settings)
      
      if problem.Status.name in ["Optimal", "PrimalFeasible"]:
          print(f"Objective: {problem.ObjValue}")
          print(f"x = {x.getValue()}, y = {y.getValue()}")
      ```
      
      ## MILP Example
      
      ```python
      problem = Problem("FacilityLocation")
      
      open_facility = problem.addVariable(lb=0, ub=1, vtype=INTEGER, name="open")
      production = problem.addVariable(lb=0, vtype=CONTINUOUS, name="production")
      
      problem.addConstraint(production <= 1000 * open_facility, name="link")
      problem.setObjective(500*open_facility + 2*production, sense=MINIMIZE)
      
      settings = SolverSettings()
      settings.set_parameter("time_limit", 120)
      settings.set_parameter("mip_relative_gap", 0.01)
      problem.solve(settings)
      
      if problem.Status.name in ["Optimal", "FeasibleFound"]:
          print(f"Open: {open_facility.getValue() > 0.5}, Production: {production.getValue()}")
      ```
      
      ## QP Example (beta — MINIMIZE only)
      
      ```python
      problem = Problem("Portfolio")
      x1 = problem.addVariable(lb=0, ub=1, vtype=CONTINUOUS, name="stock_a")
      x2 = problem.addVariable(lb=0, ub=1, vtype=CONTINUOUS, name="stock_b")
      x3 = problem.addVariable(lb=0, ub=1, vtype=CONTINUOUS, name="stock_c")
      
      problem.setObjective(
          0.04*x1*x1 + 0.02*x2*x2 + 0.01*x3*x3
          + 0.02*x1*x2 + 0.01*x1*x3 + 0.016*x2*x3,
          sense=MINIMIZE,
      )
      problem.addConstraint(x1 + x2 + x3 == 1, name="budget")
      problem.addConstraint(0.12*x1 + 0.08*x2 + 0.05*x3 >= 0.08, name="min_return")
      
      problem.solve(SolverSettings())
      if problem.Status.name in ["Optimal", "PrimalFeasible"]:
          print(f"Variance: {problem.ObjValue}")
      ```
      
      See [qp_examples.md](qp_examples.md) for least-squares, maximization workaround, and covariance matrix expansion.
      
      ## CRITICAL: Status Values Use PascalCase
      
      ```python
      # ✅ CORRECT
      if problem.Status.name in ["Optimal", "FeasibleFound"]:
          print(problem.ObjValue)
      
      # ❌ WRONG — silently never matches
      if problem.Status.name == "OPTIMAL":
          ...
      ```
      
      **LP:** `Optimal`, `NoTermination`, `NumericalError`, `PrimalInfeasible`, `DualInfeasible`, `IterationLimit`, `TimeLimit`, `PrimalFeasible`
      
      **MILP:** `Optimal`, `FeasibleFound`, `Infeasible`, `Unbounded`, `TimeLimit`, `NoTermination`
      
      **QP:** same set as LP.
      
      ## Solver Settings
      
      ```python
      settings = SolverSettings()
      settings.set_parameter("time_limit", 60)
      settings.set_parameter("mip_relative_gap", 0.01)  # MILP: stop within 1% of optimal
      settings.set_parameter("log_to_console", 1)
      ```
      
      ## Dual Values (LP / QP)
      
      ```python
      if problem.Status.name == "Optimal":
          constraint = problem.getConstraint("resource_a")
          print(f"Dual value: {constraint.DualValue}")  # NaN if model has quadratic constraints
      ```
      
      ## Common Modeling Patterns
      
      ### Binary Selection
      ```python
      items = [problem.addVariable(lb=0, ub=1, vtype=INTEGER) for _ in range(n)]
      problem.addConstraint(sum(items) == k)
      ```
      
      ### Big-M Linking
      ```python
      M = 10000
      problem.addConstraint(x <= 100 + M*(1 - y))
      ```
      
      ### If-then "must also produce"
      ```python
      problem.addConstraint(y_X <= y_Y)
      problem.addConstraint(production_Y >= 1 * y_Y)
      ```
      
      ### Large Expressions (avoid recursion limit)
      ```python
      from cuopt.linear_programming.problem import LinearExpression
      
      expr = LinearExpression([x, y, z], [1.0, 2.0, 3.0], constant=0.0)
      problem.addConstraint(expr <= 100)
      ```
      
      ## Reference Models
      
      | Model | Type | Location |
      |-------|------|----------|
      | Minimal LP | LP | [assets/python/lp_basic/](../assets/python/lp_basic/) |
      | Dual values | LP | [assets/python/lp_duals/](../assets/python/lp_duals/) |
      | PDLP warmstart | LP | [assets/python/lp_warmstart/](../assets/python/lp_warmstart/) |
      | Integer variables | MILP | [assets/python/milp_basic/](../assets/python/milp_basic/) |
      | Production planning | MILP | [assets/python/milp_production_planning/](../assets/python/milp_production_planning/) |
      | Portfolio variance | QP | [assets/python/portfolio/](../assets/python/portfolio/) |
      | Least squares | QP | [assets/python/least_squares/](../assets/python/least_squares/) |
      | Maximization workaround | QP | [assets/python/maximization_workaround/](../assets/python/maximization_workaround/) |
      | MPS file solver | LP/MILP | [assets/python/mps_solver/](../assets/python/mps_solver/) |
      
    • qp_examples.md 5.7 KB
      # QP: Python API Examples
      
      ## Portfolio Optimization
      
      ```python
      """
      Minimize portfolio variance (risk):
          minimize    x^T * Q * x
          subject to  sum(x) = 1         (fully invested)
                      r^T * x >= target  (minimum return)
                      x >= 0             (no short selling)
      
      Note: QP is beta and MUST use MINIMIZE (not MAXIMIZE)
      """
      from cuopt.linear_programming.problem import Problem, CONTINUOUS, MINIMIZE
      from cuopt.linear_programming.solver_settings import SolverSettings
      
      problem = Problem("Portfolio")
      
      # Portfolio weights (decision variables)
      x1 = problem.addVariable(lb=0, ub=1, vtype=CONTINUOUS, name="stock_a")
      x2 = problem.addVariable(lb=0, ub=1, vtype=CONTINUOUS, name="stock_b")
      x3 = problem.addVariable(lb=0, ub=1, vtype=CONTINUOUS, name="stock_c")
      
      # Expected returns
      r1, r2, r3 = 0.12, 0.08, 0.05  # 12%, 8%, 5%
      target_return = 0.08
      
      # Covariance matrix Q:
      # [[0.04, 0.01, 0.005],
      #  [0.01, 0.02, 0.008],
      #  [0.005, 0.008, 0.01]]
      #
      # Quadratic objective: x^T * Q * x
      # Expanded: 0.04*x1² + 0.02*x2² + 0.01*x3² + 2*0.01*x1*x2 + 2*0.005*x1*x3 + 2*0.008*x2*x3
      
      problem.setObjective(
          0.04*x1*x1 + 0.02*x2*x2 + 0.01*x3*x3 +
          0.02*x1*x2 + 0.01*x1*x3 + 0.016*x2*x3,
          sense=MINIMIZE  # MUST be MINIMIZE for QP!
      )
      
      # Linear constraints
      problem.addConstraint(x1 + x2 + x3 == 1, name="budget")
      problem.addConstraint(r1*x1 + r2*x2 + r3*x3 >= target_return, name="min_return")
      
      # Solve
      settings = SolverSettings()
      settings.set_parameter("time_limit", 60)
      problem.solve(settings)
      
      # Results
      if problem.Status.name in ["Optimal", "PrimalFeasible"]:
          print(f"Portfolio variance: {problem.ObjValue:.6f}")
          print(f"Portfolio std dev: {problem.ObjValue**0.5:.4f}")
          print(f"\nAllocation:")
          print(f"  Stock A: {x1.getValue()*100:.2f}%")
          print(f"  Stock B: {x2.getValue()*100:.2f}%")
          print(f"  Stock C: {x3.getValue()*100:.2f}%")
      
          actual_return = r1*x1.getValue() + r2*x2.getValue() + r3*x3.getValue()
          print(f"\nExpected return: {actual_return*100:.2f}%")
      ```
      
      ## Least Squares
      
      ```python
      """
      Minimize ||Ax - b||² = (Ax-b)^T(Ax-b)
      
      Example: Find point closest to (3, 4)
      minimize (x-3)² + (y-4)² = x² - 6x + 9 + y² - 8y + 16
      """
      from cuopt.linear_programming.problem import Problem, CONTINUOUS, MINIMIZE
      from cuopt.linear_programming.solver_settings import SolverSettings
      
      problem = Problem("LeastSquares")
      
      x = problem.addVariable(lb=-100, ub=100, vtype=CONTINUOUS, name="x")
      y = problem.addVariable(lb=-100, ub=100, vtype=CONTINUOUS, name="y")
      
      # Quadratic objective: (x-3)² + (y-4)²
      # Expanded: x² + y² - 6x - 8y + 25
      problem.setObjective(
          x*x + y*y - 6*x - 8*y + 25,
          sense=MINIMIZE
      )
      
      result = problem.solve(SolverSettings())
      
      if problem.Status.name in ["Optimal", "PrimalFeasible"]:
          print(f"x = {x.getValue():.4f}")  # Should be ~3
          print(f"y = {y.getValue():.4f}")  # Should be ~4
      else:
          raise RuntimeError(f"Solver failed with status: {problem.Status.name}")
      ```
      
      ## Quadratic with Linear Constraints
      
      ```python
      """
      minimize    x² + y² + z²
      subject to  x + y + z = 10
                  x >= 0, y >= 0, z >= 0
      """
      from cuopt.linear_programming.problem import Problem, CONTINUOUS, MINIMIZE
      
      problem = Problem("QuadraticConstrained")
      
      x = problem.addVariable(lb=0, vtype=CONTINUOUS, name="x")
      y = problem.addVariable(lb=0, vtype=CONTINUOUS, name="y")
      z = problem.addVariable(lb=0, vtype=CONTINUOUS, name="z")
      
      problem.setObjective(x*x + y*y + z*z, sense=MINIMIZE)
      problem.addConstraint(x + y + z == 10)
      
      problem.solve()
      
      if problem.Status.name == "Optimal":
          print(f"x = {x.getValue():.4f}")
          print(f"y = {y.getValue():.4f}")
          print(f"z = {z.getValue():.4f}")
          print(f"Objective = {problem.ObjValue:.4f}")
      ```
      
      ## Maximization Workaround
      
      ```python
      """
      QP only supports MINIMIZE.
      To maximize f(x), minimize -f(x).
      
      Example: maximize -x² + 4x  (parabola with max at x=2)
      """
      from cuopt.linear_programming.problem import Problem, CONTINUOUS, MINIMIZE
      
      problem = Problem("MaxWorkaround")
      
      x = problem.addVariable(lb=0, ub=10, vtype=CONTINUOUS, name="x")
      
      # Want to maximize: -x² + 4x
      # Instead minimize: -(-x² + 4x) = x² - 4x
      problem.setObjective(x*x - 4*x, sense=MINIMIZE)
      
      problem.solve()
      
      if problem.Status.name in ["Optimal", "PrimalFeasible"]:
          print(f"x = {x.getValue():.4f}")  # Should be 2
          print(f"Minimized value = {problem.ObjValue:.4f}")  # Should be -4
          print(f"Original maximum = {-problem.ObjValue:.4f}")  # Should be 4
      else:
          print(f"Solver did not find optimal solution. Status: {problem.Status.name}")
      ```
      
      ## Expanding Covariance Matrix
      
      Given covariance matrix Q and weight vector x:
      
      ```python
      # Covariance matrix
      Q = [
          [0.04, 0.01, 0.005],
          [0.01, 0.02, 0.008],
          [0.005, 0.008, 0.01]
      ]
      
      # Expansion: x^T * Q * x
      # = Q[0,0]*x1² + Q[1,1]*x2² + Q[2,2]*x3²
      #   + 2*Q[0,1]*x1*x2 + 2*Q[0,2]*x1*x3 + 2*Q[1,2]*x2*x3
      #
      # = 0.04*x1*x1 + 0.02*x2*x2 + 0.01*x3*x3
      #   + 0.02*x1*x2 + 0.01*x1*x3 + 0.016*x2*x3
      
      objective = (
          Q[0][0]*x1*x1 + Q[1][1]*x2*x2 + Q[2][2]*x3*x3 +
          2*Q[0][1]*x1*x2 + 2*Q[0][2]*x1*x3 + 2*Q[1][2]*x2*x3
      )
      ```
      
      ## Critical Reminders
      
      1. **MINIMIZE only** - solver rejects MAXIMIZE for QP
      2. **Convexity** - Q should be positive semi-definite
      3. **Beta status** - API may change in future versions
      4. **Status checking** - use PascalCase: `"Optimal"` not `"OPTIMAL"`
      
      ---
      
      ## Additional References (tested in CI)
      
      For more complete examples, read these files:
      
      | Example | File | Description |
      |---------|------|-------------|
      | Simple QP | `docs/cuopt/source/cuopt-python/lp-qp-milp/examples/simple_qp_example.py` | Basic QP setup |
      | QP with Matrix | `docs/cuopt/source/cuopt-python/lp-qp-milp/examples/qp_matrix_example.py` | CSR matrix format for Q |
      
      These examples are tested by CI (`ci/test_doc_examples.sh`) and represent canonical usage.
      
  • BENCHMARK.md 4.8 KB
    # Skill Benchmark: cuopt-numerical-optimization-api
    
    > ✅ **Overall verdict: PASS — Recommended for publication**
    
    ## Publication Recommendation
    
    Recommended for publication based on the completed evaluation evidence in this report.
    
    ## Evaluation Metadata
    
    - Skill: `cuopt-numerical-optimization-api`
    - Evaluation date: 2026-08-05
    - Evaluator version: `1.0.0`
    - Agents: Claude Code (`aws/anthropic/bedrock-claude-opus-4-8`), Codex (`openai/openai/gpt-5.5`)
    - Tasks: 9 evaluation tasks (9 positive)
    - Dataset digest: `sha256:f385c69ce235035e8e5cbfd91a8d3245b75473f0bf0d694451e988e439f6e9e1` (skill-evaluator-dataset-snapshot/1)
    - Attempts per task: 1
    - Environment: `k8s-sandbox`
    - Tier 3 evidence: required for publication
    
    Each task attempt ran in its own isolated sandbox pod.
    
    ## What This Report Answers
    
    The three-tier evaluation checks whether the skill:
    
    - is safe to use;
    - produces correct answers;
    - is discovered and activated when needed;
    - helps the agent complete the user's goal and expected workflow; and
    - avoids wasted skill and tool usage.
    
    ## Results at a Glance
    
    | Measure | Claude Code (Baseline → Skill Uplift) | Codex (Baseline → Skill Uplift) |
    |---|---:|---:|
    | Overall | 59% → 97% (+39 points) | 61% → 93% (+32 points) |
    | Security | 100% → 100% (±0 points) | 100% → 100% (±0 points) |
    | Correctness | 87% → 98% (+11 points) | 91% → 100% (+9 points) |
    | Discoverability | 28% → 100% (+72 points) | 44% → 92% (+48 points) |
    | Effectiveness | 69% → 89% (+20 points) | 68% → 81% (+12 points) |
    | Efficiency | 10% → 100% (+90 points) | 0% → 90% (+90 points) |
    
    **How to read this table:** baseline is the same task attempted without the target skill. Uplift is `skill score - baseline score`, shown in percentage points.
    
    Example: `47% → 92% (+45 points)` means the skill-assisted run scored 92%, 45 percentage points above its 47% no-skill baseline.
    
    ## Tier Status
    
    | Tier | Purpose | Status | Evidence |
    |---|---|---|---|
    | Tier 1 | Static validation | **PASSED WITH OBSERVATIONS** | 1 validator(s); 4 finding(s) |
    | Tier 2 | Semantic deduplication | **NOT RUN** | No result was recorded |
    | Tier 3 | Live agent evaluation | **PASS** | 2 agent(s); 9 task(s) |
    
    ## Findings and Observations
    
    <details>
    <summary>Show detailed findings and successful checks</summary>
    
    - **MEDIUM** SCHEMA/frontmatter_field_placement: Root field 'version' is ignored; use 'metadata.version' (`skills/cuopt-numerical-optimization-api/SKILL.md`)
    - **MEDIUM** SCHEMA/body_recommended_section: Missing recommended section: '## Instructions' (`skills/cuopt-numerical-optimization-api/SKILL.md`)
    - **MEDIUM** SCHEMA/body_recommended_section: Missing recommended section: '## Examples' (`skills/cuopt-numerical-optimization-api/SKILL.md`)
    - **LOW** SCHEMA/author_format: Author must be of the form 'Name <email@host>' (`skills/cuopt-numerical-optimization-api/SKILL.md`)
    
    </details>
    
    ## Scoring Methodology
    
    <details>
    <summary>Show dimension definitions, source signals, and thresholds</summary>
    
    | Dimension | Question | Scored signals |
    |---|---|---|
    | Security | Is it safe to use? | `security` (100%) |
    | Correctness | Is the answer correct? | `accuracy` (100%) |
    | Discoverability | Was the right skill loaded when needed? | `skill_execution` (100%) |
    | Effectiveness | Did the skill help complete the task? | `goal_accuracy` (50%) + `behavior_check` (50%) |
    | Efficiency | Did it avoid wasted tool or skill usage? | `skill_efficiency` (100%) |
    
    - Dimension bands: PASS at 50% or above; NEUTRAL from 40% to below 50%; FAIL below 40%.
    - Overall Tier 3 lift: PASS at +5 points or more; FAIL at -10 points or less; values between those bands are NEUTRAL.
    - Overall verdict: PASS only when every configured dimension passes for at least one supported agent. Lift is reported as diagnostic evidence and does not override this gate.
    - The 50% attempt pass threshold is a separate per-task gate; it is not the dimension pass threshold.
    - Effectiveness is the equal-weight mean of goal completion (`goal_accuracy`) and expected workflow adherence (`behavior_check`).
    - Token efficiency is a separate report-only signal. It does not change a dimension score or the overall verdict.
    
    Signals present in this run:
    
    - `security` (Security): unsafe operations, secret leakage, and unauthorized access.
    - `skill_execution` (Skill Execution): whether the expected skill was found and executed.
    - `skill_efficiency` (Efficiency): routing quality, workspace-aware skill reads, and productive tool use.
    - `accuracy` (Accuracy): final-answer correctness against the reference answer.
    - `goal_accuracy` (Goal Accuracy): whether the user's goal was achieved.
    - `behavior_check` (Behavior Check): whether the expected workflow behavior was followed.
    
    </details>
    
    ## Freshness
    
    Regenerate this benchmark when the skill, evaluation dataset, target agent/model, evaluator version, environment, or scoring policy changes.
    
  • skill-card.md 4.3 KB
    ## Description: <br>
    Model and solve LP, MILP, and QP problems using NVIDIA cuOpt's GPU-accelerated solver via Python, C, and CLI interfaces. <br>
    
    This skill is ready for commercial/non-commercial use. <br>
    
    ## Owner
    NVIDIA <br>
    
    ### License/Terms of Use: <br>
    Apache 2.0 <br>
    ## Use Case: <br>
    Developers and engineers solving linear programming, mixed-integer linear programming, and quadratic programming optimization problems using NVIDIA cuOpt across Python, C, and CLI interfaces. <br>
    
    ### Deployment Geography for Use: <br>
    Global <br>
    
    ## Requirements / Dependencies: <br>
    **Requires API Key or External Credential:** [Not Specified] <br>
    **Credential Type(s):** [None identified] <br>
    
    Do not include secrets in prompts/logs/output; use least-privilege credentials; rotate keys as appropriate. <br>
    
    ## Known Risks and Mitigations: <br>
    Risk: Review before execution as proposals could introduce incorrect or misleading guidance into skills. <br>
    Mitigation: Review and scan skill before deployment. <br>
    
    ## Reference(s): <br>
    - [Python API Reference](references/python_api.md) <br>
    - [C API Reference](references/c_api.md) <br>
    - [CLI API Reference](references/cli_api.md) <br>
    - [QP Examples](references/qp_examples.md) <br>
    - [cuOpt User Guide](https://docs.nvidia.com/cuopt/user-guide/latest/introduction.html) <br>
    - [Third-Party Modeling Languages](https://docs.nvidia.com/cuopt/user-guide/latest/thirdparty_modeling_languages/index.html) <br>
    
    
    ## Skill Output: <br>
    **Output Type(s):** [Code, Shell commands, Configuration instructions, Analysis] <br>
    **Output Format:** [Markdown with inline code blocks] <br>
    **Output Parameters:** [1D] <br>
    **Other Properties Related to Output:** [None] <br>
    
    ## Evaluation Agents Used: <br>
    - Claude Code (`aws/anthropic/bedrock-claude-opus-4-8`) <br>
    - Codex (`openai/openai/gpt-5.5`) <br>
    
    
    
    ## Evaluation Tasks: <br>
    9 evaluation tasks (9 positive) in isolated sandbox pods. <br>
    
    ## Evaluation Metrics Used: <br>
    Reported benchmark dimensions: <br>
    - Security: Whether the skill is safe to use (unsafe operations, secret leakage, unauthorized access). <br>
    - Correctness: Whether the final answer is correct against the reference answer. <br>
    - Discoverability: Whether the right skill was found and executed when needed. <br>
    - Effectiveness: Whether the skill helps complete the user's goal and expected workflow. <br>
    - Efficiency: Whether the skill avoids wasted tool or skill usage. <br>
    
    Underlying evaluation signals used in this run: <br>
    - `security`: Checks for unsafe operations, secret leakage, and unauthorized access. <br>
    - `skill_execution`: Whether the expected skill was found and executed. <br>
    - `skill_efficiency`: Routing quality, workspace-aware skill reads, and productive tool use. <br>
    - `accuracy`: Final-answer correctness against the reference answer. <br>
    - `goal_accuracy`: Whether the user's goal was achieved. <br>
    - `behavior_check`: Whether the expected workflow behavior was followed. <br>
    
    
    
    ## Evaluation Results: <br>
    | Measure | Claude Code (Baseline → Skill Uplift) | Codex (Baseline → Skill Uplift) |
    |---|---:|---:|
    | Overall | 59% → 97% (+39 points) | 61% → 93% (+32 points) |
    | Security | 100% → 100% (±0 points) | 100% → 100% (±0 points) |
    | Correctness | 87% → 98% (+11 points) | 91% → 100% (+9 points) |
    | Discoverability | 28% → 100% (+72 points) | 44% → 92% (+48 points) |
    | Effectiveness | 69% → 89% (+20 points) | 68% → 81% (+12 points) |
    | Efficiency | 10% → 100% (+90 points) | 0% → 90% (+90 points) |
    
    ## Testing Completed: <br>
    **[x] Agent Red-Teaming** <br>
    **[ ] Network Security** <br>
    **[ ] Product Security** <br>
    
    ## Skill Version(s): <br>
    26.10.00 (source: frontmatter) <br>
    
    ## Ethical Considerations: <br>
    NVIDIA believes Trustworthy AI is a shared responsibility and we have established policies and practices to enable development for a wide array of AI applications. When downloaded or used in accordance with our terms of service, developers should work with their internal team to ensure this skill meets requirements for the relevant industry and use case and addresses unforeseen product misuse. <br>
    
    (For Release on NVIDIA Platforms Only) <br>
    Please report quality, risk, security vulnerabilities or NVIDIA AI Concerns [here](https://app.intigriti.com/programs/nvidia/nvidiavdp/detail). <br>
    
  • SKILL.md 4.8 KB
    ---
    name: cuopt-numerical-optimization-api
    version: "26.10.00"
    description: LP, MILP, and QP (beta) with cuOpt — Python, C, and CLI. Use when the user is solving LP, MILP, or QP with any cuOpt interface.
    license: Apache-2.0
    metadata:
      author: NVIDIA cuOpt Team
      tags:
        - cuopt
        - linear-programming
        - milp
        - qp
        - python
        - c-api
        - cli
    ---
    
    
    
    # cuOpt Numerical Optimization API
    
    Model and solve LP, MILP, and QP problems using NVIDIA cuOpt's GPU-accelerated solver.
    
    ## Interface Selection
    
    Choose the reference for the user's interface:
    
    | Interface | When to use | Reference |
    |-----------|-------------|-----------|
    | **Python** | User is writing Python code | [references/python_api.md](references/python_api.md) |
    | **C / C++** | User is embedding in a C/C++ application | [references/c_api.md](references/c_api.md) |
    | **CLI** | User is solving from MPS files on the command line | [references/cli_api.md](references/cli_api.md) |
    
    If the interface is not yet clear, ask before writing any code.
    
    **Already using a modeling language?** cuOpt also works as a solver backend for third-party
    modeling tools — **AMPL, GAMS / GAMSPy, PuLP, JuMP, Pyomo, and CVXPY** — with near-zero code
    changes (point the model's solver at cuOpt). CVXPY additionally covers convex QP and, in beta,
    QCQP / SOCP. Prefer this when the user already has a model in one of these tools rather than porting
    it to the cuOpt API. See
    [Third-Party Modeling Languages](https://docs.nvidia.com/cuopt/user-guide/latest/thirdparty_modeling_languages/index.html).
    
    ## Choosing LP vs MILP vs QP
    
    **Decide from the objective and variables:**
    
    | If the objective is... | And variables are... | Use |
    |---|---|---|
    | Linear (sum of `c_i * x_i`) | All continuous | **LP** |
    | Linear | Some integer or binary | **MILP** |
    | Has squared (`x*x`) or cross (`x*y`) terms | Continuous (integer QP not supported) | **QP** (beta) |
    
    **Prefer LP when the problem allows it.** LP solves faster and has stronger optimality guarantees. Use MILP only when the problem logically requires whole numbers or yes/no decisions. Use QP only when the objective is genuinely quadratic (variance, squared error, kinetic energy).
    
    - **Use LP** when every quantity can meaningfully be fractional: flows, proportions, rates, dollars, hours, tonnes of material, etc.
    - **Use MILP** when the problem mentions **counts** of discrete entities, **yes/no** choices, or **either/or** decisions (e.g. open a facility or not, assign a person to a shift, number of trucks).
    - **Use QP** when the objective minimizes variance, squared error, or any expression with `x*x` or `x*y` terms (portfolio optimization, least squares, regularized regression).
    
    ## Integer vs Continuous from Wording
    
    | Problem wording / concept | Variable type | Examples |
    |---------------------------|---------------|----------|
    | **Discrete entities (counts)** | **INTEGER** | Workers, cars, trucks, machines, pilots, facilities, units to manufacture |
    | **Yes/no or on/off** | **INTEGER** (binary, lb=0 ub=1) | Open a facility, run a machine, assign a person to a shift |
    | **Amounts that can be fractional** | **CONTINUOUS** | Tonnes, litres, dollars, hours, kWh, proportion of capacity |
    | **Rates or fractions** | **CONTINUOUS** | Utilization, percentage, share of budget |
    
    **Rule of thumb:** "How many *things*" → INTEGER. "How much" → CONTINUOUS.
    
    ## QP Rules (all interfaces)
    
    - **MINIMIZE only** — the solver rejects MAXIMIZE for quadratic objectives. To maximize `f(x)`, minimize `-f(x)` and negate the reported objective value.
    - **Continuous variables only** — integer QP is not supported.
    - **Q should be positive semi-definite** for a convex, well-posed problem.
    - **Beta** — API may evolve; treat as production-capable for typical convex QP.
    
    ## Dual Values
    
    Duals and reduced costs are available for **LP and QP only**:
    - **MILP** — no duals (integer optima are not continuous).
    - **Quadratic constraints** — duals unavailable even for LP/QP; all values return `NaN`.
    - **PDLP warmstart** — LP only; MILP solves do not accept a PDLP warmstart.
    
    ## Common Issues (all interfaces)
    
    | Problem | Likely cause | Fix |
    |---------|-------------|-----|
    | Infeasible | Conflicting constraints | Check constraint logic and bounds |
    | Unbounded | Missing bounds | Add variable bounds |
    | Slow solve | Large problem | Set time limit; increase gap tolerance |
    | QP rejected with MAXIMIZE | QP only supports MINIMIZE | Negate the objective; negate the result |
    | QP returns non-optimal | Q not PSD or badly scaled | Check Q is PSD; rescale variables |
    
    ## Solver Settings (concepts)
    
    | Setting | Purpose |
    |---------|---------|
    | `time_limit` | Stop after N seconds |
    | `mip_relative_gap` | Stop MILP when within X% of optimal |
    | `mip_absolute_tolerance` | Absolute MIP gap stop |
    | `log_to_console` | Enable solver logging |
    
    Syntax varies by interface — see the interface reference file.
    
  • skill.oms.sig 15.9 KB · in bundle

Comments (0)

Sign in to join the conversation.

No comments yet.

Reviews (0)

No reviews yet.

Related