Skip to content

[FEA] Expand cuopt_c.h with problem-model accessors for non-Python language bindings #1703

Description

@ramakrishnap-nv

Is your feature request related to a problem? Please describe.

The Java bindings (#1524) cannot reach parts of the problem model through the C API, so java/cuopt/src/main/native/cuopt_jni.cpp includes the private pdlp/cuopt_c_internal.hpp and reaches into problem_and_stream_view_t directly. There are 18 such call sites.

That couples libcuopt_jni.so to a specific libcuopt build rather than to a stable ABI. It is fine while the module is built from the same source tree, but it blocks shipping the jar as a binary artifact: a cuOpt point release can break it in ways no version range expresses. Any other C-ABI binding (Go, Rust, C#) would hit the same wall, and a jextract-based binding could not work around it at all, since jextract can only bind the C header.

This is the problem-model counterpart to #1202, which covers solver statistics.

Describe the solution you'd like

Roughly 10 functions. Two of them are already acknowledged as TODO in cuopt_c.h:

 * TODO: there is no getter for the quadratic objective matrix (Q)
 * or the quadratic constraint rows.

Name setters — the C API reads names but cannot set them

  • cuOptSetVariableNames(problem, const char* const* names, cuopt_int_t count)
  • cuOptSetRowNames(problem, const char* const* names, cuopt_int_t count)
  • cuOptSetProblemName(problem, const char* name)
  • cuOptGetProblemName(problem, char* buf, cuopt_int_t size) — no getter exists either

Quadratic objective (Q is CSR, so this mirrors cuOptGetConstraintMatrix)

  • a non-zero count attribute, plus cuOptGetQuadraticObjective(problem, offsets, indices, values)

Quadratic constraint rows — the awkward one

quadratic_constraint_t is a variable-length array of variable-length records: each row carries a name, sense, RHS, a linear part (values + indices), and a COO Q (rows/cols/vals). Copy-out cannot express nested ragged data in one call, so it needs a shape-query-then-fill pattern, roughly:

cuOptGetNumQuadraticConstraints(problem, &n);
cuOptGetQuadraticConstraintSizes(problem, i, &n_linear, &n_quad);
cuOptGetQuadraticConstraint(problem, i, /* arrays */);
cuOptGetQuadraticConstraintName(problem, i, buf, size);

Describe alternatives you've considered

  1. Leave the bindings on private headers — current state. Works for a source build, blocks binary distribution.
  2. Return a struct — heavier ABI footprint, and does not solve the ragged quadratic-constraint case.

Additional context

  • The copy-out accessors that cannot report "no data" were split out as [BUG] Copy-out solution accessors cannot distinguish "no data" from "data is all zeros" #1706, since that is a behaviour bug rather than a missing accessor.
  • CUOPT_ATTR_PROBLEM_CATEGORY already exists; that call site just needs rewiring and needs no new API.
  • Sizing, based on the seven functions already moved in Java bindings for LP/MIP/QP #1524 (141 lines of implementation and 134 of header for 7): roughly 240 + 230 lines, plus tests. Everything except the quadratic-constraint accessors is mechanical.
  • Suggested order: name setters and the problem-name getter first (trivial), then the quadratic objective getters (closes half the existing TODO), then the quadratic constraint accessors once the shape-query pattern is agreed.

Metadata

Metadata

Assignees

Labels

awaiting responseThis expects a response from maintainer or contributor depending on who requested in last comment.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions