Model
PyEPO supports end-to-end predict-then-optimize with linear objective functions and unknown cost coefficients. At its core is the differentiable optimization solver, which computes gradients of the cost coefficients with respect to the optimal solution.
optModel is the base abstraction in PyEPO. It wraps an optimization solver or algorithm as a container, providing a unified interface for training and evaluation. PyEPO provides several pre-defined models using GurobiPy, Pyomo, COPT, OR-Tools, and MPAX:
Shortest path (GurobiPy, Pyomo, COPT, OR-Tools & MPAX)
Knapsack (GurobiPy, Pyomo, COPT, OR-Tools & MPAX)
Traveling salesman (GurobiPy, Pyomo & COPT)
Portfolio optimization (GurobiPy, Pyomo & COPT)
When building models with PyEPO, users do not need to specify the cost coefficients, since they are unknown and will be predicted from data.
For more details, see the 01 Optimization Model notebook.
User-defined Models
Users can define custom optimization problems with linear objective functions. PyEPO provides several ways to do this:
GurobiPy-based: Inherit from
optGrbModeland implement_getModel.Pyomo-based: Inherit from
optOmoModeland implement_getModel.COPT-based: Inherit from
optCoptModeland implement_getModel.OR-Tools-based: Inherit from
optOrtModel(pywraplp) oroptOrtCpModel(CP-SAT) and implement_getModel.MPAX-based: Inherit from
optMpaxModeland provide constraint matricesA,b,G,h.From scratch: Inherit from
optModeland implement_getModel,setObj,solve, andnum_cost.
The optModel interface consists of:
_getModel: Build and return the optimization model and decision variables.setObj: Set the objective function with a given cost vector.solve: Solve the problem and return the optimal solution and objective value.
User-defined GurobiPy Models
To define a GurobiPy model, inherit from pyepo.model.grb.optGrbModel and implement the _getModel method. The model sense (minimize/maximize) is automatically detected from the GurobiPy model.
- class pyepo.model.grb.optGrbModel
This is an abstract class for a Gurobi-based optimization model
- _model
Gurobi model
- Type:
GurobiPy model
- __init__()
- abstract _getModel()
An abstract method to build a model from an optimization solver
- Returns:
optimization model and variables
- Return type:
tuple
- property num_cost
number of costs to be predicted
- relax()
An unimplemented method to relax the MIP model
- setObj(c)
A method to set the objective function
- Parameters:
c (np.ndarray / list) – cost of objective function
- solve()
A method to solve the model
- Returns:
optimal solution (list) and objective value (float)
- Return type:
tuple
For example, consider the following binary optimization problem:
Users only need to implement the _getModel method:
import random
import gurobipy as gp
from gurobipy import GRB
from pyepo.model.grb import optGrbModel
class myModel(optGrbModel):
def _getModel(self):
# create a model
m = gp.Model()
# variables
x = m.addVars(5, name="x", vtype=GRB.BINARY)
# model sense
m.modelSense = GRB.MAXIMIZE
# constraints
m.addConstr(3 * x[0] + 4 * x[1] + 3 * x[2] + 6 * x[3] + 4 * x[4] <= 12)
m.addConstr(4 * x[0] + 5 * x[1] + 2 * x[2] + 3 * x[3] + 5 * x[4] <= 10)
m.addConstr(5 * x[0] + 4 * x[1] + 6 * x[2] + 2 * x[3] + 3 * x[4] <= 15)
return m, x
myoptmodel = myModel()
cost = [random.random() for _ in range(myoptmodel.num_cost)] # random cost vector
myoptmodel.setObj(cost) # set objective function
myoptmodel.solve() # solve
User-defined Pyomo Models
To define a Pyomo model, inherit from pyepo.model.omo.optOmoModel and implement the _getModel method.
- class pyepo.model.omo.optOmoModel(solver='glpk')
This is an abstract class for a Pyomo-based optimization model
- _model
Pyomo model
- Type:
Pyomo model
- solver
optimization solver in the background
- Type:
str
- __init__(solver='glpk')
- Parameters:
solver (str) – optimization solver in the background
- abstract _getModel()
An abstract method to build a model from an optimization solver
- Returns:
optimization model and variables
- Return type:
tuple
- property num_cost
number of costs to be predicted
- relax()
An unimplemented method to relax the MIP model
- setObj(c)
A method to set the objective function
- Parameters:
c (np.ndarray / list) – cost of objective function
- solve()
A method to solve the model
- Returns:
optimal solution (list) and objective value (float)
- Return type:
tuple
Warning
Unlike optGrbModel, optOmoModel requires explicitly setting modelSense in _getModel.
Here is the same problem implemented with Pyomo:
import random
from pyomo import environ as pe
from pyepo.model.omo import optOmoModel
from pyepo import EPO
class myModel(optOmoModel):
def _getModel(self):
# sense
self.modelSense = EPO.MAXIMIZE
# create a model
m = pe.ConcreteModel()
# variables
x = pe.Var([0,1,2,3,4], domain=pe.Binary)
m.x = x
# constraints
m.cons = pe.ConstraintList()
m.cons.add(3 * x[0] + 4 * x[1] + 3 * x[2] + 6 * x[3] + 4 * x[4] <= 12)
m.cons.add(4 * x[0] + 5 * x[1] + 2 * x[2] + 3 * x[3] + 5 * x[4] <= 10)
m.cons.add(5 * x[0] + 4 * x[1] + 6 * x[2] + 2 * x[3] + 3 * x[4] <= 15)
return m, x
myoptmodel = myModel(solver="gurobi")
cost = [random.random() for _ in range(myoptmodel.num_cost)] # random cost vector
myoptmodel.setObj(cost) # set objective function
myoptmodel.solve() # solve
User-defined COPT Models
To define a COPT model, inherit from pyepo.model.copt.optCoptModel and implement the _getModel method. The model sense (minimize/maximize) is automatically detected from the COPT model.
- class pyepo.model.copt.optCoptModel
This is an abstract class for a Cardinal Optimizer optimization model
- _model
COPT model
- Type:
COPT model
- __init__()
- abstract _getModel()
An abstract method to build a model from an optimization solver
- Returns:
optimization model and variables
- Return type:
tuple
- property num_cost
number of costs to be predicted
- setObj(c)
A method to set the objective function
- Parameters:
c (np.ndarray / list) – cost of objective function
- solve()
A method to solve the model
- Returns:
optimal solution (list) and objective value (float)
- Return type:
tuple
Here is the same problem implemented with COPT:
import random
from coptpy import Envr, COPT
from pyepo.model.copt import optCoptModel
class myModel(optCoptModel):
def _getModel(self):
# create a model
m = Envr().createModel()
# variables
x = m.addVars(range(5), vtype=COPT.BINARY)
# model sense
m.setObjSense(COPT.MAXIMIZE)
# constraints
m.addConstr(3 * x[0] + 4 * x[1] + 3 * x[2] + 6 * x[3] + 4 * x[4] <= 12)
m.addConstr(4 * x[0] + 5 * x[1] + 2 * x[2] + 3 * x[3] + 5 * x[4] <= 10)
m.addConstr(5 * x[0] + 4 * x[1] + 6 * x[2] + 2 * x[3] + 3 * x[4] <= 15)
return m, x
myoptmodel = myModel()
cost = [random.random() for _ in range(myoptmodel.num_cost)] # random cost vector
myoptmodel.setObj(cost) # set objective function
myoptmodel.solve() # solve
User-defined OR-Tools Models
OR-Tools provides two solving paradigms: pywraplp (LP/MIP solvers) and CP-SAT (constraint programming). PyEPO provides base classes for both.
pywraplp — Inherit from pyepo.model.ort.optOrtModel and implement _getModel. The solver parameter selects the backend (e.g., "scip", "glop", "cbc").
- class pyepo.model.ort.optOrtModel(solver='scip')
This is an abstract class for an OR-Tools pywraplp optimization model
- _model
OR-Tools linear solver
- Type:
pywraplp.Solver
- solver
solver backend (e.g. “scip”, “glop”, “cbc”)
- Type:
str
- __init__(solver='scip')
- Parameters:
solver (str) – solver backend for pywraplp
- abstract _getModel()
An abstract method to build a model from an optimization solver
- Returns:
optimization model and variables
- Return type:
tuple
- property num_cost
number of costs to be predicted
- setObj(c)
A method to set the objective function
- Parameters:
c (np.ndarray / list) – cost of objective function
- solve()
A method to solve the model
- Returns:
optimal solution (list) and objective value (float)
- Return type:
tuple
Warning
Unlike optGrbModel, optOrtModel requires explicitly setting modelSense in _getModel.
import random
from ortools.linear_solver import pywraplp
from pyepo.model.ort import optOrtModel
from pyepo import EPO
class myModel(optOrtModel):
def _getModel(self):
# sense
self.modelSense = EPO.MAXIMIZE
# create a model
m = pywraplp.Solver.CreateSolver("SCIP")
# variables
x = {i: m.BoolVar(f"x_{i}") for i in range(5)}
# constraints
m.Add(3 * x[0] + 4 * x[1] + 3 * x[2] + 6 * x[3] + 4 * x[4] <= 12)
m.Add(4 * x[0] + 5 * x[1] + 2 * x[2] + 3 * x[3] + 5 * x[4] <= 10)
m.Add(5 * x[0] + 4 * x[1] + 6 * x[2] + 2 * x[3] + 3 * x[4] <= 15)
return m, x
myoptmodel = myModel(solver="scip")
cost = [random.random() for _ in range(myoptmodel.num_cost)] # random cost vector
myoptmodel.setObj(cost) # set objective function
myoptmodel.solve() # solve
CP-SAT — Inherit from pyepo.model.ort.optOrtCpModel and implement _getModel. CP-SAT is an integer-only solver; float cost vectors are automatically scaled internally.
- class pyepo.model.ort.optOrtCpModel
This is an abstract class for an OR-Tools CP-SAT optimization model
- _model
OR-Tools CP-SAT model
- Type:
cp_model.CpModel
- __init__()
- abstract _getModel()
An abstract method to build a model from an optimization solver
- Returns:
optimization model and variables
- Return type:
tuple
- property num_cost
number of costs to be predicted
- setObj(c)
A method to set the objective function
- Parameters:
c (np.ndarray / list) – cost of objective function
- solve()
A method to solve the model
- Returns:
optimal solution (list) and objective value (float)
- Return type:
tuple
from ortools.sat.python import cp_model
from pyepo.model.ort import optOrtCpModel
from pyepo import EPO
class myCpModel(optOrtCpModel):
def _getModel(self):
# sense
self.modelSense = EPO.MAXIMIZE
# create a model
m = cp_model.CpModel()
# variables
x = {i: m.NewBoolVar(f"x_{i}") for i in range(5)}
# constraints (integer coefficients)
m.Add(3 * x[0] + 4 * x[1] + 3 * x[2] + 6 * x[3] + 4 * x[4] <= 12)
m.Add(4 * x[0] + 5 * x[1] + 2 * x[2] + 3 * x[3] + 5 * x[4] <= 10)
m.Add(5 * x[0] + 4 * x[1] + 6 * x[2] + 2 * x[3] + 3 * x[4] <= 15)
return m, x
myoptmodel = myCpModel()
Note
CP-SAT does not support LP relaxation. Calling relax() will raise a RuntimeError.
User-defined MPAX Models
MPAX (Mathematical Programming in JAX) is a hardware-accelerated mathematical programming framework based on the PDHG (Primal-Dual Hybrid Gradient) algorithm, designed for large-scale LP problems.
optMpaxModel is a PyEPO model that uses MPAX to solve LP relaxations via PDHG. It accepts constraints in matrix/vector form:
A,b: Equality constraints \(Ax = b\). Omit if there are no equality constraints.
G,h: Inequality constraints \(Gx \leq h\). Omit if there are no inequality constraints.
l: Lower bounds (default: 0, i.e., non-negative variables).
u: Upper bounds (default: infinity, i.e., unbounded).
use_sparse_matrix(default:True): Whether to use sparse matrix storage.
minimize(default:True): Whether to minimize the objective.
- class pyepo.model.mpax.optMpaxModel(A=None, b=None, G=None, h=None, l=None, u=None, use_sparse_matrix=True, minimize=True)
This is an abstract class for an MPAX-based optimization model
- A
The matrix of equality constraints.
- Type:
jnp.ndarray, BCOO or BCSR
- b
The right hand side of equality constraints.
- Type:
jnp.ndarray
- G
The matrix for inequality constraints.
- Type:
jnp.ndarray, BCOO or BCSR
- h
The right hand side of inequality constraints.
- Type:
jnp.ndarray
- l
The lower bound of the variables.
- Type:
jnp.ndarray
- u
The upper bound of the variables.
- Type:
jnp.ndarray
- use_sparse_matrix
Whether to use sparse matrix format, by default True.
- Type:
bool
- minimize
Whether to minimize objective, by default True.
- Type:
bool
- __init__(A=None, b=None, G=None, h=None, l=None, u=None, use_sparse_matrix=True, minimize=True)
- _getModel()
Placeholder method for MPAX. MPAX does not require an explicit model creation.
- property num_cost
number of costs to be predicted
- relax()
An unimplemented method to relax the MIP model
- setObj(c)
A method to set the objective function
- Parameters:
c (np.ndarray / list) – cost of objective function
- solve()
A method to solve the model
- Returns:
optimal solution (list) and objective value (jnp.float32)
- Return type:
tuple
from pyepo.model.mpax import optMpaxModel
optmodel = optMpaxModel(A=A, b=b, G=G, h=h, use_sparse_matrix=False, minimize=True)
optmodel.setObj(cost) # set objective function
optmodel.solve() # solve
User-defined Models from Scratch
For complete flexibility, pyepo.model.opt.optModel allows users to build models with any solver or algorithm. Override _getModel, setObj, solve, and num_cost to integrate a custom solver.
- class pyepo.model.opt.optModel
This is an abstract class for an optimization model
- _model
underlying solver model object
- Type:
optimization model
- __init__()
- abstract _getModel()
An abstract method to build a model from an optimization solver
- Returns:
optimization model and variables
- Return type:
tuple
- property num_cost
number of costs to be predicted
- abstract setObj(c)
An abstract method to set the objective function
- Parameters:
c (ndarray) – cost of objective function
- abstract solve()
An abstract method to solve the model
- Returns:
optimal solution (list) and objective value (float)
- Return type:
tuple
Warning
optModel requires setting modelSense in _getModel. If not set, the default is minimization.
The following example uses networkx with the Dijkstra algorithm to solve a shortest path problem:
import random
import numpy as np
import networkx as nx
from pyepo.model.opt import optModel
class myShortestPathModel(optModel):
def __init__(self, grid):
"""
Args:
grid (tuple): size of grid network
"""
self.grid = grid
self.arcs = self._getArcs()
super().__init__()
def _getArcs(self):
"""
A method to get list of arcs for grid network
Returns:
list: arcs
"""
arcs = []
for i in range(self.grid[0]):
# edges on rows
for j in range(self.grid[1] - 1):
v = i * self.grid[1] + j
arcs.append((v, v + 1))
# edges in columns
if i == self.grid[0] - 1:
continue
for j in range(self.grid[1]):
v = i * self.grid[1] + j
arcs.append((v, v + self.grid[1]))
return arcs
def _getModel(self):
"""
A method to build model
Returns:
tuple: optimization model and variables
"""
# build graph as optimization model
g = nx.Graph()
# add arcs as variables
g.add_edges_from(self.arcs, cost=0)
return g, g.edges
def setObj(self, c):
"""
A method to set objective function
Args:
c (ndarray): cost of objective function
"""
for i, e in enumerate(self.arcs):
self._model.edges[e]["cost"] = c[i]
def solve(self):
"""
A method to solve model
Returns:
tuple: optimal solution (list) and objective value (float)
"""
# dijkstra
path = nx.shortest_path(self._model, weight="cost", source=0, target=self.grid[0]*self.grid[1]-1)
# convert path into active edges
edges = []
u = 0
for v in path[1:]:
edges.append((u,v))
u = v
# init sol & obj
sol = np.zeros(self.num_cost)
obj = 0
# convert active edges into solution and obj
for i, e in enumerate(self.arcs):
if e in edges:
sol[i] = 1 # active edge
obj += self._model.edges[e]["cost"] # cost of active edge
return sol, obj
# solve model
grid = (5,5)
myoptmodel = myShortestPathModel(grid)
cost = [random.random() for _ in range(myoptmodel.num_cost)] # random cost vector
myoptmodel.setObj(cost) # set objective function
sol, obj = myoptmodel.solve() # solve
# print res
print('Obj: {}'.format(obj))
for i, e in enumerate(myoptmodel.arcs):
if sol[i] > 1e-3:
print(e)
Pre-defined Models
PyEPO includes pre-defined models for several classic optimization problems.
Shortest Path
The shortest path problem finds the minimum-cost path from the northwest corner to the southeast corner of an (h, w) grid network. The default grid size is (5, 5).
The problem is formulated as a minimum cost flow linear program.
GurobiPy
- class pyepo.model.grb.shortestPathModel(grid)
This class is an optimization model for the shortest path problem
- _model
Gurobi model
- Type:
GurobiPy model
- grid
Size of grid network
- Type:
tuple of int
- arcs
List of arcs
- Type:
list
- __init__(grid)
- Parameters:
grid (tuple of int) – size of grid network
- property num_cost
number of costs to be predicted
- setObj(c)
A method to set the objective function
- Parameters:
c (np.ndarray / list) – cost of objective function
- solve()
A method to solve the model
- Returns:
optimal solution (list) and objective value (float)
- Return type:
tuple
import pyepo
grid = (5,5) # network grid
optmodel = pyepo.model.grb.shortestPathModel(grid) # build model
The setObj and solve methods can be called manually, but they are invoked automatically during training.
import random
cost = [random.random() for _ in range(optmodel.num_cost)] # random cost vector
optmodel.setObj(cost) # set objective function
optmodel.solve() # solve
Pyomo
- class pyepo.model.omo.shortestPathModel(grid, solver='glpk')
This class is an optimization model for the shortest path problem
- _model
Pyomo model
- Type:
Pyomo model
- solver
optimization solver in the background
- Type:
str
- grid
size of grid network
- Type:
tuple of int
- arcs
list of arcs
- Type:
list
- __init__(grid, solver='glpk')
- Parameters:
grid (tuple of int) – size of grid network
solver (str) – optimization solver in the background
- property num_cost
number of costs to be predicted
- setObj(c)
A method to set the objective function
- Parameters:
c (np.ndarray / list) – cost of objective function
- solve()
A method to solve the model
- Returns:
optimal solution (list) and objective value (float)
- Return type:
tuple
Pyomo supports multiple backend solvers (e.g., BARON, CBC, CPLEX, Gurobi). Specify the solver via the solver parameter:
import pyepo
grid = (5,5) # network grid
optmodel = pyepo.model.omo.shortestPathModel(grid, solver="glpk") # build model with GLPK
optmodel = pyepo.model.omo.shortestPathModel(grid, solver="gurobi") # build model with Gurobi
To list available solvers:
pyomo help --solvers
COPT
- class pyepo.model.copt.shortestPathModel(grid)
This class is an optimization model for the shortest path problem
- _model
COPT model
- Type:
COPT model
- grid
size of grid network
- Type:
tuple of int
- arcs
list of arcs
- Type:
list
- __init__(grid)
- Parameters:
grid (tuple of int) – size of grid network
- property num_cost
number of costs to be predicted
- setObj(c)
A method to set the objective function
- Parameters:
c (np.ndarray / list) – cost of objective function
- solve()
A method to solve the model
- Returns:
optimal solution (list) and objective value (float)
- Return type:
tuple
import pyepo
grid = (5,5) # network grid
optmodel = pyepo.model.copt.shortestPathModel(grid) # build model
OR-Tools
OR-Tools provides two approaches: pywraplp (LP/MIP) and CP-SAT (constraint programming).
- class pyepo.model.ort.shortestPathModel(grid, solver='glop')
This class is an optimization model for the shortest path problem
- _model
OR-Tools linear solver
- Type:
pywraplp.Solver
- solver
solver backend
- Type:
str
- grid
size of grid network
- Type:
tuple of int
- arcs
list of arcs
- Type:
list
- __init__(grid, solver='glop')
- Parameters:
grid (tuple of int) – size of grid network
solver (str) – solver backend for pywraplp
- property num_cost
number of costs to be predicted
- setObj(c)
A method to set the objective function
- Parameters:
c (np.ndarray / list) – cost of objective function
- solve()
A method to solve the model
- Returns:
optimal solution (list) and objective value (float)
- Return type:
tuple
import pyepo
grid = (5,5) # network grid
optmodel = pyepo.model.ort.shortestPathModel(grid) # pywraplp with GLOP (default)
optmodel = pyepo.model.ort.shortestPathModel(grid, solver="scip") # pywraplp with SCIP
- class pyepo.model.ort.shortestPathCpModel(grid)
This class is an optimization model for the shortest path problem using CP-SAT
- _model
OR-Tools CP-SAT model
- Type:
cp_model.CpModel
- grid
size of grid network
- Type:
tuple of int
- arcs
list of arcs
- Type:
list
- __init__(grid)
- Parameters:
grid (tuple of int) – size of grid network
- property num_cost
number of costs to be predicted
- setObj(c)
A method to set the objective function
- Parameters:
c (np.ndarray / list) – cost of objective function
- solve()
A method to solve the model
- Returns:
optimal solution (list) and objective value (float)
- Return type:
tuple
import pyepo
grid = (5,5) # network grid
optmodel = pyepo.model.ort.shortestPathCpModel(grid) # CP-SAT
MPAX
- class pyepo.model.mpax.shortestPathModel(grid)
This class is an optimization model for the shortest path problem
- grid
Size of grid network
- Type:
tuple of int
- arcs
List of arcs
- Type:
list
- __init__(grid)
- Parameters:
grid (tuple of int) – size of grid network
- property num_cost
number of costs to be predicted
- setObj(c)
A method to set the objective function
- Parameters:
c (np.ndarray / list) – cost of objective function
- solve()
A method to solve the model
- Returns:
optimal solution (list) and objective value (jnp.float32)
- Return type:
tuple
import pyepo
grid = (5,5) # network grid
optmodel = pyepo.model.mpax.shortestPathModel(grid) # build model
Knapsack
The multi-dimensional knapsack problem is a maximization problem: select a subset of items such that total weight does not exceed resource capacities and total value is maximized. Consider a 3-dimensional example:
The constraint coefficients weights and right-hand sides capacities define the problem.
Note
The number of dimensions and items are determined by the shape of weights and capacities.
GurobiPy
- class pyepo.model.grb.knapsackModel(weights, capacity)
This class is an optimization model for the knapsack problem
- _model
Gurobi model
- Type:
GurobiPy model
- weights
Weights of items
- Type:
np.ndarray / list
- capacity
Total capacity
- Type:
np.ndarray / list
- items
List of item index
- Type:
list
- __init__(weights, capacity)
- Parameters:
weights (np.ndarray / list) – weights of items
capacity (np.ndarray / list) – total capacity
- property num_cost
number of costs to be predicted
- relax()
A method to get linear relaxation model
- setObj(c)
A method to set the objective function
- Parameters:
c (np.ndarray / list) – cost of objective function
- solve()
A method to solve the model
- Returns:
optimal solution (list) and objective value (float)
- Return type:
tuple
import pyepo
weights = [[3, 4, 3, 6, 4],
[4, 5, 2, 3, 5],
[5, 4, 6, 2, 3]] # constraints coefficients
capacities = [12, 10, 15] # constraints rhs
optmodel = pyepo.model.grb.knapsackModel(weights, capacities) # build model
import random
cost = [random.random() for _ in range(optmodel.num_cost)] # random cost vector
optmodel.setObj(cost) # set objective function
optmodel.solve() # solve
The relax method returns an LP relaxation by removing integrality constraints:
optmodel_rel = optmodel.relax() # relax
Pyomo
- class pyepo.model.omo.knapsackModel(weights, capacity, solver='glpk')
This class is an optimization model for the knapsack problem
- _model
Pyomo model
- Type:
Pyomo model
- solver
optimization solver in the background
- Type:
str
- weights
weights of items
- Type:
np.ndarray
- capacity
total capacity
- Type:
np.ndarray
- items
list of item index
- Type:
list
- __init__(weights, capacity, solver='glpk')
- Parameters:
weights (np.ndarray / list) – weights of items
capacity (np.ndarray / list) – total capacity
solver (str) – optimization solver in the background
- property num_cost
number of costs to be predicted
- relax()
A method to get linear relaxation model
- setObj(c)
A method to set the objective function
- Parameters:
c (np.ndarray / list) – cost of objective function
- solve()
A method to solve the model
- Returns:
optimal solution (list) and objective value (float)
- Return type:
tuple
import pyepo
weights = [[3, 4, 3, 6, 4],
[4, 5, 2, 3, 5],
[5, 4, 6, 2, 3]] # constraints coefficients
capacities = [12, 10, 15] # constraints rhs
# build model with GLPK
optmodel = pyepo.model.omo.knapsackModel(weights, capacities, solver="glpk")
# build model with Gurobi
optmodel = pyepo.model.omo.knapsackModel(weights, capacities, solver="gurobi")
COPT
- class pyepo.model.copt.knapsackModel(weights, capacity)
This class is an optimization model for the knapsack problem
- _model
COPT model
- Type:
COPT model
- weights
weights of items
- Type:
np.ndarray
- capacity
total capacity
- Type:
np.ndarray
- items
list of item index
- Type:
list
- __init__(weights, capacity)
- Parameters:
weights (np.ndarray / list) – weights of items
capacity (np.ndarray / list) – total capacity
- property num_cost
number of costs to be predicted
- relax()
A method to get linear relaxation model
- setObj(c)
A method to set the objective function
- Parameters:
c (np.ndarray / list) – cost of objective function
- solve()
A method to solve the model
- Returns:
optimal solution (list) and objective value (float)
- Return type:
tuple
import pyepo
weights = [[3, 4, 3, 6, 4],
[4, 5, 2, 3, 5],
[5, 4, 6, 2, 3]] # constraints coefficients
capacities = [12, 10, 15] # constraints rhs
optmodel = pyepo.model.copt.knapsackModel(weights, capacities) # build model
OR-Tools
- class pyepo.model.ort.knapsackModel(weights, capacity, solver='scip')
This class is an optimization model for the knapsack problem
- _model
OR-Tools linear solver
- Type:
pywraplp.Solver
- solver
solver backend
- Type:
str
- weights
weights of items
- Type:
np.ndarray
- capacity
total capacity
- Type:
np.ndarray
- items
list of item index
- Type:
list
- __init__(weights, capacity, solver='scip')
- Parameters:
weights (np.ndarray / list) – weights of items
capacity (np.ndarray / list) – total capacity
solver (str) – solver backend for pywraplp
- property num_cost
number of costs to be predicted
- relax()
A method to get linear relaxation model
- setObj(c)
A method to set the objective function
- Parameters:
c (np.ndarray / list) – cost of objective function
- solve()
A method to solve the model
- Returns:
optimal solution (list) and objective value (float)
- Return type:
tuple
import pyepo
weights = [[3, 4, 3, 6, 4],
[4, 5, 2, 3, 5],
[5, 4, 6, 2, 3]] # constraints coefficients
capacities = [12, 10, 15] # constraints rhs
optmodel = pyepo.model.ort.knapsackModel(weights, capacities) # pywraplp with SCIP (default)
- class pyepo.model.ort.knapsackCpModel(weights, capacity)
This class is an optimization model for the knapsack problem using CP-SAT
- _model
OR-Tools CP-SAT model
- Type:
cp_model.CpModel
- weights
weights of items
- Type:
np.ndarray
- capacity
total capacity
- Type:
np.ndarray
- items
list of item index
- Type:
list
- __init__(weights, capacity)
- Parameters:
weights (np.ndarray / list) – weights of items
capacity (np.ndarray / list) – total capacity
- property num_cost
number of costs to be predicted
- setObj(c)
A method to set the objective function
- Parameters:
c (np.ndarray / list) – cost of objective function
- solve()
A method to solve the model
- Returns:
optimal solution (list) and objective value (float)
- Return type:
tuple
import pyepo
weights = [[3, 4, 3, 6, 4],
[4, 5, 2, 3, 5],
[5, 4, 6, 2, 3]] # integer coefficients for CP-SAT
capacities = [12, 10, 15] # constraints rhs
optmodel = pyepo.model.ort.knapsackCpModel(weights, capacities) # CP-SAT
Note
CP-SAT requires integer coefficients. Float weights will be truncated to integers.
MPAX
MPAX solves the LP relaxation of the knapsack problem using the PDHG algorithm.
- class pyepo.model.mpax.knapsackModel(weights, capacity)
This class is an optimization model for the relaxed knapsack problem
- _model
MPAX model
- weights
Weights of items
- Type:
np.ndarray / list
- capacity
Total capacity
- Type:
np.ndarray / list
- items
List of item index
- Type:
list
- __init__(weights, capacity)
- Parameters:
weights (np.ndarray / list) – weights of items
capacity (np.ndarray / list) – total capacity
- property num_cost
number of costs to be predicted
- setObj(c)
A method to set the objective function
- Parameters:
c (np.ndarray / list) – cost of objective function
- solve()
A method to solve the model
- Returns:
optimal solution (list) and objective value (jnp.float32)
- Return type:
tuple
import pyepo
import numpy as np
weights = np.array([[3, 4, 3, 6, 4],
[4, 5, 2, 3, 5],
[5, 4, 6, 2, 3]]) # constraints coefficients
capacities = [12, 10, 15] # constraints rhs
optmodel = pyepo.model.mpax.knapsackModel(weights, capacities) # build model
Traveling Salesman
The traveling salesman problem (TSP) seeks the shortest route that visits each city exactly once and returns to the origin. We consider the symmetric TSP with 20 nodes.
Three ILP formulations are available: Dantzig-Fulkerson-Johnson (DFJ), Gavish-Graves (GG), and Miller-Tucker-Zemlin (MTZ).
Note
The DFJ formulation uses lazy constraints and is available with GurobiPy and COPT. The GG and MTZ formulations are available with GurobiPy, Pyomo, and COPT.
GurobiPy
DFJ Formulation
- class pyepo.model.grb.tspDFJModel(num_nodes)
This class is an optimization model for the traveling salesman problem based on Danzig–Fulkerson–Johnson (DFJ) formulation and constraint generation.
- _model
Gurobi model
- Type:
GurobiPy model
- num_nodes
Number of nodes
- Type:
int
- edges
List of edge index
- Type:
list
- __init__(num_nodes)
- Parameters:
num_nodes (int) – number of nodes
- property num_cost
number of costs to be predicted
- setObj(c)
A method to set the objective function
- Parameters:
c (list) – cost vector
- solve()
A method to solve model
The DFJ formulation has exponentially many subtour elimination constraints, solved via column generation. LP relaxation is not supported.
import pyepo
import random
num_nodes = 20 # number of nodes
optmodel = pyepo.model.grb.tspDFJModel(num_nodes) # build model
cost = [random.random() for _ in range(optmodel.num_cost)] # random cost vector
optmodel.setObj(cost) # set objective function
optmodel.solve() # solve
GG Formulation
- class pyepo.model.grb.tspGGModel(num_nodes)
This class is an optimization model for the traveling salesman problem based on Gavish–Graves (GG) formulation.
- _model
Gurobi model
- Type:
GurobiPy model
- num_nodes
Number of nodes
- Type:
int
- edges
List of edge index
- Type:
list
- __init__(num_nodes)
- Parameters:
num_nodes (int) – number of nodes
- property num_cost
number of costs to be predicted
- relax()
A method to get linear relaxation model
- setObj(c)
A method to set the objective function
- Parameters:
c (list) – cost vector
- solve()
A method to solve model
import pyepo
import random
num_nodes = 20 # number of nodes
optmodel = pyepo.model.grb.tspGGModel(num_nodes) # build model
cost = [random.random() for _ in range(optmodel.num_cost)] # random cost vector
optmodel.setObj(cost) # set objective function
optmodel.solve() # solve
optmodel.relax() # relax
MTZ Formulation
- class pyepo.model.grb.tspMTZModel(num_nodes)
This class is an optimization model for the traveling salesman problem based on Miller-Tucker-Zemlin (MTZ) formulation.
- _model
Gurobi model
- Type:
GurobiPy model
- num_nodes
Number of nodes
- Type:
int
- edges
List of edge index
- Type:
list
- __init__(num_nodes)
- Parameters:
num_nodes (int) – number of nodes
- property num_cost
number of costs to be predicted
- relax()
A method to get linear relaxation model
- setObj(c)
A method to set the objective function
- Parameters:
c (list) – cost vector
- solve()
A method to solve model
import pyepo
import random
num_nodes = 20 # number of nodes
optmodel = pyepo.model.grb.tspMTZModel(num_nodes) # build model
cost = [random.random() for _ in range(optmodel.num_cost)] # random cost vector
optmodel.setObj(cost) # set objective function
optmodel.solve() # solve
optmodel.relax() # relax
Pyomo
The GG and MTZ formulations are available with Pyomo. The DFJ formulation is not supported in Pyomo due to the lack of a native callback API.
- class pyepo.model.omo.tspGGModel(num_nodes, solver='glpk')
This class is an optimization model for the traveling salesman problem based on Gavish-Graves (GG) formulation.
- _model
Pyomo model
- Type:
Pyomo model
- solver
optimization solver in the background
- Type:
str
- num_nodes
Number of nodes
- Type:
int
- edges
List of edge index
- Type:
list
- __init__(num_nodes, solver='glpk')
- Parameters:
num_nodes (int) – number of nodes
solver (str) – optimization solver in the background
- property num_cost
number of costs to be predicted
- relax()
A method to get linear relaxation model
- setObj(c)
A method to set the objective function
- Parameters:
c (list) – cost vector
- solve()
A method to solve model
- class pyepo.model.omo.tspMTZModel(num_nodes, solver='glpk')
This class is an optimization model for the traveling salesman problem based on Miller-Tucker-Zemlin (MTZ) formulation.
- _model
Pyomo model
- Type:
Pyomo model
- solver
optimization solver in the background
- Type:
str
- num_nodes
Number of nodes
- Type:
int
- edges
List of edge index
- Type:
list
- __init__(num_nodes, solver='glpk')
- Parameters:
num_nodes (int) – number of nodes
solver (str) – optimization solver in the background
- property num_cost
number of costs to be predicted
- relax()
A method to get linear relaxation model
- setObj(c)
A method to set the objective function
- Parameters:
c (list) – cost vector
- solve()
A method to solve model
import pyepo
import random
num_nodes = 20 # number of nodes
# GG formulation with Gurobi solver
optmodel = pyepo.model.omo.tspGGModel(num_nodes, solver="gurobi")
# MTZ formulation with GLPK solver
optmodel = pyepo.model.omo.tspMTZModel(num_nodes, solver="glpk")
cost = [random.random() for _ in range(optmodel.num_cost)] # random cost vector
optmodel.setObj(cost) # set objective function
optmodel.solve() # solve
COPT
All three formulations (DFJ, GG, MTZ) are available with COPT. The DFJ formulation uses COPT’s callback API for lazy subtour elimination constraints.
- class pyepo.model.copt.tspDFJModel(num_nodes)
This class is an optimization model for the traveling salesman problem based on Danzig-Fulkerson-Johnson (DFJ) formulation and constraint generation.
- _model
COPT model
- Type:
COPT model
- num_nodes
Number of nodes
- Type:
int
- edges
List of edge index
- Type:
list
- __init__(num_nodes)
- Parameters:
num_nodes (int) – number of nodes
- property num_cost
number of costs to be predicted
- setObj(c)
A method to set the objective function
- Parameters:
c (list) – cost vector
- solve()
A method to solve model
- class pyepo.model.copt.tspGGModel(num_nodes)
This class is an optimization model for the traveling salesman problem based on Gavish-Graves (GG) formulation.
- _model
COPT model
- Type:
COPT model
- num_nodes
Number of nodes
- Type:
int
- edges
List of edge index
- Type:
list
- __init__(num_nodes)
- Parameters:
num_nodes (int) – number of nodes
- property num_cost
number of costs to be predicted
- relax()
A method to get linear relaxation model
- setObj(c)
A method to set the objective function
- Parameters:
c (list) – cost vector
- solve()
A method to solve model
- class pyepo.model.copt.tspMTZModel(num_nodes)
This class is an optimization model for the traveling salesman problem based on Miller-Tucker-Zemlin (MTZ) formulation.
- _model
COPT model
- Type:
COPT model
- num_nodes
Number of nodes
- Type:
int
- edges
List of edge index
- Type:
list
- __init__(num_nodes)
- Parameters:
num_nodes (int) – number of nodes
- property num_cost
number of costs to be predicted
- relax()
A method to get linear relaxation model
- setObj(c)
A method to set the objective function
- Parameters:
c (list) – cost vector
- solve()
A method to solve model
import pyepo
import random
num_nodes = 20 # number of nodes
# DFJ formulation
optmodel = pyepo.model.copt.tspDFJModel(num_nodes)
# GG formulation
optmodel = pyepo.model.copt.tspGGModel(num_nodes)
# MTZ formulation
optmodel = pyepo.model.copt.tspMTZModel(num_nodes)
cost = [random.random() for _ in range(optmodel.num_cost)] # random cost vector
optmodel.setObj(cost) # set objective function
optmodel.solve() # solve
Portfolio
Portfolio optimization selects an asset allocation that maximizes expected return for a given level of risk:
GurobiPy
- class pyepo.model.grb.portfolioModel(num_assets, covariance, gamma=2.25)
This class is an optimization model for the portfolio problem
- _model
Gurobi model
- Type:
GurobiPy model
- num_assets
number of assets
- Type:
int
- covariance
covariance matrix of the returns
- Type:
numpy.ndarray
- risk_level
risk level
- Type:
float
- __init__(num_assets, covariance, gamma=2.25)
- Parameters:
num_assets (int) – number of assets
covariance (numpy.ndarray) – covariance matrix of the returns
gamma (float) – risk level parameter
- property num_cost
number of costs to be predicted
- setObj(c)
A method to set the objective function
- Parameters:
c (np.ndarray / list) – cost of objective function
- solve()
A method to solve the model
- Returns:
optimal solution (list) and objective value (float)
- Return type:
tuple
import pyepo
import numpy as np
m = 50 # number of assets
cov = np.cov(np.random.randn(10, m), rowvar=False) # covariance matrix
optmodel = pyepo.model.grb.portfolioModel(m, cov) # build model
import random
revenue = [random.random() for _ in range(optmodel.num_cost)] # random cost vector
optmodel.setObj(revenue) # set objective function
optmodel.solve() # solve
Pyomo
- class pyepo.model.omo.portfolioModel(num_assets, covariance, gamma=2.25, solver='glpk')
This class is an optimization model for the portfolio problem
- _model
Pyomo model
- Type:
Pyomo model
- solver
optimization solver in the background
- Type:
str
- num_assets
number of assets
- Type:
int
- covariance
covariance matrix of the returns
- Type:
numpy.ndarray
- risk_level
risk level
- Type:
float
- __init__(num_assets, covariance, gamma=2.25, solver='glpk')
- Parameters:
num_assets (int) – number of assets
covariance (numpy.ndarray) – covariance matrix of the returns
gamma (float) – risk level parameter
solver (str) – optimization solver in the background
- property num_cost
number of costs to be predicted
- setObj(c)
A method to set the objective function
- Parameters:
c (np.ndarray / list) – cost of objective function
- solve()
A method to solve the model
- Returns:
optimal solution (list) and objective value (float)
- Return type:
tuple
import pyepo
import numpy as np
m = 50 # number of assets
cov = np.cov(np.random.randn(10, m), rowvar=False) # covariance matrix
optmodel = pyepo.model.omo.portfolioModel(m, cov, solver="gurobi") # build model
COPT
- class pyepo.model.copt.portfolioModel(num_assets, covariance, gamma=2.25)
This class is an optimization model for the portfolio problem
- _model
COPT model
- Type:
COPT model
- num_assets
number of assets
- Type:
int
- covariance
covariance matrix of the returns
- Type:
numpy.ndarray
- risk_level
risk level
- Type:
float
- __init__(num_assets, covariance, gamma=2.25)
- Parameters:
num_assets (int) – number of assets
covariance (numpy.ndarray) – covariance matrix of the returns
gamma (float) – risk level parameter
- property num_cost
number of costs to be predicted
- setObj(c)
A method to set the objective function
- Parameters:
c (np.ndarray / list) – cost of objective function
- solve()
A method to solve the model
- Returns:
optimal solution (list) and objective value (float)
- Return type:
tuple
import pyepo
import numpy as np
m = 50 # number of assets
cov = np.cov(np.random.randn(10, m), rowvar=False) # covariance matrix
optmodel = pyepo.model.copt.portfolioModel(m, cov) # build model