cuopt-debugging
針對 cuOpt LP/MILP 問題進行疑難排解,包括錯誤、錯誤結果、不可行解、效能問題及狀態碼。當使用者提到…時使用。
npx skills add https://github.com/nvidia/cuopt-examples --skill cuopt-debuggingcuOpt Debugging Skill
Diagnose and fix issues with cuOpt LP/MILP solutions, errors, and performance.
Before You Start: Required Questions
Ask these to understand the problem:
-
What's the symptom?
- Error message?
- Wrong/unexpected results?
- Empty solution?
- Performance too slow?
-
What's the status?
problem.Status.name— what value does it show?
-
Can you share?
- The error message (exact text)
- The code that produces it
- Problem size (variables, constraints)
Quick Diagnosis by Symptom
"Solution is empty/None but status looks OK"
Most common cause: Wrong status string case
# ❌ WRONG - "OPTIMAL" never matches, silently fails
if problem.Status.name == "OPTIMAL":
print(problem.ObjValue) # Never runs!
# ✅ CORRECT - use PascalCase
if problem.Status.name in ["Optimal", "FeasibleFound"]:
print(problem.ObjValue)
Diagnostic code:
print(f"Actual status: '{problem.Status.name}'")
print(f"Matches 'Optimal': {problem.Status.name == 'Optimal'}")
print(f"Matches 'OPTIMAL': {problem.Status.name == 'OPTIMAL'}")
"Objective value is wrong/zero"
Check if variables are actually used:
for var in problem.getVariables():
print(f"{var.VariableName} = {var.Value}")
print(f"Objective: {problem.ObjValue}")
# Or with direct variable references
for var in [x, y, z]:
print(f"{var.VariableName}: {var.getValue()}")
Common causes:
- Constraints too restrictive (all zeros is feasible)
- Objective coefficients have wrong sign
- Wrong variable in objective
"Infeasible" status
For LP/MILP:
if problem.Status.name in ["PrimalInfeasible", "Infeasible"]:
print("Problem has no feasible solution")
# Review constraints for conflicts
for c in problem.getConstraints():
print(f"{c.ConstraintName}")
Common causes:
- Conflicting constraints (x <= 5 AND x >= 10)
- Bounds too tight
- Missing a "slack" variable for soft constraints
"Integer variable has fractional value"
# Check how variable was defined
int_var = problem.addVariable(
lb=0, ub=10,
vtype=INTEGER, # Must be INTEGER, not CONTINUOUS
name="count"
)
# Also check if status is actually optimal
if problem.Status.name == "FeasibleFound":
print("Warning: not fully optimal, may have fractional intermediate values")
"Unbounded" status
Problem has no finite optimum:
if problem.Status.name in ["DualInfeasible", "Unbounded"]:
print("Problem is unbounded - objective can improve infinitely")
Common causes:
- Missing variable upper/lower bounds
- Constraint direction wrong (>= instead of <=)
- Missing constraints
"Maximum recursion depth exceeded" when building expressions
Building large objectives or constraints with many chained + operations can hit Python recursion limits. Use LinearExpression instead:
from cuopt.linear_programming.problem import LinearExpression
# Instead of: expr = c1*v1 + c2*v2 + ... + cn*vn (many terms)
vars_list = [v1, v2, v3, ...]
coeffs_list = [c1, c2, c3, ...]
expr = LinearExpression(vars_list, coeffs_list, constant=0.0)
problem.setObjective(expr, sense=MINIMIZE)
See the LP/MILP "Building large expressions" section and reference models in the project for examples.
OutOfMemoryError
Check problem size:
print(f"Variables: {len(problem.getVariables())}")
print(f"Constraints: {len(problem.getConstraints())}")
Mitigations:
- Reduce problem size
- Use sparse constraint matrix
- Set time limit to get partial solution
Status Code Reference
LP Status Values
| Status | Meaning |
|---|---|
Optimal | Found optimal solution |
PrimalFeasible | Found feasible but may not be optimal |
PrimalInfeasible | No feasible solution exists |
DualInfeasible | Problem is unbounded |
TimeLimit | Stopped due to time limit |
IterationLimit | Stopped due to iteration limit |
NumericalError | Numerical issues encountered |
NoTermination | Solver didn't converge |
MILP Status Values
| Status | Meaning |
|---|---|
Optimal | Found optimal solution |
FeasibleFound | Found feasible, within gap tolerance |
Infeasible | No feasible solution exists |
Unbounded | Problem is unbounded |
TimeLimit | Stopped due to time limit |
NoTermination | No solution found yet |
Performance Debugging
Slow LP/MILP Solve
settings = SolverSettings()
settings.set_parameter("log_to_console", 1) # See progress
settings.set_parameter("time_limit", 60) # Don't wait forever
# For MILP, accept good-enough solution
settings.set_parameter("mip_relative_gap", 0.05) # 5% gap
Check Solve Time
problem.solve(settings)
print(f"Solve time: {problem.SolveTime:.2f} seconds")
Diagnostic Checklist
□ Status checked with correct case (PascalCase)?
□ All variables have correct vtype (INTEGER vs CONTINUOUS)?
□ Constraint directions correct (<= vs >= vs ==)?
□ Objective sense correct (MINIMIZE vs MAXIMIZE)?
□ Variable bounds specified where needed?
Diagnostic Code Snippets
See resources/diagnostic_snippets.md for copy-paste diagnostic code:
- Status checking
- Variable inspection
- Constraint analysis
- Memory and performance checks
When to Escalate
File a GitHub issue if:
- Reproducible bug with minimal example
- Include: cuOpt version, CUDA version, error message, minimal repro code