Gc_pwl_func Examples#
This section includes source code for all of the Gurobi gc_pwl_func examples.
The same source code can be found in the examples
directory of the
Gurobi distribution.
/* Copyright 2024, Gurobi Optimization, LLC
This example considers the following nonconvex nonlinear problem
maximize 2 x + y
subject to exp(x) + 4 sqrt(y) <= 9
x, y >= 0
We show you two approaches to solve this:
1) Use a piecewise-linear approach to handle general function
constraints (such as exp and sqrt).
a) Add two variables
u = exp(x)
v = sqrt(y)
b) Compute points (x, u) of u = exp(x) for some step length (e.g., x
= 0, 1e-3, 2e-3, ..., xmax) and points (y, v) of v = sqrt(y) for
some step length (e.g., y = 0, 1e-3, 2e-3, ..., ymax). We need to
compute xmax and ymax (which is easy for this example, but this
does not hold in general).
c) Use the points to add two general constraints of type
piecewise-linear.
2) Use the Gurobis built-in general function constraints directly (EXP
and POW). Here, we do not need to compute the points and the maximal
possible values, which will be done internally by Gurobi. In this
approach, we show how to "zoom in" on the optimal solution and
tighten tolerances to improve the solution quality.
*/
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include "gurobi_c.h"
static double f(double u) { return exp(u); }
static double g(double u) { return sqrt(u); }
static int
printsol(GRBmodel *m)
{
double x[4];
double vio;
int error = 0;
error = GRBgetdblattrarray(m, "X", 0, 4, x);
if (error) goto QUIT;
printf("x = %g, u = %g\n", x[0], x[2]);
printf("y = %g, v = %g\n", x[1], x[3]);
/* Calculate violation of exp(x) + 4 sqrt(y) <= 9 */
vio = f(x[0]) + 4*g(x[1]) - 9;
if (vio < 0.0) vio = 0.0;
printf("Vio = %g\n", vio);
QUIT:
return error;
}
int
main(int argc,
char *argv[])
{
GRBenv *env = NULL;
GRBmodel *model = NULL;
int error = 0;
double lb, ub;
int i, len;
double intv = 1e-3;
double xmax, ymax, t;
int ind[2];
double val[2];
double x[4];
double *xpts = NULL;
double *ypts = NULL;
double *vpts = NULL;
double *upts = NULL;
/* Create environment */
error = GRBloadenv(&env, NULL);
if (error) goto QUIT;
/* Create a new model */
error = GRBnewmodel(env, &model, NULL, 0, NULL, NULL, NULL, NULL, NULL);
if (error) goto QUIT;
/* Add variables */
lb = 0.0; ub = GRB_INFINITY;
error = GRBaddvar(model, 0, NULL, NULL, 2.0, lb, ub, GRB_CONTINUOUS, "x");
if (error) goto QUIT;
error = GRBaddvar(model, 0, NULL, NULL, 1.0, lb, ub, GRB_CONTINUOUS, "y");
if (error) goto QUIT;
error = GRBaddvar(model, 0, NULL, NULL, 0.0, lb, ub, GRB_CONTINUOUS, "u");
if (error) goto QUIT;
error = GRBaddvar(model, 0, NULL, NULL, 0.0, lb, ub, GRB_CONTINUOUS, "v");
if (error) goto QUIT;
/* Change objective sense to maximization */
error = GRBsetintattr(model, GRB_INT_ATTR_MODELSENSE, GRB_MAXIMIZE);
if (error) goto QUIT;
/* Add linear constraint: u + 4*v <= 9 */
ind[0] = 2; ind[1] = 3;
val[0] = 1; val[1] = 4;
error = GRBaddconstr(model, 2, ind, val, GRB_LESS_EQUAL, 9.0, "c1");
if (error) goto QUIT;
/* Approach 1) PWL constraint approach */
xmax = log(9.0);
len = (int) ceil(xmax/intv) + 1;
xpts = (double *) malloc(len*sizeof(double));
upts = (double *) malloc(len*sizeof(double));
for (i = 0; i < len; i++) {
xpts[i] = i*intv;
upts[i] = f(i*intv);
}
error = GRBaddgenconstrPWL(model, "gc1", 0, 2, len, xpts, upts);
if (error) goto QUIT;
ymax = (9.0/4.0)*(9.0/4.0);
len = (int) ceil(ymax/intv) + 1;
ypts = (double *) malloc(len*sizeof(double));
vpts = (double *) malloc(len*sizeof(double));
for (i = 0; i < len; i++) {
ypts[i] = i*intv;
vpts[i] = g(i*intv);
}
error = GRBaddgenconstrPWL(model, "gc2", 1, 3, len, ypts, vpts);
if (error) goto QUIT;
/* Optimize the model and print solution */
error = GRBoptimize(model);
if (error) goto QUIT;
error = printsol(model);
if (error) goto QUIT;
/* Approach 2) General function constraint approach with auto PWL
* translation by Gurobi
*/
/* restore unsolved state and get rid of PWL constraints */
error = GRBreset(model, 0);
if (error) goto QUIT;
ind[0] = 0; ind[1] = 1;
error = GRBdelgenconstrs(model, 2, ind);
if (error) goto QUIT;
error = GRBupdatemodel(model);
if (error) goto QUIT;
error = GRBaddgenconstrExp(model, "gcf1", 0, 2, NULL);
if (error) goto QUIT;
error = GRBaddgenconstrPow(model, "gcf2", 1, 3, 0.5, NULL);
if (error) goto QUIT;
/* Use the equal piece length approach with the length = 1e-3 */
error = GRBsetintparam(GRBgetenv(model), "FuncPieces", 1);
if (error) goto QUIT;
error = GRBsetdblparam(GRBgetenv(model), "FuncPieceLength", 1e-3);
if (error) goto QUIT;
/* Optimize the model and print solution */
error = GRBoptimize(model);
if (error) goto QUIT;
error = printsol(model);
if (error) goto QUIT;
/* Zoom in, use optimal solution to reduce the ranges and use a smaller
* pclen=1e-5 to solve it
*/
error = GRBgetdblattrarray(model, "X", 0, 4, x);
if (error) goto QUIT;
t = x[0] - 0.01;
if (t < 0.0) t = 0.0;
error = GRBsetdblattrelement(model, "LB", 0, t);
if (error) goto QUIT;
t = x[1] - 0.01;
if (t < 0.0) t = 0.0;
error = GRBsetdblattrelement(model, "LB", 1, t);
if (error) goto QUIT;
error = GRBsetdblattrelement(model, "UB", 0, x[0]+0.01);
if (error) goto QUIT;
error = GRBsetdblattrelement(model, "UB", 1, x[1]+0.01);
if (error) goto QUIT;
error = GRBupdatemodel(model);
if (error) goto QUIT;
error = GRBreset(model, 0);
if (error) goto QUIT;
error = GRBsetdblparam(GRBgetenv(model), "FuncPieceLength", 1e-5);
if (error) goto QUIT;
/* Optimize the model and print solution */
error = GRBoptimize(model);
if (error) goto QUIT;
error = printsol(model);
if (error) goto QUIT;
QUIT:
if (error) {
printf("ERROR: %s\n", GRBgeterrormsg(env));
exit(1);
}
/* Free data */
if (xpts) free(xpts);
if (ypts) free(ypts);
if (upts) free(upts);
if (vpts) free(vpts);
/* Free model */
GRBfreemodel(model);
/* Free environment */
GRBfreeenv(env);
return 0;
}
/* Copyright 2024, Gurobi Optimization, LLC
This example considers the following nonconvex nonlinear problem
maximize 2 x + y
subject to exp(x) + 4 sqrt(y) <= 9
x, y >= 0
We show you two approaches to solve this:
1) Use a piecewise-linear approach to handle general function
constraints (such as exp and sqrt).
a) Add two variables
u = exp(x)
v = sqrt(y)
b) Compute points (x, u) of u = exp(x) for some step length (e.g., x
= 0, 1e-3, 2e-3, ..., xmax) and points (y, v) of v = sqrt(y) for
some step length (e.g., y = 0, 1e-3, 2e-3, ..., ymax). We need to
compute xmax and ymax (which is easy for this example, but this
does not hold in general).
c) Use the points to add two general constraints of type
piecewise-linear.
2) Use the Gurobis built-in general function constraints directly (EXP
and POW). Here, we do not need to compute the points and the maximal
possible values, which will be done internally by Gurobi. In this
approach, we show how to "zoom in" on the optimal solution and
tighten tolerances to improve the solution quality.
*/
#if defined (WIN32) || defined (WIN64)
#include <Windows.h>
#endif
#include "gurobi_c++.h"
#include <cmath>
using namespace std;
static double f(double u) { return exp(u); }
static double g(double u) { return sqrt(u); }
static void
printsol(GRBModel& m, GRBVar& x, GRBVar& y, GRBVar& u, GRBVar& v)
{
cout << "x = " << x.get(GRB_DoubleAttr_X) << ", u = " << u.get(GRB_DoubleAttr_X) << endl;
cout << "y = " << y.get(GRB_DoubleAttr_X) << ", v = " << v.get(GRB_DoubleAttr_X) << endl;
cout << "Obj = " << m.get(GRB_DoubleAttr_ObjVal) << endl;
// Calculate violation of exp(x) + 4 sqrt(y) <= 9
double vio = f(x.get(GRB_DoubleAttr_X)) + 4 * g(y.get(GRB_DoubleAttr_X)) - 9;
if (vio < 0.0) vio = 0.0;
cout << "Vio = " << vio << endl;
}
int
main(int argc, char* argv[])
{
double* xpts = NULL;
double* ypts = NULL;
double* vpts = NULL;
double* upts = NULL;
try {
// Create environment
GRBEnv env = GRBEnv();
// Create a new model
GRBModel m = GRBModel(env);
// Create variables
double lb = 0.0, ub = GRB_INFINITY;
GRBVar x = m.addVar(lb, ub, 0.0, GRB_CONTINUOUS, "x");
GRBVar y = m.addVar(lb, ub, 0.0, GRB_CONTINUOUS, "y");
GRBVar u = m.addVar(lb, ub, 0.0, GRB_CONTINUOUS, "u");
GRBVar v = m.addVar(lb, ub, 0.0, GRB_CONTINUOUS, "v");
// Set objective
m.setObjective(2*x + y, GRB_MAXIMIZE);
// Add linear constraint
m.addConstr(u + 4*v <= 9, "l1");
// Approach 1) PWL constraint approach
double intv = 1e-3;
double xmax = log(9.0);
int len = (int) ceil(xmax/intv) + 1;
xpts = new double[len];
upts = new double[len];
for (int i = 0; i < len; i++) {
xpts[i] = i*intv;
upts[i] = f(i*intv);
}
GRBGenConstr gc1 = m.addGenConstrPWL(x, u, len, xpts, upts, "gc1");
double ymax = (9.0/4.0)*(9.0/4.0);
len = (int) ceil(ymax/intv) + 1;
ypts = new double[len];
vpts = new double[len];
for (int i = 0; i < len; i++) {
ypts[i] = i*intv;
vpts[i] = g(i*intv);
}
GRBGenConstr gc2 = m.addGenConstrPWL(y, v, len, ypts, vpts, "gc2");
// Optimize the model and print solution
m.optimize();
printsol(m, x, y, u, v);
// Approach 2) General function constraint approach with auto PWL
// translation by Gurobi
// restore unsolved state and get rid of PWL constraints
m.reset();
m.remove(gc1);
m.remove(gc2);
m.update();
m.addGenConstrExp(x, u, "gcf1");
m.addGenConstrPow(y, v, 0.5, "gcf2");
// Use the equal piece length approach with the length = 1e-3
m.set(GRB_IntParam_FuncPieces, 1);
m.set(GRB_DoubleParam_FuncPieceLength, 1e-3);
// Optimize the model and print solution
m.optimize();
printsol(m, x, y, u, v);
// Zoom in, use optimal solution to reduce the ranges and use a smaller
// pclen=1e-5 to solve it
double xval = x.get(GRB_DoubleAttr_X);
double yval = y.get(GRB_DoubleAttr_X);
x.set(GRB_DoubleAttr_LB, max(x.get(GRB_DoubleAttr_LB), xval-0.01));
x.set(GRB_DoubleAttr_UB, min(x.get(GRB_DoubleAttr_UB), xval+0.01));
y.set(GRB_DoubleAttr_LB, max(y.get(GRB_DoubleAttr_LB), yval-0.01));
y.set(GRB_DoubleAttr_UB, min(y.get(GRB_DoubleAttr_UB), yval+0.01));
m.update();
m.reset();
m.set(GRB_DoubleParam_FuncPieceLength, 1e-5);
// Optimize the model and print solution
m.optimize();
printsol(m, x, y, u, v);
} catch(GRBException e) {
cout << "Error code = " << e.getErrorCode() << endl;
cout << e.getMessage() << endl;
} catch(...) {
cout << "Exception during optimization" << endl;
}
if (xpts) delete[] xpts;
if (ypts) delete[] ypts;
if (upts) delete[] upts;
if (vpts) delete[] vpts;
return 0;
}
/* Copyright 2024, Gurobi Optimization, LLC
This example considers the following nonconvex nonlinear problem
maximize 2 x + y
subject to exp(x) + 4 sqrt(y) <= 9
x, y >= 0
We show you two approaches to solve this:
1) Use a piecewise-linear approach to handle general function
constraints (such as exp and sqrt).
a) Add two variables
u = exp(x)
v = sqrt(y)
b) Compute points (x, u) of u = exp(x) for some step length (e.g., x
= 0, 1e-3, 2e-3, ..., xmax) and points (y, v) of v = sqrt(y) for
some step length (e.g., y = 0, 1e-3, 2e-3, ..., ymax). We need to
compute xmax and ymax (which is easy for this example, but this
does not hold in general).
c) Use the points to add two general constraints of type
piecewise-linear.
2) Use the Gurobis built-in general function constraints directly (EXP
and POW). Here, we do not need to compute the points and the maximal
possible values, which will be done internally by Gurobi. In this
approach, we show how to "zoom in" on the optimal solution and
tighten tolerances to improve the solution quality.
*/
using System;
using Gurobi;
class gc_pwl_func_cs {
private static double f(double u) { return Math.Exp(u); }
private static double g(double u) { return Math.Sqrt(u); }
private static void printsol(GRBModel m, GRBVar x, GRBVar y, GRBVar u, GRBVar v) {
Console.WriteLine("x = " + x.X + ", u = " + u.X);
Console.WriteLine("y = " + y.X + ", v = " + v.X);
Console.WriteLine("Obj = " + m.ObjVal);
// Calculate violation of exp(x) + 4 sqrt(y) <= 9
double vio = f(x.X) + 4 * g(y.X) - 9;
if (vio < 0.0) vio = 0.0;
Console.WriteLine("Vio = " + vio);
}
static void Main() {
try {
// Create environment
GRBEnv env = new GRBEnv();
// Create a new m
GRBModel m = new GRBModel(env);
double lb = 0.0, ub = GRB.INFINITY;
GRBVar x = m.AddVar(lb, ub, 0.0, GRB.CONTINUOUS, "x");
GRBVar y = m.AddVar(lb, ub, 0.0, GRB.CONTINUOUS, "y");
GRBVar u = m.AddVar(lb, ub, 0.0, GRB.CONTINUOUS, "u");
GRBVar v = m.AddVar(lb, ub, 0.0, GRB.CONTINUOUS, "v");
// Set objective
m.SetObjective(2*x + y, GRB.MAXIMIZE);
// Add linear constraint
m.AddConstr(u + 4*v <= 9, "l1");
// Approach 1) PWL constraint approach
double intv = 1e-3;
double xmax = Math.Log(9.0);
int len = (int) Math.Ceiling(xmax/intv) + 1;
double[] xpts = new double[len];
double[] upts = new double[len];
for (int i = 0; i < len; i++) {
xpts[i] = i*intv;
upts[i] = f(i*intv);
}
GRBGenConstr gc1 = m.AddGenConstrPWL(x, u, xpts, upts, "gc1");
double ymax = (9.0/4.0)*(9.0/4.0);
len = (int) Math.Ceiling(ymax/intv) + 1;
double[] ypts = new double[len];
double[] vpts = new double[len];
for (int i = 0; i < len; i++) {
ypts[i] = i*intv;
vpts[i] = g(i*intv);
}
GRBGenConstr gc2 = m.AddGenConstrPWL(y, v, ypts, vpts, "gc2");
// Optimize the model and print solution
m.Optimize();
printsol(m, x, y, u, v);
// Approach 2) General function constraint approach with auto PWL
// translation by Gurobi
// restore unsolved state and get rid of PWL constraints
m.Reset();
m.Remove(gc1);
m.Remove(gc2);
m.Update();
GRBGenConstr gcf1 = m.AddGenConstrExp(x, u, "gcf1", "");
GRBGenConstr gcf2 = m.AddGenConstrPow(y, v, 0.5, "gcf2", "");
// Use the equal piece length approach with the length = 1e-3
m.Parameters.FuncPieces = 1;
m.Parameters.FuncPieceLength = 1e-3;
// Optimize the model and print solution
m.Optimize();
printsol(m, x, y, u, v);
// Zoom in, use optimal solution to reduce the ranges and use a smaller
// pclen=1e-5 to solve it
x.LB = Math.Max(x.LB, x.X-0.01);
x.UB = Math.Min(x.UB, x.X+0.01);
y.LB = Math.Max(y.LB, y.X-0.01);
y.UB = Math.Min(y.UB, y.X+0.01);
m.Update();
m.Reset();
m.Parameters.FuncPieceLength = 1e-5;
// Optimize the model and print solution
m.Optimize();
printsol(m, x, y, u, v);
// Dispose of model and environment
m.Dispose();
env.Dispose();
} catch (GRBException e) {
Console.WriteLine("Error code: " + e.ErrorCode + ". " + e.Message);
}
}
}
/* Copyright 2024, Gurobi Optimization, LLC
This example considers the following nonconvex nonlinear problem
maximize 2 x + y
subject to exp(x) + 4 sqrt(y) <= 9
x, y >= 0
We show you two approaches to solve this:
1) Use a piecewise-linear approach to handle general function
constraints (such as exp and sqrt).
a) Add two variables
u = exp(x)
v = sqrt(y)
b) Compute points (x, u) of u = exp(x) for some step length (e.g., x
= 0, 1e-3, 2e-3, ..., xmax) and points (y, v) of v = sqrt(y) for
some step length (e.g., y = 0, 1e-3, 2e-3, ..., ymax). We need to
compute xmax and ymax (which is easy for this example, but this
does not hold in general).
c) Use the points to add two general constraints of type
piecewise-linear.
2) Use the Gurobis built-in general function constraints directly (EXP
and POW). Here, we do not need to compute the points and the maximal
possible values, which will be done internally by Gurobi. In this
approach, we show how to "zoom in" on the optimal solution and
tighten tolerances to improve the solution quality.
*/
import com.gurobi.gurobi.*;
public class GCPWLFunc {
private static double f(double u) { return Math.exp(u); }
private static double g(double u) { return Math.sqrt(u); }
private static void printsol(GRBModel m, GRBVar x, GRBVar y, GRBVar u, GRBVar v)
throws GRBException {
assert(m.get(GRB.IntAttr.Status) == GRB.OPTIMAL);
System.out.println("x = " + x.get(GRB.DoubleAttr.X) + ", u = " + u.get(GRB.DoubleAttr.X));
System.out.println("y = " + y.get(GRB.DoubleAttr.X) + ", v = " + v.get(GRB.DoubleAttr.X));
System.out.println("Obj = " + m.get(GRB.DoubleAttr.ObjVal));
// Calculate violation of exp(x) + 4 sqrt(y) <= 9
double vio = f(x.get(GRB.DoubleAttr.X)) + 4 * g(y.get(GRB.DoubleAttr.X)) - 9;
if (vio < 0.0) vio = 0.0;
System.out.println("Vio = " + vio);
}
public static void main(String[] args) {
try {
// Create environment
GRBEnv env = new GRBEnv();
// Create a new m
GRBModel m = new GRBModel(env);
double lb = 0.0, ub = GRB.INFINITY;
GRBVar x = m.addVar(lb, ub, 0.0, GRB.CONTINUOUS, "x");
GRBVar y = m.addVar(lb, ub, 0.0, GRB.CONTINUOUS, "y");
GRBVar u = m.addVar(lb, ub, 0.0, GRB.CONTINUOUS, "u");
GRBVar v = m.addVar(lb, ub, 0.0, GRB.CONTINUOUS, "v");
// Set objective
GRBLinExpr obj = new GRBLinExpr();
obj.addTerm(2.0, x); obj.addTerm(1.0, y);
m.setObjective(obj, GRB.MAXIMIZE);
// Add linear constraint
GRBLinExpr expr = new GRBLinExpr();
expr.addTerm(1.0, u); expr.addTerm(4.0, v);
m.addConstr(expr, GRB.LESS_EQUAL, 9.0, "l1");
// Approach 1) PWL constraint approach
double intv = 1e-3;
double xmax = Math.log(9.0);
int len = (int) Math.ceil(xmax/intv) + 1;
double[] xpts = new double[len];
double[] upts = new double[len];
for (int i = 0; i < len; i++) {
xpts[i] = i*intv;
upts[i] = f(i*intv);
}
GRBGenConstr gc1 = m.addGenConstrPWL(x, u, xpts, upts, "gc1");
double ymax = (9.0/4.0)*(9.0/4.0);
len = (int) Math.ceil(ymax/intv) + 1;
double[] ypts = new double[len];
double[] vpts = new double[len];
for (int i = 0; i < len; i++) {
ypts[i] = i*intv;
vpts[i] = g(i*intv);
}
GRBGenConstr gc2 = m.addGenConstrPWL(y, v, ypts, vpts, "gc2");
// Optimize the model and print solution
m.optimize();
printsol(m, x, y, u, v);
// Approach 2) General function constraint approach with auto PWL
// translation by Gurobi
// restore unsolved state and get rid of PWL constraints
m.reset();
m.remove(gc1);
m.remove(gc2);
m.update();
GRBGenConstr gcf1 = m.addGenConstrExp(x, u, "gcf1", null);
GRBGenConstr gcf2 = m.addGenConstrPow(y, v, 0.5, "gcf2", "");
// Use the equal piece length approach with the length = 1e-3
m.set(GRB.IntParam.FuncPieces, 1);
m.set(GRB.DoubleParam.FuncPieceLength, 1e-3);
// Optimize the model and print solution
m.optimize();
printsol(m, x, y, u, v);
// Zoom in, use optimal solution to reduce the ranges and use a smaller
// pclen=1e-5 to solve it
double xval = x.get(GRB.DoubleAttr.X);
double yval = y.get(GRB.DoubleAttr.X);
x.set(GRB.DoubleAttr.LB, Math.max(x.get(GRB.DoubleAttr.LB), xval-0.01));
x.set(GRB.DoubleAttr.UB, Math.min(x.get(GRB.DoubleAttr.UB), xval+0.01));
y.set(GRB.DoubleAttr.LB, Math.max(y.get(GRB.DoubleAttr.LB), yval-0.01));
y.set(GRB.DoubleAttr.UB, Math.min(y.get(GRB.DoubleAttr.UB), yval+0.01));
m.update();
m.reset();
m.set(GRB.DoubleParam.FuncPieceLength, 1e-5);
// Optimize the model and print solution
m.optimize();
printsol(m, x, y, u, v);
// Dispose of model and environment
m.dispose();
env.dispose();
} catch (GRBException e) {
System.out.println("Error code: " + e.getErrorCode() + ". " +
e.getMessage());
}
}
}
function gc_pwl_func
% Copyright 2024, Gurobi Optimization, LLC
%
% This example considers the following nonconvex nonlinear problem
%
% maximize 2 x + y
% subject to exp(x) + 4 sqrt(y) <= 9
% x, y >= 0
%
% We show you two approaches to solve this:
%
% 1) Use a piecewise-linear approach to handle general function
% constraints (such as exp and sqrt).
% a) Add two variables
% u = exp(x)
% v = sqrt(y)
% b) Compute points (x, u) of u = exp(x) for some step length (e.g., x
% = 0, 1e-3, 2e-3, ..., xmax) and points (y, v) of v = sqrt(y) for
% some step length (e.g., y = 0, 1e-3, 2e-3, ..., ymax). We need to
% compute xmax and ymax (which is easy for this example, but this
% does not hold in general).
% c) Use the points to add two general constraints of type
% piecewise-linear.
%
% 2) Use the Gurobis built-in general function constraints directly (EXP
% and POW). Here, we do not need to compute the points and the maximal
% possible values, which will be done internally by Gurobi. In this
% approach, we show how to "zoom in" on the optimal solution and
% tighten tolerances to improve the solution quality.
%
% Four nonneg. variables x, y, u, v, one linear constraint u + 4*v <= 9
m.varnames = {'x', 'y', 'u', 'v'};
m.lb = zeros(4, 1);
m.ub = +inf(4, 1);
m.A = sparse([0, 0, 1, 4]);
m.rhs = 9;
% Objective
m.modelsense = 'max';
m.obj = [2; 1; 0; 0];
% First approach: PWL constraints
% Approximate u \approx exp(x), equispaced points in [0, xmax], xmax = log(9)
m.genconpwl(1).xvar = 1;
m.genconpwl(1).yvar = 3;
m.genconpwl(1).xpts = 0:1e-3:log(9);
m.genconpwl(1).ypts = exp(m.genconpwl(1).xpts);
% Approximate v \approx sqrt(y), equispaced points in [0, ymax], ymax = (9/4)^2
m.genconpwl(2).xvar = 2;
m.genconpwl(2).yvar = 4;
m.genconpwl(2).xpts = 0:1e-3:(9/4)^2;
m.genconpwl(2).ypts = sqrt(m.genconpwl(2).xpts);
% Solve and print solution
result = gurobi(m);
printsol(result.objval, result.x(1), result.x(2), result.x(3), result.x(4));
% Second approach: General function constraint approach with auto PWL
% translation by Gurobi
% Delete explicit PWL approximations from model
m = rmfield(m, 'genconpwl');
% Set u \approx exp(x)
m.genconexp.xvar = 1;
m.genconexp.yvar = 3;
m.genconexp.name = 'gcf1';
% Set v \approx sqrt(y) = y^0.5
m.genconpow.xvar = 2;
m.genconpow.yvar = 4;
m.genconpow.a = 0.5;
m.genconpow.name = 'gcf2';
% Parameters for discretization: use equal piece length with length = 1e-3
params.FuncPieces = 1;
params.FuncPieceLength = 1e-3;
% Solve and print solution
result = gurobi(m, params);
printsol(result.objval, result.x(1), result.x(2), result.x(3), result.x(4));
% Zoom in, use optimal solution to reduce the ranges and use a smaller
% pclen=1-5 to resolve
m.lb(1) = max(m.lb(1), result.x(1) - 0.01);
m.ub(1) = min(m.ub(1), result.x(1) + 0.01);
m.lb(2) = max(m.lb(2), result.x(2) - 0.01);
m.ub(2) = min(m.ub(2), result.x(2) + 0.01);
params.FuncPieceLength = 1e-5;
% Solve and print solution
result = gurobi(m, params);
printsol(result.objval, result.x(1), result.x(2), result.x(3), result.x(4));
end
function printsol(objval, x, y, u, v)
fprintf('x = %g, u = %g\n', x, u);
fprintf('y = %g, v = %g\n', y, v);
fprintf('Obj = %g\n', objval);
% Calculate violation of exp(x) + 4 sqrt(y) <= 9
vio = exp(x) + 4 * sqrt(y) - 9;
if vio < 0
vio = 0;
end
fprintf('Vio = %g\n', vio);
end
#!/usr/bin/env python3.11
# Copyright 2024, Gurobi Optimization, LLC
# This example considers the following nonconvex nonlinear problem
#
# maximize 2 x + y
# subject to exp(x) + 4 sqrt(y) <= 9
# x, y >= 0
#
# We show you two approaches to solve this:
#
# 1) Use a piecewise-linear approach to handle general function
# constraints (such as exp and sqrt).
# a) Add two variables
# u = exp(x)
# v = sqrt(y)
# b) Compute points (x, u) of u = exp(x) for some step length (e.g., x
# = 0, 1e-3, 2e-3, ..., xmax) and points (y, v) of v = sqrt(y) for
# some step length (e.g., y = 0, 1e-3, 2e-3, ..., ymax). We need to
# compute xmax and ymax (which is easy for this example, but this
# does not hold in general).
# c) Use the points to add two general constraints of type
# piecewise-linear.
#
# 2) Use the Gurobis built-in general function constraints directly (EXP
# and POW). Here, we do not need to compute the points and the maximal
# possible values, which will be done internally by Gurobi. In this
# approach, we show how to "zoom in" on the optimal solution and
# tighten tolerances to improve the solution quality.
#
import math
import gurobipy as gp
from gurobipy import GRB
def printsol(m, x, y, u, v):
print(f"x = {x.X}, u = {u.X}")
print(f"y = {y.X}, v = {v.X}")
print(f"Obj = {m.ObjVal}")
# Calculate violation of exp(x) + 4 sqrt(y) <= 9
vio = math.exp(x.X) + 4 * math.sqrt(y.X) - 9
if vio < 0:
vio = 0
print(f"Vio = {vio}")
try:
# Create a new model
m = gp.Model()
# Create variables
x = m.addVar(name="x")
y = m.addVar(name="y")
u = m.addVar(name="u")
v = m.addVar(name="v")
# Set objective
m.setObjective(2 * x + y, GRB.MAXIMIZE)
# Add constraints
lc = m.addConstr(u + 4 * v <= 9)
# Approach 1) PWL constraint approach
xpts = []
ypts = []
upts = []
vpts = []
intv = 1e-3
xmax = math.log(9)
t = 0.0
while t < xmax + intv:
xpts.append(t)
upts.append(math.exp(t))
t += intv
ymax = (9.0 / 4) * (9.0 / 4)
t = 0.0
while t < ymax + intv:
ypts.append(t)
vpts.append(math.sqrt(t))
t += intv
gc1 = m.addGenConstrPWL(x, u, xpts, upts, "gc1")
gc2 = m.addGenConstrPWL(y, v, ypts, vpts, "gc2")
# Optimize the model
m.optimize()
printsol(m, x, y, u, v)
# Approach 2) General function constraint approach with auto PWL
# translation by Gurobi
# restore unsolved state and get rid of PWL constraints
m.reset()
m.remove(gc1)
m.remove(gc2)
m.update()
# u = exp(x)
gcf1 = m.addGenConstrExp(x, u, name="gcf1")
# v = y^(0.5)
gcf2 = m.addGenConstrPow(y, v, 0.5, name="gcf2")
# Use the equal piece length approach with the length = 1e-3
m.Params.FuncPieces = 1
m.Params.FuncPieceLength = 1e-3
# Optimize the model
m.optimize()
printsol(m, x, y, u, v)
# Zoom in, use optimal solution to reduce the ranges and use a smaller
# pclen=1-5 to solve it
x.LB = max(x.LB, x.X - 0.01)
x.UB = min(x.UB, x.X + 0.01)
y.LB = max(y.LB, y.X - 0.01)
y.UB = min(y.UB, y.X + 0.01)
m.update()
m.reset()
m.Params.FuncPieceLength = 1e-5
# Optimize the model
m.optimize()
printsol(m, x, y, u, v)
except gp.GurobiError as e:
print(f"Error code {e.errno}: {e}")
except AttributeError:
print("Encountered an attribute error")
# Copyright 2024, Gurobi Optimization, LLC
#
# This example considers the following nonconvex nonlinear problem
#
# maximize 2 x + y
# subject to exp(x) + 4 sqrt(y) <= 9
# x, y >= 0
#
# We show you two approaches to solve this:
#
# 1) Use a piecewise-linear approach to handle general function
# constraints (such as exp and sqrt).
# a) Add two variables
# u = exp(x)
# v = sqrt(y)
# b) Compute points (x, u) of u = exp(x) for some step length (e.g., x
# = 0, 1e-3, 2e-3, ..., xmax) and points (y, v) of v = sqrt(y) for
# some step length (e.g., y = 0, 1e-3, 2e-3, ..., ymax). We need to
# compute xmax and ymax (which is easy for this example, but this
# does not hold in general).
# c) Use the points to add two general constraints of type
# piecewise-linear.
#
# 2) Use the Gurobis built-in general function constraints directly (EXP
# and POW). Here, we do not need to compute the points and the maximal
# possible values, which will be done internally by Gurobi. In this
# approach, we show how to "zoom in" on the optimal solution and
# tighten tolerances to improve the solution quality.
library(gurobi)
printsol <- function(model, result) {
print(sprintf('%s = %g, %s = %g',
model$varnames[1], result$x[1],
model$varnames[3], result$x[3]))
print(sprintf('%s = %g, %s = %g',
model$varnames[2], result$x[2],
model$varnames[4], result$x[4]))
print(sprintf('Obj = %g', + result$objval))
# Calculate violation of exp(x) + 4 sqrt(y) <= 9
vio <- exp(result$x[1]) + 4 * sqrt(result$x[2]) - 9
if (vio < 0.0)
vio <- 0.0
print(sprintf('Vio = %g', vio))
}
model <- list()
# Four nonneg. variables x, y, u, v, one linear constraint u + 4*v <= 9
model$varnames <- c('x', 'y', 'u', 'v')
model$lb <- c(rep(0, 4))
model$ub <- c(rep(Inf, 4))
model$A <- matrix(c(0, 0, 1, 4), nrow = 1)
model$rhs <- 9
# Objective
model$modelsense <- 'max'
model$obj <- c(2, 1, 0, 0)
# First approach: PWL constraints
model$genconpwl <- list()
intv <- 1e-3
# Approximate u \approx exp(x), equispaced points in [0, xmax], xmax = log(9)
model$genconpwl[[1]] <- list()
model$genconpwl[[1]]$xvar <- 1L
model$genconpwl[[1]]$yvar <- 3L
xmax <- log(9)
point <- 0
t <- 0
while (t < xmax + intv) {
point <- point + 1
model$genconpwl[[1]]$xpts[point] <- t
model$genconpwl[[1]]$ypts[point] <- exp(t)
t <- t + intv
}
# Approximate v \approx sqrt(y), equispaced points in [0, ymax], ymax = (9/4)^2
model$genconpwl[[2]] <- list()
model$genconpwl[[2]]$xvar <- 2L
model$genconpwl[[2]]$yvar <- 4L
ymax <- (9/4)^2
point <- 0
t <- 0
while (t < ymax + intv) {
point <- point + 1
model$genconpwl[[2]]$xpts[point] <- t
model$genconpwl[[2]]$ypts[point] <- sqrt(t)
t <- t + intv
}
# Solve and print solution
result = gurobi(model)
printsol(model, result)
# Second approach: General function constraint approach with auto PWL
# translation by Gurobi
# Delete explicit PWL approximations from model
model$genconpwl <- NULL
# Set u \approx exp(x)
model$genconexp <- list()
model$genconexp[[1]] <- list()
model$genconexp[[1]]$xvar <- 1L
model$genconexp[[1]]$yvar <- 3L
model$genconexp[[1]]$name <- 'gcf1'
# Set v \approx sqrt(y) = y^0.5
model$genconpow <- list()
model$genconpow[[1]] <- list()
model$genconpow[[1]]$xvar <- 2L
model$genconpow[[1]]$yvar <- 4L
model$genconpow[[1]]$a <- 0.5
model$genconpow[[1]]$name <- 'gcf2'
# Parameters for discretization: use equal piece length with length = 1e-3
params <- list()
params$FuncPieces <- 1
params$FuncPieceLength <- 1e-3
# Solve and print solution
result = gurobi(model, params)
printsol(model, result)
# Zoom in, use optimal solution to reduce the ranges and use a smaller
# pclen=1-5 to resolve
model$lb[1] <- max(model$lb[1], result$x[1] - 0.01)
model$ub[1] <- min(model$ub[1], result$x[1] + 0.01)
model$lb[2] <- max(model$lb[2], result$x[2] - 0.01)
model$ub[2] <- min(model$ub[2], result$x[2] + 0.01)
params$FuncPieceLength <- 1e-5
# Solve and print solution
result = gurobi(model, params)
printsol(model, result)
# Clear space
rm(model, result)
' Copyright 2024, Gurobi Optimization, LLC
'
' This example considers the following nonconvex nonlinear problem
'
' maximize 2 x + y
' subject to exp(x) + 4 sqrt(y) <= 9
' x, y >= 0
'
' We show you two approaches to solve this:
'
' 1) Use a piecewise-linear approach to handle general function
' constraints (such as exp and sqrt).
' a) Add two variables
' u = exp(x)
' v = sqrt(y)
' b) Compute points (x, u) of u = exp(x) for some step length (e.g., x
' = 0, 1e-3, 2e-3, ..., xmax) and points (y, v) of v = sqrt(y) for
' some step length (e.g., y = 0, 1e-3, 2e-3, ..., ymax). We need to
' compute xmax and ymax (which is easy for this example, but this
' does not hold in general).
' c) Use the points to add two general constraints of type
' piecewise-linear.
'
' 2) Use the Gurobis built-in general function constraints directly (EXP
' and POW). Here, we do not need to compute the points and the maximal
' possible values, which will be done internally by Gurobi. In this
' approach, we show how to "zoom in" on the optimal solution and
' tighten tolerances to improve the solution quality.
Imports System
Imports Gurobi
Class gc_pwl_func_vb
Shared Function f(u As Double) As Double
Return Math.Exp(u)
End Function
Shared Function g(u As Double) As Double
Return Math.Sqrt(u)
End Function
Shared Sub printsol(m As GRBModel, x As GRBVar, _
y As GRBVar, u As GRBVar, v As GRBVar)
Console.WriteLine("x = " & x.X & ", u = " & u.X)
Console.WriteLine("y = " & y.X & ", v = " & v.X)
Console.WriteLine("Obj = " & m.ObjVal)
' Calculate violation of exp(x) + 4 sqrt(y) <= 9
Dim vio As Double = f(x.X) + 4 * g(y.X) - 9
If vio < 0.0 Then
vio = 0.0
End If
Console.WriteLine("Vio = " & vio)
End Sub
Shared Sub Main()
Try
' Create environment
Dim env As New GRBEnv()
' Create a new m
Dim m As New GRBModel(env)
Dim lb As Double = 0.0
Dim ub As Double = GRB.INFINITY
Dim x As GRBVar = m.AddVar(lb, ub, 0.0, GRB.CONTINUOUS, "x")
Dim y As GRBVar = m.AddVar(lb, ub, 0.0, GRB.CONTINUOUS, "y")
Dim u As GRBVar = m.AddVar(lb, ub, 0.0, GRB.CONTINUOUS, "u")
Dim v As GRBVar = m.AddVar(lb, ub, 0.0, GRB.CONTINUOUS, "v")
' Set objective
m.SetObjective(2*x + y, GRB.MAXIMIZE)
' Add linear constraint
m.AddConstr(u + 4*v <= 9, "l1")
' PWL constraint approach
Dim intv As Double = 1e-3
Dim xmax As Double = Math.Log(9.0)
Dim npts As Integer = Math.Ceiling(xmax/intv) + 1
Dim xpts As Double() = new Double(npts -1) {}
Dim upts As Double() = new Double(npts -1) {}
For i As Integer = 0 To npts - 1
xpts(i) = i*intv
upts(i) = f(i*intv)
Next
Dim gc1 As GRBGenConstr = m.AddGenConstrPWL(x, u, xpts, upts, "gc1")
Dim ymax As Double = (9.0/4.0)*(9.0/4.0)
npts = Math.Ceiling(ymax/intv) + 1
Dim ypts As Double() = new Double(npts -1) {}
Dim vpts As Double() = new Double(npts -1) {}
For i As Integer = 0 To npts - 1
ypts(i) = i*intv
vpts(i) = g(i*intv)
Next
Dim gc2 As GRBGenConstr = m.AddGenConstrPWL(y, v, ypts, vpts, "gc2")
' Optimize the model and print solution
m.Optimize()
printsol(m, x, y, u, v)
' General function approach with auto PWL translation by Gurobi
m.Reset()
m.Remove(gc1)
m.Remove(gc2)
m.Update()
Dim gcf1 As GRBGenConstr = m.AddGenConstrExp(x, u, "gcf1", "")
Dim gcf2 As GRBGenConstr = m.AddGenConstrPow(y, v, 0.5, "gcf2", "")
' Use the equal piece length approach with the length = 1e-3
m.Parameters.FuncPieces = 1
m.Parameters.FuncPieceLength = 1e-3
' Optimize the model and print solution
m.Optimize()
printsol(m, x, y, u, v)
' Use optimal solution to reduce the ranges and use smaller pclen to solve
x.LB = Math.Max(x.LB, x.X-0.01)
x.UB = Math.Min(x.UB, x.X+0.01)
y.LB = Math.Max(y.LB, y.X-0.01)
y.UB = Math.Min(y.UB, y.X+0.01)
m.Update()
m.Reset()
m.Parameters.FuncPieceLength = 1e-5
' Optimize the model and print solution
m.Optimize()
printsol(m, x, y, u, v)
' Dispose of model and environment
m.Dispose()
env.Dispose()
Catch e As GRBException
Console.WriteLine("Error code: " + e.ErrorCode + ". " + e.Message)
End Try
End Sub
End Class