Java Quickstart Guide#

NVIDIA cuOpt provides experimental Java bindings for LP, MIP, QP, QCQP, and SOCP, built from java/cuopt. It is not part of the top-level cuOpt build.

Installation#

Choose your install method below; the selector is pre-set for Java. Copy the Docker command and run it in your environment — cuopt.jar and libcuopt_jni.so are already at /opt/cuopt/java inside the container, so no build step is needed. Use -cp /opt/cuopt/java/cuopt.jar for both compilation and execution, and pass -Dcuopt.native.dir=/opt/cuopt/java only to the java command. See Installation for all interfaces and options.

Using the Maven Artifact#

com.nvidia.cuopt:cuopt publishes classifier jars (cuda12, cuda12-arm64, cuda13, cuda13-arm64) to the Sonatype snapshot and release repositories. Each classifier jar embeds libcuopt_jni.so and cuOpt’s own native dependencies (libcuopt, rmm, cuDSS, NCCL, TBB), which NativeLibraryLoader extracts to a temp directory and loads automatically — no cuopt.native.dir is required:

<repositories>
  <repository>
    <id>sonatype-snapshots</id>
    <url>https://central.sonatype.com/repository/maven-snapshots</url>
    <releases><enabled>false</enabled></releases>
    <snapshots><enabled>true</enabled></snapshots>
  </repository>
</repositories>

<dependency>
  <groupId>com.nvidia.cuopt</groupId>
  <artifactId>cuopt</artifactId>
  <version>26.10.0-SNAPSHOT</version>
  <classifier>cuda12</classifier>
</dependency>

Note

The embedded libraries do not include the CUDA toolkit’s own math libraries (libcublas, libcusolver, etc.) — install them separately, or use an nvidia/cuda:*-runtime-* base image instead, which already has them without installing cuOpt itself. Loading the jar without them fails with an UnsatisfiedLinkError naming the missing CUDA library.

# Debian/Ubuntu (with NVIDIA's apt repo already configured)
sudo apt-get install cuda-libraries-12-9

# RHEL/Rocky/Fedora (with NVIDIA's dnf repo already configured)
sudo dnf install cuda-libraries-12-9

cuda-libraries is much lighter than the full CUDA toolkit. See NVIDIA’s CUDA repository setup if the repo isn’t configured yet.

Building from source is covered in java/cuopt/README.md.

Smoke Test#

After installation, verify cuOpt Java is working by compiling and running a minimal LP inside the container.

SmokeTest.java

 1/*
 2 * SPDX-FileCopyrightText: Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
 3 * SPDX-License-Identifier: Apache-2.0
 4 */
 5import com.nvidia.cuopt.mathematicaloptimization.*;
 6
 7public class SmokeTest {
 8  public static void main(String[] args) throws Exception {
 9    try (Problem problem = new Problem("smoke-test")) {
10      Variable x = problem.addVariable(0, Double.POSITIVE_INFINITY, 0,
11          VariableType.CONTINUOUS, "x");
12      Variable y = problem.addVariable(0, Double.POSITIVE_INFINITY, 0,
13          VariableType.CONTINUOUS, "y");
14      problem.addConstraint(LinearExpression.of(x).plus(y).ge(1.0), "c0");
15      problem.setObjective(LinearExpression.of(x).plus(y), ObjectiveSense.MINIMIZE);
16      try (Solution solution = problem.solve()) {
17        System.out.println(solution.getTerminationStatus());
18        System.out.println(solution.getPrimalObjective());
19      }
20    }
21  }
22}
javac -cp /opt/cuopt/java/cuopt.jar -d . SmokeTest.java
java -Dcuopt.native.dir=/opt/cuopt/java -cp /opt/cuopt/java/cuopt.jar:. SmokeTest

Example Response:

OPTIMAL
1.0

LP Example#

A Problem owns the variables and constraints. Expressions are assembled with methods that return a new expression, and a constraint is formed by comparing one against a bound with le, ge or eq.

