Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
9e8fba9
Java bindings for LP/MIP/QP
nvidiacbrissette Jul 7, 2026
9e76c16
removing some logs etc.
nvidiacbrissette Jul 7, 2026
c61bb62
many PR updates based on comments.
nvidiacbrissette Jul 9, 2026
e8f178d
Fully removed DataModel
nvidiacbrissette Jul 9, 2026
85e5440
Reorganized pr.yaml to avoid conflicts.
nvidiacbrissette Jul 9, 2026
fa275f6
Changes in response to comments.
nvidiacbrissette Jul 17, 2026
54bfe2d
style and test updates.
nvidiacbrissette Jul 29, 2026
1f5a5fb
Merge branch 'main' into cbrissette/cuopt-bindings
ramakrishnap-nv Aug 10, 2026
275f657
Move the Java native extensions into the public C API
ramakrishnap-nv Aug 11, 2026
233a9c1
Add PDLP warm-start settings and harden the CUDA driver probe
ramakrishnap-nv Aug 11, 2026
7063df8
Route problem bound getters through the C API
ramakrishnap-nv Aug 11, 2026
93c907a
Keep the LP solution getters on the internal path
ramakrishnap-nv Aug 11, 2026
9decf1e
Wire the Java module into build.sh and align it with cuvs
ramakrishnap-nv Aug 11, 2026
d2ceef7
Guard against JNI symbol drift and complete the POM metadata
ramakrishnap-nv Aug 11, 2026
f0a264f
Add an escape hatch to the JNI symbol check
ramakrishnap-nv Aug 11, 2026
57aaeb6
Address CodeRabbit review on the pushed changes
ramakrishnap-nv Aug 12, 2026
d87382c
Fix pre-commit failures
ramakrishnap-nv Aug 12, 2026
4db2d2b
Merge branch 'main' into cbrissette/cuopt-bindings
ramakrishnap-nv Aug 12, 2026
bbe4b5b
Merge branch 'main' into cbrissette/cuopt-bindings
ramakrishnap-nv Aug 12, 2026
99c3964
Expose solver statistics as solution attributes
ramakrishnap-nv Aug 12, 2026
5972293
Align the solution attribute constants
ramakrishnap-nv Aug 12, 2026
4eb70d8
Record why the parameter entry points were dropped, not deferred
ramakrishnap-nv Aug 12, 2026
d981aec
Sync the C API review changes from #1715
ramakrishnap-nv Aug 13, 2026
6a04604
Sync the attribute dispatch change from #1715
ramakrishnap-nv Aug 13, 2026
8d854d3
Merge remote-tracking branch 'origin/main' into pr-1524-java
ramakrishnap-nv Aug 14, 2026
dc8b4b0
Address the self-contained review comments on the Java surface
ramakrishnap-nv Aug 14, 2026
39cbff3
Remove the IP paragraph from the Java docs
ramakrishnap-nv Aug 14, 2026
8b178d9
Remove Problem.isSolved
ramakrishnap-nv Aug 14, 2026
ce50c37
Trim the Java surface to what is needed
ramakrishnap-nv Aug 17, 2026
d1ebd46
Drop the C API changes from this branch
ramakrishnap-nv Aug 17, 2026
8a06bf2
Give the Java CI environment the headers libcuopt's headers need
ramakrishnap-nv Aug 18, 2026
acd9be0
Merge remote-tracking branch 'origin/main' into pr-1524-java
ramakrishnap-nv Aug 18, 2026
d757259
Drop solver statistics from the Java API
ramakrishnap-nv Aug 18, 2026
84a9af6
Read solver statistics as solution attributes
ramakrishnap-nv Aug 18, 2026
44302d9
Cover the model mutation and MIP start paths
ramakrishnap-nv Aug 18, 2026
785faec
Merge remote-tracking branch 'origin/main' into pr-1524-java
ramakrishnap-nv Aug 18, 2026
d4660f3
Merge remote-tracking branch 'origin/main' into pr-1524-java
ramakrishnap-nv Aug 19, 2026
86cd996
Retry Maven Central resolution on transient failures
ramakrishnap-nv Aug 19, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
188 changes: 188 additions & 0 deletions docs/cuopt/source/cuopt-java/convex/convex-api.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
===================================
Convex Optimization API Reference
===================================

