nlobj_c++.cpp#

/* 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.
*/

#include "gurobi_c++.h"
using namespace std;

int
main(int   argc,
     char *argv[])
{

  try {

    /*  Create an environment */
    GRBEnv env = GRBEnv("nlobj.log");

    /*  Create an empty model */
    GRBModel model = 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 */
    model.addConstr(x + y >= 1, "c0");

    /* Build the nonlinear objective: sin(x) * x + x^2 * y
     *
     * Expression tree (7 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    nnodes     = 10;
    int    opcode[10] = { 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[10]   = { -1.0,
                          -1.0,
                          -1.0,
                          (double)x.index(),
                          (double)x.index(),
                          -1.0,
                          -1.0,
                          (double)x.index(),
                          2.0,
                          (double)y.index() };
    int    parent[10] = { -1, 0, 1, 2, 1, 0, 5, 6, 6, 5 };

    /*  Set nonlinear objective (minimize by default) */
    model.setNLObj(nnodes, opcode, data, parent);

    /*  Optimize model */
    model.optimize();

    int status = model.get(GRB_IntAttr_Status);
    if (status == GRB_OPTIMAL) {
      cout << "First solve (nonlinear objective):" << endl;
      cout << "  x = " << x.get(GRB_DoubleAttr_X) << endl;
      cout << "  y = " << y.get(GRB_DoubleAttr_X) << endl;
      cout
        << "  Obj = "
        << model.get(GRB_DoubleAttr_ObjVal)
        << endl;
    }

    /*  Retrieve the nonlinear objective and verify the number of
    nodes */
    int nnodes_out = -1 ;
    model.getNLObj(&nnodes_out, NULL, NULL, NULL);
    cout
      << "\nRetrieved NL objective with "
      << nnodes_out
      << " nodes"
      << endl;

    /*  Delete the nonlinear objective */
    model.delNLObj();
    cout << "Deleted nonlinear objective" << endl;

    /*  Set a simple linear objective instead : minimize x + y */
    model.setObjective(x + y);

    /*  Re-optimize */
    model.optimize();

    status = model.get(GRB_IntAttr_Status);
    if (status == GRB_OPTIMAL) {
      cout << "\nSecond solve (linear objective):" << endl;
      cout << "  x = " << x.get(GRB_DoubleAttr_X) << endl;
      cout << "  y = " << y.get(GRB_DoubleAttr_X) << endl;
      cout
        << "  Obj = "
        << model.get(GRB_DoubleAttr_ObjVal)
        << endl;
    }

  } catch (GRBException e) {
    cout << "Error code = " << e.getErrorCode() << endl;
    cout << e.getMessage() << endl;
  } catch (...) {
    cout << "Exception during optimization" << endl;
  }

  return 0;
}