Piecewise Examples#
This section includes source code for all of the Gurobi piecewise examples.
The same source code can be found in the examples
directory of the
Gurobi distribution.
/* Copyright 2025, Gurobi Optimization, LLC */
/* This example considers the following separable, convex problem:
minimize f(x) - y + g(z)
subject to x + 2 y + 3 z <= 4
x + y >= 1
x, y, z <= 1
where f(u) = exp(-u) and g(u) = 2 u^2 - 4 u, for all real u. It
formulates and solves a simpler LP model by approximating f and
g with piecewise-linear functions. Then it transforms the model
into a MIP by negating the approximation for f, which corresponds
to a non-convex piecewise-linear function, and solves it again.
*/
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include "gurobi_c.h"
double f(double u) { return exp(-u); }
double g(double u) { return 2 * u * u - 4 * u; }
int
main(int argc,
char *argv[])
{
GRBenv *env = NULL;
GRBmodel *model = NULL;
int error = 0;
double lb, ub;
int npts, i;
double *ptu = NULL;
double *ptf = NULL;
double *ptg = NULL;
int ind[3];
double val[3];
int ismip;
double objval;
double sol[3];
/* 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 = 1.0;
error = GRBaddvar(model, 0, NULL, NULL, 0.0, lb, ub, GRB_CONTINUOUS, "x");
if (error) goto QUIT;
error = GRBaddvar(model, 0, NULL, NULL, 0.0, lb, ub, GRB_CONTINUOUS, "y");
if (error) goto QUIT;
error = GRBaddvar(model, 0, NULL, NULL, 0.0, lb, ub, GRB_CONTINUOUS, "z");
if (error) goto QUIT;
/* Set objective for y */
error = GRBsetdblattrelement(model, GRB_DBL_ATTR_OBJ, 1, -1.0);
if (error) goto QUIT;
/* Add piecewise-linear objective functions for x and z */
npts = 101;
ptu = (double *) malloc(npts * sizeof(double));
ptf = (double *) malloc(npts * sizeof(double));
ptg = (double *) malloc(npts * sizeof(double));
for (i = 0; i < npts; i++) {
ptu[i] = lb + (ub - lb) * i / (npts - 1);
ptf[i] = f(ptu[i]);
ptg[i] = g(ptu[i]);
}
error = GRBsetpwlobj(model, 0, npts, ptu, ptf);
if (error) goto QUIT;
error = GRBsetpwlobj(model, 2, npts, ptu, ptg);
if (error) goto QUIT;
/* Add constraint: x + 2 y + 3 z <= 4 */
ind[0] = 0; ind[1] = 1; ind[2] = 2;
val[0] = 1; val[1] = 2; val[2] = 3;
error = GRBaddconstr(model, 3, ind, val, GRB_LESS_EQUAL, 4.0, "c0");
if (error) goto QUIT;
/* Add constraint: x + y >= 1 */
ind[0] = 0; ind[1] = 1;
val[0] = 1; val[1] = 1;
error = GRBaddconstr(model, 2, ind, val, GRB_GREATER_EQUAL, 1.0, "c1");
if (error) goto QUIT;
/* Optimize model as an LP */
error = GRBoptimize(model);
if (error) goto QUIT;
error = GRBgetintattr(model, "IsMIP", &ismip);
if (error) goto QUIT;
error = GRBgetdblattr(model, "ObjVal", &objval);
if (error) goto QUIT;
error = GRBgetdblattrarray(model, "X", 0, 3, sol);
if (error) goto QUIT;
printf("IsMIP: %d\n", ismip);
printf("x %g\ny %g\nz %g\n", sol[0], sol[1], sol[2]);
printf("Obj: %g\n", objval);
printf("\n");
/* Negate piecewise-linear objective function for x */
for (i = 0; i < npts; i++) {
ptf[i] = -ptf[i];
}
error = GRBsetpwlobj(model, 0, npts, ptu, ptf);
if (error) goto QUIT;
/* Optimize model as a MIP */
error = GRBoptimize(model);
if (error) goto QUIT;
error = GRBgetintattr(model, "IsMIP", &ismip);
if (error) goto QUIT;
error = GRBgetdblattr(model, "ObjVal", &objval);
if (error) goto QUIT;
error = GRBgetdblattrarray(model, "X", 0, 3, sol);
if (error) goto QUIT;
printf("IsMIP: %d\n", ismip);
printf("x %g\ny %g\nz %g\n", sol[0], sol[1], sol[2]);
printf("Obj: %g\n", objval);
QUIT:
/* Error reporting */
if (error) {
printf("ERROR: %s\n", GRBgeterrormsg(env));
exit(1);
}
/* Free data */
free(ptu);
free(ptf);
free(ptg);
/* Free model */
GRBfreemodel(model);
/* Free environment */
GRBfreeenv(env);
return 0;
}
/* Copyright 2025, Gurobi Optimization, LLC */
/* This example considers the following separable, convex problem:
minimize f(x) - y + g(z)
subject to x + 2 y + 3 z <= 4
x + y >= 1
x, y, z <= 1
where f(u) = exp(-u) and g(u) = 2 u^2 - 4 u, for all real u. It
formulates and solves a simpler LP model by approximating f and
g with piecewise-linear functions. Then it transforms the model
into a MIP by negating the approximation for f, which corresponds
to a non-convex piecewise-linear function, and solves it again.
*/
#include "gurobi_c++.h"
#include <cmath>
using namespace std;
double f(double u) { return exp(-u); }
double g(double u) { return 2 * u * u - 4 * u; }
int
main(int argc,
char *argv[])
{
double *ptu = NULL;
double *ptf = NULL;
double *ptg = NULL;
try {
// Create environment
GRBEnv env = GRBEnv();
// Create a new model
GRBModel model = GRBModel(env);
// Create variables
double lb = 0.0, ub = 1.0;
GRBVar x = model.addVar(lb, ub, 0.0, GRB_CONTINUOUS, "x");
GRBVar y = model.addVar(lb, ub, 0.0, GRB_CONTINUOUS, "y");
GRBVar z = model.addVar(lb, ub, 0.0, GRB_CONTINUOUS, "z");
// Set objective for y
model.setObjective(-y);
// Add piecewise-linear objective functions for x and z
int npts = 101;
ptu = new double[npts];
ptf = new double[npts];
ptg = new double[npts];
for (int i = 0; i < npts; i++) {
ptu[i] = lb + (ub - lb) * i / (npts - 1);
ptf[i] = f(ptu[i]);
ptg[i] = g(ptu[i]);
}
model.setPWLObj(x, npts, ptu, ptf);
model.setPWLObj(z, npts, ptu, ptg);
// Add constraint: x + 2 y + 3 z <= 4
model.addConstr(x + 2 * y + 3 * z <= 4, "c0");
// Add constraint: x + y >= 1
model.addConstr(x + y >= 1, "c1");
// Optimize model as an LP
model.optimize();
cout << "IsMIP: " << model.get(GRB_IntAttr_IsMIP) << endl;
cout << x.get(GRB_StringAttr_VarName) << " "
<< x.get(GRB_DoubleAttr_X) << endl;
cout << y.get(GRB_StringAttr_VarName) << " "
<< y.get(GRB_DoubleAttr_X) << endl;
cout << z.get(GRB_StringAttr_VarName) << " "
<< z.get(GRB_DoubleAttr_X) << endl;
cout << "Obj: " << model.get(GRB_DoubleAttr_ObjVal) << endl;
cout << endl;
// Negate piecewise-linear objective function for x
for (int i = 0; i < npts; i++) {
ptf[i] = -ptf[i];
}
model.setPWLObj(x, npts, ptu, ptf);
// Optimize model as a MIP
model.optimize();
cout << "IsMIP: " << model.get(GRB_IntAttr_IsMIP) << endl;
cout << x.get(GRB_StringAttr_VarName) << " "
<< x.get(GRB_DoubleAttr_X) << endl;
cout << y.get(GRB_StringAttr_VarName) << " "
<< y.get(GRB_DoubleAttr_X) << endl;
cout << z.get(GRB_StringAttr_VarName) << " "
<< z.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;
}
delete[] ptu;
delete[] ptf;
delete[] ptg;
return 0;
}
/* Copyright 2025, Gurobi Optimization, LLC */
/* This example considers the following separable, convex problem:
minimize f(x) - y + g(z)
subject to x + 2 y + 3 z <= 4
x + y >= 1
x, y, z <= 1
where f(u) = exp(-u) and g(u) = 2 u^2 - 4 u, for all real u. It
formulates and solves a simpler LP model by approximating f and
g with piecewise-linear functions. Then it transforms the model
into a MIP by negating the approximation for f, which corresponds
to a non-convex piecewise-linear function, and solves it again.
*/
using System;
using Gurobi;
class piecewise_cs
{
private static double f(double u) { return Math.Exp(-u); }
private static double g(double u) { return 2 * u * u - 4 * u; }
static void Main()
{
try {
// Create environment
GRBEnv env = new GRBEnv();
// Create a new model
GRBModel model = new GRBModel(env);
// Create variables
double lb = 0.0, ub = 1.0;
GRBVar x = model.AddVar(lb, ub, 0.0, GRB.CONTINUOUS, "x");
GRBVar y = model.AddVar(lb, ub, 0.0, GRB.CONTINUOUS, "y");
GRBVar z = model.AddVar(lb, ub, 0.0, GRB.CONTINUOUS, "z");
// Set objective for y
model.SetObjective(-y);
// Add piecewise-linear objective functions for x and z
int npts = 101;
double[] ptu = new double[npts];
double[] ptf = new double[npts];
double[] ptg = new double[npts];
for (int i = 0; i < npts; i++) {
ptu[i] = lb + (ub - lb) * i / (npts - 1);
ptf[i] = f(ptu[i]);
ptg[i] = g(ptu[i]);
}
model.SetPWLObj(x, ptu, ptf);
model.SetPWLObj(z, ptu, ptg);
// Add constraint: x + 2 y + 3 z <= 4
model.AddConstr(x + 2 * y + 3 * z <= 4.0, "c0");
// Add constraint: x + y >= 1
model.AddConstr(x + y >= 1.0, "c1");
// Optimize model as an LP
model.Optimize();
Console.WriteLine("IsMIP: " + model.IsMIP);
Console.WriteLine(x.VarName + " " + x.X);
Console.WriteLine(y.VarName + " " + y.X);
Console.WriteLine(z.VarName + " " + z.X);
Console.WriteLine("Obj: " + model.ObjVal);
Console.WriteLine();
// Negate piecewise-linear objective function for x
for (int i = 0; i < npts; i++) {
ptf[i] = -ptf[i];
}
model.SetPWLObj(x, ptu, ptf);
// Optimize model as a MIP
model.Optimize();
Console.WriteLine("IsMIP: " + model.IsMIP);
Console.WriteLine(x.VarName + " " + x.X);
Console.WriteLine(y.VarName + " " + y.X);
Console.WriteLine(z.VarName + " " + z.X);
Console.WriteLine("Obj: " + model.ObjVal);
// Dispose of model and environment
model.Dispose();
env.Dispose();
} catch (GRBException e) {
Console.WriteLine("Error code: " + e.ErrorCode + ". " + e.Message);
}
}
}
/* Copyright 2025, Gurobi Optimization, LLC */
/* This example considers the following separable, convex problem:
minimize f(x) - y + g(z)
subject to x + 2 y + 3 z <= 4
x + y >= 1
x, y, z <= 1
where f(u) = exp(-u) and g(u) = 2 u^2 - 4 u, for all real u. It
formulates and solves a simpler LP model by approximating f and
g with piecewise-linear functions. Then it transforms the model
into a MIP by negating the approximation for f, which corresponds
to a non-convex piecewise-linear function, and solves it again.
*/
import com.gurobi.gurobi.*;
public class Piecewise {
private static double f(double u) { return Math.exp(-u); }
private static double g(double u) { return 2 * u * u - 4 * u; }
public static void main(String[] args) {
try {
// Create environment
GRBEnv env = new GRBEnv();
// Create a new model
GRBModel model = new GRBModel(env);
// Create variables
double lb = 0.0, ub = 1.0;
GRBVar x = model.addVar(lb, ub, 0.0, GRB.CONTINUOUS, "x");
GRBVar y = model.addVar(lb, ub, 0.0, GRB.CONTINUOUS, "y");
GRBVar z = model.addVar(lb, ub, 0.0, GRB.CONTINUOUS, "z");
// Set objective for y
GRBLinExpr obj = new GRBLinExpr();
obj.addTerm(-1.0, y);
model.setObjective(obj);
// Add piecewise-linear objective functions for x and z
int npts = 101;
double[] ptu = new double[npts];
double[] ptf = new double[npts];
double[] ptg = new double[npts];
for (int i = 0; i < npts; i++) {
ptu[i] = lb + (ub - lb) * i / (npts - 1);
ptf[i] = f(ptu[i]);
ptg[i] = g(ptu[i]);
}
model.setPWLObj(x, ptu, ptf);
model.setPWLObj(z, ptu, ptg);
// Add constraint: x + 2 y + 3 z <= 4
GRBLinExpr expr = new GRBLinExpr();
expr.addTerm(1.0, x); expr.addTerm(2.0, y); expr.addTerm(3.0, z);
model.addConstr(expr, GRB.LESS_EQUAL, 4.0, "c0");
// Add constraint: x + y >= 1
expr = new GRBLinExpr();
expr.addTerm(1.0, x); expr.addTerm(1.0, y);
model.addConstr(expr, GRB.GREATER_EQUAL, 1.0, "c1");
// Optimize model as an LP
model.optimize();
System.out.println("IsMIP: " + model.get(GRB.IntAttr.IsMIP));
System.out.println(x.get(GRB.StringAttr.VarName)
+ " " +x.get(GRB.DoubleAttr.X));
System.out.println(y.get(GRB.StringAttr.VarName)
+ " " +y.get(GRB.DoubleAttr.X));
System.out.println(z.get(GRB.StringAttr.VarName)
+ " " +z.get(GRB.DoubleAttr.X));
System.out.println("Obj: " + model.get(GRB.DoubleAttr.ObjVal));
System.out.println();
// Negate piecewise-linear objective function for x
for (int i = 0; i < npts; i++) {
ptf[i] = -ptf[i];
}
model.setPWLObj(x, ptu, ptf);
// Optimize model as a MIP
model.optimize();
System.out.println("IsMIP: " + model.get(GRB.IntAttr.IsMIP));
System.out.println(x.get(GRB.StringAttr.VarName)
+ " " +x.get(GRB.DoubleAttr.X));
System.out.println(y.get(GRB.StringAttr.VarName)
+ " " +y.get(GRB.DoubleAttr.X));
System.out.println(z.get(GRB.StringAttr.VarName)
+ " " +z.get(GRB.DoubleAttr.X));
System.out.println("Obj: " + model.get(GRB.DoubleAttr.ObjVal));
// Dispose of model and environment
model.dispose();
env.dispose();
} catch (GRBException e) {
System.out.println("Error code: " + e.getErrorCode() + ". " +
e.getMessage());
}
}
}
function piecewise()
% Copyright 2025, Gurobi Optimization, LLC
%
% This example considers the following separable, convex problem:
%
% minimize f(x) - y + g(z)
% subject to x + 2 y + 3 z <= 4
% x + y >= 1
% x, y, z <= 1
%
% where f(u) = exp(-u) and g(u) = 2 u^2 - 4 u, for all real u. It
% formulates and solves a simpler LP model by approximating f and
% g with piecewise-linear functions. Then it transforms the model
% into a MIP by negating the approximation for f, which corresponds
% to a non-convex piecewise-linear function, and solves it again.
names = {'x'; 'y'; 'z'};
model.A = sparse([1 2 3; 1 1 0]);
model.obj = [0; -1; 0];
model.rhs = [4; 1];
model.sense = '<>';
model.vtype = 'C';
model.lb = [0; 0; 0];
model.ub = [1; 1; 1];
model.varnames = names;
% Compute f and g on 101 points in [0,1]
u = linspace(0.0, 1.0, 101);
f = exp(-u);
g = 2*u.^2 - 4*u;
% Set piecewise-linear objective f(x)
model.pwlobj(1).var = 1;
model.pwlobj(1).x = u;
model.pwlobj(1).y = f;
% Set piecewise-linear objective g(z)
model.pwlobj(2).var = 3;
model.pwlobj(2).x = u;
model.pwlobj(2).y = g;
% Optimize model as LP
result = gurobi(model);
disp(result);
for v=1:length(names)
fprintf('%s %d\n', names{v}, result.x(v));
end
fprintf('Obj: %e\n', result.objval);
% Negate piecewise-linear objective function for x
f = -f;
model.pwlobj(1).y = f;
gurobi_write(model, 'pwl.lp')
% Optimize model as a MIP
result = gurobi(model);
disp(result);
for v=1:length(names)
fprintf('%s %d\n', names{v}, result.x(v));
end
fprintf('Obj: %e\n', result.objval);
end
#!/usr/bin/env python3.11
# Copyright 2025, Gurobi Optimization, LLC
# This example considers the following separable, convex problem:
#
# minimize f(x) - y + g(z)
# subject to x + 2 y + 3 z <= 4
# x + y >= 1
# x, y, z <= 1
#
# where f(u) = exp(-u) and g(u) = 2 u^2 - 4 u, for all real u. It
# formulates and solves a simpler LP model by approximating f and
# g with piecewise-linear functions. Then it transforms the model
# into a MIP by negating the approximation for f, which corresponds
# to a non-convex piecewise-linear function, and solves it again.
import gurobipy as gp
from math import exp
def f(u):
return exp(-u)
def g(u):
return 2 * u * u - 4 * u
try:
# Create a new model
m = gp.Model()
# Create variables
lb = 0.0
ub = 1.0
x = m.addVar(lb, ub, name="x")
y = m.addVar(lb, ub, name="y")
z = m.addVar(lb, ub, name="z")
# Set objective for y
m.setObjective(-y)
# Add piecewise-linear objective functions for x and z
npts = 101
ptu = []
ptf = []
ptg = []
for i in range(npts):
ptu.append(lb + (ub - lb) * i / (npts - 1))
ptf.append(f(ptu[i]))
ptg.append(g(ptu[i]))
m.setPWLObj(x, ptu, ptf)
m.setPWLObj(z, ptu, ptg)
# Add constraint: x + 2 y + 3 z <= 4
m.addConstr(x + 2 * y + 3 * z <= 4, "c0")
# Add constraint: x + y >= 1
m.addConstr(x + y >= 1, "c1")
# Optimize model as an LP
m.optimize()
print(f"IsMIP: {m.IsMIP}")
for v in m.getVars():
print(f"{v.VarName} {v.X:g}")
print(f"Obj: {m.ObjVal:g}")
print("")
# Negate piecewise-linear objective function for x
for i in range(npts):
ptf[i] = -ptf[i]
m.setPWLObj(x, ptu, ptf)
# Optimize model as a MIP
m.optimize()
print(f"IsMIP: {m.IsMIP}")
for v in m.getVars():
print(f"{v.VarName} {v.X:g}")
print(f"Obj: {m.ObjVal:g}")
except gp.GurobiError as e:
print(f"Error code {e.errno}: {e}")
except AttributeError:
print("Encountered an attribute error")
# Copyright 2025, Gurobi Optimization, LLC
#
# This example considers the following separable, convex problem:
#
# minimize
# f(x) - y + g(z)
# subject to
# x + 2 y + 3 z <= 4
# x + y >= 1
# x, y, z <= 1
#
# where f(u) = exp(-u) and g(u) = 2 u^2 - 4u, for all real u. It
# formulates and solves a simpler LP model by approximating f and
# g with piecewise-linear functions. Then it transforms the model
# into a MIP by negating the approximation for f, which gives
# a non-convex piecewise-linear function, and solves it again.
library(gurobi)
model <- list()
model$A <- matrix(c(1,2,3,1,1,0), nrow=2, byrow=T)
model$obj <- c(0,-1,0)
model$ub <- c(1,1,1)
model$rhs <- c(4,1)
model$sense <- c('<', '>')
# Uniformly spaced points in [0.0, 1.0]
u <- seq(from=0, to=1, by=0.01)
# First piecewise-linear function: f(x) = exp(-x)
pwl1 <- list()
pwl1$var <- 1
pwl1$x <- u
pwl1$y <- sapply(u, function(x) exp(-x))
# Second piecewise-linear function: g(z) = 2 z^2 - 4 z
pwl2 <- list()
pwl2$var <- 3
pwl2$x <- u
pwl2$y <- sapply(u, function(z) 2 * z * z - 4 * z)
model$pwlobj <- list(pwl1, pwl2)
result <- gurobi(model)
print(result$objval)
print(result$x)
# Negate piecewise-linear function on x, making it non-convex
model$pwlobj[[1]]$y <- sapply(u, function(x) -exp(-x))
result <- gurobi(model)
gurobi_write(model, "pwl.lp")
print(result$objval)
print(result$x)
# Clear space
rm(model, pwl1, pwl2, result)
' Copyright 2025, Gurobi Optimization, LLC
' This example considers the following separable, convex problem:
'
' minimize f(x) - y + g(z)
' subject to x + 2 y + 3 z <= 4
' x + y >= 1
' x, y, z <= 1
'
' where f(u) = exp(-u) and g(u) = 2 u^2 - 4 u, for all real u. It
' formulates and solves a simpler LP model by approximating f and
' g with piecewise-linear functions. Then it transforms the model
' into a MIP by negating the approximation for f, which corresponds
' to a non-convex piecewise-linear function, and solves it again.
Imports System
Imports Gurobi
Class piecewise_vb
Shared Function f(u As Double) As Double
Return Math.Exp(-u)
End Function
Shared Function g(u As Double) As Double
Return 2 * u * u - 4 * u
End Function
Shared Sub Main()
Try
' Create environment
Dim env As New GRBEnv()
' Create a new model
Dim model As New GRBModel(env)
' Create variables
Dim lb As Double = 0.0, ub As Double = 1.0
Dim x As GRBVar = model.AddVar(lb, ub, 0.0, GRB.CONTINUOUS, "x")
Dim y As GRBVar = model.AddVar(lb, ub, 0.0, GRB.CONTINUOUS, "y")
Dim z As GRBVar = model.AddVar(lb, ub, 0.0, GRB.CONTINUOUS, "z")
' Set objective for y
model.SetObjective(-y)
' Add piecewise-linear objective functions for x and z
Dim npts As Integer = 101
Dim ptu As Double() = New Double(npts - 1) {}
Dim ptf As Double() = New Double(npts - 1) {}
Dim ptg As Double() = New Double(npts - 1) {}
For i As Integer = 0 To npts - 1
ptu(i) = lb + (ub - lb) * i / (npts - 1)
ptf(i) = f(ptu(i))
ptg(i) = g(ptu(i))
Next
model.SetPWLObj(x, ptu, ptf)
model.SetPWLObj(z, ptu, ptg)
' Add constraint: x + 2 y + 3 z <= 4
model.AddConstr(x + 2 * y + 3 * z <= 4.0, "c0")
' Add constraint: x + y >= 1
model.AddConstr(x + y >= 1.0, "c1")
' Optimize model as an LP
model.Optimize()
Console.WriteLine("IsMIP: " & model.IsMIP)
Console.WriteLine(x.VarName & " " & x.X)
Console.WriteLine(y.VarName & " " & y.X)
Console.WriteLine(z.VarName & " " & z.X)
Console.WriteLine("Obj: " & model.ObjVal)
Console.WriteLine()
' Negate piecewise-linear objective function for x
For i As Integer = 0 To npts - 1
ptf(i) = -ptf(i)
Next
model.SetPWLObj(x, ptu, ptf)
' Optimize model as a MIP
model.Optimize()
Console.WriteLine("IsMIP: " & model.IsMIP)
Console.WriteLine(x.VarName & " " & x.X)
Console.WriteLine(y.VarName & " " & y.X)
Console.WriteLine(z.VarName & " " & z.X)
Console.WriteLine("Obj: " & model.ObjVal)
' Dispose of model and environment
model.Dispose()
env.Dispose()
Catch e As GRBException
Console.WriteLine("Error code: " + e.ErrorCode & ". " + e.Message)
End Try
End Sub
End Class