The Java LP/QP bindings are in the package
``com.nvidia.cuopt.linearprogramming``. The public API is documented below by
Comment thread
nvidiacbrissette marked this conversation as resolved.
Outdated
role. Method names are Java names and therefore use fluent methods instead of
Python operator overloads.

High-level model
----------------

``Problem`` is the recommended entry point for models built in Java.
Comment thread
nvidiacbrissette marked this conversation as resolved.
Outdated

.. list-table:: ``Problem``
:header-rows: 1
:widths: 28 72

* - API
- Description
* - ``new Problem()`` / ``new Problem(String name)``
- Create an empty model, optionally with a problem name.
* - ``addVariable(...)``
- Add a variable with lower/upper bounds, objective coefficient, variable type, and name.
* - ``addConstraint(Constraint, String name)``
- Add a linear or quadratic constraint.
* - ``setObjective(LinearExpression, ObjectiveSense)``
- Set a linear objective.
* - ``setObjective(QuadraticExpression, ObjectiveSense)``
- Set a quadratic objective with optional linear and constant terms.
* - ``solve()`` / ``solve(SolverSettings)``
- Convert the model to a native ``DataModel`` and return a ``Solution``.
* - ``toDataModel()``
Comment thread
nvidiacbrissette marked this conversation as resolved.
Outdated
- Materialize the high-level model as the lower-level native data model.
* - ``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.

* - ``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.

- Write or load MPS/QPS-backed models. The fixed-format overloads accept a boolean flag.
* - ``update()`` / ``updateConstraint(...)`` / ``updateObjective(...)``
- Update model state and reset solved values where appropriate.
* - ``relax()``
- Return a copy with variables converted to continuous type.

The model also exposes ``getVariables``, ``getVariable``, ``getConstraints``,
``getConstraint``, ``getNumVariables``, ``getNumConstraints``,
``getNumNonZeros``, ``isMip``, ``isSolved``, ``getStatus``,
Comment thread
nvidiacbrissette marked this conversation as resolved.
Outdated
``getObjectiveValue``, and ``getSolveTime``.

Low-level data model
--------------------

``DataModel`` is useful when the problem is already available as arrays or
when direct access to native CSR and quadratic data is required.

Create a model with one of the following factories:

.. code-block:: java

DataModel.createProblem(
numConstraints, numVariables, objectiveSense, objectiveOffset,
objectiveCoefficients, constraintMatrix, constraintSense, rhs,
variableLowerBounds, variableUpperBounds, variableTypes);

DataModel.createRangedProblem(
numConstraints, numVariables, objectiveSense, objectiveOffset,
objectiveCoefficients, constraintMatrix, constraintLowerBounds,
constraintUpperBounds, variableLowerBounds, variableUpperBounds,
variableTypes);

``CsrMatrix`` stores ``rowOffsets``, ``columnIndices``, and ``values``. The
arrays are available through ``getRowOffsets``, ``getColumnIndices``, and
``getValues``.

The mutable ``DataModel`` setters cover:

* objective sense, coefficients, offset, and scaling factor;
* linear constraint CSR arrays, row types, RHS, and ranged bounds;
* variable bounds, types, names, and row names;
* objective and problem names;
* initial primal and dual solutions; and
* quadratic objective matrices and quadratic constraints.

The corresponding getters include ``getConstraintMatrix``,
``getConstraintMatrixValues``, ``getConstraintMatrixIndices``,
``getConstraintMatrixOffsets``, ``getConstraintRhs``,
``getConstraintLowerBounds``, ``getConstraintUpperBounds``,
``getQuadraticObjectiveValues``, ``getQuadraticObjectiveIndices``,
``getQuadraticObjectiveOffsets``, ``getQuadraticConstraints``,
``getVariableNames``, ``getRowNames``, ``getObjectiveName``,
``getProblemName``, ``getProblemCategory``, and ``toDict``.

