/* Copyright 2026, Gurobi Optimization, LLC */
/* This example formulates and solves the following simple nonlinear model
using the nonlinear objective API:
minimize sin(x) * x + x^2 * y
subject to x + y >= 1
-1 <= x <= 2
0 <= y <= 2
The nonlinear objective is set via setNLObj() using an expression tree.
Then we retrieve the tree with getNLObj() and verify it, delete it with
delNLObj(), replace it with a simple linear objective, and re-optimize.
*/
import com.gurobi.gurobi.*;
public class NLObj {
public static void main(String[] args) {
try {
// Create environment
GRBEnv env = new GRBEnv("nlobj.log");
// Create empty model
GRBModel model = new GRBModel(env);
// Create variables
GRBVar x = model.addVar(-1.0, 2.0, 0.0, GRB.CONTINUOUS, "x");
GRBVar y = model.addVar( 0.0, 2.0, 0.0, GRB.CONTINUOUS, "y");
// Add constraint: 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, "c0");
/* 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[] opcode = 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[] data = 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[] parent = new int[] {-1, 0, 1, 2, 1, 0, 5, 6, 6, 5};
// Set nonlinear objective
model.setNLObj(opcode, data, parent);
// Optimize model
model.optimize();
System.out.println("\nFirst solve (nonlinear objective)");
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 {
System.out.println("Optimization did not produce an optimal solution");
}
// Retrieve the nonlinear objective and print the number of nodes
int[] nnodes = new int[1];
model.getNLObj(nnodes, null, null, null);
System.out.println("\nRetrieved NL objective with " + nnodes[0] + " nodes");
// Delete the nonlinear objective
model.delNLObj();
System.out.println("Deleted nonlinear objective");
// Set a simple linear objective instead: minimize x + y
GRBLinExpr linobj = new GRBLinExpr();
linobj.addTerm(1.0, x);
linobj.addTerm(1.0, y);
model.setObjective(linobj, GRB.MINIMIZE);
// Re-optimize
model.optimize();
System.out.println("\nSecond solve (linear objective)");
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 {
System.out.println("Optimization did not produce an optimal solution");
}
// Dispose of model and environment
model.dispose();
env.dispose();
} catch (GRBException e) {
System.out.println("Error code: " + e.getErrorCode() + ". " +
e.getMessage());
}
}
}