|
|
@ -2,7 +2,7 @@
|
|
|
|
# Copyright (C) 2020, UChicago Argonne, LLC. All rights reserved.
|
|
|
|
# Copyright (C) 2020, UChicago Argonne, LLC. All rights reserved.
|
|
|
|
# Released under the modified BSD license. See COPYING.md for more details.
|
|
|
|
# Released under the modified BSD license. See COPYING.md for more details.
|
|
|
|
|
|
|
|
|
|
|
|
using JuMP, LinearAlgebra, Geodesy, Cbc, Clp, ProgressBars
|
|
|
|
using JuMP, LinearAlgebra, Geodesy, Cbc, Clp, ProgressBars, Printf
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
mutable struct ManufacturingModel
|
|
|
|
mutable struct ManufacturingModel
|
|
|
@ -83,7 +83,7 @@ end
|
|
|
|
|
|
|
|
|
|
|
|
function create_objective_function!(model::ManufacturingModel)
|
|
|
|
function create_objective_function!(model::ManufacturingModel)
|
|
|
|
mip, vars, graph, T = model.mip, model.vars, model.graph, model.instance.time
|
|
|
|
mip, vars, graph, T = model.mip, model.vars, model.graph, model.instance.time
|
|
|
|
obj = @expression(mip, 0 * @variable(mip))
|
|
|
|
obj = AffExpr(0.0)
|
|
|
|
|
|
|
|
|
|
|
|
# Process node costs
|
|
|
|
# Process node costs
|
|
|
|
for n in values(graph.process_nodes), t in 1:T
|
|
|
|
for n in values(graph.process_nodes), t in 1:T
|
|
|
@ -158,9 +158,12 @@ end
|
|
|
|
function create_process_node_constraints!(model::ManufacturingModel)
|
|
|
|
function create_process_node_constraints!(model::ManufacturingModel)
|
|
|
|
mip, vars, graph, T = model.mip, model.vars, model.graph, model.instance.time
|
|
|
|
mip, vars, graph, T = model.mip, model.vars, model.graph, model.instance.time
|
|
|
|
|
|
|
|
|
|
|
|
for n in graph.process_nodes, t in 1:T
|
|
|
|
for t in 1:T, n in graph.process_nodes
|
|
|
|
# Output amount is implied by input amount
|
|
|
|
# Output amount is implied by input amount
|
|
|
|
input_sum = isempty(n.incoming_arcs) ? 0 : sum(vars.flow[a, t] for a in n.incoming_arcs)
|
|
|
|
input_sum = AffExpr(0.0)
|
|
|
|
|
|
|
|
for a in n.incoming_arcs
|
|
|
|
|
|
|
|
add_to_expression!(input_sum, 1.0, vars.flow[a, t])
|
|
|
|
|
|
|
|
end
|
|
|
|
for a in n.outgoing_arcs
|
|
|
|
for a in n.outgoing_arcs
|
|
|
|
@constraint(mip, vars.flow[a, t] == a.values["weight"] * input_sum)
|
|
|
|
@constraint(mip, vars.flow[a, t] == a.values["weight"] * input_sum)
|
|
|
|
end
|
|
|
|
end
|
|
|
@ -196,19 +199,25 @@ end
|
|
|
|
function solve(filename::String;
|
|
|
|
function solve(filename::String;
|
|
|
|
milp_optimizer=optimizer_with_attributes(Cbc.Optimizer, "logLevel" => 0),
|
|
|
|
milp_optimizer=optimizer_with_attributes(Cbc.Optimizer, "logLevel" => 0),
|
|
|
|
lp_optimizer=optimizer_with_attributes(Clp.Optimizer, "LogLevel" => 0))
|
|
|
|
lp_optimizer=optimizer_with_attributes(Clp.Optimizer, "LogLevel" => 0))
|
|
|
|
println("Reading $filename...")
|
|
|
|
|
|
|
|
|
|
|
|
@info "Reading $filename..."
|
|
|
|
instance = RELOG.load(filename)
|
|
|
|
instance = RELOG.load(filename)
|
|
|
|
|
|
|
|
|
|
|
|
println("Building graph...")
|
|
|
|
@info "Building graph..."
|
|
|
|
graph = RELOG.build_graph(instance)
|
|
|
|
graph = RELOG.build_graph(instance)
|
|
|
|
|
|
|
|
@info @sprintf(" %12d time periods", instance.time)
|
|
|
|
|
|
|
|
@info @sprintf(" %12d process nodes", length(graph.process_nodes))
|
|
|
|
|
|
|
|
@info @sprintf(" %12d shipping nodes (plant)", length(graph.plant_shipping_nodes))
|
|
|
|
|
|
|
|
@info @sprintf(" %12d shipping nodes (collection)", length(graph.collection_shipping_nodes))
|
|
|
|
|
|
|
|
@info @sprintf(" %12d arcs", length(graph.arcs))
|
|
|
|
|
|
|
|
|
|
|
|
println("Building optimization model...")
|
|
|
|
@info "Building optimization model..."
|
|
|
|
model = RELOG.build_model(instance, graph, milp_optimizer)
|
|
|
|
model = RELOG.build_model(instance, graph, milp_optimizer)
|
|
|
|
|
|
|
|
|
|
|
|
println("Optimizing MILP...")
|
|
|
|
@info "Optimizing MILP..."
|
|
|
|
JuMP.optimize!(model.mip)
|
|
|
|
JuMP.optimize!(model.mip)
|
|
|
|
|
|
|
|
|
|
|
|
println("Re-optimizing with integer variables fixed...")
|
|
|
|
@info "Re-optimizing with integer variables fixed..."
|
|
|
|
all_vars = JuMP.all_variables(model.mip)
|
|
|
|
all_vars = JuMP.all_variables(model.mip)
|
|
|
|
vals = Dict(var => JuMP.value(var) for var in all_vars)
|
|
|
|
vals = Dict(var => JuMP.value(var) for var in all_vars)
|
|
|
|
JuMP.set_optimizer(model.mip, lp_optimizer)
|
|
|
|
JuMP.set_optimizer(model.mip, lp_optimizer)
|
|
|
@ -220,7 +229,7 @@ function solve(filename::String;
|
|
|
|
end
|
|
|
|
end
|
|
|
|
JuMP.optimize!(model.mip)
|
|
|
|
JuMP.optimize!(model.mip)
|
|
|
|
|
|
|
|
|
|
|
|
println("Extracting solution...")
|
|
|
|
@info "Extracting solution..."
|
|
|
|
return get_solution(model)
|
|
|
|
return get_solution(model)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|