Implement basic reports; fix boat example

This commit is contained in:
2023-12-06 14:39:28 -06:00
parent 06642c631f
commit 319e5f1ed3
11 changed files with 228 additions and 3092 deletions

View File

@@ -5,5 +5,8 @@ include("instance/parse.jl")
include("model/jumpext.jl")
include("model/dist.jl")
include("model/build.jl")
include("reports/plants.jl")
include("reports/transportation.jl")
include("reports/centers.jl")
end # module RELOG

View File

@@ -6,14 +6,15 @@ function build_model(instance::Instance; optimizer, variable_names::Bool = false
products = instance.products
plants = instance.plants
T = 1:instance.time_horizon
model.ext[:instance] = instance
# Transportation edges
# -------------------------------------------------------------------------
# Connectivity
E = []
E_in = Dict(src => [] for src in plants centers)
E_out = Dict(src => [] for src in plants centers)
model.ext[:E] = E = []
model.ext[:E_in] = E_in = Dict(src => [] for src in plants centers)
model.ext[:E_out] = E_out = Dict(src => [] for src in plants centers)
function push_edge!(src, dst, m)
push!(E, (src, dst, m))
@@ -28,7 +29,7 @@ function build_model(instance::Instance; optimizer, variable_names::Bool = false
# Plant to plant
for p2 in plants
p1 != p2 || continue
m keys(p2.input_mix) || continue
m keys(p2.input_mix) || continue
push_edge!(p1, p2, m)
end
@@ -57,7 +58,7 @@ function build_model(instance::Instance; optimizer, variable_names::Bool = false
end
# Distances
distances = Dict()
model.ext[:distances] = distances = Dict()
for (p1, p2, m) in E
d = _calculate_distance(p1.latitude, p1.longitude, p2.latitude, p2.longitude)
distances[p1, p2, m] = d
@@ -86,9 +87,6 @@ function build_model(instance::Instance; optimizer, variable_names::Bool = false
for p in plants, m in keys(p.output), t in T
z_prod[p.name, m.name, t] = @variable(model, lower_bound = 0)
end
for c in centers, m in c.outputs, t in T
z_prod[c.name, m.name, t] = @variable(model, lower_bound = 0)
end
# Amount of product m disposed at plant/center p at time T
z_disp = _init(model, :z_disp)

47
src/reports/centers.jl Normal file
View File

@@ -0,0 +1,47 @@
# RELOG: Reverse Logistics Optimization
# Copyright (C) 2020, UChicago Argonne, LLC. All rights reserved.
# Released under the modified BSD license. See COPYING.md for more details.
using DataFrames
using CSV
function centers_report(model)::DataFrame
df = DataFrame()
df."center" = String[]
df."year" = Int[]
df."input product" = String[]
df."input amount (tonne)" = Float64[]
centers = model.ext[:instance].centers
T = 1:model.ext[:instance].time_horizon
for c in centers, t in T
input_name = (c.input === nothing) ? "" : c.input.name
input = round(value(model[:z_input][c.name, t]), digits = 3)
push!(df, [c.name, t, input_name, input])
end
return df
end
function center_outputs_report(model)::DataFrame
df = DataFrame()
df."center" = String[]
df."output product" = String[]
df."year" = Int[]
df."amount collected (tonne)" = Float64[]
df."amount disposed (tonne)" = Float64[]
centers = model.ext[:instance].centers
T = 1:model.ext[:instance].time_horizon
for c in centers, m in c.outputs, t in T
collected = round(value(model[:z_collected][c.name, m.name, t]), digits = 3)
disposed = round(value(model[:z_disp][c.name, m.name, t]), digits = 3)
push!(df, [c.name, m.name, t, collected, disposed])
end
return df
end
write_centers_report(solution, filename) = CSV.write(filename, centers_report(solution))
write_center_outputs_report(solution, filename) =
CSV.write(filename, center_outputs_report(solution))

49
src/reports/plants.jl Normal file
View File

@@ -0,0 +1,49 @@
# RELOG: Reverse Logistics Optimization
# Copyright (C) 2020, UChicago Argonne, LLC. All rights reserved.
# Released under the modified BSD license. See COPYING.md for more details.
using DataFrames
using CSV
function plants_report(model)::DataFrame
df = DataFrame()
df."plant" = String[]
df."year" = Int[]
df."operational?" = Bool[]
df."input amount (tonne)" = Float64[]
plants = model.ext[:instance].plants
T = 1:model.ext[:instance].time_horizon
for p in plants, t in T
operational = JuMP.value(model[:x][p.name, t]) > 0.5
input = value(model[:z_input][p.name, t])
operational || continue
push!(df, [p.name, t, operational, input])
end
return df
end
function plant_outputs_report(model)::DataFrame
df = DataFrame()
df."plant" = String[]
df."output product" = String[]
df."year" = Int[]
df."amount produced (tonne)" = Float64[]
df."amount disposed (tonne)" = Float64[]
plants = model.ext[:instance].plants
T = 1:model.ext[:instance].time_horizon
for p in plants, m in keys(p.output), t in T
produced = JuMP.value(model[:z_prod][p.name, m.name, t])
disposed = JuMP.value(model[:z_disp][p.name, m.name, t])
produced > 1e-3 || continue
push!(df, [p.name, m.name, t, produced, disposed])
end
return df
end
write_plants_report(solution, filename) = CSV.write(filename, plants_report(solution))
write_plant_outputs_report(solution, filename) =
CSV.write(filename, plant_outputs_report(solution))

View File

@@ -0,0 +1,31 @@
# RELOG: Reverse Logistics Optimization
# Copyright (C) 2020, UChicago Argonne, LLC. All rights reserved.
# Released under the modified BSD license. See COPYING.md for more details.
using DataFrames
using CSV
function transportation_report(model)::DataFrame
df = DataFrame()
df."source" = String[]
df."destination" = String[]
df."product" = String[]
df."year" = Int[]
df."amount sent (tonne)" = Float64[]
df."distance (km)" = Float64[]
E = model.ext[:E]
distances = model.ext[:distances]
T = 1:model.ext[:instance].time_horizon
for (p1, p2, m) in E, t in T
amount = value(model[:y][p1.name, p2.name, m.name, t])
amount > 1e-3 || continue
distance = distances[p1, p2, m]
push!(df, [p1.name, p2.name, m.name, t, amount, distance])
end
return df
end
write_transportation_report(solution, filename) =
CSV.write(filename, transportation_report(solution))