Skip to content

Java bindings for LP/MIP/QP - #1524

Open
nvidiacbrissette wants to merge 24 commits into
NVIDIA:mainfrom
nvidiacbrissette:cbrissette/cuopt-bindings
Open

Java bindings for LP/MIP/QP#1524
nvidiacbrissette wants to merge 24 commits into
NVIDIA:mainfrom
nvidiacbrissette:cbrissette/cuopt-bindings

Conversation

@nvidiacbrissette

@nvidiacbrissette nvidiacbrissette commented Jul 7, 2026

Copy link
Copy Markdown

Description

Java bindings at parity with the LP/MIP/QP surface, plus tests and docs.

The bindings are hand-written JNI over the public C API. Contributes to #1535 and #860.

Native surface

The bindings originally carried cuopt_java_native_api.{hpp,cpp}, a Java-local shim declaring seven entry points that libcuopt did not export. It reimplemented the memory layout of the opaque cuOptSolverSettings handle in order to reach the underlying solver_settings_t, so any change to solver_settings_handle_t would have silently corrupted it.

All seven are now part of the public C API, implemented in cuopt_c.cpp beside the functions they belong with:

Parameters cuOptLoadParametersFromFile, cuOptDumpParametersToFile, cuOptGetNumSolverParameters, cuOptGetSolverParameterName
Solution stats cuOptSolutionIsMIP, cuOptGetLPSolverStats, cuOptGetMIPSolverStats

This covers the fields requested in #1202. Note for reviewers: #1202 proposed 11 individual getters and explicitly weighed that against a bulk call. This PR ships the bulk shape (two functions with nullable out-pointers), inherited from the original shim. If the individual-getter shape is preferred, say so and I will split them — flagging rather than silently closing #1202.

Build and CI

  • ./build.sh java and ./build.sh java --run-java-tests — an opt-in target, matching how cuvs exposes its Java build. Prefers cpp/build so it works without --install, and falls back to the conda prefix, which is what CI uses.
  • ci/build_java.sh calls build.sh rather than duplicating the invocation.
  • java/cuopt/scripts/test.sh carries a CUOPT_PRELOAD_LIBS escape hatch to work around [BUG] Build-tree libcuopt.so resolves librmm from the conda prefix instead of its own _deps, failing at dlopen #1704; it can be removed once that is fixed.
  • Java CI jobs moved off stale release/26.08 shared-workflow pins to @main with ci-conda:26.10-latest, and the redundant compute-matrix job was dropped.

Guard against JNI symbol drift

The bindings are hand-written, so a Java static native declaration and its Java_com_nvidia_..._name entry point can drift apart with nothing to catch it. JNI resolves methods lazily, so the library still loads and the failure only appears when something calls the method.

java/cuopt/scripts/check_jni_symbols.sh diffs the prototypes javac -h derives from the Java sources against the symbols the built library exports, and fails on a mismatch in either direction. It runs after every native build. It reads the built artifact rather than parsing source, so the macro-generated entry points need no special casing.

Packaging

Version is 26.10.0 — Maven has no notion of the zero-padded RAPIDS patch field, and 26.10.00 would sort oddly against a later 26.10.1. update-version.sh derives it. Sources and javadoc jars are attached, and the POM carries the url, licenses, scm, and developers metadata Maven Central requires.

Known gaps

These are deliberate, not oversights.

  1. The JNI still includes pdlp/cuopt_c_internal.hpp for the problem path — name setters, quadratic objective and quadratic constraint getters, and length reporting for duals and reduced costs. That couples libcuopt_jni.so to a specific libcuopt build rather than to a stable ABI, which matters before this is published as a binary artifact. Tracked in [FEA] Expand cuopt_c.h with problem-model accessors for non-Python language bindings #1703.
  2. Publishing is not wired up. Artifact metadata is complete; signing and upload are not. Tracked by the "Publishing & support" item in Java API support #1535.

Checklist

@nvidiacbrissette
nvidiacbrissette requested review from a team as code owners July 7, 2026 19:34
@nvidiacbrissette
nvidiacbrissette requested a review from tmckayus July 7, 2026 19:34
@copy-pr-bot

