/* Copyright 2026, Gurobi Optimization, LLC */
/* This example formulates and solves the following simple nonlinear model
using the nonlinear constraint API:
minimize x - y
subject to sin(x) * x + x^2 * y <= 1
y = cos(x) (<=> cos(x) - y = 0)
-1 <= x <= 2
0 <= y <= 2
The nonlinear constraint is set via addNLConstr() using an expression tree.
Then we retrieve the tree with getNLConstrLHS() and verify it, delete it with
remove(), replace it with a simple linear constraint, and re-optimize.
*/
import com.gurobi.gurobi.*;
public class NLConstr {
public static void main(String[] args) {
try {
// Create environment
GRBEnv env = new GRBEnv("nlconstr.log");
// Create empty model
GRBModel model = new GRBModel(env);
// Create variables
GRBVar x = model.addVar(-1.0, 2.0, 1.0, GRB.CONTINUOUS, "x");
GRBVar y = model.addVar( 0.0, 2.0, -1.0, GRB.CONTINUOUS, "y");
/* Expression tree for sin(x) * x + x^2 * y (10 nodes)
*
* node 0: PLUS (root)
* node 1: MULTIPLY (child of 0) -> sin(x) * x
* node 2: SIN (child of 1)
* node 3: VARIABLE x (child of 2)
* node 4: VARIABLE x (child of 1)
* node 5: MULTIPLY (child of 0) -> x^2 * y
* node 6: POW (child of 5)
* node 7: VARIABLE x (child of 6)
* node 8: CONSTANT 2 (child of 6)
* node 9: VARIABLE y (child of 5)
*/
int[] opcode1 = new int[] {
GRB.OPCODE_PLUS, // 0: root
GRB.OPCODE_MULTIPLY, // 1: sin(x)*x
GRB.OPCODE_SIN, // 2: sin(...)
GRB.OPCODE_VARIABLE, // 3: x
GRB.OPCODE_VARIABLE, // 4: x
GRB.OPCODE_MULTIPLY, // 5: x^2 * y
GRB.OPCODE_POW, // 6: x^2
GRB.OPCODE_VARIABLE, // 7: x
GRB.OPCODE_CONSTANT, // 8: 2.0
GRB.OPCODE_VARIABLE // 9: y
};
double[] data1 = new double[] {
-1.0, -1.0, -1.0,
x.index(), // x index
x.index(), // x index
-1.0, -1.0,
x.index(), // x index
2.0,
y.index() // y index
};
int[] parent1 = new int[] {-1, 0, 1, 2, 1, 0, 5, 6, 6, 5};
/* Expression tree for cos(x) - y = 0 (4 nodes)
*
* node 0: MINUS (root)
* node 1: COS (child of 0)
* node 2: VARIABLE x (child of 1)
* node 3: VARIABLE y (child of 0)
*/
int[] opcode2 = new int[] {
GRB.OPCODE_MINUS, // 0: root
GRB.OPCODE_COS, // 1: cos(...)
GRB.OPCODE_VARIABLE, // 2: x
GRB.OPCODE_VARIABLE, // 3: y
};
double[] data2 = new double[] {
-1.0, -1.0,
x.index(), // x index
y.index() // y index
};
int[] parent2 = new int[] {-1, 0, 1, 0};
// Add nonlinear constraint: sin(x) * x + x^2 * y <= 1
GRBNLConstr nlc1 = model.addNLConstr(opcode1, data1, parent1,
GRB.LESS_EQUAL, 1.0,
"NonlinearConstraint1");
// Add nonlinear constraint: cos(x) - y = 0
GRBNLConstr nlc2 = model.addNLConstr(opcode2, data2, parent2,
GRB.EQUAL, 0.0,
"NonlinearConstraint2");
// Optimize model
model.optimize();
System.out.println("\nFirst solve (nonlinear constraints)");
if (model.get(GRB.IntAttr.Status) == GRB.OPTIMAL) {
System.out.printf("Optimal objective: %.4e%n",
model.get(GRB.DoubleAttr.ObjVal));
System.out.printf(" x=%.6f, y=%.6f%n",
x.get(GRB.DoubleAttr.X),
y.get(GRB.DoubleAttr.X));
} else if (model.get(GRB.IntAttr.Status) == GRB.INF_OR_UNBD) {
System.out.println("Model is infeasible or unbounded");
} else {
System.out.println("Optimization was stopped early");
}
// Retrieve the nonlinear constraint and print the number of nodes
int[] nnodes = new int[1];
model.getNLConstrLHS(nlc1, nnodes, null, null, null);
System.out.println("\nRetrieved NL constraint with " + nnodes[0] +
" nodes");
// Delete nonlinear constraints
model.remove(nlc1);
model.remove(nlc2);
model.update();
System.out.println("Deleted nonlinear constraints");
// Add a simple linear constraint instead: x + y >= 1
GRBLinExpr expr = new GRBLinExpr();
expr.addTerm(1.0, x);
expr.addTerm(1.0, y);
model.addConstr(expr, GRB.GREATER_EQUAL, 1.0, "LinearConstraint");
// Re-optimize
model.optimize();
System.out.println("\nSecond solve (linear constraint)");
if (model.get(GRB.IntAttr.Status) == GRB.OPTIMAL) {
System.out.printf("Optimal objective: %.4e%n",
model.get(GRB.DoubleAttr.ObjVal));
System.out.printf(" x=%.6f, y=%.6f%n",
x.get(GRB.DoubleAttr.X),
y.get(GRB.DoubleAttr.X));
} else if (model.get(GRB.IntAttr.Status) == GRB.INF_OR_UNBD) {
System.out.println("Model is infeasible or unbounded");
} else {
System.out.println("Optimization was stopped early");
}
// Dispose of model and environment
model.dispose();
env.dispose();
} catch (GRBException e) {
System.out.println("Error code: " + e.getErrorCode() + ". " +
e.getMessage());
}
}
}