MIP Examples#
These examples show mixed-integer modeling, MIP starts, semi-continuous variables, and incumbent callbacks in Java.
Simple MIP#
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 SimpleMip {
8 public static void main(String[] args) throws Exception {
9 try (Problem problem = new Problem("simple-milp")) {
10 Variable x = problem.addVariable(
11 0.0, 100.0, 3.0, VariableType.INTEGER, "x");
12 Variable y = problem.addVariable(
13 0.0, 100.0, 5.0, VariableType.INTEGER, "y");
14
15 problem.addConstraint(
16 LinearExpression.of(x).times(2.0).plus(y).le(8.0), "capacity");
17 problem.setObjective(
18 LinearExpression.of(x).times(3.0).plus(y, 5.0),
19 ObjectiveSense.MAXIMIZE);
20
21 try (SolverSettings settings = new SolverSettings()
22 .setSetting(CuOptConstants.CUOPT_TIME_LIMIT, 10.0);
23 Solution solution = problem.solve(settings)) {
24 System.out.println("Status: " + solution.getTerminationStatus());
25 System.out.println("x = " + x.getValue());
26 System.out.println("y = " + y.getValue());
27 System.out.println("Objective = " + solution.getPrimalObjective());
28 System.out.println("MIP gap = " + solution.getMIPGap());
29 System.out.println("Bound = " + solution.getSolutionBound());
30 }
31 }
32 }
33}
Example Response:
Status: OPTIMAL
x = 0.0
y = 8.0
Objective = 40.0
MIP gap = 0.0
Bound = 40.0
The MIP solver can return a feasible solution before proving optimality. Use the termination status, MIP gap, and solution bound together when interpreting the result.
Semi-Continuous Variables#
SEMI_CONTINUOUS variables are zero or lie within their declared bounds.
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 SemiContinuous {
8 public static void main(String[] args) throws Exception {
9 try (Problem problem = new Problem("semi-continuous")) {
10 Variable production = problem.addVariable(
11 10.0, 100.0, 1.0,
12 VariableType.SEMI_CONTINUOUS, "production");
13
14 // cuOptCreateProblem currently requires at least one linear constraint row.
15 problem.addConstraint(LinearExpression.of(production).le(1000.0), "capacity");
16
17 problem.setObjective(production, ObjectiveSense.MINIMIZE);
18
19 try (Solution solution = problem.solve()) {
20 System.out.println("production = " + production.getValue());
21 }
22 }
23 }
24}
MIP Starts#
Set starts on variables when using the high-level Problem API:
x.setMIPStart(3.0);
y.setMIPStart(2.0);
try (SolverSettings settings = new SolverSettings();
Solution solution = problem.solve(settings)) {
System.out.println(solution.getPrimalObjective());
}
Setting a start per variable avoids handling the ordering at all, and is the form to prefer.
SolverSettings.addMIPStart takes a complete array instead, indexed by
Variable.getIndex(). It is the way to supply more than one starting point,
since it can be called repeatedly while each Variable holds a single value.
Build it from getVariables so the ordering comes from the problem rather
than from you:
try (SolverSettings settings = new SolverSettings()) {
double[] values = new double[problem.getNumVariables()];
for (Variable variable : problem.getVariables()) {
values[variable.getIndex()] = variable.getMIPStart();
}
settings.addMIPStart(values);
try (Solution solution = problem.solve(settings)) {
System.out.println(solution.getPrimalObjective());
}
}
MIP starts are currently unsupported with presolve on.
Incumbent Callback#
Register an incumbent callback before solving:
try (SolverSettings settings = new SolverSettings()) {
settings.setMIPCallback(
(incumbent, objective, bound, userData) -> {
System.out.println(
"incumbent objective=" + objective + ", bound=" + bound);
},
null,
problem.getNumVariables());
try (Solution solution = problem.solve(settings)) {
System.out.println("Final status: " + solution.getTerminationStatus());
}
}
The callback receives a defensive copy of the incumbent vector, the incumbent objective, the current solution bound, and the user data object.
The vector is in variable-index order. To read specific variables out of it
without depending on that order, pass them to Problem.fromIncumbent, which
returns their values in the order you ask for:
try (SolverSettings settings = new SolverSettings()) {
settings.setMIPCallback(
(incumbent, objective, bound, userData) -> {
double[] picked = Problem.fromIncumbent(incumbent, y, x);
System.out.println("y=" + picked[0] + " x=" + picked[1]);
},
null,
problem.getNumVariables());
try (Solution solution = problem.solve(settings)) {
System.out.println("Final status: " + solution.getTerminationStatus());
}
}
LP Relaxation#
Relax the integer variables before solving:
for (Variable variable : problem.getVariables()) {
variable.setVariableType(VariableType.CONTINUOUS);
}
try (Solution solution = problem.solve()) {
System.out.println("LP relaxation objective = " + solution.getPrimalObjective());
}