5 Commits

Author SHA1 Message Date
Kavitha G Menon
2cf97d6bee Capacity expansion model
Add the model file with capacity expansion constraints and subsequent modifications
2024-08-09 15:59:15 -05:00
9e0f8c5796 solve: Allow custom graph 2023-07-27 10:38:53 -05:00
5693ef2aa2 Reformat source code 2023-07-26 10:25:11 -05:00
bc05b49222 Make resolve compatible with solve(heuristic=true) 2023-07-26 10:17:37 -05:00
3e54e767c4 Fix failing test 2023-07-26 10:00:07 -05:00
7 changed files with 1753 additions and 21 deletions

1699
model-3-CapEx.jl Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -17,6 +17,24 @@ function resolve(model_old, instance::Instance; optimizer = nothing)::OrderedDic
lp_optimizer = _get_default_lp_optimizer()
end
@info "Filtering candidate locations..."
selected_pairs = Set()
for ((node_old, t), var_old) in model_old[:is_open]
if JuMP.value(var_old) > 0.1
push!(
selected_pairs,
(node_old.location.plant_name, node_old.location.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 "Building new graph..."
graph = build_graph(instance)
_print_graph_stats(instance, graph)
@@ -48,10 +66,9 @@ function _fix_plants!(model_old, model_new)::Nothing
# Fix open_plant variables
for ((node_old, t), var_old) in model_old[:open_plant]
value_old = JuMP.value(var_old)
node_new = model_new[:graph].name_to_process_node_map[(
node_old.location.plant_name,
node_old.location.location_name,
)]
key = (node_old.location.plant_name, node_old.location.location_name)
key keys(model_new[:graph].name_to_process_node_map) || continue
node_new = model_new[:graph].name_to_process_node_map[key]
var_new = model_new[:open_plant][node_new, t]
JuMP.unset_binary(var_new)
JuMP.fix(var_new, value_old)
@@ -61,10 +78,9 @@ function _fix_plants!(model_old, model_new)::Nothing
for ((node_old, t), var_old) in model_old[:is_open]
t > 0 || continue
value_old = JuMP.value(var_old)
node_new = model_new[:graph].name_to_process_node_map[(
node_old.location.plant_name,
node_old.location.location_name,
)]
key = (node_old.location.plant_name, node_old.location.location_name)
key keys(model_new[:graph].name_to_process_node_map) || continue
node_new = model_new[:graph].name_to_process_node_map[key]
var_new = model_new[:is_open][node_new, t]
JuMP.unset_binary(var_new)
JuMP.fix(var_new, value_old)
@@ -73,10 +89,9 @@ function _fix_plants!(model_old, model_new)::Nothing
# Fix plant capacities
for ((node_old, t), var_old) in model_old[:capacity]
value_old = JuMP.value(var_old)
node_new = model_new[:graph].name_to_process_node_map[(
node_old.location.plant_name,
node_old.location.location_name,
)]
key = (node_old.location.plant_name, node_old.location.location_name)
key keys(model_new[:graph].name_to_process_node_map) || continue
node_new = model_new[:graph].name_to_process_node_map[key]
var_new = model_new[:capacity][node_new, t]
JuMP.delete_lower_bound(var_new)
JuMP.delete_upper_bound(var_new)
@@ -87,10 +102,9 @@ function _fix_plants!(model_old, model_new)::Nothing
for ((node_old, t), var_old) in model_old[:expansion]
t > 0 || continue
value_old = JuMP.value(var_old)
node_new = model_new[:graph].name_to_process_node_map[(
node_old.location.plant_name,
node_old.location.location_name,
)]
key = (node_old.location.plant_name, node_old.location.location_name)
key keys(model_new[:graph].name_to_process_node_map) || continue
node_new = model_new[:graph].name_to_process_node_map[key]
var_new = model_new[:expansion][node_new, t]
JuMP.delete_lower_bound(var_new)
JuMP.delete_upper_bound(var_new)

View File

@@ -32,6 +32,7 @@ function solve(
output = nothing,
marginal_costs = true,
return_model = false,
graph = nothing,
)
if lp_optimizer == nothing
@@ -51,7 +52,9 @@ function solve(
@info "Building graph..."
graph = RELOG.build_graph(instance)
if graph === nothing
graph = RELOG.build_graph(instance)
end
_print_graph_stats(instance, graph)
@info "Building optimization model..."

View File

@@ -53,4 +53,5 @@ function products_report(solution; marginal_costs)::DataFrame
return df
end
write_products_report(solution, filename; marginal_costs = true) = CSV.write(filename, products_report(solution; marginal_costs))
write_products_report(solution, filename; marginal_costs = true) =
CSV.write(filename, products_report(solution; marginal_costs))

View File

@@ -13,7 +13,11 @@ function write(solution::AbstractDict, filename::AbstractString)
end
end
function write_reports(solution::AbstractDict, basename::AbstractString; marginal_costs = true)
function write_reports(
solution::AbstractDict,
basename::AbstractString;
marginal_costs = true,
)
RELOG.write_products_report(solution, "$(basename)_products.csv"; marginal_costs)
RELOG.write_plants_report(solution, "$(basename)_plants.csv")
RELOG.write_plant_outputs_report(solution, "$(basename)_plant_outputs.csv")

View File

@@ -72,7 +72,10 @@ function instance_parse_test()
@test plant.sizes[1].opening_cost == [3000, 3000]
@test plant.sizes[1].fixed_operating_cost == [50, 50]
@test plant.sizes[1].variable_operating_cost == [50, 50]
@test plant.sizes[1] == plant.sizes[2]
@test plant.sizes[2].capacity == 1000.0
@test plant.sizes[2].opening_cost == [3000, 3000]
@test plant.sizes[2].fixed_operating_cost == [50, 50]
@test plant.sizes[2].variable_operating_cost == [50, 50]
p4 = product_name_to_product["P4"]
@test plant.output[p3] == 0.05

View File

@@ -4,10 +4,18 @@
using RELOG
function model_resolve_test()
@testset "Resolve" begin
@testset "Resolve (exact)" begin
# Shoud not crash
filename = fixture("s1.json")
solution_old, model_old = RELOG.solve(filename, return_model = true)
solution_new = RELOG.resolve(model_old, filename)
end
@testset "Resolve (heuristic)" begin
# Shoud not crash
filename = fixture("s1.json")
solution_old, model_old =
RELOG.solve(filename, return_model = true, heuristic = true)
solution_new = RELOG.resolve(model_old, filename)
end
end