Use ``clearQuadraticConstraints`` to remove all quadratic constraints from a
mutable data model. ``DataModel`` implements ``AutoCloseable``.

Variables, expressions, and constraints
----------------------------------------

``Variable`` stores the model index, bounds, objective coefficient, type,
name, solved value, reduced cost, and optional MIP start. Its mutable methods
return the variable so calls can be chained:

.. code-block:: java

Variable x = problem.addVariable(
0.0, Double.POSITIVE_INFINITY, 1.0,
VariableType.CONTINUOUS, "x");
x.setUpperBound(100.0).setObjectiveCoefficient(2.0);

``LinearExpression`` supports ``of``, ``ofConstant``, ``plus``, ``minus``,
``times``, ``dividedBy``, ``constant``, and the comparison methods ``le``,
``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

arithmetic pattern. It can also contain linear and constant terms. Its
``le`` and ``ge`` methods return quadratic constraints; ``eq`` throws because
equality quadratic constraints are not supported.

The enums used in model construction are:

* ``ObjectiveSense.MINIMIZE`` and ``ObjectiveSense.MAXIMIZE``;
* ``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.


Solver settings
---------------

``SolverSettings`` owns native solver configuration and implements
``AutoCloseable``. Parameters can be set with the overloaded
``setParameter`` methods for ``String``, ``int``, ``double``, and ``boolean``
Comment thread
nvidiacbrissette marked this conversation as resolved.
Outdated
values. Use ``getParameter`` or ``getParameterAsString`` for the native string
representation, and ``getTypedParameter`` when a Java ``Boolean``,
``Integer``, ``Double``, or ``String`` value is preferred.

The settings API also includes:

* ``getSolverParameterNames`` and the static setting accessors;
* ``setMethod`` and ``setPdlpSolverMode``;
* ``setOptimalityTolerance``;
* primal and dual initial solutions;
* ``dumpParametersToFile`` and ``loadParametersFromFile``;
* ``toDict``;
* ``setPdlpWarmStartData``; and
Comment thread
nvidiacbrissette marked this conversation as resolved.
Outdated
* MIP callback registration through ``setMipCallback``.

``SolverMethod`` includes ``PDLP``, ``DUAL_SIMPLEX``, ``BARRIER``,
``CONCURRENT``, and ``UNSET``. ``PDLPSolverMode`` exposes the supported PDLP
solver modes.

Solutions and statistics
------------------------

``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.

* ``getPrimalObjective`` and ``getDualObjective``;
* ``getTerminationStatus`` and ``getTerminationReason``;
* ``getErrorStatus`` and ``getErrorMessage``;
* ``getSolveTime`` and ``getProblemCategory``; and
* ``getVars`` when variable names are available.

LP solutions additionally expose ``getLpStats`` and PDLP warm-start data.
Comment thread
nvidiacbrissette marked this conversation as resolved.
Outdated
``LPStats`` contains primal residual, dual residual, gap, iteration count, and
the ``SolverMethod`` used. MIP-only solution fields are documented in
:doc:`../mip/mip-api`.

MPS, batching, and errors
-------------------------

``DataModel.read``, ``DataModel.parseMps``, ``Problem.read``, and
Comment thread
nvidiacbrissette marked this conversation as resolved.
Outdated
``Problem.readMPS`` support MPS/QPS parsing, including a fixed-format boolean
overload. ``writeMPS`` writes a model for round trips or use by another cuOpt
interface.

``BatchSolve.solve(List<DataModel>, SolverSettings)`` is a sequential Java
compatibility entry point. It returns ``BatchSolveResult``, containing the
solutions and elapsed solve time.

Native failures are reported as ``CuOptException`` with a cuOpt status code
available through ``getStatusCode``. Accessing an LP-only field on a MIP
solution, or a MIP-only field on an LP solution, raises
``IllegalStateException``.
182 changes: 182 additions & 0 deletions docs/cuopt/source/cuopt-java/convex/convex-examples.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
============================
Convex Optimization Examples
============================

