@ -197,7 +197,9 @@ default_lp_optimizer = optimizer_with_attributes(Clp.Optimizer, "LogLevel" => 0)
function solve ( instance :: Instance ;
function solve ( instance :: Instance ;
optimizer = nothing ,
optimizer = nothing ,
output = nothing )
output = nothing ,
marginal_costs = true ,
)
milp_optimizer = lp_optimizer = optimizer
milp_optimizer = lp_optimizer = optimizer
if optimizer == nothing
if optimizer == nothing
@ -224,6 +226,7 @@ function solve(instance::Instance;
return OrderedDict ( )
return OrderedDict ( )
end
end
if marginal_costs
@info " 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 = OrderedDict ( var => JuMP . value ( var ) for var in all_vars )
vals = OrderedDict ( var => JuMP . value ( var ) for var in all_vars )
@ -235,9 +238,10 @@ function solve(instance::Instance;
end
end
end
end
JuMP . optimize! ( model . mip )
JuMP . optimize! ( model . mip )
end
@info " Extracting solution... "
@info " Extracting solution... "
solution = get_solution ( model )
solution = get_solution ( model , marginal_costs = marginal_costs )
if output != nothing
if output != nothing
@info " Writing solution: $output "
@info " Writing solution: $output "
@ -249,13 +253,43 @@ function solve(instance::Instance;
return solution
return solution
end
end
function solve ( filename :: String ; kwargs ... )
function solve ( filename :: AbstractString ;
heuristic = false ,
kwargs ... ,
)
@info " Reading $filename ... "
@info " Reading $filename ... "
instance = RELOG . parsefile ( filename )
instance = RELOG . parsefile ( filename )
return solve ( instance ; kwargs ... )
if heuristic
@info " Solving single-period version... "
compressed = _compress ( instance )
csol = solve ( compressed ;
output = nothing ,
marginal_costs = false ,
kwargs ... )
@info " Filtering candidate locations... "
selected_pairs = [ ]
for ( plant_name , plant_dict ) in csol [ " Plants " ]
for ( location_name , location_dict ) in plant_dict
push! ( selected_pairs , ( plant_name , location_name ) )
end
end
filtered_plants = [ ]
for p in instance . plants
if ( p . plant_name , p . location_name ) in selected_pairs
push! ( filtered_plants , p )
end
end
instance . plants = filtered_plants
@info " Solving original version... "
end
end
sol = solve ( instance ; kwargs ... )
return sol
end
function get_solution ( model :: ManufacturingModel )
function get_solution ( model :: ManufacturingModel ;
marginal_costs = true ,
)
mip , vars , eqs , graph , instance = model . mip , model . vars , model . eqs , model . graph , model . instance
mip , vars , eqs , graph , instance = model . mip , model . vars , model . eqs , model . graph , model . instance
T = instance . time
T = instance . time
@ -291,16 +325,18 @@ function get_solution(model::ManufacturingModel)
end
end
# Products
# Products
if marginal_costs
for n in graph . collection_shipping_nodes
for n in graph . collection_shipping_nodes
location_dict = OrderedDict { Any , Any } (
location_dict = OrderedDict { Any , Any } (
" Marginal cost ( \$ /tonne) " => [ round ( abs ( JuMP . shadow_price ( eqs . balance [ n , t ] ) ) , digits = 2 )
" Marginal cost ( \$ /tonne) " => [ round ( abs ( JuMP . shadow_price ( eqs . balance [ n , t ] ) ) , digits = 2 )
for t in 1 : T ] ,
for t in 1 : T ]
)
)
if n . product . name ∉ keys ( output [ " Products " ] )
if n . product . name ∉ keys ( output [ " Products " ] )
output [ " Products " ] [ n . product . name ] = OrderedDict ( )
output [ " Products " ] [ n . product . name ] = OrderedDict ( )
end
end
output [ " Products " ] [ n . product . name ] [ n . location . name ] = location_dict
output [ " Products " ] [ n . product . name ] [ n . location . name ] = location_dict
end
end
end
# Plants
# Plants
for plant in instance . plants
for plant in instance . plants