You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Is your feature request related to a problem? Please describe.
The C API (cpp/include/cuopt/linear_programming/cuopt_c.h) does not expose all of the solver statistics that the C++ structs lp_solution_t and mip_ret_t carry. Python sidesteps this gap by binding directly to the C++ structs via Cython (see python/cuopt/cuopt/linear_programming/solver/solver.pxd:181-205), so Python users see fields like nb_iterations, residuals, gap, solved_by, MIP nodes, simplex iterations, presolve time, and violation metrics.
Non-Python language bindings that go through the C ABI cannot see these fields. The first concrete consumer is cuopt-java (PR #1192), which binds via Java FFM (jextract on cuopt_c.h). The Java records LpStats, MilpStats, and SolverMethod were defined with fields matching Python's surface but currently report NaN / -1 / UNSET for anything not exposed by the C API. Future bindings (Go, Rust, C#, …) would hit the same wall.
Describe the solution you'd like
Add thin C getters to cuopt_c.h (and corresponding implementations in cuopt_c.cpp) that read the existing fields off lp_solution_t / mip_ret_t. Approximately 11 new functions, each a one-line wrapper around an existing struct field.
Naming/signatures should match the existing cuOptGet* convention (return cuopt_int_t error code, take an output pointer). The exact function names are open for review.
Describe alternatives you've considered
Bind language bindings directly to C++ — what Python does. Not viable for FFM/CFFI/cgo style bindings that target the C ABI, since C++ name mangling and ABI stability aren't guaranteed.
Is your feature request related to a problem? Please describe.
The C API (
cpp/include/cuopt/linear_programming/cuopt_c.h) does not expose all of the solver statistics that the C++ structslp_solution_tandmip_ret_tcarry. Python sidesteps this gap by binding directly to the C++ structs via Cython (seepython/cuopt/cuopt/linear_programming/solver/solver.pxd:181-205), so Python users see fields likenb_iterations, residuals, gap,solved_by, MIP nodes, simplex iterations, presolve time, and violation metrics.Non-Python language bindings that go through the C ABI cannot see these fields. The first concrete consumer is cuopt-java (PR #1192), which binds via Java FFM (jextract on
cuopt_c.h). The Java recordsLpStats,MilpStats, andSolverMethodwere defined with fields matching Python's surface but currently reportNaN/-1/UNSETfor anything not exposed by the C API. Future bindings (Go, Rust, C#, …) would hit the same wall.Describe the solution you'd like
Add thin C getters to
cuopt_c.h(and corresponding implementations incuopt_c.cpp) that read the existing fields offlp_solution_t/mip_ret_t. Approximately 11 new functions, each a one-line wrapper around an existing struct field.LP (read from
lp_solution_t):cuOptGetPrimalResidual(cuOptSolution, cuopt_float_t*)→l2_primal_residual_cuOptGetDualResidual(cuOptSolution, cuopt_float_t*)→l2_dual_residual_cuOptGetGap(cuOptSolution, cuopt_float_t*)→gap_cuOptGetIterationCount(cuOptSolution, cuopt_int_t*)→nb_iterations_cuOptGetSolvedBy(cuOptSolution, cuopt_int_t*)→solved_by_(method_t)MIP (read from
mip_ret_t):cuOptGetPresolveTime(cuOptSolution, cuopt_float_t*)→presolve_time_cuOptGetNumNodes(cuOptSolution, cuopt_int_t*)→nodes_cuOptGetNumSimplexIterations(cuOptSolution, cuopt_int_t*)→simplex_iterations_cuOptGetMaxConstraintViolation(cuOptSolution, cuopt_float_t*)→max_constraint_violation_cuOptGetMaxIntViolation(cuOptSolution, cuopt_float_t*)→max_int_violation_cuOptGetMaxVariableBoundViolation(cuOptSolution, cuopt_float_t*)→max_variable_bound_violation_Naming/signatures should match the existing
cuOptGet*convention (returncuopt_int_terror code, take an output pointer). The exact function names are open for review.Describe alternatives you've considered
cuOptGetStatsreturning a struct — possible but heavier ABI footprint; individual getters are smaller and easier to evolve.Additional context
cpp/src/linear_programming/...(wherelp_solution_t/mip_ret_tare defined)python/cuopt/cuopt/linear_programming/solver/solver.pxd:181-205python/cuopt/cuopt/linear_programming/solution/solution.py:206-222java/cuopt-java/src/main/java22/com/nvidia/cuopt/internal/CuOptProviderImpl.java:425-441Once the C API ships these, the Java side becomes ~30 lines of straightforward FFM wiring.