/* 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 GRBaddnlconstr() using an expression tree.
Then we retrieve the tree with GRBgetnlconstr() and verify it, delete it with
GRBdelnlconstrs(), replace it with a simple linear constraint, and re-optimize.
*/
#include <stdlib.h>
#include <stdio.h>
#include "gurobi_c.h"
int
main(int argc,
char *argv[])
{
GRBenv *env = NULL;
GRBmodel *model = NULL;
int error = 0;
/* Variable data: x (index 0), y (index 1) */
double lb[2] = {-1.0, 0.0};
double ub[2] = { 2.0, 2.0};
char *varnames[2] = {"x", "y"};
double obj[2] = {1.0, -1.0};
/* 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 nnodes1 = 10;
int opcode1[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 data1[10] = {-1.0, -1.0, -1.0,
0.0, /* x index */
0.0, /* x index */
-1.0, -1.0,
0.0, /* x index */
2.0,
1.0}; /* y index */
int parent1[10] = {-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 nnodes2 = 4;
int opcode2[4] = {GRB_OPCODE_MINUS, /* 0: root */
GRB_OPCODE_COS, /* 1: cos(...) */
GRB_OPCODE_VARIABLE, /* 2: x */
GRB_OPCODE_VARIABLE}; /* 3: y */
double data2[4] = {-1.0, -1.0,
0.0, /* x index */
1.0}; /* y index */
int parent2[4] = {-1, 0, 1, 0};
/* Data for querying solution and NL constraint */
double sol[2];
int optimstatus;
double objval;
int nnodes_out;
/* Create environment */
error = GRBloadenv(&env, "nlconstr.log");
if (error) goto QUIT;
/* Create model with two variables */
error = GRBnewmodel(env, &model, "nlconstr", 2, obj, lb, ub, NULL,
varnames);
if (error) goto QUIT;
/* Add constraint: sin(x) * x + x^2 * y <= 1 */
error = GRBaddnlconstr(model, nnodes1, opcode1, data1, parent1,
GRB_LESS_EQUAL, 1.0, "NonlinearConstraint1");
if (error) goto QUIT;
/* Add constraint: cos(x) - y = 0 */
error = GRBaddnlconstr(model, nnodes2, opcode2, data2, parent2,
GRB_EQUAL, 0.0, "NonlinearConstraint2");
if (error) goto QUIT;
/* Optimize model */
error = GRBoptimize(model);
if (error) goto QUIT;
/* Capture solution information */
error = GRBgetintattr(model, GRB_INT_ATTR_STATUS, &optimstatus);
if (error) goto QUIT;
printf("\nFirst solve (nonlinear constraints)\n");
if (optimstatus == GRB_OPTIMAL) {
error = GRBgetdblattr(model, GRB_DBL_ATTR_OBJVAL, &objval);
if (error) goto QUIT;
error = GRBgetdblattrarray(model, GRB_DBL_ATTR_X, 0, 2, sol);
if (error) goto QUIT;
printf("Optimal objective: %.4e\n", objval);
printf(" x=%.6f, y=%.6f\n", sol[0], sol[1]);
} else if (optimstatus == GRB_INF_OR_UNBD) {
printf("Model is infeasible or unbounded\n");
} else {
printf("Optimization was stopped early\n");
}
/* Retrieve number of nodes of first nonlinear constraint and print it */
error = GRBgetnlconstr(model, 0, &nnodes_out, NULL, NULL, NULL);
if (error) goto QUIT;
printf("\nRetrieved NL constraint with %d nodes\n", nnodes_out);
/* Delete both nonlinear constraints */
{
int ind[2] = {0, 1};
error = GRBdelnlconstrs(model, 2, ind);
if (error) goto QUIT;
printf("Deleted nonlinear constraints\n");
}
/* Add a simple linear constraint instead: x + y >= 1 */
{
int ind[2] = {0, 1};
double val[2] = {1.0, 1.0};
error = GRBaddconstr(model, 2, ind, val, GRB_GREATER_EQUAL, 1.0, "LinearConstraint");
if (error) goto QUIT;
}
/* Re-optimize */
error = GRBoptimize(model);
if (error) goto QUIT;
error = GRBgetintattr(model, GRB_INT_ATTR_STATUS, &optimstatus);
if (error) goto QUIT;
printf("\nSecond solve (linear constraint)\n");
if (optimstatus == GRB_OPTIMAL) {
error = GRBgetdblattr(model, GRB_DBL_ATTR_OBJVAL, &objval);
if (error) goto QUIT;
error = GRBgetdblattrarray(model, GRB_DBL_ATTR_X, 0, 2, sol);
if (error) goto QUIT;
printf("Optimal objective: %.4e\n", objval);
printf(" x=%.6f, y=%.6f\n", sol[0], sol[1]);
} else if (optimstatus == GRB_INF_OR_UNBD) {
printf("Model is infeasible or unbounded\n");
} else {
printf("Optimization was stopped early\n");
}
QUIT:
/* Error reporting */
if (error) {
printf("ERROR: %s\n", GRBgeterrormsg(env));
exit(1);
}
/* Free model */
GRBfreemodel(model);
/* Free environment */
GRBfreeenv(env);
return 0;
}