Pay to open, save on transport.
Chapter: XIII — Facility location · lesson id facility-uncapacitated · practice lesson
Two candidate facilities, three customers. Opening facility f costs f_f. Serving customer c from facility f costs c_{c,f}. Each customer must be served by exactly one facility, and a facility can only serve a customer if it's open.
Two variable families: y_f binary (open / not), x_{c,f} binary (assignment). The coupling constraint x_{c,f} ≤ y_f is what makes this an integer programme rather than two independent problems.
Open costs {5, 6}, transport costs [[2, 4], [3, 1], [4, 2]]. Optimum: open only facility 2, total cost 6 + (4 + 1 + 2) = 13.
Setup costs {5, 6}, transport per customer-facility. Without capacities, how many facilities open?
model facility
set F = {1, 2}
set C = {1, 2, 3}
const f = {5, 6}, forall j in F
const t = {{2, 4}, {3, 1}, {4, 2}}, forall i in C, forall j in F
bin y, forall j in F
bin x, forall i in C, forall j in F
constr sum_{j in F}{x_{i,j}} = 1, forall i in C
constr x_{i,j} <= y_{j}, forall i in C, forall j in F
min sum_{j in F}{f_{j} * y_{j}} + sum_{i in C}{sum_{j in F}{t_{i,j} * x_{i,j}}}
end
import elytica
def main():
elytica.init_model("facility")
elytica.run_model("facility")
for i in [1,2]:
print("y"+str(i), "=", elytica.get_variable_value("facility", "y"+str(i)))
for i in [1,2,3]:
for j in [1,2]:
name = "x"+str(i)+","+str(j)
print(name, "=", elytica.get_variable_value("facility", name))
print("obj =", elytica.get_best_primal_bound("facility"))
return 0
Open just facility 2 — pays 6, then serves all three customers for 4+1+2 = 7. Total 13.
no-error — Model solvesnumeric-match — Facility 2 opensnumeric-match — Facility 1 stays closednumeric-match — Total cost is 13code-contains — Reads the objective from the solver (no hardcoding)code-contains — Reads variable values from the solver (no hardcoding)New setup and transport costs. Which facility is worth opening this time?
model facility_v
set F = {1, 2}
set C = {1, 2, 3}
const f = {6, 3}, forall j in F
const t = {{4, 2}, {5, 1}, {3, 2}}, forall i in C, forall j in F
bin y, forall j in F
bin x, forall i in C, forall j in F
constr sum_{j in F}{x_{i,j}} = 1, forall i in C
constr x_{i,j} <= y_{j}, forall i in C, forall j in F
min sum_{j in F}{f_{j} * y_{j}} + sum_{i in C}{sum_{j in F}{t_{i,j} * x_{i,j}}}
end
import elytica
def main():
elytica.init_model("facility_v")
elytica.run_model("facility_v")
for i in [1,2]:
print("y"+str(i), "=", elytica.get_variable_value("facility_v", "y"+str(i)))
for i in [1,2,3]:
for j in [1,2]:
name = "x"+str(i)+","+str(j)
print(name, "=", elytica.get_variable_value("facility_v", name))
print("obj =", elytica.get_best_primal_bound("facility_v"))
return 0
Read this through MCP: read with path: "lessons/facility-uncapacitated", or resource hlpl://lessons/facility-uncapacitated.