NLObj.java#

/* 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());
    }
  }
}