LpExample.java

 1/*
 2 * SPDX-FileCopyrightText: Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
 3 * SPDX-License-Identifier: Apache-2.0
 4 */
 5import com.nvidia.cuopt.mathematicaloptimization.*;
 6
 7public class LpExample {
 8  public static void main(String[] args) throws Exception {
 9    try (Problem problem = new Problem("simple")) {
10      Variable x = problem.addVariable(0, Double.POSITIVE_INFINITY, 0,
11          VariableType.CONTINUOUS, "x");
12      Variable y = problem.addVariable(0, Double.POSITIVE_INFINITY, 0,
13          VariableType.CONTINUOUS, "y");
14
15      problem.addConstraint(LinearExpression.of(x).plus(y).ge(1.0), "c0");
16      problem.setObjective(LinearExpression.of(x).plus(y), ObjectiveSense.MINIMIZE);
17
18      try (SolverSettings settings = new SolverSettings()
19               .setSetting(CuOptConstants.CUOPT_METHOD, SolverMethod.PDLP.nativeValue());
20           Solution solution = problem.solve(settings)) {
21        System.out.println(solution.getTerminationStatus());
22        System.out.println(solution.getPrimalObjective());
23      }
24    }
25  }
26}

MIP Example#

MipExample.java

 1/*
 2 * SPDX-FileCopyrightText: Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
 3 * SPDX-License-Identifier: Apache-2.0
 4 */
 5import com.nvidia.cuopt.mathematicaloptimization.*;
 6
 7public class MipExample {
 8  public static void main(String[] args) throws Exception {
 9    try (Problem problem = new Problem("integer")) {
10      Variable x = problem.addVariable(0, 10, 1.0, VariableType.INTEGER, "x");
11      problem.addConstraint(LinearExpression.of(x).ge(1.0));
12
13      try (SolverSettings settings = new SolverSettings()
14               .setSetting(CuOptConstants.CUOPT_TIME_LIMIT, 10.0);
15           Solution solution = problem.solve(settings)) {
16        System.out.println(solution.getMIPGap());
17        System.out.println(solution.getSolutionBound());
18      }
19    }
20  }
21}

QP Example#

QpQuickstart.java

 1/*
 2 * SPDX-FileCopyrightText: Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
 3 * SPDX-License-Identifier: Apache-2.0
 4 */
 5import com.nvidia.cuopt.mathematicaloptimization.*;
 6
 7public class QpQuickstart {
 8  public static void main(String[] args) throws Exception {
 9    try (Problem problem = new Problem("quadratic")) {
10      Variable x = problem.addVariable(0.0, 10.0, 0.0, VariableType.CONTINUOUS, "x");
11      Variable y = problem.addVariable(0.0, 10.0, 0.0, VariableType.CONTINUOUS, "y");
12      problem.addConstraint(LinearExpression.of(x).plus(y).ge(5.0));
13      problem.setObjective(
14          QuadraticExpression.of(x, x, 1.0).plus(y, y, 4.0),
15          ObjectiveSense.MINIMIZE);
16      try (Solution solution = problem.solve()) {
17        System.out.println(solution.getPrimalObjective());
18      }
19    }
20  }
21}

MPS I/O#

MpsRoundtrip.java and sample.mps

 1/*
 2 * SPDX-FileCopyrightText: Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
 3 * SPDX-License-Identifier: Apache-2.0
 4 */
 5import com.nvidia.cuopt.mathematicaloptimization.*;
 6
 7public class MpsRoundtrip {
 8  public static void main(String[] args) throws Exception {
 9    try (Problem problem = Problem.read("sample.mps")) {
10      System.out.println("Variables: " + problem.getNumVariables());
11      problem.write("roundtrip.mps");
12    }
13  }
14}

Lifecycle#

SolverSettings and Solution own native handles and implement AutoCloseable, so close them with try-with-resources. They also register a Cleaner fallback, but closing them deterministically keeps native memory pressure predictable.

Expressions are built and compared through methods — plus, minus, le, ge and eq — each returning a new object rather than mutating the receiver. The following pages document the implemented LP/MIP/QP/QCQP/SOCP surface.