nlobj_c.c#

/* 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 GRBsetnlobj() using an expression tree.
   Then we retrieve the tree with GRBgetnlobj() and verify it, delete it with
   GRBdelnlobj(), replace it with a simple linear objective, 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"};

  /* 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    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,
                        0.0,  /* x index */
                        0.0,  /* x index */
                       -1.0, -1.0,
                        0.0,  /* x index */
                        2.0,
                        1.0}; /* y index */
  int    parent[10] = {-1, 0, 1, 2, 1, 0, 5, 6, 6, 5};

  /* Data for querying solution and NL objective */
  double  sol[2];
  int     optimstatus;
  double  objval;
  int     nnodes_out;
  double  linobj[2];

  /* Create environment */
  error = GRBloadenv(&env, "nlobj.log");
  if (error) goto QUIT;

  /* Create model with two variables, no linear objective */
  error = GRBnewmodel(env, &model, "nlobj", 2, NULL, lb, ub, NULL,
                      varnames);
  if (error) goto QUIT;

  /* Add constraint: x + y >= 1 */
  {
    int    cind[2] = {0, 1};
    double cval[2] = {1.0, 1.0};
    error = GRBaddconstr(model, 2, cind, cval, GRB_GREATER_EQUAL, 1.0, "c0");
    if (error) goto QUIT;
  }

  /* Set nonlinear objective */
  error = GRBsetnlobj(model, nnodes, opcode, data, parent);
  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 objective)\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 the nonlinear objective and print the number of nodes */
  error = GRBgetnlobj(model, &nnodes_out, NULL, NULL, NULL);
  if (error) goto QUIT;
  printf("\nRetrieved NL objective with %d nodes\n", nnodes_out);

  /* Delete the nonlinear objective */
  error = GRBdelnlobj(model);
  if (error) goto QUIT;
  printf("Deleted nonlinear objective\n");

  /* Set a simple linear objective instead: minimize x + y */
  linobj[0] = 1.0;
  linobj[1] = 1.0;
  error = GRBsetdblattrarray(model, GRB_DBL_ATTR_OBJ, 0, 2, linobj);
  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 objective)\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;
}