mirror of
https://github.com/ANL-CEEESA/RELOG.git
synced 2025-12-05 23:38:52 -06:00
Implement initial plant capacity
This commit is contained in:
@@ -110,13 +110,14 @@ The **plants** section describes the available types of reverse manufacturing pl
|
|||||||
|
|
||||||
Each type of plant is associated with a set of potential locations where it can be built. Each location is represented by a dictionary with the following keys:
|
Each type of plant is associated with a set of potential locations where it can be built. Each location is represented by a dictionary with the following keys:
|
||||||
|
|
||||||
| Key | Description |
|
| Key | Description |
|
||||||
| :------------------- | -------------------------------------------------------------------------------- |
|
| :------------------------- | -------------------------------------------------------------------------------- |
|
||||||
| `latitude (deg)` | The latitude of the location, in degrees. |
|
| `latitude (deg)` | The latitude of the location, in degrees. |
|
||||||
| `longitude (deg)` | The longitude of the location, in degrees. |
|
| `longitude (deg)` | The longitude of the location, in degrees. |
|
||||||
| `disposal` | A dictionary describing what products can be disposed locally at the plant. |
|
| `disposal` | A dictionary describing what products can be disposed locally at the plant. |
|
||||||
| `storage` | A dictionary describing the plant's storage. |
|
| `storage` | A dictionary describing the plant's storage. |
|
||||||
| `capacities (tonne)` | A dictionary describing what plant sizes are allowed, and their characteristics. |
|
| `capacities (tonne)` | A dictionary describing what plant sizes are allowed, and their characteristics. |
|
||||||
|
| `initial capacity (tonne)` | Capacity already available at this location. Optional. |
|
||||||
|
|
||||||
The `storage` dictionary should contain the following keys:
|
The `storage` dictionary should contain the following keys:
|
||||||
|
|
||||||
|
|||||||
@@ -25,9 +25,10 @@ In this page, we describe the precise mathematical optimization model used by RE
|
|||||||
| $c^\text{open}_{pt}$ | Cost of opening plant $p$ at time $t$, at minimum capacity | $ |
|
| $c^\text{open}_{pt}$ | Cost of opening plant $p$ at time $t$, at minimum capacity | $ |
|
||||||
| $c^\text{p-disp}_{pmt}$ | Cost of disposing recovered material $m$ at plant $p$ during time $t$ | \$/tonne/km |
|
| $c^\text{p-disp}_{pmt}$ | Cost of disposing recovered material $m$ at plant $p$ during time $t$ | \$/tonne/km |
|
||||||
| $c^\text{store}_{pt}$ | Cost of storing primary material at plant $p$ at time $t$ | \$/tonne |
|
| $c^\text{store}_{pt}$ | Cost of storing primary material at plant $p$ at time $t$ | \$/tonne |
|
||||||
| $c^\text{var}_{pt}$ | Variable cost of processing primary material at plant $p$ at time $t$ | \$/tonne |
|
| $c^\text{proc}_{pt}$ | Variable cost of processing primary material at plant $p$ at time $t$ | \$/tonne |
|
||||||
| $m^\text{max}_p$ | Maximum capacity of plant $p$ | tonne |
|
| $m^\text{max}_p$ | Maximum capacity of plant $p$ | tonne |
|
||||||
| $m^\text{min}_p$ | Minimum capacity of plant $p$ | tonne |
|
| $m^\text{min}_p$ | Minimum capacity of plant $p$ | tonne |
|
||||||
|
| $m^\text{init}_p$ | Initial capacity of plant $p$ | tonne |
|
||||||
| $m^\text{p-disp}_{pmt}$ | Maximum amount of recovered material $m$ that plant $p$ can dispose of during time $t$ | tonne |
|
| $m^\text{p-disp}_{pmt}$ | Maximum amount of recovered material $m$ that plant $p$ can dispose of during time $t$ | tonne |
|
||||||
| $m^\text{store}_p$ | Maximum amount of primary material that plant $p$ can store for later processing. | tonne |
|
| $m^\text{store}_p$ | Maximum amount of primary material that plant $p$ can store for later processing. | tonne |
|
||||||
|
|
||||||
@@ -72,7 +73,7 @@ RELOG minimizes the overall capital, production and transportation costs:
|
|||||||
\sum_{t \in T} \sum_{p \in P} \left[
|
\sum_{t \in T} \sum_{p \in P} \left[
|
||||||
c^\text{open}_{pt} u_{pt} +
|
c^\text{open}_{pt} u_{pt} +
|
||||||
c^\text{f-base}_{pt} x_{pt} +
|
c^\text{f-base}_{pt} x_{pt} +
|
||||||
\sum_{i=1}^t c^\text{f-exp}_{pt} w_{pi} +
|
c^\text{f-exp}_{pt} \left( \sum_{i=0}^t w_{pi} \right) +
|
||||||
c^{\text{exp}}_{pt} w_{pt}
|
c^{\text{exp}}_{pt} w_{pt}
|
||||||
\right] + \\
|
\right] + \\
|
||||||
&
|
&
|
||||||
@@ -138,7 +139,7 @@ In the fifth line, we have acquisition and disposal cost at the collection cente
|
|||||||
|
|
||||||
```math
|
```math
|
||||||
\begin{align*}
|
\begin{align*}
|
||||||
& z^{\text{proc}}_{pt} \leq m^\text{min}_p x_p + \sum_{i=1}^t w_p
|
& z^{\text{proc}}_{pt} \leq m^\text{min}_p x_p + \sum_{i=0}^t w_p
|
||||||
& \forall p \in P, t \in T
|
& \forall p \in P, t \in T
|
||||||
\end{align*}
|
\end{align*}
|
||||||
```
|
```
|
||||||
@@ -156,7 +157,7 @@ In the fifth line, we have acquisition and disposal cost at the collection cente
|
|||||||
|
|
||||||
```math
|
```math
|
||||||
\begin{align*}
|
\begin{align*}
|
||||||
& \sum_{i=1}^t w_p \leq m^\text{max}_p x_p
|
& \sum_{i=0}^t w_p \leq \left( m^\text{max}_p - m^\text{min}_p \right) x_p
|
||||||
& \forall p \in P, t \in T
|
& \forall p \in P, t \in T
|
||||||
\end{align*}
|
\end{align*}
|
||||||
```
|
```
|
||||||
@@ -184,9 +185,19 @@ In the fifth line, we have acquisition and disposal cost at the collection cente
|
|||||||
```math
|
```math
|
||||||
\begin{align*}
|
\begin{align*}
|
||||||
& x_{pt} = x_{p,t-1} + u_{pt}
|
& x_{pt} = x_{p,t-1} + u_{pt}
|
||||||
& \forall p \in P, t \in T \setminus \{1\} \\
|
& \forall p \in P, t \in T \\
|
||||||
& x_{p,1} = u_{p,1}
|
\end{align*}
|
||||||
& \forall p \in P
|
```
|
||||||
|
|
||||||
|
- Boundary constants:
|
||||||
|
|
||||||
|
```math
|
||||||
|
\begin{align*}
|
||||||
|
& x_{p,0} = \begin{cases}
|
||||||
|
0 & \text{ if } m^\text{init}_p = 0 \\
|
||||||
|
1 & \text{ otherwise }
|
||||||
|
\end{cases} \\
|
||||||
|
& w_{p,0} = \max\left\{0, m^\text{init}_p - m^\text{min}_p \right\}
|
||||||
\end{align*}
|
\end{align*}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -76,14 +76,14 @@ function parse(json)::Instance
|
|||||||
prod_centers = []
|
prod_centers = []
|
||||||
|
|
||||||
product = Product(
|
product = Product(
|
||||||
product_name,
|
acquisition_cost = acquisition_cost,
|
||||||
cost,
|
collection_centers = prod_centers,
|
||||||
energy,
|
disposal_cost = disposal_cost,
|
||||||
emissions,
|
disposal_limit = disposal_limit,
|
||||||
disposal_limit,
|
name = product_name,
|
||||||
disposal_cost,
|
transportation_cost = cost,
|
||||||
acquisition_cost,
|
transportation_emissions = emissions,
|
||||||
prod_centers,
|
transportation_energy = energy,
|
||||||
)
|
)
|
||||||
push!(products, product)
|
push!(products, product)
|
||||||
prod_name_to_product[product_name] = product
|
prod_name_to_product[product_name] = product
|
||||||
@@ -97,12 +97,12 @@ function parse(json)::Instance
|
|||||||
center_dict["longitude (deg)"] = region.centroid.lon
|
center_dict["longitude (deg)"] = region.centroid.lon
|
||||||
end
|
end
|
||||||
center = CollectionCenter(
|
center = CollectionCenter(
|
||||||
length(collection_centers) + 1,
|
amount = center_dict["amount (tonne)"],
|
||||||
center_name,
|
index = length(collection_centers) + 1,
|
||||||
center_dict["latitude (deg)"],
|
latitude = center_dict["latitude (deg)"],
|
||||||
center_dict["longitude (deg)"],
|
longitude = center_dict["longitude (deg)"],
|
||||||
product,
|
name = center_name,
|
||||||
center_dict["amount (tonne)"],
|
product = product,
|
||||||
)
|
)
|
||||||
push!(prod_centers, center)
|
push!(prod_centers, center)
|
||||||
push!(collection_centers, center)
|
push!(collection_centers, center)
|
||||||
@@ -164,16 +164,22 @@ function parse(json)::Instance
|
|||||||
push!(
|
push!(
|
||||||
sizes,
|
sizes,
|
||||||
PlantSize(
|
PlantSize(
|
||||||
Base.parse(Float64, capacity_name),
|
capacity = Base.parse(Float64, capacity_name),
|
||||||
capacity_dict["variable operating cost (\$/tonne)"],
|
fixed_operating_cost = capacity_dict["fixed operating cost (\$)"],
|
||||||
capacity_dict["fixed operating cost (\$)"],
|
opening_cost = capacity_dict["opening cost (\$)"],
|
||||||
capacity_dict["opening cost (\$)"],
|
variable_operating_cost = capacity_dict["variable operating cost (\$/tonne)"],
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
length(sizes) > 1 || push!(sizes, sizes[1])
|
length(sizes) > 1 || push!(sizes, sizes[1])
|
||||||
sort!(sizes, by = x -> x.capacity)
|
sort!(sizes, by = x -> x.capacity)
|
||||||
|
|
||||||
|
# Initial capacity
|
||||||
|
initial_capacity = 0
|
||||||
|
if "initial capacity (tonne)" in keys(location_dict)
|
||||||
|
initial_capacity = location_dict["initial capacity (tonne)"]
|
||||||
|
end
|
||||||
|
|
||||||
# Storage
|
# Storage
|
||||||
storage_limit = 0
|
storage_limit = 0
|
||||||
storage_cost = zeros(T)
|
storage_cost = zeros(T)
|
||||||
@@ -192,20 +198,21 @@ function parse(json)::Instance
|
|||||||
end
|
end
|
||||||
|
|
||||||
plant = Plant(
|
plant = Plant(
|
||||||
length(plants) + 1,
|
disposal_cost = disposal_cost,
|
||||||
plant_name,
|
disposal_limit = disposal_limit,
|
||||||
location_name,
|
emissions = emissions,
|
||||||
input,
|
energy = energy,
|
||||||
output,
|
index = length(plants) + 1,
|
||||||
location_dict["latitude (deg)"],
|
initial_capacity = initial_capacity,
|
||||||
location_dict["longitude (deg)"],
|
input = input,
|
||||||
disposal_limit,
|
latitude = location_dict["latitude (deg)"],
|
||||||
disposal_cost,
|
location_name = location_name,
|
||||||
sizes,
|
longitude = location_dict["longitude (deg)"],
|
||||||
energy,
|
output = output,
|
||||||
emissions,
|
plant_name = plant_name,
|
||||||
storage_limit,
|
sizes = sizes,
|
||||||
storage_cost,
|
storage_cost = storage_cost,
|
||||||
|
storage_limit = storage_limit,
|
||||||
)
|
)
|
||||||
|
|
||||||
push!(plants, plant)
|
push!(plants, plant)
|
||||||
@@ -216,11 +223,11 @@ function parse(json)::Instance
|
|||||||
@info @sprintf("%12d candidate plant locations", length(plants))
|
@info @sprintf("%12d candidate plant locations", length(plants))
|
||||||
|
|
||||||
return Instance(
|
return Instance(
|
||||||
T,
|
time = T,
|
||||||
products,
|
products = products,
|
||||||
collection_centers,
|
collection_centers = collection_centers,
|
||||||
plants,
|
plants = plants,
|
||||||
building_period,
|
building_period = building_period,
|
||||||
distance_metric,
|
distance_metric = distance_metric,
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -8,48 +8,49 @@ using JSONSchema
|
|||||||
using Printf
|
using Printf
|
||||||
using Statistics
|
using Statistics
|
||||||
|
|
||||||
mutable struct Product
|
Base.@kwdef mutable struct Product
|
||||||
name::String
|
|
||||||
transportation_cost::Vector{Float64}
|
|
||||||
transportation_energy::Vector{Float64}
|
|
||||||
transportation_emissions::Dict{String,Vector{Float64}}
|
|
||||||
disposal_limit::Vector{Float64}
|
|
||||||
disposal_cost::Vector{Float64}
|
|
||||||
acquisition_cost::Vector{Float64}
|
acquisition_cost::Vector{Float64}
|
||||||
collection_centers::Vector
|
collection_centers::Vector
|
||||||
|
disposal_cost::Vector{Float64}
|
||||||
|
disposal_limit::Vector{Float64}
|
||||||
|
name::String
|
||||||
|
transportation_cost::Vector{Float64}
|
||||||
|
transportation_emissions::Dict{String,Vector{Float64}}
|
||||||
|
transportation_energy::Vector{Float64}
|
||||||
end
|
end
|
||||||
|
|
||||||
mutable struct CollectionCenter
|
Base.@kwdef mutable struct CollectionCenter
|
||||||
|
amount::Vector{Float64}
|
||||||
index::Int64
|
index::Int64
|
||||||
name::String
|
|
||||||
latitude::Float64
|
latitude::Float64
|
||||||
longitude::Float64
|
longitude::Float64
|
||||||
|
name::String
|
||||||
product::Product
|
product::Product
|
||||||
amount::Vector{Float64}
|
|
||||||
end
|
end
|
||||||
|
|
||||||
mutable struct PlantSize
|
Base.@kwdef mutable struct PlantSize
|
||||||
capacity::Float64
|
capacity::Float64
|
||||||
variable_operating_cost::Vector{Float64}
|
|
||||||
fixed_operating_cost::Vector{Float64}
|
fixed_operating_cost::Vector{Float64}
|
||||||
opening_cost::Vector{Float64}
|
opening_cost::Vector{Float64}
|
||||||
|
variable_operating_cost::Vector{Float64}
|
||||||
end
|
end
|
||||||
|
|
||||||
mutable struct Plant
|
Base.@kwdef mutable struct Plant
|
||||||
index::Int64
|
|
||||||
plant_name::String
|
|
||||||
location_name::String
|
|
||||||
input::Product
|
|
||||||
output::Dict{Product,Float64}
|
|
||||||
latitude::Float64
|
|
||||||
longitude::Float64
|
|
||||||
disposal_limit::Dict{Product,Vector{Float64}}
|
|
||||||
disposal_cost::Dict{Product,Vector{Float64}}
|
disposal_cost::Dict{Product,Vector{Float64}}
|
||||||
sizes::Vector{PlantSize}
|
disposal_limit::Dict{Product,Vector{Float64}}
|
||||||
energy::Vector{Float64}
|
|
||||||
emissions::Dict{String,Vector{Float64}}
|
emissions::Dict{String,Vector{Float64}}
|
||||||
storage_limit::Float64
|
energy::Vector{Float64}
|
||||||
|
index::Int64
|
||||||
|
initial_capacity::Float64
|
||||||
|
input::Product
|
||||||
|
latitude::Float64
|
||||||
|
location_name::String
|
||||||
|
longitude::Float64
|
||||||
|
output::Dict{Product,Float64}
|
||||||
|
plant_name::String
|
||||||
|
sizes::Vector{PlantSize}
|
||||||
storage_cost::Vector{Float64}
|
storage_cost::Vector{Float64}
|
||||||
|
storage_limit::Float64
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
@@ -62,11 +63,11 @@ end
|
|||||||
|
|
||||||
mutable struct EuclideanDistance <: DistanceMetric end
|
mutable struct EuclideanDistance <: DistanceMetric end
|
||||||
|
|
||||||
mutable struct Instance
|
Base.@kwdef mutable struct Instance
|
||||||
time::Int64
|
|
||||||
products::Vector{Product}
|
|
||||||
collection_centers::Vector{CollectionCenter}
|
|
||||||
plants::Vector{Plant}
|
|
||||||
building_period::Vector{Int64}
|
building_period::Vector{Int64}
|
||||||
|
collection_centers::Vector{CollectionCenter}
|
||||||
distance_metric::DistanceMetric
|
distance_metric::DistanceMetric
|
||||||
|
plants::Vector{Plant}
|
||||||
|
products::Vector{Product}
|
||||||
|
time::Int64
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ function create_vars!(model::JuMP.Model)
|
|||||||
(n, t) => @variable(model, binary = true) for n in values(graph.process_nodes),
|
(n, t) => @variable(model, binary = true) for n in values(graph.process_nodes),
|
||||||
t = 1:T
|
t = 1:T
|
||||||
)
|
)
|
||||||
model[:is_open] = Dict(
|
model[:is_open] = Dict{Tuple,Any}(
|
||||||
(n, t) => @variable(model, binary = true) for n in values(graph.process_nodes),
|
(n, t) => @variable(model, binary = true) for n in values(graph.process_nodes),
|
||||||
t = 1:T
|
t = 1:T
|
||||||
)
|
)
|
||||||
@@ -55,13 +55,21 @@ function create_vars!(model::JuMP.Model)
|
|||||||
upper_bound = n.location.sizes[2].capacity
|
upper_bound = n.location.sizes[2].capacity
|
||||||
) for n in values(graph.process_nodes), t = 1:T
|
) for n in values(graph.process_nodes), t = 1:T
|
||||||
)
|
)
|
||||||
model[:expansion] = Dict(
|
model[:expansion] = Dict{Tuple,Any}(
|
||||||
(n, t) => @variable(
|
(n, t) => @variable(
|
||||||
model,
|
model,
|
||||||
lower_bound = 0,
|
lower_bound = 0,
|
||||||
upper_bound = n.location.sizes[2].capacity - n.location.sizes[1].capacity
|
upper_bound = n.location.sizes[2].capacity - n.location.sizes[1].capacity
|
||||||
) for n in values(graph.process_nodes), t = 1:T
|
) for n in values(graph.process_nodes), t = 1:T
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Boundary constants
|
||||||
|
for n in values(graph.process_nodes)
|
||||||
|
m_init = n.location.initial_capacity
|
||||||
|
m_min = n.location.sizes[1].capacity
|
||||||
|
model[:is_open][n, 0] = m_init == 0 ? 0 : 1
|
||||||
|
model[:expansion][n, 0] = max(0, m_init - m_min)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
@@ -132,6 +140,7 @@ function create_objective_function!(model::JuMP.Model)
|
|||||||
)
|
)
|
||||||
else
|
else
|
||||||
add_to_expression!(obj, slope_open(n.location, t), model[:expansion][n, t])
|
add_to_expression!(obj, slope_open(n.location, t), model[:expansion][n, t])
|
||||||
|
add_to_expression!(obj, -slope_open(n.location, 1) * model[:expansion][n, 0])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -244,11 +253,11 @@ function create_process_node_constraints!(model::JuMP.Model)
|
|||||||
# Can only process up to capacity
|
# Can only process up to capacity
|
||||||
@constraint(model, model[:process][n, t] <= model[:capacity][n, t])
|
@constraint(model, model[:process][n, t] <= model[:capacity][n, t])
|
||||||
|
|
||||||
|
# Plant capacity can only increase over time
|
||||||
if t > 1
|
if t > 1
|
||||||
# Plant capacity can only increase over time
|
|
||||||
@constraint(model, model[:capacity][n, t] >= model[:capacity][n, t-1])
|
@constraint(model, model[:capacity][n, t] >= model[:capacity][n, t-1])
|
||||||
@constraint(model, model[:expansion][n, t] >= model[:expansion][n, t-1])
|
|
||||||
end
|
end
|
||||||
|
@constraint(model, model[:expansion][n, t] >= model[:expansion][n, t-1])
|
||||||
|
|
||||||
# Amount received equals amount processed plus stored
|
# Amount received equals amount processed plus stored
|
||||||
store_in = 0
|
store_in = 0
|
||||||
@@ -266,14 +275,10 @@ function create_process_node_constraints!(model::JuMP.Model)
|
|||||||
|
|
||||||
# Plant is currently open if it was already open in the previous time period or
|
# Plant is currently open if it was already open in the previous time period or
|
||||||
# if it was built just now
|
# if it was built just now
|
||||||
if t > 1
|
@constraint(
|
||||||
@constraint(
|
model,
|
||||||
model,
|
model[:is_open][n, t] == model[:is_open][n, t-1] + model[:open_plant][n, t]
|
||||||
model[:is_open][n, t] == model[:is_open][n, t-1] + model[:open_plant][n, t]
|
)
|
||||||
)
|
|
||||||
else
|
|
||||||
@constraint(model, model[:is_open][n, t] == model[:open_plant][n, t])
|
|
||||||
end
|
|
||||||
|
|
||||||
# Plant can only be opened during building period
|
# Plant can only be opened during building period
|
||||||
if t ∉ model[:instance].building_period
|
if t ∉ model[:instance].building_period
|
||||||
|
|||||||
@@ -96,7 +96,10 @@ function get_solution(model::JuMP.Model; marginal_costs = true)
|
|||||||
"Expansion cost (\$)" => [
|
"Expansion cost (\$)" => [
|
||||||
(
|
(
|
||||||
if t == 1
|
if t == 1
|
||||||
slope_open(plant, t) * JuMP.value(model[:expansion][process_node, t])
|
slope_open(plant, t) * (
|
||||||
|
JuMP.value(model[:expansion][process_node, t]) -
|
||||||
|
model[:expansion][process_node, 0]
|
||||||
|
)
|
||||||
else
|
else
|
||||||
slope_open(plant, t) * (
|
slope_open(plant, t) * (
|
||||||
JuMP.value(model[:expansion][process_node, t]) -
|
JuMP.value(model[:expansion][process_node, t]) -
|
||||||
|
|||||||
@@ -59,6 +59,7 @@ function _fix_plants!(model_old, model_new)::Nothing
|
|||||||
|
|
||||||
# Fix is_open variables
|
# Fix is_open variables
|
||||||
for ((node_old, t), var_old) in model_old[:is_open]
|
for ((node_old, t), var_old) in model_old[:is_open]
|
||||||
|
t > 0 || continue
|
||||||
value_old = JuMP.value(var_old)
|
value_old = JuMP.value(var_old)
|
||||||
node_new = model_new[:graph].name_to_process_node_map[(
|
node_new = model_new[:graph].name_to_process_node_map[(
|
||||||
node_old.location.plant_name,
|
node_old.location.plant_name,
|
||||||
@@ -84,6 +85,7 @@ function _fix_plants!(model_old, model_new)::Nothing
|
|||||||
|
|
||||||
# Fix plant expansion
|
# Fix plant expansion
|
||||||
for ((node_old, t), var_old) in model_old[:expansion]
|
for ((node_old, t), var_old) in model_old[:expansion]
|
||||||
|
t > 0 || continue
|
||||||
value_old = JuMP.value(var_old)
|
value_old = JuMP.value(var_old)
|
||||||
node_new = model_new[:graph].name_to_process_node_map[(
|
node_new = model_new[:graph].name_to_process_node_map[(
|
||||||
node_old.location.plant_name,
|
node_old.location.plant_name,
|
||||||
|
|||||||
@@ -65,6 +65,9 @@
|
|||||||
"longitude (deg)": {
|
"longitude (deg)": {
|
||||||
"type": "number"
|
"type": "number"
|
||||||
},
|
},
|
||||||
|
"initial capacity (tonne)": {
|
||||||
|
"type": "number"
|
||||||
|
},
|
||||||
"disposal": {
|
"disposal": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"additionalProperties": {
|
"additionalProperties": {
|
||||||
|
|||||||
1
test/fixtures/s1.json
vendored
1
test/fixtures/s1.json
vendored
@@ -103,6 +103,7 @@
|
|||||||
"limit (tonne)": [1.0, 1.0]
|
"limit (tonne)": [1.0, 1.0]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"initial capacity (tonne)": 500.0,
|
||||||
"capacities (tonne)": {
|
"capacities (tonne)": {
|
||||||
"250.0": {
|
"250.0": {
|
||||||
"opening cost ($)": [500.0, 500.0],
|
"opening cost ($)": [500.0, 500.0],
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ function instance_parse_test()
|
|||||||
@test plant.input.name == "P1"
|
@test plant.input.name == "P1"
|
||||||
@test plant.latitude == 0
|
@test plant.latitude == 0
|
||||||
@test plant.longitude == 0
|
@test plant.longitude == 0
|
||||||
|
@test plant.initial_capacity == 500.0
|
||||||
|
|
||||||
@test length(plant.sizes) == 2
|
@test length(plant.sizes) == 2
|
||||||
@test plant.sizes[1].capacity == 250
|
@test plant.sizes[1].capacity == 250
|
||||||
@@ -64,6 +65,7 @@ function instance_parse_test()
|
|||||||
@test plant.input.name == "P2"
|
@test plant.input.name == "P2"
|
||||||
@test plant.latitude == 25
|
@test plant.latitude == 25
|
||||||
@test plant.longitude == 65
|
@test plant.longitude == 65
|
||||||
|
@test plant.initial_capacity == 0
|
||||||
|
|
||||||
@test length(plant.sizes) == 2
|
@test length(plant.sizes) == 2
|
||||||
@test plant.sizes[1].capacity == 1000.0
|
@test plant.sizes[1].capacity == 1000.0
|
||||||
|
|||||||
@@ -21,9 +21,12 @@ function model_build_test()
|
|||||||
@test length(model[:plant_dispose]) == 16
|
@test length(model[:plant_dispose]) == 16
|
||||||
@test length(model[:open_plant]) == 12
|
@test length(model[:open_plant]) == 12
|
||||||
@test length(model[:capacity]) == 12
|
@test length(model[:capacity]) == 12
|
||||||
@test length(model[:expansion]) == 12
|
@test length(model[:expansion]) == 18
|
||||||
|
|
||||||
l1 = process_node_by_location_name["L1"]
|
l1 = process_node_by_location_name["L1"]
|
||||||
|
@test model[:is_open][l1, 0] == 1
|
||||||
|
@test model[:expansion][l1, 0] == 250
|
||||||
|
|
||||||
v = model[:capacity][l1, 1]
|
v = model[:capacity][l1, 1]
|
||||||
@test lower_bound(v) == 0.0
|
@test lower_bound(v) == 0.0
|
||||||
@test upper_bound(v) == 1000.0
|
@test upper_bound(v) == 1000.0
|
||||||
@@ -35,5 +38,9 @@ function model_build_test()
|
|||||||
v = model[:plant_dispose][shipping_node_by_loc_and_prod_names["L1", "P2"], 1]
|
v = model[:plant_dispose][shipping_node_by_loc_and_prod_names["L1", "P2"], 1]
|
||||||
@test lower_bound(v) == 0.0
|
@test lower_bound(v) == 0.0
|
||||||
@test upper_bound(v) == 1.0
|
@test upper_bound(v) == 1.0
|
||||||
|
|
||||||
|
l2 = process_node_by_location_name["L2"]
|
||||||
|
@test model[:is_open][l2, 0] == 0
|
||||||
|
@test model[:expansion][l2, 0] == 0
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user