mirror of
https://github.com/ANL-CEEESA/RELOG.git
synced 2025-12-06 07:48:50 -06:00
Allow disposal at collection centers
This commit is contained in:
@@ -11,6 +11,10 @@ All notable changes to this project will be documented in this file.
|
||||
[semver]: https://semver.org/spec/v2.0.0.html
|
||||
[pkjjl]: https://pkgdocs.julialang.org/v1/compatibility/#compat-pre-1.0
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
- Allow product disposal at collection centers
|
||||
|
||||
## [0.5.1] -- 2021-07-23
|
||||
## Added
|
||||
- Allow user to specify locations as unique identifiers, instead of latitude and longitude (e.g. `us-state:IL` or `2018-us-county:17043`)
|
||||
|
||||
2
Makefile
2
Makefile
@@ -1,6 +1,6 @@
|
||||
JULIA := julia --project=.
|
||||
SRC_FILES := $(wildcard src/*.jl test/*.jl)
|
||||
VERSION := 0.5
|
||||
VERSION := dev
|
||||
|
||||
all: docs test
|
||||
|
||||
|
||||
@@ -29,6 +29,8 @@ function _compress(instance::Instance)::Instance
|
||||
for (emission_name, emission_value) in p.transportation_emissions
|
||||
p.transportation_emissions[emission_name] = [mean(emission_value)]
|
||||
end
|
||||
p.disposal_limit = [maximum(p.disposal_limit) * T]
|
||||
p.disposal_cost = [mean(p.disposal_cost)]
|
||||
end
|
||||
|
||||
# Compress collection centers
|
||||
@@ -58,3 +60,42 @@ function _compress(instance::Instance)::Instance
|
||||
|
||||
return compressed
|
||||
end
|
||||
|
||||
function _slice(instance::Instance, T::UnitRange)::Instance
|
||||
sliced = deepcopy(instance)
|
||||
sliced.time = length(T)
|
||||
|
||||
for p in sliced.products
|
||||
p.transportation_cost = p.transportation_cost[T]
|
||||
p.transportation_energy = p.transportation_energy[T]
|
||||
for (emission_name, emission_value) in p.transportation_emissions
|
||||
p.transportation_emissions[emission_name] = emission_value[T]
|
||||
end
|
||||
p.disposal_limit = p.disposal_limit[T]
|
||||
p.disposal_cost = p.disposal_cost[T]
|
||||
end
|
||||
|
||||
for c in sliced.collection_centers
|
||||
c.amount = c.amount[T]
|
||||
end
|
||||
|
||||
for plant in sliced.plants
|
||||
plant.energy = plant.energy[T]
|
||||
for (emission_name, emission_value) in plant.emissions
|
||||
plant.emissions[emission_name] = emission_value[T]
|
||||
end
|
||||
for s in plant.sizes
|
||||
s.variable_operating_cost = s.variable_operating_cost[T]
|
||||
s.opening_cost = s.opening_cost[T]
|
||||
s.fixed_operating_cost = s.fixed_operating_cost[T]
|
||||
end
|
||||
for (prod_name, disp_limit) in plant.disposal_limit
|
||||
plant.disposal_limit[prod_name] = disp_limit[T]
|
||||
end
|
||||
for (prod_name, disp_cost) in plant.disposal_cost
|
||||
plant.disposal_cost[prod_name] = disp_cost[T]
|
||||
end
|
||||
end
|
||||
|
||||
return sliced
|
||||
end
|
||||
@@ -24,11 +24,15 @@ function create_vars!(model::JuMP.Model)
|
||||
(n, t) => @variable(
|
||||
model,
|
||||
lower_bound = 0,
|
||||
upper_bound = n.location.disposal_limit[n.product][t]
|
||||
upper_bound = n.location.disposal_limit[n.product][t],
|
||||
) for n in values(graph.plant_shipping_nodes), t = 1:T
|
||||
)
|
||||
model[:collection_dispose] = Dict(
|
||||
(n, t) => @variable(model, lower_bound = 0,) for
|
||||
(n, t) => @variable(
|
||||
model,
|
||||
lower_bound = 0,
|
||||
upper_bound = n.location.amount[t],
|
||||
) for
|
||||
n in values(graph.collection_shipping_nodes), t = 1:T
|
||||
)
|
||||
model[:store] = Dict(
|
||||
@@ -90,7 +94,7 @@ function create_objective_function!(model::JuMP.Model)
|
||||
# Process node costs
|
||||
for n in values(graph.process_nodes), t = 1:T
|
||||
|
||||
# Transportation and variable operating costs
|
||||
# Transportation costs
|
||||
for a in n.incoming_arcs
|
||||
c = n.location.input.transportation_cost[t] * a.values["distance"]
|
||||
add_to_expression!(obj, c, model[:flow][a, t])
|
||||
@@ -137,7 +141,6 @@ function create_objective_function!(model::JuMP.Model)
|
||||
|
||||
# Plant shipping node costs
|
||||
for n in values(graph.plant_shipping_nodes), t = 1:T
|
||||
|
||||
# Disposal costs
|
||||
add_to_expression!(
|
||||
obj,
|
||||
@@ -148,7 +151,6 @@ function create_objective_function!(model::JuMP.Model)
|
||||
|
||||
# Collection shipping node costs
|
||||
for n in values(graph.collection_shipping_nodes), t = 1:T
|
||||
|
||||
# Disposal costs
|
||||
add_to_expression!(
|
||||
obj,
|
||||
@@ -170,7 +172,7 @@ function create_shipping_node_constraints!(model::JuMP.Model)
|
||||
model[:eq_balance][n, t] = @constraint(
|
||||
model,
|
||||
sum(model[:flow][a, t] for a in n.outgoing_arcs) ==
|
||||
n.location.amount[t] + model[:collection_dispose][n, t]
|
||||
n.location.amount[t] - model[:collection_dispose][n, t],
|
||||
)
|
||||
end
|
||||
for prod in model[:instance].products
|
||||
|
||||
@@ -29,29 +29,32 @@ function solve(
|
||||
instance::Instance;
|
||||
optimizer = nothing,
|
||||
output = nothing,
|
||||
graph = nothing,
|
||||
marginal_costs = true,
|
||||
return_model = false,
|
||||
)
|
||||
|
||||
milp_optimizer = lp_optimizer = optimizer
|
||||
if optimizer == nothing
|
||||
if optimizer === nothing
|
||||
milp_optimizer = _get_default_milp_optimizer()
|
||||
lp_optimizer = _get_default_lp_optimizer()
|
||||
end
|
||||
|
||||
if graph === nothing
|
||||
@info "Building graph..."
|
||||
graph = RELOG.build_graph(instance)
|
||||
_print_graph_stats(instance, graph)
|
||||
end
|
||||
|
||||
@info "Building optimization model..."
|
||||
model = RELOG.build_model(instance, graph, milp_optimizer)
|
||||
|
||||
@info "Optimizing MILP..."
|
||||
JuMP.optimize!(model)
|
||||
|
||||
if !has_values(model)
|
||||
error("No solution available")
|
||||
end
|
||||
solution = get_solution(model, marginal_costs = false)
|
||||
|
||||
if marginal_costs
|
||||
@info "Re-optimizing with integer variables fixed..."
|
||||
@@ -65,12 +68,15 @@ function solve(
|
||||
end
|
||||
end
|
||||
JuMP.optimize!(model)
|
||||
if has_values(model)
|
||||
@info "Extracting solution..."
|
||||
solution = get_solution(model, marginal_costs = true)
|
||||
else
|
||||
@warn "Error computing marginal costs. Ignoring."
|
||||
end
|
||||
end
|
||||
|
||||
@info "Extracting solution..."
|
||||
solution = get_solution(model, marginal_costs = marginal_costs)
|
||||
|
||||
if output != nothing
|
||||
if output !== nothing
|
||||
write(solution, output)
|
||||
end
|
||||
|
||||
@@ -87,7 +93,7 @@ function solve(filename::AbstractString; heuristic = false, kwargs...)
|
||||
if heuristic && instance.time > 1
|
||||
@info "Solving single-period version..."
|
||||
compressed = _compress(instance)
|
||||
csol = solve(compressed; output = nothing, marginal_costs = false, kwargs...)
|
||||
csol, model = solve(compressed; output = nothing, marginal_costs = false, return_model = true, kwargs...)
|
||||
@info "Filtering candidate locations..."
|
||||
selected_pairs = []
|
||||
for (plant_name, plant_dict) in csol["Plants"]
|
||||
|
||||
Reference in New Issue
Block a user