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