Sailco, a simple example #
Sailco manufactures sailboats. During the next 4 months the company must meet the following demands for their sailboats:
Month | 1 | 2 | 3 | 4 |
---|---|---|---|---|
Number of boats | 40 | 60 | 70 | 25 |
At the beginning of Month 1, Sailco has 10 boats in inventory. Each month it must determine how many boats to produce. During any month, Sailco can produce up to 40 boats with regular labor and an unlimited number of boats with overtime labor. Boats produced with regular labor cost 400 USD each to produce, while boats produced with overtime labor cost 450 USD each. It costs 20 USD to hold a boat in inventory from one month to the next. Find the production and inventory schedule that minimizes the cost of meeting the next 4 months’ demands
using JuMP, HiGHS, DataStructures, NamedArrays
Solution #
m = Model(HiGHS.Optimizer)
demands = [40, 60, 70, 25]
# boats built with regular labor
@variable(m, 0 <= x[1:4] <= 40)
# boats built with overtime labor
@variable(m, y[1:4] >= 0)
# inventory
@variable(m, h[1:5] >= 0)
# for each month
for i in range(1,4)
# boats plus the inventory must be larger than the demand
# @constraint(m, x[i] + y[i] + h[i] >= demands[i])
# inventory next month is equal to all boats available minus the demand of that month
@constraint(m, h[i+1] == h[i] + x[i] + y[i] - demands[i])
end
# first month inventory is 10
@constraint(m, h[1] == 10)
# minimize the total cost
@objective(m, Min, 400*sum(x) + 450*sum(y) + 20*sum(h))
optimize!(m)
println("Solver terminated with status ", termination_status(m))
println("Boats built with regular labor each month: ", Array{Int}(value.(x)))
println("Boats built with overtime labor each month: ", Array{Int}(value.(y)))
println("Inventory: ", Array{Int}(value.(h)))
println("Minimum cost: \`$", objective_value(m))
# for each month
for i in range(1,4)
# inventory next month is equal to all boats available minus the demand of that month
@constraint(m, h[i+1] == h[i] + x[i] + y[i] - demands[i])
end
can be rewritten as
@constraint(m, flows[i in 1:4], h[i] + x[i] + y[i] == demands[i] + h[i])
Minimum-cost flow problem #
Lumber transportation problem (J. Reeb and S. Leavengood) #
Millco has three wood mills and is planning three new logging sites. Each mill has a maximum capacity and each logging site can harvest a certain number of truckloads of lumber per day. The cost of a haul is 2 USD/mile of distance. If distances from logging sites to mills are given below, how should the hauls be routed to minimize hauling costs while meeting all demands?
Logging Site | Mill A | Mill B | Mill C | Max loads per day per logging site |
---|---|---|---|---|
1 | 8 | 15 | 50 | 20 |
2 | 10 | 17 | 20 | 30 |
3 | 30 | 26 | 15 | 45 |
Mill demand (truckloads/day) | 30 | 35 | 30 |
m = Model(HiGHS.Optimizer)
sites = [1, 2, 3]
mills = [:A, :B, :C]
cost_per_haul = 4
supply = Dict(zip(sites, [20, 30, 45]))
demand = Dict(zip(mills, [30, 35, 30]))
dist = NamedArray([8 15 50; 10 17 20; 30 26 15], (sites, mills), ("Sites", "Mills"))
@variable(m, x[sites, mills] >= 0)
@constraint(m, sup[i in sites], sum(x[i,j] for j in mills) == supply[i])
@constraint(m, dem[j in mills], sum(x[i,j] for i in sites) == demand[j])
@objective(m, Min, cost_per_haul * sum( x[i,j]*dist[i,j] for i in sites, j in mills ))
optimize!(m)
NamedArray(Int[value(x[i,j]) for i in sites, j in mills], (sites, mills), ("Sites", "Mills"))
Swim relay problem (Van Roy and Mason) #
The coach of a swim team needs to assign swimmers to a 200-yard medley relay team to compete in a tournament. The problem is that his best swimmers are good in more than one stroke, so it’s not clear which swimmer to assign to which stroke. Here are the best times for each swimmer:
Stroke | Carl | Chris | David | Tony | Ken |
---|---|---|---|---|---|
Backstroke | 37.7 | 32.9 | 33.8 | 37.0 | 35.4 |
Breaststroke | 43.4 | 33.1 | 42.2 | 34.7 | 41.8 |
Butterfly | 33.3 | 28.5 | 38.9 | 30.4 | 33.6 |
Freestyle | 29.2 | 26.4 | 29.6 | 28.5 | 31.1 |
This can be considered as a transportation problem like the Lumber transportation problem we talked about above.
m = Model(HiGHS.Optimizer)
strokes = [:ackstroke, :breaststroke, :butterfly, :freestyle]
persons = [:carl, :chris, :david, :tony, :ken]
speed = NamedArray(
[
37.7 32.9 33.8 37 35.4;
43.4 33.1 42.2 34.7 41.8;
33.3 28.5 38.9 30.4 33.6;
29.2 26.4 29.6 28.5 31.1
], (strokes, persons), ("Stroke", "Person"))
supply = Dict(zip(strokes, [1,1,1,1]))
@variable(m, x[strokes, persons] >= 0)
# each person should swim at most once
@constraint(m, swimmer[p in persons], sum(x[s, p] for s in strokes) <= 1)
# each stroke should be assigned to exactly one person
@constraint(m, assignment[s in strokes], sum(x[s, p] for p in persons) == 1)
# minimize the time consumed
@objective(m, Min, sum(x[s, p] * speed[s,p] for s in strokes, p in persons))
optimize!(m)
NamedArray([value(x[s,p]) for s in strokes, p in persons], (strokes, persons), ("Stroke", "Person"))
Last modified on 2024-12-07