gurobipy-pandas: a quick example¶

  • We have a set of projects, each requiring resources
  • We have a set of teams, each with some capacity
  • Goal: allocate projects to maximize revenue
In [2]:
projects.head(3)  # w_i 
Out[2]:
resource
project
p0 1.1
p1 1.4
p2 1.2
In [3]:
teams.head(3)  # c_j
Out[3]:
capacity
team
t0 2.4
t1 1.8
t2 1.1

Decision variables¶

  • Define $x_{ij} \in \lbrace 0, 1 \rbrace$. If team $j$ completes project $i$, then $x_{ij} = 1$. If team $j$ completes project $i$, we profit $p_{ij}$. Maximize profit!
$$ \max \sum_{i \in I} \sum_{j \in J} p_{i} x_{ij} $$
In [4]:
# gurobipy-pandas creates variables as a series
model = gp.Model()
model.ModelSense = GRB.MAXIMIZE
assignments = project_values.gppd.add_vars(
    model, vtype=GRB.BINARY, obj="profit", name="x"
)
assignments.head()  # p_ij & x_ij
Out[4]:
profit x
project team
p0 t4 0.4 <gurobi.Var x[p0,t4]>
p1 t4 1.3 <gurobi.Var x[p1,t4]>
p2 t0 1.7 <gurobi.Var x[p2,t0]>
t1 1.7 <gurobi.Var x[p2,t1]>
t2 1.7 <gurobi.Var x[p2,t2]>

Capacity constraint¶

  • Assigned projects are limited by team capacity
$$ \sum_{i \in I} w_{i} x_{ij} \le c_{j} \quad \forall j \in J $$
In [5]:
# gurobipy-pandas adds one constraint per grouped constraint
capacity_constraints = gppd.add_constrs(
    model,
    (projects["resource"] * assignments["x"]).groupby("team").sum(),
    GRB.LESS_EQUAL,
    teams["capacity"],
    name='capacity',
)
capacity_constraints.apply(model.getRow).head()
Out[5]:
team
t0    1.2 x[p2,t0] + 0.9 x[p4,t0] + 1.3 x[p5,t0] + x...
t1    1.2 x[p2,t1] + 0.9 x[p4,t1] + 1.3 x[p5,t1] + x...
t2    1.2 x[p2,t2] + 0.9 x[p4,t2] + 1.3 x[p5,t2] + x...
t3    1.2 x[p2,t3] + 0.9 x[p4,t3] + 1.3 x[p5,t3] + x...
t4    1.1 x[p0,t4] + 1.4 x[p1,t4] + 1.2 x[p2,t4] + 1...
Name: capacity, dtype: object

Solutions¶

  • Gurobi solves the model, allocating projects to maximize profit
  • Solution values retrieved as a series on our original index
In [7]:
model.optimize()
(
    assignments["x"].gppd.X.to_frame()
    .query("x >= 0.9").reset_index()
    .groupby("team").agg({"project": list})
)
Out[7]:
project
team
t0 [p4, p5]
t1 [p2]
t2 [p11]
t3 [p6, p29]
t4 [p14, p15, p26]