copy-pr-bot Bot commented Jul 7, 2026

Copy link
Copy Markdown

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@coderabbitai

coderabbitai Bot commented Jul 7, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Changes

Java bindings

Layer / File(s) Summary
Modeling contracts and expressions
java/cuopt/src/main/java/com/nvidia/cuopt/mathematicalprogramming/*
Adds Java variables, expressions, constraints, objectives, enums, callbacks, statistics, and validation behavior.
JNI bridge and native wrappers
java/cuopt/src/main/native/*, cpp/include/cuopt/mathematical_optimization/cuopt_c.h, cpp/src/pdlp/cuopt_c.cpp
Adds native declarations and JNI implementations for model creation, solving, settings, callbacks, persistence, solution fields, and statistics.
Problem modeling and solve flow
java/cuopt/src/main/java/com/nvidia/cuopt/mathematicalprogramming/Problem.java
Adds model construction, MPS I/O, CSR/QCSR inspection, updates, relaxation, MIP starts, solving, and result propagation.
Build, packaging, and CI
java/cuopt/*, ci/*, build.sh, .github/workflows/*, dependencies.yaml
Adds Maven/CMake builds, native scripts, generated constants, Java dependencies, CI jobs, artifacts, and release version handling.
Validation and documentation
java/cuopt/src/test/*, docs/cuopt/source/cuopt-java/*, docs/cuopt/source/index.rst
Adds modeling and native integration tests plus Java quick-start, convex, and MIP documentation.

Estimated code review effort: 5 (Critical) | ~120 minutes

Suggested reviewers: tmckayus, chris-maes, hlinsen

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 1.68% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly and concisely identifies the main change: Java bindings for LP, MIP, and QP functionality.
Description check ✅ Passed The description directly explains the Java bindings, native C API changes, build and CI updates, packaging, tests, documentation, and known gaps.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@mlubin mlubin left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I saw the PR is closed, sending my comments as I had them already written up.

Comment thread java/cuopt/src/main/java/com/nvidia/cuopt/linearprogramming/BatchSolve.java Outdated

extern "C" {

cuopt_int_t cuOptLoadParametersFromFile(cuOptSolverSettings settings, const char* path);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should discuss merging these extensions into the C API.

@@ -0,0 +1,1367 @@
/*
* SPDX-FileCopyrightText: Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd recommend avoiding a test dependency on the python interface. The java interface should stand on its own.

Comment thread java/cuopt/README.md Outdated
@@ -0,0 +1,25 @@
# cuOpt Java bindings (beta)

This directory is an isolated, customer-specific beta module for the cuOpt

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this how we want to ship it?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We would want to follow cuvs and try to publish to maven https://mvnrepository.com/artifact/com.nvidia.cuvs/cuvs-java

Comment thread docs/cuopt/source/cuopt-java/convex/convex-api.rst Outdated
@nvidiacbrissette

Copy link
Copy Markdown
Author

Sorry that was an accident. Reopening.

@@ -0,0 +1,28 @@
/home/cbrissette/cuopt/java/cuopt/src/main/java/com/nvidia/cuopt/linearprogramming/BatchSolve.java

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need these files ? may be we can delete all the run time files so developers can concentrate on main parts.

@ramakrishnap-nv ramakrishnap-nv left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Focused review on APIs and shipping (vs how cuvs ships Java).

APIs: the surface is broad and, pleasingly, closely in sync with the Python API — the algebraic Problem layer matches Python's (camelCase) modeling methods almost 1:1, and DataModel maps cleanly (snake_case→camelCase). A few parity gaps and Java-idiom nits are noted inline.

Shipping: the main blockers — don't commit target/, and wire the build into CI/release the way cuvs does (ci/build_java.sh/ci/test_java.sh, dependencies.yaml java key, workflow jobs, version marker, docs toctree).

Non-blocking review comments below.

Comment thread java/cuopt/scripts/build_native.sh
Comment thread java/cuopt/pom.xml Outdated
Comment thread docs/cuopt/source/cuopt-java/index.rst
}

/** Return true for maximize and false for minimize, matching Python get_sense(). */
public boolean getSense() {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Parity note (not a rename request): getSense() correctly matches the Python DataModel.get_sense() (bool, True=maximize) — good. Two parity gaps vs Python though: (1) Python puts set_initial_primal_solution/set_initial_dual_solution on DataModel, whereas here they're on SolverSettings; (2) Python DataModel also exposes getters this class seems to lack: get_quadratic_objective_{values,indices,offsets}, get_variable_names/get_row_names, get_objective_name/get_problem_name, get_ascii_row_types.

resetSolvedValues();
}

