|
|
@ -100,7 +100,7 @@ function create_shipping_node_constraints!(model::ManufacturingModel)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function create_process_node_constraints!(model)
|
|
|
|
function create_process_node_constraints!(model::ManufacturingModel)
|
|
|
|
mip, vars, graph = model.mip, model.vars, model.graph
|
|
|
|
mip, vars, graph = model.mip, model.vars, model.graph
|
|
|
|
|
|
|
|
|
|
|
|
for n in graph.process_nodes
|
|
|
|
for n in graph.process_nodes
|
|
|
@ -135,137 +135,128 @@ function solve(filename::String; optimizer=Cbc.Optimizer)
|
|
|
|
println("Optimizing...")
|
|
|
|
println("Optimizing...")
|
|
|
|
JuMP.optimize!(model.mip)
|
|
|
|
JuMP.optimize!(model.mip)
|
|
|
|
|
|
|
|
|
|
|
|
# println("Extracting solution...")
|
|
|
|
println("Extracting solution...")
|
|
|
|
# return get_solution(instance, model)
|
|
|
|
return get_solution(model)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
# function get_solution(instance::ReverseManufacturingInstance,
|
|
|
|
function get_solution(model::ManufacturingModel)
|
|
|
|
# model::ReverseManufacturingModel)
|
|
|
|
mip, vars, graph, instance = model.mip, model.vars, model.graph, model.instance
|
|
|
|
# vals = Dict()
|
|
|
|
output = Dict(
|
|
|
|
# for a in values(model.arcs)
|
|
|
|
"plants" => Dict(),
|
|
|
|
# vals[a] = JuMP.value(model.vars.flow[a])
|
|
|
|
"costs" => Dict(
|
|
|
|
# end
|
|
|
|
"fixed" => 0.0,
|
|
|
|
# for n in values(model.process_nodes)
|
|
|
|
"variable" => 0.0,
|
|
|
|
# vals[n] = JuMP.value(model.vars.open_plant[n])
|
|
|
|
"transportation" => 0.0,
|
|
|
|
# end
|
|
|
|
"disposal" => 0.0,
|
|
|
|
|
|
|
|
"total" => 0.0,
|
|
|
|
|
|
|
|
"expansion" => 0.0,
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
# output = Dict(
|
|
|
|
plant_to_process_node = Dict(n.plant => n for n in graph.process_nodes)
|
|
|
|
# "plants" => Dict(),
|
|
|
|
plant_to_shipping_nodes = Dict()
|
|
|
|
# "costs" => Dict(
|
|
|
|
for p in instance.plants
|
|
|
|
# "fixed" => 0.0,
|
|
|
|
plant_to_shipping_nodes[p] = []
|
|
|
|
# "variable" => 0.0,
|
|
|
|
for a in plant_to_process_node[p].outgoing_arcs
|
|
|
|
# "transportation" => 0.0,
|
|
|
|
push!(plant_to_shipping_nodes[p], a.dest)
|
|
|
|
# "disposal" => 0.0,
|
|
|
|
end
|
|
|
|
# "total" => 0.0,
|
|
|
|
end
|
|
|
|
# "expansion" => 0.0,
|
|
|
|
|
|
|
|
# )
|
|
|
|
for plant in instance.plants
|
|
|
|
# )
|
|
|
|
skip_plant = true
|
|
|
|
|
|
|
|
process_node = plant_to_process_node[plant]
|
|
|
|
# for (plant_name, plant) in instance.plants
|
|
|
|
plant_dict = Dict{Any, Any}(
|
|
|
|
# skip_plant = true
|
|
|
|
"input" => Dict(),
|
|
|
|
# plant_dict = Dict{Any, Any}()
|
|
|
|
"output" => Dict(
|
|
|
|
# input_product_name = plant["input"]
|
|
|
|
"send" => Dict(),
|
|
|
|
|
|
|
|
"dispose" => Dict(),
|
|
|
|
# for (location_name, location) in plant["locations"]
|
|
|
|
),
|
|
|
|
# skip_location = true
|
|
|
|
"total input" => 0.0,
|
|
|
|
# process_node = model.process_nodes[input_product_name, plant_name, location_name]
|
|
|
|
"total output" => Dict(),
|
|
|
|
|
|
|
|
"latitude" => plant.latitude,
|
|
|
|
# plant_loc_dict = Dict{Any, Any}(
|
|
|
|
"longitude" => plant.longitude,
|
|
|
|
# "input" => Dict(),
|
|
|
|
"capacity" => JuMP.value(vars.capacity[process_node]),
|
|
|
|
# "output" => Dict(
|
|
|
|
"fixed cost" => JuMP.value(vars.open_plant[process_node]) * (plant.opening_cost + plant.fixed_operating_cost),
|
|
|
|
# "send" => Dict(),
|
|
|
|
"expansion cost" => JuMP.value(vars.expansion[process_node]) * plant.expansion_cost,
|
|
|
|
# "dispose" => Dict(),
|
|
|
|
)
|
|
|
|
# ),
|
|
|
|
output["costs"]["fixed"] += plant_dict["fixed cost"]
|
|
|
|
# "total input" => 0.0,
|
|
|
|
output["costs"]["expansion"] += plant_dict["expansion cost"]
|
|
|
|
# "total output" => Dict(),
|
|
|
|
|
|
|
|
# "latitude" => location["latitude"],
|
|
|
|
|
|
|
|
# "longitude" => location["longitude"],
|
|
|
|
|
|
|
|
# "capacity" => round(JuMP.value(model.vars.capacity[process_node]), digits=2)
|
|
|
|
|
|
|
|
# )
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# plant_loc_dict["fixed cost"] = round(vals[process_node] * process_node.fixed_cost, digits=5)
|
|
|
|
|
|
|
|
# plant_loc_dict["expansion cost"] = round(JuMP.value(model.vars.expansion[process_node]) * process_node.expansion_cost, digits=5)
|
|
|
|
|
|
|
|
# output["costs"]["fixed"] += plant_loc_dict["fixed cost"]
|
|
|
|
|
|
|
|
# output["costs"]["expansion"] += plant_loc_dict["expansion cost"]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# # Inputs
|
|
|
|
# Inputs
|
|
|
|
# for a in process_node.incoming_arcs
|
|
|
|
for a in process_node.incoming_arcs
|
|
|
|
# if vals[a] <= 1e-3
|
|
|
|
val = JuMP.value(vars.flow[a])
|
|
|
|
# continue
|
|
|
|
if val <= 1e-3
|
|
|
|
# end
|
|
|
|
continue
|
|
|
|
# skip_plant = skip_location = false
|
|
|
|
end
|
|
|
|
# val = round(vals[a], digits=5)
|
|
|
|
skip_plant = false
|
|
|
|
# if !(a.source.plant_name in keys(plant_loc_dict["input"]))
|
|
|
|
dict = Dict{Any, Any}(
|
|
|
|
# plant_loc_dict["input"][a.source.plant_name] = Dict()
|
|
|
|
"amount" => val,
|
|
|
|
# end
|
|
|
|
"distance" => a.values["distance"],
|
|
|
|
# if a.source.plant_name == "Origin"
|
|
|
|
"latitude" => a.source.location.latitude,
|
|
|
|
# product = instance.products[a.source.product_name]
|
|
|
|
"longitude" => a.source.location.longitude,
|
|
|
|
# source_location = product["initial amounts"][a.source.location_name]
|
|
|
|
"transportation cost" => a.source.product.transportation_cost * val,
|
|
|
|
# else
|
|
|
|
"variable operating cost" => plant.variable_operating_cost * val,
|
|
|
|
# source_plant = instance.plants[a.source.plant_name]
|
|
|
|
)
|
|
|
|
# source_location = source_plant["locations"][a.source.location_name]
|
|
|
|
if a.source.location isa CollectionCenter
|
|
|
|
# end
|
|
|
|
plant_name = "Origin"
|
|
|
|
|
|
|
|
location_name = a.source.location.name
|
|
|
|
# # Input
|
|
|
|
else
|
|
|
|
# cost_transportation = round(a.costs["transportation"] * val, digits=5)
|
|
|
|
plant_name = a.source.location.plant_name
|
|
|
|
# plant_loc_dict["input"][a.source.plant_name][a.source.location_name] = dict = Dict()
|
|
|
|
location_name = a.source.location.location_name
|
|
|
|
# cost_variable = round(a.costs["variable"] * val, digits=5)
|
|
|
|
end
|
|
|
|
# dict["amount"] = val
|
|
|
|
|
|
|
|
# dict["distance"] = a.values["distance"]
|
|
|
|
if plant_name ∉ keys(plant_dict["input"])
|
|
|
|
# dict["transportation cost"] = cost_transportation
|
|
|
|
plant_dict["input"][plant_name] = Dict()
|
|
|
|
# dict["variable operating cost"] = cost_variable
|
|
|
|
end
|
|
|
|
# dict["latitude"] = source_location["latitude"]
|
|
|
|
plant_dict["input"][plant_name][location_name] = dict
|
|
|
|
# dict["longitude"] = source_location["longitude"]
|
|
|
|
plant_dict["total input"] += val
|
|
|
|
# plant_loc_dict["total input"] += val
|
|
|
|
output["costs"]["transportation"] += dict["transportation cost"]
|
|
|
|
|
|
|
|
output["costs"]["variable"] += dict["variable operating cost"]
|
|
|
|
# output["costs"]["transportation"] += cost_transportation
|
|
|
|
end
|
|
|
|
# output["costs"]["variable"] += cost_variable
|
|
|
|
|
|
|
|
# end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# # Outputs
|
|
|
|
# Outputs
|
|
|
|
# for output_product_name in keys(plant["outputs"])
|
|
|
|
for shipping_node in plant_to_shipping_nodes[plant]
|
|
|
|
# plant_loc_dict["total output"][output_product_name] = 0.0
|
|
|
|
product_name = shipping_node.product.name
|
|
|
|
# plant_loc_dict["output"]["send"][output_product_name] = product_dict = Dict()
|
|
|
|
plant_dict["total output"][product_name] = 0.0
|
|
|
|
# shipping_node = model.shipping_nodes[output_product_name, plant_name, location_name]
|
|
|
|
plant_dict["output"]["send"][product_name] = product_dict = Dict()
|
|
|
|
|
|
|
|
|
|
|
|
# disposal_amount = JuMP.value(model.vars.dispose[shipping_node])
|
|
|
|
disposal_amount = JuMP.value(vars.dispose[shipping_node])
|
|
|
|
# if disposal_amount > 1e-5
|
|
|
|
if disposal_amount > 1e-5
|
|
|
|
# plant_loc_dict["output"]["dispose"][output_product_name] = disposal_dict = Dict()
|
|
|
|
plant_dict["output"]["dispose"][product_name] = disposal_dict = Dict()
|
|
|
|
# disposal_dict["amount"] = JuMP.value(model.vars.dispose[shipping_node])
|
|
|
|
disposal_dict["amount"] = JuMP.value(model.vars.dispose[shipping_node])
|
|
|
|
# disposal_dict["cost"] = disposal_dict["amount"] * shipping_node.disposal_cost
|
|
|
|
disposal_dict["cost"] = disposal_dict["amount"] * plant.disposal_cost[shipping_node.product]
|
|
|
|
# plant_loc_dict["total output"][output_product_name] += disposal_amount
|
|
|
|
plant_dict["total output"][product_name] += disposal_amount
|
|
|
|
# output["costs"]["disposal"] += disposal_dict["cost"]
|
|
|
|
output["costs"]["disposal"] += disposal_dict["cost"]
|
|
|
|
# end
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
# for a in shipping_node.outgoing_arcs
|
|
|
|
for a in shipping_node.outgoing_arcs
|
|
|
|
# if vals[a] <= 1e-3
|
|
|
|
val = JuMP.value(vars.flow[a])
|
|
|
|
# continue
|
|
|
|
if val <= 1e-3
|
|
|
|
# end
|
|
|
|
continue
|
|
|
|
# skip_plant = skip_location = false
|
|
|
|
end
|
|
|
|
# if !(a.dest.plant_name in keys(product_dict))
|
|
|
|
skip_plant = false
|
|
|
|
# product_dict[a.dest.plant_name] = Dict{Any,Any}()
|
|
|
|
dict = Dict(
|
|
|
|
# end
|
|
|
|
"amount" => val,
|
|
|
|
# dest_location = instance.plants[a.dest.plant_name]["locations"][a.dest.location_name]
|
|
|
|
"distance" => a.values["distance"],
|
|
|
|
# val = round(vals[a], digits=5)
|
|
|
|
"latitude" => a.dest.plant.latitude,
|
|
|
|
# plant_loc_dict["total output"][output_product_name] += val
|
|
|
|
"longitude" => a.dest.plant.longitude,
|
|
|
|
# product_dict[a.dest.plant_name][a.dest.location_name] = dict = Dict()
|
|
|
|
)
|
|
|
|
# dict["amount"] = val
|
|
|
|
if a.dest.plant.plant_name ∉ keys(product_dict)
|
|
|
|
# dict["distance"] = a.values["distance"]
|
|
|
|
product_dict[a.dest.plant.plant_name] = Dict()
|
|
|
|
# dict["latitude"] = dest_location["latitude"]
|
|
|
|
end
|
|
|
|
# dict["longitude"] = dest_location["longitude"]
|
|
|
|
product_dict[a.dest.plant.plant_name][a.dest.plant.location_name] = dict
|
|
|
|
# end
|
|
|
|
plant_dict["total output"][product_name] += val
|
|
|
|
# end
|
|
|
|
end
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
# if !skip_location
|
|
|
|
if !skip_plant
|
|
|
|
# plant_dict[location_name] = plant_loc_dict
|
|
|
|
if plant.plant_name ∉ keys(output["plants"])
|
|
|
|
# end
|
|
|
|
output["plants"][plant.plant_name] = Dict()
|
|
|
|
# end
|
|
|
|
end
|
|
|
|
# if !skip_plant
|
|
|
|
output["plants"][plant.plant_name][plant.location_name] = plant_dict
|
|
|
|
# output["plants"][plant_name] = plant_dict
|
|
|
|
end
|
|
|
|
# end
|
|
|
|
end
|
|
|
|
# end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# output["costs"]["total"] = sum(values(output["costs"]))
|
|
|
|
|
|
|
|
# return output
|
|
|
|
|
|
|
|
# end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
output["costs"]["total"] = sum(values(output["costs"]))
|
|
|
|
|
|
|
|
return output
|
|
|
|
|
|
|
|
end
|
|
|
|