These examples show the Java modeling patterns corresponding to the Python
LP/QP examples. They assume the Java module has been compiled as described in
:doc:`../quick-start` and that the application can load ``libcuopt_jni``.

Simple linear programming
--------------------------

The high-level API uses fluent expressions and explicit comparison methods.

.. code-block:: java

import com.nvidia.cuopt.linearprogramming.*;

try (Problem problem = new Problem("simple-lp")) {
Variable x = problem.addVariable(
0.0, Double.POSITIVE_INFINITY, 1.0,
VariableType.CONTINUOUS, "x");
Variable y = problem.addVariable(
0.0, Double.POSITIVE_INFINITY, 1.0,
VariableType.CONTINUOUS, "y");

problem.addConstraint(
LinearExpression.of(x).plus(y).ge(10.0), "demand");
problem.setObjective(
LinearExpression.of(x).plus(y), ObjectiveSense.MINIMIZE);

try (SolverSettings settings = new SolverSettings()
.setMethod(SolverMethod.PDLP);
Solution solution = problem.solve(settings)) {
System.out.println("Status: " + solution.getTerminationStatus());
System.out.println("x = " + x.getValue());
System.out.println("y = " + y.getValue());
System.out.println("Objective = " + solution.getPrimalObjective());
}
}

``Problem.solve`` copies the model to a native ``DataModel`` and populates
the ``Variable`` and ``Constraint`` objects after the solve. The solution
object remains available for detailed native results and statistics.

Low-level CSR linear program
-----------------------------

Use ``DataModel`` when the input is already in CSR form:

.. code-block:: java

CsrMatrix matrix = new CsrMatrix(
new int[] {0, 2}, // row offsets
new int[] {0, 1}, // column indices
new double[] {1.0, 1.0});

try (DataModel model = DataModel.createProblem(
1, 2,
ObjectiveSense.MINIMIZE,
0.0,
new double[] {1.0, 1.0},
matrix,
new byte[] {(byte) 'G'},
Comment thread
nvidiacbrissette marked this conversation as resolved.
Outdated
new double[] {10.0},
new double[] {0.0, 0.0},
new double[] {Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY},
new byte[] {(byte) 'C', (byte) 'C'});
SolverSettings settings = new SolverSettings().setMethod(SolverMethod.PDLP);
Solution solution = model.solve(settings)) {
System.out.println(solution.getPrimalObjective());
System.out.println(model.getConstraintMatrix().getRowOffsets().length);
}

For ranged rows, use ``createRangedProblem`` with
``constraintLowerBounds`` and ``constraintUpperBounds`` instead of row sense
and RHS arrays. The mutable setters provide the same representation after an
empty ``new DataModel()``.

Simple quadratic programming
-----------------------------

Quadratic objectives combine quadratic, linear, and constant terms:

.. code-block:: java

try (Problem problem = new Problem("simple-qp")) {
Variable x = problem.addVariable(0.0, 10.0, 0.0, VariableType.CONTINUOUS, "x");
Variable y = problem.addVariable(0.0, 10.0, 0.0, VariableType.CONTINUOUS, "y");

QuadraticExpression objective = QuadraticExpression
.of(x, x, 1.0)
.plus(y, y, 1.0)
.plus(LinearExpression.of(x).times(-1.0))
.plus(LinearExpression.of(y).times(-1.0));

problem.addConstraint(
LinearExpression.of(x).plus(y).eq(1.0), "sum");
problem.setObjective(objective, ObjectiveSense.MINIMIZE);

try (Solution solution = problem.solve()) {
System.out.println("x = " + x.getValue());
System.out.println("y = " + y.getValue());
System.out.println("Objective = " + solution.getPrimalObjective());
System.out.println("LP stats gap = " + solution.getLpStats().getGap());
}
}

The lower-level equivalent is ``DataModel.setQuadraticObjective`` with a
``QuadraticExpression`` or ``setQuadraticObjectiveMatrix`` with quadratic CSR
arrays. For QP solutions, ``getPrimalSolution``, ``getDualSolution``,
``getReducedCost``, ``getDualObjective``, and ``getLpStats`` are available when
the solver returns the corresponding values.

Quadratic constraints
---------------------

Quadratic constraints can be added to a high-level ``Problem`` or directly to
a ``DataModel``:

.. code-block:: java

try (Problem problem = new Problem("quadratic-constraint")) {
Variable x = problem.addVariable(0.0, 10.0, 1.0, VariableType.CONTINUOUS, "x");
Variable y = problem.addVariable(0.0, 10.0, 1.0, VariableType.CONTINUOUS, "y");

QuadraticExpression radius = QuadraticExpression
.of(x, x, 1.0)
.plus(y, y, 1.0);
problem.addConstraint(radius.le(4.0), "radius");
problem.setObjective(
LinearExpression.of(x).plus(y), ObjectiveSense.MAXIMIZE);

try (Solution solution = problem.solve()) {
System.out.println(solution.getTerminationStatus());
}
}

Only ``LE`` and ``GE`` quadratic constraints are supported. Calling
``QuadraticExpression.eq`` or adding an equality quadratic constraint raises
Comment thread
nvidiacbrissette marked this conversation as resolved.
Outdated
``IllegalArgumentException``.

Reading and writing MPS/QPS
---------------------------

``DataModel`` and ``Problem`` expose both extension-dispatch and direct MPS
entry points:

.. code-block:: java

try (DataModel model = DataModel.read("model.mps")) {
System.out.println("Variables: " + model.getNumVariables());
System.out.println("QP terms: " + model.getQuadraticObjectiveValues().length);
model.writeMPS("roundtrip.mps");
}

try (DataModel fixed = DataModel.parseMps("fixed-format.mps", true)) {
// Use fixed-format parsing explicitly.
}

``Problem.read`` and ``Problem.readMPS`` build the high-level Java model from
the parsed data. Parsing failures are reported as ``CuOptException`` with the
cuOpt status code available from ``getStatusCode``.

Inspecting solutions and PDLP warm starts
------------------------------------------

LP solutions expose residuals and solver metadata through ``LPStats``. When
PDLP warm-start data is available, retrieve a defensive-copy representation:

.. code-block:: java

try (SolverSettings settings = new SolverSettings().setMethod(SolverMethod.PDLP);
Solution solution = problem.solve(settings)) {
if (solution.hasPdlpWarmStartData()) {
PDLPWarmStartData warmStart = solution.getPdlpWarmStartData();
System.out.println(warmStart.getCurrentPrimalSolution().length);
System.out.println(warmStart.getTotalPdlpIterations());
}
}

The same ``PDLPWarmStartData`` can be supplied to
``SolverSettings.setPdlpWarmStartData`` for a subsequent compatible LP solve.
26 changes: 26 additions & 0 deletions docs/cuopt/source/cuopt-java/convex/index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
=====================================
Convex Optimization (LP/QP)
=====================================

This section documents the Java bindings for continuous linear and quadratic
optimization. The Java API includes both:

* a high-level modeling API based on ``Problem``, ``Variable``, expressions,
and constraints; and
* a lower-level ``DataModel`` API that exposes CSR data, ranged bounds,
quadratic matrices, MPS I/O, and solver results.

Quadratic constraints are supported for ``LE`` and ``GE`` constraints. Equality
quadratic constraints are rejected by the Java API. Dedicated SOCP modeling
Comment thread
nvidiacbrissette marked this conversation as resolved.
Outdated
helpers are not currently exposed; cone models can be represented through the
supported quadratic-expression API when they satisfy cuOpt's quadratic
constraint requirements.

.. toctree::
:maxdepth: 3
:caption: LP/QP Java API
:name: LP/QP Java API Reference
:titlesonly:

convex-api.rst
convex-examples.rst
Loading