public Object getObjective() {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getObjective() returns Object — callers must downcast. Prefer a typed return (or overloads). Same for SolverSettings.getTypedParameter() / getMipCallbacks(). (The modeling API otherwise tracks the Python Problem layer 1:1 — nice.)

Comment thread java/cuopt/src/main/java/com/nvidia/cuopt/linearprogramming/CsrMatrix.java Outdated
Comment thread docs/cuopt/source/cuopt-java/convex/convex-api.rst Outdated
Comment thread docs/cuopt/source/cuopt-java/convex/convex-api.rst Outdated
Comment thread docs/cuopt/source/cuopt-java/convex/convex-api.rst Outdated
Comment thread docs/cuopt/source/cuopt-java/convex/convex-api.rst Outdated
Comment thread docs/cuopt/source/cuopt-java/convex/convex-api.rst Outdated
Comment thread docs/cuopt/source/cuopt-java/convex/convex-api.rst Outdated
Comment thread docs/cuopt/source/cuopt-java/convex/convex-api.rst Outdated
Comment thread docs/cuopt/source/cuopt-java/convex/convex-examples.rst Outdated
Comment thread docs/cuopt/source/cuopt-java/convex/convex-examples.rst Outdated
Comment thread docs/cuopt/source/cuopt-java/convex/index.rst Outdated
Comment thread docs/cuopt/source/cuopt-java/index.rst Outdated
Comment thread java/cuopt/src/main/java/com/nvidia/cuopt/linearprogramming/PDLPSolverMode.java Outdated
public enum ProblemCategory {
LP(0),
MIP(1),
IP(2);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should deprecate IP across the whole code base.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed for Java.

Comment thread java/cuopt/src/main/java/com/nvidia/cuopt/linearprogramming/SolverMethod.java Outdated

@chris-maes chris-maes left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for adding the JAVA API. Let's make sure that capitalization is consistent before merging.

* @return A status code indicating success or failure. Returns CUOPT_INVALID_ARGUMENT if the
* solution is a MIP solution.
*/
cuopt_int_t cuOptGetLPSolverStats(cuOptSolution solution,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe these stats are already exposed through attributes. And if not, they should be. Rather than adding a new C API call.

* @return A status code indicating success or failure. Returns CUOPT_INVALID_ARGUMENT if the
* solution is an LP solution.
*/
cuopt_int_t cuOptGetMIPSolverStats(cuOptSolution solution,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See previous comment about trying to access these via attributes.

* @return A status code indicating success or failure. Returns CUOPT_INVALID_ARGUMENT if the file
* is missing or malformed.
*/
cuopt_int_t cuOptLoadParametersFromFile(cuOptSolverSettings settings, const char* path);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the use case for these parameter API calls?

*
* @param[in] path - Path of the file to write.
*
* @param[in] hyperparameters_only - Non-zero to write only hyperparameters, zero to write every

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should not expose hyperparameters via a public API. Parameters are marked as hyperparameters, precisely because we do not want to broadly advertise them.

* - ``solve()`` / ``solve(SolverSettings)``
- Solve the problem and return a ``Solution``.
* - ``getCSR()`` / ``getQCSR()``
- Inspect the linear or quadratic objective matrix in CSR form.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is a linear objective matrix? Does this return the constraint matrix? Or the objective?

I'd suggest renaming these functions to make what they do more clear.

- Solve the problem and return a ``Solution``.
* - ``getCSR()`` / ``getQCSR()``
- Inspect the linear or quadratic objective matrix in CSR form.
* - ``writeMPS(String)`` / ``read(String)`` / ``readMPS(String)``

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

writeMPS and readMPS are deprecated. We should only support read and write and then dispatch based on file type.


``Problem`` also exposes ``getVariables``, ``getVariable``, ``getConstraints``,
``getConstraint``, ``getNumVariables``, ``getNumConstraints``,
``getNumNonZeros``, ``isMIP``, ``isSolved``, ``getStatus``,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove isSolved, users should use getStatus to determine the status. of the solves.

Also instead of having individual accessor functions, we should probably move to an attribute based model. See changes to C API.

``ge``, and ``eq``. Comparisons return a ``Constraint``.

``QuadraticExpression`` supports quadratic terms through
``QuadraticExpression.of(first, second, coefficient)`` and the same fluent

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: what does "fluent" mean in this context? Maybe reword for clarity?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW fluent is a standard term for describing APIs: https://en.wikipedia.org/wiki/Fluent_interface

``le`` and ``ge`` methods return quadratic constraints. It does not expose an
``eq`` method because equality quadratic constraints are not supported.

Both expression classes implement ``ObjectiveExpression``, which exposes the

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need an ObjectiveExpression? We should be able to use LinearExpressions and QuadraticExpression for both objectives and constraints.

``VariableType.SEMI_CONTINUOUS``; and
* ``ProblemCategory`` for the native problem classification.

``ProblemCategory.IP`` is deprecated. Java normalizes the legacy native IP

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need to include or mention deprecated API. Remove all references to IP.

* ``ConstraintSense.LE``, ``ConstraintSense.GE``, and ``ConstraintSense.EQ``;
* ``VariableType.CONTINUOUS``, ``VariableType.INTEGER``, and
``VariableType.SEMI_CONTINUOUS``; and
* ``ProblemCategory`` for the native problem classification.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is ProblemCategory used for? Could we get away with just isMIP()?


``Constraint`` provides ``getSense``, ``getRHS``, ``getCoefficient``,
``getLinearExpression``, ``getQuadraticExpression``, ``isQuadratic``,
``computeSlack``, ``getSlack``, and ``getDualValue``.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is computeSlack needed. Let's provide the slack inside the C++ engine.


``Solution`` implements ``AutoCloseable`` and exposes:

* ``getPrimalSolution``, ``getDualSolution``, and ``getReducedCost``;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure we want getPrimalSolution, getDualSolution and getReducedCost? These should be accessed via the constraints and variables.

* ``getSolveTime`` and ``getProblemCategory``; and
* ``getVars`` when variable names are available.

LP solutions additionally expose ``getLPStats``. ``LPStats`` contains primal

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's add attributes instead of stats.

MPS and Errors
--------------

``Problem.read`` and ``Problem.readMPS`` support MPS/QPS parsing, including a

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove MPS read/write.

@ramakrishnap-nv

Copy link
Copy Markdown
Collaborator

@chris-maes thanks for the review — replying to the C API comments in one place since they're connected.

Two facts first, because I think one of them changes the picture

There is no solution-scoped attribute API today. All five attribute getters are cuOptGetProblem*Attribute, and every CUOPT_ATTR_* / CUOPT_ARRAY_ATTR_* constant is problem-scoped. So these stats aren't reachable through attributes at present — your "and if not, they should be" is the actual proposal, and it means adding cuOptGetSolutionIntAttribute / cuOptGetSolutionFloatAttribute plus a CUOPT_SOLUTION_ATTR_* block.

None of these stats were reachable by any route before this PR. Checking main, of the eleven fields in #1202 — primal/dual residual, gap, iteration count, solved-by, presolve time, node count, simplex iterations, and the three violation metrics — zero are exposed. The solution accessors that do exist (cuOptGetTerminationStatus, cuOptGetObjectiveValue, cuOptGetMIPGap, cuOptGetSolutionBound, cuOptGetSolveTime, primal/dual/reduced costs) cover the outcome, not the diagnostics. Note cuOptGetMIPGap is the MIP optimality gap, which is a different quantity from the LP primal-dual gap in that list.

Why we think they're worth supporting

The data already exists on lp_solution_interface_t / mip_solution_interface_t, so this is pure exposure — no computation, no solve-time cost. Concretely:

  • Judging a non-optimal answer. When a solve returns on a time limit rather than OPTIMAL, residuals and gap are the only way to tell a nearly-converged solution from a useless one. Without them a C-ABI caller sees a status and a vector of numbers and cannot assess them.
  • Verifying a returned MIP solution. max_constraint_violation, max_int_violation, and max_variable_bound_violation are what a caller checks before acting on a solution in production. This is the one we'd argue hardest for.
  • Knowing which algorithm actually solved it. With CUOPT_METHOD_CONCURRENT the caller otherwise cannot tell whether PDLP or dual simplex produced the answer, which matters for tuning and reproducibility.
  • Performance work. Iteration counts, node counts, simplex iterations, and presolve time are the basis for benchmarking and spotting regressions.

Two more general points. Python already exposes all of this by binding to the C++ structs through Cython, so today the C ABI is a second-class path — that asymmetry is what #1202 was filed about. And users arriving from Gurobi or CPLEX expect IterCount / NodeCount / violation metrics as a matter of course.

Where we agree, and what we'd propose

Attributes are the right shape for these. All eleven are scalar ints and floats, which is exactly what the attribute model is for. There's also a maintenance argument specific to the bindings: cuOpt already generates CuOptConstants.java from constants.h, so a new attribute constant reaches Java with zero hand-written code, whereas a new function needs a JNI entry point, a native declaration, and a wrapper. Every future stat would be free on the binding side. That argues for attributes over the eleven individual getters proposed in #1202 as well.

What we'd suggest is a shape-based rule rather than attributes everywhere, since it's the rule the C API already follows:

  • scalars (stats, flags, counts) → attributes
  • homogeneous arrays sized by a known dimension (bounds, senses) → array attributes
  • structured, ragged, or multi-output → dedicated functions

The third case is why cuOptGetConstraintMatrix is a function rather than an attribute: CSR is three parallel arrays. The same applies to the quadratic constraint rows in #1703, where each row is a variable-length record containing variable-length arrays — no attribute scheme expresses that.

Happy to convert the two bulk cuOptGet{LP,MIP}SolverStats calls in this PR to solution attributes on that basis. It's more work than what's here now, but nothing has shipped yet, so it costs no deprecation or ABI break — this is the cheapest moment to change direction.

Conceded

cuOptSolutionIsMIP should go. You're right. It's redundant: Solution is already constructed with the problem's category, so the Java side has the answer without a native call, and a C caller normally holds the problem handle for cuOptIsMIP. We'll drop it.

The hyperparameters_only flag should go too — agreed that a public header shouldn't advertise the concept. We'll remove the flag and always dump non-hyperparameters.

One question back

On the parameter calls (cuOptLoadParametersFromFile, cuOptDumpParametersToFile, cuOptGetNumSolverParameters, cuOptGetSolverParameterName): the use case is settings introspection and file round-tripping, matching what Python offers — Java's getSolverSettingNames() and load/dumpSettingsToFile are built on them. They're convenience rather than necessity, and we're happy to drop them from this PR if you'd rather keep the C API lean and revisit separately.

Reworks the C API surface this PR adds, following review. Seven functions
become two.

Statistics are now read with cuOptGetSolutionIntAttribute and
cuOptGetSolutionFloatAttribute using CUOPT_SOLUTION_ATTR_* selectors, in place
of cuOptGetLPSolverStats and cuOptGetMIPSolverStats. This matches how problem
data is already read, and it means a future statistic is a new constant rather
than a new exported symbol, so existing callers keep working without a relink.
It also costs the bindings nothing: CuOptConstants.java is generated from
constants.h, so a new selector reaches Java with no hand-written code, where a
new function needs a JNI entry point, a native declaration, and a wrapper.

Selectors are numbered in their own range so a problem selector passed to a
solution accessor is rejected rather than silently read, and LP selectors
require an LP solution while MIP selectors require a MIP solution.

cuOptSolutionIsMIP is removed as redundant. Solution is constructed with the
category of the problem it was solved for, so it already knows whether it came
from the MIP solver, and a C caller holding the problem handle has cuOptIsMIP.

The four parameter-file and parameter-enumeration entry points are removed
rather than promoted. Nothing needs them to build, solve, or read a solution,
and one of them exposed the hyperparameters concept through a public header,
which it should not. The capability is recorded in NVIDIA#1705 so it is deferred
rather than lost. On the Java side this drops getSolverSettingNames, toDict,
and the settings-file methods; setOptimalityTolerance now names the six LP
tolerances explicitly instead of discovering them by matching parameter names,
which is also less fragile than the previous filter.

Verified: 69/69 C API gtests, including new tests that the accessors reject a
mismatched value type, the wrong solver's selectors, unknown selectors, and
null arguments; 26/26 Java tests; all pre-commit hooks.

Signed-off-by: Ramakrishna Prabhu <ramakrishnap@nvidia.com>
clang-format widens the value column to the longest macro name in the block.

Signed-off-by: Ramakrishna Prabhu <ramakrishnap@nvidia.com>
@ramakrishnap-nv

Copy link
Copy Markdown
Collaborator

/ok to test 5972293

@mlubin

mlubin commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

IMO changes to the C API should be in a separate PR, not combined with a 7000 line diff here.

NVIDIA#1705 tracked the removed parameter enumeration and settings-file entry points
as deferred work. mlubin pointed out that bindings can be generated from
constants.h, which makes runtime enumeration unnecessary.

That holds structurally, not just in practice: every one of the 117 parameter
registrations in solver_settings.cu is written as a CUOPT_* macro from
constants.h, and none of the 109 distinct registered names is absent from the
header. The list get_parameter_names() returns is therefore derived from the
same header the bindings generate from, and cannot contain anything extra.
Loading and dumping a settings file is expressible on top of cuOptSetParameter
and cuOptGetParameter, so that half needs no new C surface either.

NVIDIA#1705 is closed. Point the README at the reasoning rather than describing the
capability as pending.

Signed-off-by: Ramakrishna Prabhu <ramakrishnap@nvidia.com>
@ramakrishnap-nv

Copy link
Copy Markdown
Collaborator

/ok to test 4eb70d8

@ramakrishnap-nv

Copy link
Copy Markdown
Collaborator

@mlubin agreed — the C API changes are now #1715, off main, 318 lines across 4 files with no reference to Java.

This PR is stacked on it. The cpp/ changes still show in this diff because the Java bindings call cuOptGetSolutionIntAttribute / cuOptGetSolutionFloatAttribute and would not build without them; they will drop out of this diff automatically once #1715 merges and main is merged back in.

Two related issues were also split out of the earlier discussion, so each is reviewable on its own:

#1705 is closed: you were right that runtime parameter enumeration is unnecessary. Every one of the 117 parameter registrations is written as a CUOPT_* macro from constants.h, and none of the 109 distinct registered names is missing from the header, so a binding generated from that header has the complete set by construction.

Documentation wording and the scoped solution guard in the C API tests, kept
identical to the branch behind NVIDIA#1715 so this stack stays consistent until that
PR merges and these files drop out of this diff.

Signed-off-by: Ramakrishna Prabhu <ramakrishnap@nvidia.com>
@ramakrishnap-nv

Copy link
Copy Markdown
Collaborator

/ok to test d981aec

Keeps the cpp/ files in this stack identical to the branch behind NVIDIA#1715.

Signed-off-by: Ramakrishna Prabhu <ramakrishnap@nvidia.com>
@ramakrishnap-nv

Copy link
Copy Markdown
Collaborator

/ok to test 6a04604

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature request New feature or request non-breaking Introduces a non-breaking change

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants