mirror of
https://github.com/ANL-CEEESA/RELOG.git
synced 2025-12-05 23:38:52 -06:00
Compare commits
15 Commits
circular
...
7dbc3cf90b
| Author | SHA1 | Date | |
|---|---|---|---|
| 7dbc3cf90b | |||
| b7d16fee3e | |||
| eedf023b47 | |||
| 5eee29547c | |||
| 897717677f | |||
| 480547933b | |||
| 744b043461 | |||
| f4e97ff7f2 | |||
| f35c84abe9 | |||
| 003922ac70 | |||
| 4ce52b7420 | |||
| 9e0f8c5796 | |||
|
5693ef2aa2
|
|||
|
bc05b49222
|
|||
|
3e54e767c4
|
@@ -1,7 +1,8 @@
|
||||
# Input data format
|
||||
|
||||
RELOG accepts as input a JSON file with four sections: `parameters`, `products`,
|
||||
`centers` and `plants`. Below, we describe each section in more detail.
|
||||
RELOG accepts as input a JSON file with five sections: `parameters`, `products`,
|
||||
`centers`, `plants` and `emissions`. Below, we describe each section in more
|
||||
detail.
|
||||
|
||||
## Parameters
|
||||
|
||||
@@ -44,7 +45,7 @@ RELOG accepts as input a JSON file with four sections: `parameters`, `products`,
|
||||
"CO2": 0.052,
|
||||
"CH4": 0.003
|
||||
},
|
||||
"disposal limit (tonne)": 100.0,
|
||||
"disposal limit (tonne)": 100.0
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -151,6 +152,7 @@ RELOG accepts as input a JSON file with four sections: `parameters`, `products`,
|
||||
| `disposal cost ($/tonne)` | Dictionary mapping the name of each output product to the cost of disposing it at the plant. |
|
||||
| `disposal limit (tonne)` | Dictionary mapping the name of each output product to the maximum amount allowed to be disposed of at the plant. May be `null` if unlimited. |
|
||||
| `capacities` | List describing what plant sizes are allowed, and their characteristics. |
|
||||
| `initial capacity (tonne)` | Capacity already available. If the plant has not been built yet, this should be `0`. |
|
||||
|
||||
The entries in the `capacities` list should be dictionaries with the following
|
||||
keys:
|
||||
@@ -159,9 +161,8 @@ keys:
|
||||
| :---------------------------------- | :-------------------------------------------------------------------------------------------------- |
|
||||
| `size (tonne)` | The size of the plant. |
|
||||
| `opening cost ($)` | The cost to open a plant of this size. |
|
||||
| `fixed operating cost ($)` | The cost to keep the plant open, even if the plant doesn't process anything. Must be a time series. |
|
||||
| `variable operating cost ($/tonne)` | The cost that the plant incurs to process each tonne of input. Must be a time series. |
|
||||
| `initial capacity (tonne)` | Capacity already available. If the plant has not been built yet, this should be `0`. |
|
||||
| `fixed operating cost ($)` | The cost to keep the plant open, even if the plant doesn't process anything. |
|
||||
| `variable operating cost ($/tonne)` | The cost that the plant incurs to process each tonne of input. Must be the same for all capacities. |
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -218,3 +219,31 @@ keys:
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Emissions
|
||||
|
||||
| Key | Description |
|
||||
| :------------------ | :------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `limit (tonne)` | Maximum amount of this greenhouse gas allowed to be emitted per year across the entire supply chain. Entry may be `null` if unlimited. |
|
||||
| `penalty ($/tonne)` | Penalty cost per tonne of this greenhouse gas emitted. |
|
||||
|
||||
#### Example
|
||||
|
||||
```json
|
||||
{
|
||||
"emissions": {
|
||||
"CO2": {
|
||||
"limit (tonne)": 1000.0,
|
||||
"penalty ($/tonne)": 50.0
|
||||
},
|
||||
"CH4": {
|
||||
"limit (tonne)": null,
|
||||
"penalty ($/tonne)": 1200.0
|
||||
},
|
||||
"N2O": {
|
||||
"limit (tonne)": 10.0,
|
||||
"penalty ($/tonne)": 15000.0
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
The mathematical model employed by RELOG is based on three main components:
|
||||
|
||||
1. **Products and Materials:** Inputs and outputs for both manufacturing and
|
||||
recycling plants. This include raw materials, whether virgin or recovered,
|
||||
recycling plants. This includes raw materials, whether virgin or recovered,
|
||||
and final products, whether new or at their end-of-life. Each product has
|
||||
associated transportation parameters, such as costs, energy and emissions.
|
||||
|
||||
@@ -50,24 +50,34 @@ The mathematical model employed by RELOG is based on three main components:
|
||||
## Constants
|
||||
|
||||
| Symbol | Description | Unit |
|
||||
| :-------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------- |
|
||||
| :---------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------- |
|
||||
| $K^{\text{dist}}_{uv}$ | Distance between plants/centers $u$ and $v$ | km |
|
||||
| $K^\text{cap}_{p}$ | Capacity of plant $p$, if the plant is open | tonne |
|
||||
| $K^\text{cap-init}_p$ | Initial capacity of plant $p$ | tonne |
|
||||
| $K^\text{cap-max}_p$ | Maximum capacity of plant $p$ | tonne |
|
||||
| $K^\text{cap-min}_p$ | Minimum capacity of plant $p$ | tonne |
|
||||
| $K^\text{disp-limit}_{mt}$ | Maximum amount of material $m$ that can be disposed of (globally) at time $t$ | tonne |
|
||||
| $K^\text{disp-limit}_{mut}$ | Maximum amount of material $m$ that can be disposed of at plant/center $u$ at time $t$ | tonne |
|
||||
| $K^\text{em-limit}_{gt}$ | Maximum amount of greenhouse gas $g$ allowed to be emitted (globally) at time $t$ | tonne |
|
||||
| $K^\text{em-plant}_{gpt}$ | Amount of greenhouse gas $g$ released by plant $p$ at time $t$ for each tonne of input material processed | tonne/tonne |
|
||||
| $K^\text{em-tr}_{gmt}$ | Amount of greenhouse gas $g$ released by transporting 1 tonne of material $m$ over one km at time $t$ | tonne/km-tonne |
|
||||
| $K^\text{mix}_{pmt}$ | If plant $p$ receives one tonne of input material at time $t$, then $K^\text{mix}_{pmt}$ is the amount of product $m$ in this mix. Must be between zero and one, and the sum of these amounts must equal to one. | tonne |
|
||||
| $K^\text{out-fix}_{cmt}$ | Fixed amount of material $m$ collected at center $c$ at time $t$ | tonne |
|
||||
| $K^\text{out-var-len}_{cm}$ | Length of the $K^\text{out-var}_{c,m,*}$ vector. | -- |
|
||||
| $K^\text{out-var}_{cmi}$ | Factor used to calculate variable amount of material $m$ collected at center $c$. See `eq_z_collected` for more details. | -- |
|
||||
| $K^\text{output}_{pmt}$ | Amount of material $m$ produced by plant $p$ at time $t$ for each tonne of input material processed | tonne |
|
||||
| $K^\text{tr-em}_{gmt}$ | Amount of greenhouse gas $g$ released by transporting 1 tonne of material $m$ over one km at time $t$ | tonne/km-tonne |
|
||||
| $R^\text{tr}_{mt}$ | Cost to send material $m$ at time $t$ | \$/km-tonne |
|
||||
| $K^\text{storage-limit}_{pm}$ | Maximum amount of material $m$ that can be stored at plant $p$ at any time | tonne |
|
||||
| $R^\text{collect}_{cmt}$ | Cost of collecting material $m$ at center $c$ at time $t$ | \$/tonne |
|
||||
| $R^\text{disp}_{umt}$ | Cost to dispose of material at plant/center $u$ at time $t$ | \$/tonne |
|
||||
| $R^\text{fix}_{ut}$ | Fixed operating cost for plant/center $u$ at time $t$ | \$ |
|
||||
| $R^\text{open}_{pt}$ | Cost to open plant $p$ at time $t$ | \$ |
|
||||
| $R^\text{em}_{gt}$ | Penalty cost per tonne of greenhouse gas $g$ emitted at time $t$ | \$/tonne |
|
||||
| $R^\text{expand}_{pt}$ | Cost to increase capacity of plant $p$ at time $t$ | \$/tonne |
|
||||
| $R^\text{fix-exp}_{pt}$ | Increase in fixed operational cost for plant $p$ at time $t$ for every additional tonne of capacity | \$/tonne |
|
||||
| $R^\text{fix-min}_{pt}$ | Fixed operating cost for plant $p$ at time $t$ at minimum capacity | \$ |
|
||||
| $R^\text{fix}_{ct}$ | Fixed operating cost for center $c$ at time $t$ | \$ |
|
||||
| $R^\text{open}_{pt}$ | Cost to open plant $p$ at time $t$, at minimum capacity | \$ |
|
||||
| $R^\text{rev}_{ct}$ | Revenue for selling the input product of center $c$ at this center at time $t$ | \$/tonne |
|
||||
| $R^\text{storage}_{pmt}$ | Cost to store one tonne of material $m$ at plant $p$ at time $t$ for one year | \$/tonne |
|
||||
| $R^\text{tr}_{mt}$ | Cost to send material $m$ at time $t$ | \$/km-tonne |
|
||||
| $R^\text{var}_{pt}$ | Cost to process one tonne of input material at plant $p$ at time $t$ | \$/tonne |
|
||||
| $K^\text{out-fix}_{cmt}$ | Fixed amount of material $m$ collected at center $m$ at time $t$ | \$/tonne |
|
||||
| $K^\text{out-var}_{c,m,i}$ | Factor used to calculate variable amount of material $m$ collected at center $m$. See `eq_z_collected` for more details. | -- |
|
||||
| $K^\text{out-var-len}_{cm}$ | Length of the $K^\text{out-var}_{c,m,*}$ vector. | -- |
|
||||
|
||||
## Decision variables
|
||||
|
||||
@@ -75,15 +85,19 @@ The mathematical model employed by RELOG is based on three main components:
|
||||
| :--------------------------- | :------------------------------------------- | :------------------------------------------------------------------------------------------------------ | :----- |
|
||||
| $x_{pt}$ | `x[p.name, t]` | One if plant $p$ is operational at time $t$ | binary |
|
||||
| $y_{uvmt}$ | `y[u.name, v.name, m.name, t]` | Amount of product $m$ sent from plant/center $u$ to plant/center $v$ at time $t$ | tonne |
|
||||
| $z^{\text{exp}}_{pt}$ | `z_exp[p.name, t]` | Extra capacity installed at plant $p$ at time $t$ above the minimum capacity | tonne |
|
||||
| $z^{\text{collected}}_{cmt}$ | `z_collected[c.name, m.name, t]` | Amount of material $m$ collected by center $c$ at time $t$ | tonne |
|
||||
| $z^{\text{disp}}_{umt}$ | `z_disp[u.name, m.name, t]` | Amount of product $m$ disposed of at plant/center $u$ at time $t$ | tonne |
|
||||
| $z^{\text{input}}_{ut}$ | `z_input[u.name, t]` | Total plant/center input at time $t$ | tonne |
|
||||
| $z^{\text{em-plant}}_{gpt}$ | `z_em_plant[g.name, p.name, t]` | Amount of greenhouse gas $g$ released by plant $p$ at time $t$ | tonne |
|
||||
| $z^{\text{em-tr}}_{guvmt}$ | `z_em_tr[g.name, u.name, v.name, m.name, t]` | Amount of greenhouse gas $g$ released at time $t$ due to transportation of material $m$ from $u$ to $v$ | tonne |
|
||||
| $z^{\text{input}}_{ut}$ | `z_input[u.name, t]` | Total amount received by plant/center $u$ at time $t$ | tonne |
|
||||
| $z^{\text{prod}}_{umt}$ | `z_prod[u.name, m.name, t]` | Amount of product $m$ produced by plant/center $u$ at time $t$ | tonne |
|
||||
| $z^{\text{tr-em}}_{guvmt}$ | `z_tr_em[g.name, u.name, v.name, m.name, t]` | Amount of greenhouse gas $g$ released at time $t$ due to transportation of material $m$ from $u$ to $v$ | tonne |
|
||||
| $z^{\text{storage}}_{pmt}$ | `z_storage[p.name, m.name, t]` | Amount of input material $m$ stored at plant $p$ at the end of time $t$ | tonne |
|
||||
| $z^{\text{process}}_{pt}$ | `z_process[p.name, t]` | Total amount of input material processed by plant $p$ at time $t$ | tonne |
|
||||
|
||||
## Objective function
|
||||
|
||||
The goals is to minimize a linear objective function with the following terms:
|
||||
The goal is to minimize a linear objective function with the following terms:
|
||||
|
||||
- Transportation costs, which depend on transportation distance
|
||||
$K^{\text{dist}}_{uv}$ and product-specific factor $R^\text{tr}_{mt}$:
|
||||
@@ -127,7 +141,9 @@ The goals is to minimize a linear objective function with the following terms:
|
||||
\sum_{p \in P} \sum_{m \in M^+_p} \sum_{t \in T} R^\text{disp}_{pmt} z^\text{disp}_{pmt}
|
||||
```
|
||||
|
||||
- Plant opening cost:
|
||||
- Plant opening cost, incurred when the plant goes from non-operational at time
|
||||
$t-1$ to operational at time $t$. Never incurred if the plant is initially
|
||||
open:
|
||||
|
||||
```math
|
||||
\sum_{p \in P} \sum_{t \in T} R^\text{open}_{pt} \left(
|
||||
@@ -136,10 +152,20 @@ The goals is to minimize a linear objective function with the following terms:
|
||||
```
|
||||
|
||||
- Plant fixed operating cost, incurred for every time period, regardless of
|
||||
input or output amounts, as long as the plant is operational:
|
||||
input or output amounts, as long as the plant is operational. Depends on the
|
||||
size of the plant:
|
||||
|
||||
```math
|
||||
\sum_{p \in P} \sum_{t \in T} R^\text{fix}_{pt} x_{pt}
|
||||
\sum_{p \in P} \sum_{t \in T} \left(
|
||||
R^\text{fix-min}_{pt} x_{pt} +
|
||||
R^\text{fix-exp}_{pt} z^\text{exp}_{pt}
|
||||
\right)
|
||||
```
|
||||
|
||||
- Plant expansion cost, incurred whenever plant capacity increases:
|
||||
|
||||
```math
|
||||
\sum_{p \in P} \sum_{t \in T} R^\text{expand}_{pt} \left(z^\text{exp}_{pt} - z^\text{exp}_{p,t-1} \right)
|
||||
```
|
||||
|
||||
- Plant variable operating cost, incurred for each tonne of input material
|
||||
@@ -149,6 +175,20 @@ The goals is to minimize a linear objective function with the following terms:
|
||||
\sum_{p \in P} \sum_{(u,m) \in E^-(p)} \sum_{t \in T} R^\text{var}_{pt} y_{upmt}
|
||||
```
|
||||
|
||||
- Plant storage cost, incurred for each tonne of material stored at the plant:
|
||||
|
||||
```math
|
||||
\sum_{p \in P} \sum_{m \in M^-_p} \sum_{t \in T} R^\text{storage}_{pmt} z^{\text{storage}}_{pmt}
|
||||
```
|
||||
|
||||
- Emissions penalty cost, incurred for each tonne of greenhouse gas emitted:
|
||||
|
||||
```math
|
||||
\sum_{g \in G} \sum_{t \in T} R^\text{em}_{gt} \left(
|
||||
\sum_{p \in P} z^{\text{em-plant}}_{gpt} + \sum_{(u,v,m) \in E} z^{\text{em-tr}}_{guvmt}
|
||||
\right)
|
||||
```
|
||||
|
||||
## Constraints
|
||||
|
||||
- Definition of plant input (`eq_z_input[p.name, t]`):
|
||||
@@ -160,13 +200,22 @@ The goals is to minimize a linear objective function with the following terms:
|
||||
\end{align*}
|
||||
```
|
||||
|
||||
- Plant input mix must have correct proportion
|
||||
(`eq_input_mix[p.name, m.name, t]`):
|
||||
- Definition of plant processing (`eq_z_process[p.name, t]`):
|
||||
|
||||
```math
|
||||
\begin{align*}
|
||||
& \sum_{u : (u,m) \in E^-(p)} y_{upmt}
|
||||
= K^\text{mix}_{pmt} z^{\text{input}}_{pt}
|
||||
& z^{\text{process}}_{pt} = z^{\text{input}}_{pt} + \sum_{m \in M^-_p} \left(z^{\text{storage}}_{p,m,t-1} - z^{\text{storage}}_{pmt}\right)
|
||||
& \forall p \in P, t \in T
|
||||
\end{align*}
|
||||
```
|
||||
|
||||
- Plant processing mix must have correct proportion
|
||||
(`eq_process_mix[p.name, m.name, t]`):
|
||||
|
||||
```math
|
||||
\begin{align*}
|
||||
& \sum_{u : (u,m) \in E^-(p)} y_{upmt} + z^{\text{storage}}_{p,m,t-1} - z^{\text{storage}}_{pmt}
|
||||
= K^\text{mix}_{pmt} z^{\text{process}}_{pt}
|
||||
& \forall p \in P, m \in M^-_p, t \in T
|
||||
\end{align*}
|
||||
```
|
||||
@@ -175,7 +224,7 @@ The goals is to minimize a linear objective function with the following terms:
|
||||
|
||||
```math
|
||||
\begin{align*}
|
||||
& z^\text{prod}_{pmt} = K^\text{output}_{pmt} z^\text{input}_{pt}
|
||||
& z^\text{prod}_{pmt} = K^\text{output}_{pmt} z^{\text{process}}_{pt}
|
||||
& \forall p \in P, m \in M^+_p, t \in T
|
||||
\end{align*}
|
||||
```
|
||||
@@ -190,16 +239,65 @@ The goals is to minimize a linear objective function with the following terms:
|
||||
\end{align*}
|
||||
```
|
||||
|
||||
- Plants have a maximum capacity; furthermore, if the plant is not open, its
|
||||
capacity is zero (`eq_capacity[p.name,t]`)
|
||||
- Plant can only be expanded if the plant is open, and up to a certain amount
|
||||
(`eq_exp_ub[p.name, t]`):
|
||||
|
||||
```math
|
||||
\begin{align*}
|
||||
& z^\text{input}_{pt} \leq K^\text{cap}_p x_{pt}
|
||||
& z^\text{exp}_{pt} \leq \left(K^\text{cap-max}_p - K^\text{cap-min}_p) x_{pt}
|
||||
& \forall p \in P, t \in T
|
||||
\end{align*}
|
||||
```
|
||||
|
||||
- Plant capacity cannot decrease over time (`eq_capacity_nondecreasing[p.name, t]`):
|
||||
|
||||
```math
|
||||
\begin{align*}
|
||||
& z^\text{exp}_{pt} \geq z^\text{exp}_{p,t-1}
|
||||
& \forall p \in P, t \in T
|
||||
\end{align*}
|
||||
```
|
||||
|
||||
- Plant is initially open if initial capacity is positive:
|
||||
|
||||
```math
|
||||
\begin{align*}
|
||||
& x_{p,0} = \begin{cases}
|
||||
0 & \text{ if } K^\text{cap-init}_p = 0 \\
|
||||
1 & \text{otherwise}
|
||||
\end{cases}
|
||||
& \forall p \in P
|
||||
\end{align*}
|
||||
```
|
||||
|
||||
- Calculation of initial plant expansion:
|
||||
|
||||
```math
|
||||
\begin{align*}
|
||||
& z^\text{exp}_{p,0} = K^\text{cap-init}_p - K^\text{cap-min}_p
|
||||
& \forall p \in P
|
||||
\end{align*}
|
||||
```
|
||||
|
||||
- Plants cannot process more than their current capacity
|
||||
(`eq_process_limit[p.name,t]`)
|
||||
|
||||
```math
|
||||
\begin{align*}
|
||||
& z^\text{process}_{pt} \leq K^\text{cap-min}_p x_{pt} + z^\text{exp}_{pt}
|
||||
& \forall p \in P, t \in T
|
||||
\end{align*}
|
||||
```
|
||||
|
||||
- Storage limit at the plants (`eq_storage_limit[p.name, m.name, t]`):
|
||||
|
||||
```math
|
||||
\begin{align*}
|
||||
& z^{\text{storage}}_{pmt} \leq K^\text{storage-limit}_{pm}
|
||||
& \forall p \in P, m \in M^-_p, t \in T
|
||||
\end{align*}
|
||||
```
|
||||
|
||||
- Disposal limit at the plants (`eq_disposal_limit[p.name, m.name, t]`):
|
||||
|
||||
```math
|
||||
@@ -269,11 +367,49 @@ The goals is to minimize a linear objective function with the following terms:
|
||||
\end{align*}
|
||||
```
|
||||
|
||||
- Computation of transportation emissions (`eq_tr_em[g.name, u.name, v.name, m.name, t`)
|
||||
- Computation of transportation emissions
|
||||
(`eq_emission_tr[g.name, u.name, v.name, m.name, t]`):
|
||||
|
||||
```math
|
||||
\begin{align*}
|
||||
& z^{\text{tr-em}}_{guvmt} = K^{\text{dist}}_{uv} K^\text{tr-em}_{gmt} y_{uvmt}
|
||||
& z^{\text{em-tr}}_{guvmt} = K^{\text{dist}}_{uv} K^\text{em-tr}_{gmt} y_{uvmt}
|
||||
& \forall g \in G, (u, v, m) \in E, t \in T
|
||||
\end{align*}
|
||||
```
|
||||
|
||||
- Computation of plant emissions (`eq_emission_plant[g.name, p.name, t]`):
|
||||
|
||||
```math
|
||||
\begin{align*}
|
||||
& z^{\text{em-plant}}_{gpt} = K^\text{em-plant}_{gpt} z^{\text{process}}_{pt}
|
||||
& \forall g \in G, p \in P, t \in T
|
||||
\end{align*}
|
||||
```
|
||||
|
||||
- Global emissions limit (`eq_emission_limit[g.name, t]`):
|
||||
|
||||
```math
|
||||
\begin{align*}
|
||||
& \sum_{p \in P} z^{\text{em-plant}}_{gpt} + \sum_{(u,v,m) \in E} z^{\text{em-tr}}_{guvmt} \leq K^\text{em-limit}_{gt}
|
||||
& \forall g \in G, t \in T
|
||||
\end{align*}
|
||||
```
|
||||
|
||||
- All stored materials must be processed by the end of the time horizon
|
||||
(`eq_storage_final[p.name, m.name]`):
|
||||
|
||||
```math
|
||||
\begin{align*}
|
||||
& z^{\text{storage}}_{p,m,t^{max}} = 0
|
||||
& \forall p \in P, m \in M^-_p
|
||||
\end{align*}
|
||||
```
|
||||
|
||||
- Initial storage is zero (`eq_storage_initial[p.name, m.name]`):
|
||||
|
||||
```math
|
||||
\begin{align*}
|
||||
& z^{\text{storage}}_{p,m,0} = 0
|
||||
& \forall p \in P, m \in M^-_p
|
||||
\end{align*}
|
||||
```
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
module RELOG
|
||||
|
||||
_round(x::Number) = round(x, digits = 5)
|
||||
function _round(x::Number)
|
||||
if abs(x) < 1e-5
|
||||
return 0
|
||||
else
|
||||
return round(x, digits = 5)
|
||||
end
|
||||
end
|
||||
|
||||
include("instance/structs.jl")
|
||||
include("instance/parse.jl")
|
||||
|
||||
@@ -2,7 +2,7 @@ using JSON
|
||||
using OrderedCollections
|
||||
|
||||
function parsefile(path::String)::Instance
|
||||
return RELOG.parse(JSON.parsefile(path, dicttype = () -> OrderedDict()))
|
||||
return RELOG.parse(JSON.parsefile(path; dicttype = OrderedDict))
|
||||
end
|
||||
|
||||
function parse(json)::Instance
|
||||
@@ -110,6 +110,32 @@ function parse(json)::Instance
|
||||
)
|
||||
end
|
||||
|
||||
# Validate capacity count and duplicate if needed
|
||||
if length(capacities) == 0
|
||||
error("Plant '$name' must have at least one capacity defined")
|
||||
elseif length(capacities) == 1
|
||||
# Duplicate the single capacity
|
||||
push!(capacities, capacities[1])
|
||||
elseif length(capacities) > 2
|
||||
error(
|
||||
"Plant '$name' cannot have more than 2 capacities, got $(length(capacities))",
|
||||
)
|
||||
end
|
||||
|
||||
# Validate capacity sizes are non-decreasing
|
||||
if capacities[1].size > capacities[2].size
|
||||
error(
|
||||
"Plant '$name' capacity sizes must be non-decreasing: $(capacities[1].size) > $(capacities[2].size)",
|
||||
)
|
||||
end
|
||||
|
||||
# Validate variable operating costs are the same
|
||||
if capacities[1].var_operating_cost != capacities[2].var_operating_cost
|
||||
error(
|
||||
"Plant '$name' variable operating costs must be the same across all capacities",
|
||||
)
|
||||
end
|
||||
|
||||
plant = Plant(;
|
||||
name,
|
||||
latitude,
|
||||
@@ -128,6 +154,19 @@ function parse(json)::Instance
|
||||
plants_by_name[name] = plant
|
||||
end
|
||||
|
||||
# Read emissions
|
||||
emissions = Emissions[]
|
||||
emissions_by_name = OrderedDict{String,Emissions}()
|
||||
if haskey(json, "emissions")
|
||||
for (name, edict) in json["emissions"]
|
||||
limit = timeseries(edict["limit (tonne)"], null_val = Inf)
|
||||
penalty = timeseries(edict["penalty (\$/tonne)"])
|
||||
emission = Emissions(; name, limit, penalty)
|
||||
push!(emissions, emission)
|
||||
emissions_by_name[name] = emission
|
||||
end
|
||||
end
|
||||
|
||||
return Instance(;
|
||||
time_horizon,
|
||||
building_period,
|
||||
@@ -138,5 +177,7 @@ function parse(json)::Instance
|
||||
centers_by_name,
|
||||
plants,
|
||||
plants_by_name,
|
||||
emissions,
|
||||
emissions_by_name,
|
||||
)
|
||||
end
|
||||
|
||||
@@ -54,6 +54,12 @@ Base.@kwdef struct Plant
|
||||
initial_capacity::Float64
|
||||
end
|
||||
|
||||
Base.@kwdef struct Emissions
|
||||
name::String
|
||||
limit::Vector{Float64}
|
||||
penalty::Vector{Float64}
|
||||
end
|
||||
|
||||
Base.@kwdef struct Instance
|
||||
building_period::Vector{Int}
|
||||
centers_by_name::OrderedDict{String,Center}
|
||||
@@ -64,4 +70,6 @@ Base.@kwdef struct Instance
|
||||
time_horizon::Int
|
||||
plants::Vector{Plant}
|
||||
plants_by_name::OrderedDict{String,Plant}
|
||||
emissions_by_name::OrderedDict{String,Emissions}
|
||||
emissions::Vector{Emissions}
|
||||
end
|
||||
|
||||
@@ -1,5 +1,26 @@
|
||||
# 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 JuMP
|
||||
|
||||
function R_expand(p::Plant, t::Int)
|
||||
denominator = p.capacities[2].size - p.capacities[1].size
|
||||
if denominator == 0
|
||||
return 0.0
|
||||
end
|
||||
return (p.capacities[2].opening_cost[t] - p.capacities[1].opening_cost[t]) / denominator
|
||||
end
|
||||
|
||||
function R_fix_exp(p::Plant, t::Int)
|
||||
denominator = p.capacities[2].size - p.capacities[1].size
|
||||
if denominator == 0
|
||||
return 0.0
|
||||
end
|
||||
return (p.capacities[2].fix_operating_cost[t] - p.capacities[1].fix_operating_cost[t]) /
|
||||
denominator
|
||||
end
|
||||
|
||||
function build_model(instance::Instance; optimizer, variable_names::Bool = false)
|
||||
model = JuMP.Model(optimizer)
|
||||
centers = instance.centers
|
||||
@@ -8,6 +29,15 @@ function build_model(instance::Instance; optimizer, variable_names::Bool = false
|
||||
T = 1:instance.time_horizon
|
||||
model.ext[:instance] = instance
|
||||
|
||||
# Constants
|
||||
# -------------------------------------------------------------------------
|
||||
K_cap_min = Dict(p => p.capacities[1].size for p in plants)
|
||||
K_cap_max = Dict(p => p.capacities[2].size for p in plants)
|
||||
R_open = Dict((p, t) => p.capacities[1].opening_cost[t] for p in plants for t in T)
|
||||
R_fix_min =
|
||||
Dict((p, t) => p.capacities[1].fix_operating_cost[t] for p in plants for t in T)
|
||||
|
||||
|
||||
# Transportation edges
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
@@ -112,16 +142,48 @@ function build_model(instance::Instance; optimizer, variable_names::Bool = false
|
||||
z_input[c.name, t] = @variable(model, lower_bound = 0)
|
||||
end
|
||||
|
||||
# Plant expansion
|
||||
z_exp = _init(model, :z_exp)
|
||||
for p in plants
|
||||
z_exp[p.name, 0] = max(0, p.initial_capacity - K_cap_min[p])
|
||||
end
|
||||
for p in plants, t in T
|
||||
z_exp[p.name, t] = @variable(model, lower_bound = 0)
|
||||
end
|
||||
|
||||
# Total amount collected by the center
|
||||
z_collected = _init(model, :z_collected)
|
||||
for c in centers, m in c.outputs, t in T
|
||||
z_collected[c.name, m.name, t] = @variable(model, lower_bound = 0)
|
||||
end
|
||||
|
||||
# Amount of input material stored at plant at end of time period
|
||||
z_storage = _init(model, :z_storage)
|
||||
for p in plants
|
||||
for m in keys(p.input_mix)
|
||||
z_storage[p.name, m.name, 0] = 0 # Initial storage is zero
|
||||
end
|
||||
end
|
||||
for p in plants, m in keys(p.input_mix), t in T
|
||||
z_storage[p.name, m.name, t] = @variable(model, lower_bound = 0)
|
||||
end
|
||||
|
||||
# Total amount of input material processed by plant
|
||||
z_process = _init(model, :z_process)
|
||||
for p in plants, t in T
|
||||
z_process[p.name, t] = @variable(model, lower_bound = 0)
|
||||
end
|
||||
|
||||
# Transportation emissions by greenhouse gas
|
||||
z_tr_em = _init(model, :z_tr_em)
|
||||
z_em_tr = _init(model, :z_em_tr)
|
||||
for (p1, p2, m) in E, t in T, g in keys(m.tr_emissions)
|
||||
z_tr_em[g, p1.name, p2.name, m.name, t] = @variable(model, lower_bound = 0)
|
||||
z_em_tr[g, p1.name, p2.name, m.name, t] = @variable(model, lower_bound = 0)
|
||||
end
|
||||
|
||||
# Plant emissions by greenhouse gas
|
||||
z_em_plant = _init(model, :z_em_plant)
|
||||
for p in plants, t in T, g in keys(p.emissions)
|
||||
z_em_plant[g, p.name, t] = @variable(model, lower_bound = 0)
|
||||
end
|
||||
|
||||
|
||||
@@ -165,16 +227,18 @@ function build_model(instance::Instance; optimizer, variable_names::Bool = false
|
||||
|
||||
# Plants: Opening cost
|
||||
for p in plants, t in T
|
||||
add_to_expression!(
|
||||
obj,
|
||||
p.capacities[1].opening_cost[t],
|
||||
(x[p.name, t] - x[p.name, t-1]),
|
||||
)
|
||||
add_to_expression!(obj, R_open[p, t], (x[p.name, t] - x[p.name, t-1]))
|
||||
end
|
||||
|
||||
# Plants: Fixed operating cost
|
||||
for p in plants, t in T
|
||||
add_to_expression!(obj, p.capacities[1].fix_operating_cost[t], x[p.name, t])
|
||||
add_to_expression!(obj, R_fix_min[p, t], x[p.name, t])
|
||||
add_to_expression!(obj, R_fix_exp(p, t), z_exp[p.name, t])
|
||||
end
|
||||
|
||||
# Plants: Expansion cost
|
||||
for p in plants, t in T
|
||||
add_to_expression!(obj, R_expand(p, t), z_exp[p.name, t] - z_exp[p.name, t-1])
|
||||
end
|
||||
|
||||
# Plants: Variable operating cost
|
||||
@@ -186,6 +250,35 @@ function build_model(instance::Instance; optimizer, variable_names::Bool = false
|
||||
)
|
||||
end
|
||||
|
||||
# Plants: Storage cost
|
||||
for p in plants, m in keys(p.storage_cost), t in T
|
||||
add_to_expression!(obj, p.storage_cost[m][t], z_storage[p.name, m.name, t])
|
||||
end
|
||||
|
||||
# Emissions penalty cost
|
||||
for emission in instance.emissions, t in T
|
||||
# Plant emissions penalty
|
||||
for p in plants
|
||||
if emission.name in keys(p.emissions)
|
||||
add_to_expression!(
|
||||
obj,
|
||||
emission.penalty[t],
|
||||
z_em_plant[emission.name, p.name, t],
|
||||
)
|
||||
end
|
||||
end
|
||||
# Transportation emissions penalty
|
||||
for (p1, p2, m) in E
|
||||
if emission.name in keys(m.tr_emissions)
|
||||
add_to_expression!(
|
||||
obj,
|
||||
emission.penalty[t],
|
||||
z_em_tr[emission.name, p1.name, p2.name, m.name, t],
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@objective(model, Min, obj)
|
||||
|
||||
# Constraints
|
||||
@@ -201,13 +294,27 @@ function build_model(instance::Instance; optimizer, variable_names::Bool = false
|
||||
)
|
||||
end
|
||||
|
||||
# Plants: Must meet input mix
|
||||
eq_input_mix = _init(model, :eq_input_mix)
|
||||
for p in plants, m in keys(p.input_mix), t in T
|
||||
eq_input_mix[p.name, m.name, t] = @constraint(
|
||||
# Plants: Definition of total processing amount
|
||||
eq_z_process = _init(model, :eq_z_process)
|
||||
for p in plants, t in T
|
||||
eq_z_process[p.name, t] = @constraint(
|
||||
model,
|
||||
sum(y[src.name, p.name, m.name, t] for (src, m2) in E_in[p] if m == m2) ==
|
||||
z_input[p.name, t] * p.input_mix[m][t]
|
||||
z_process[p.name, t] ==
|
||||
z_input[p.name, t] + sum(
|
||||
z_storage[p.name, m.name, t-1] - z_storage[p.name, m.name, t] for
|
||||
m in keys(p.input_mix)
|
||||
)
|
||||
)
|
||||
end
|
||||
|
||||
# Plants: Processing mix must have correct proportion
|
||||
eq_process_mix = _init(model, :eq_process_mix)
|
||||
for p in plants, m in keys(p.input_mix), t in T
|
||||
eq_process_mix[p.name, m.name, t] = @constraint(
|
||||
model,
|
||||
sum(y[src.name, p.name, m.name, t] for (src, m2) in E_in[p] if m == m2) +
|
||||
z_storage[p.name, m.name, t-1] - z_storage[p.name, m.name, t] ==
|
||||
z_process[p.name, t] * p.input_mix[m][t]
|
||||
)
|
||||
end
|
||||
|
||||
@@ -216,7 +323,7 @@ function build_model(instance::Instance; optimizer, variable_names::Bool = false
|
||||
for p in plants, m in keys(p.output), t in T
|
||||
eq_z_prod[p.name, m.name, t] = @constraint(
|
||||
model,
|
||||
z_prod[p.name, m.name, t] == z_input[p.name, t] * p.output[m][t]
|
||||
z_prod[p.name, m.name, t] == z_process[p.name, t] * p.output[m][t]
|
||||
)
|
||||
end
|
||||
|
||||
@@ -231,11 +338,22 @@ function build_model(instance::Instance; optimizer, variable_names::Bool = false
|
||||
)
|
||||
end
|
||||
|
||||
# Plants: Capacity limit
|
||||
eq_capacity = _init(model, :eq_capacity)
|
||||
# Plants: Expansion upper bound
|
||||
eq_exp_ub = _init(model, :eq_exp_ub)
|
||||
for p in plants, t in T
|
||||
eq_capacity[p.name, t] =
|
||||
@constraint(model, z_input[p.name, t] <= p.capacities[1].size * x[p.name, t])
|
||||
eq_exp_ub[p.name, t] = @constraint(
|
||||
model,
|
||||
z_exp[p.name, t] <= (K_cap_max[p] - K_cap_min[p]) * x[p.name, t]
|
||||
)
|
||||
end
|
||||
|
||||
# Plants: Processing limit
|
||||
eq_process_limit = _init(model, :eq_process_limit)
|
||||
for p in plants, t in T
|
||||
eq_process_limit[p.name, t] = @constraint(
|
||||
model,
|
||||
z_process[p.name, t] <= K_cap_min[p] * x[p.name, t] + z_exp[p.name, t]
|
||||
)
|
||||
end
|
||||
|
||||
# Plants: Disposal limit
|
||||
@@ -252,6 +370,13 @@ function build_model(instance::Instance; optimizer, variable_names::Bool = false
|
||||
eq_keep_open[p.name, t] = @constraint(model, x[p.name, t] >= x[p.name, t-1])
|
||||
end
|
||||
|
||||
# Plants: Capacity cannot decrease over time
|
||||
eq_capacity_nondecreasing = _init(model, :eq_capacity_nondecreasing)
|
||||
for p in plants, t in T
|
||||
eq_capacity_nondecreasing[p.name, t] =
|
||||
@constraint(model, z_exp[p.name, t] >= z_exp[p.name, t-1])
|
||||
end
|
||||
|
||||
# Plants: Building period
|
||||
eq_building_period = _init(model, :eq_building_period)
|
||||
for p in plants, t in T
|
||||
@@ -317,15 +442,56 @@ function build_model(instance::Instance; optimizer, variable_names::Bool = false
|
||||
end
|
||||
|
||||
# Transportation emissions
|
||||
eq_tr_em = _init(model, :eq_tr_em)
|
||||
eq_emission_tr = _init(model, :eq_emission_tr)
|
||||
for (p1, p2, m) in E, t in T, g in keys(m.tr_emissions)
|
||||
eq_tr_em[g, p1.name, p2.name, m.name, t] = @constraint(
|
||||
eq_emission_tr[g, p1.name, p2.name, m.name, t] = @constraint(
|
||||
model,
|
||||
z_tr_em[g, p1.name, p2.name, m.name, t] ==
|
||||
z_em_tr[g, p1.name, p2.name, m.name, t] ==
|
||||
distances[p1, p2, m] * m.tr_emissions[g][t] * y[p1.name, p2.name, m.name, t]
|
||||
)
|
||||
end
|
||||
|
||||
# Plant emissions
|
||||
eq_emission_plant = _init(model, :eq_emission_plant)
|
||||
for p in plants, t in T, g in keys(p.emissions)
|
||||
eq_emission_plant[g, p.name, t] = @constraint(
|
||||
model,
|
||||
z_em_plant[g, p.name, t] == p.emissions[g][t] * z_process[p.name, t]
|
||||
)
|
||||
end
|
||||
|
||||
# Storage limit at plants
|
||||
eq_storage_limit = _init(model, :eq_storage_limit)
|
||||
for p in plants, m in keys(p.storage_limit), t in T
|
||||
if isfinite(p.storage_limit[m][t])
|
||||
eq_storage_limit[p.name, m.name, t] =
|
||||
@constraint(model, z_storage[p.name, m.name, t] <= p.storage_limit[m][t])
|
||||
end
|
||||
end
|
||||
|
||||
# All stored materials must be processed by end of time horizon
|
||||
eq_storage_final = _init(model, :eq_storage_final)
|
||||
for p in plants, m in keys(p.input_mix)
|
||||
eq_storage_final[p.name, m.name] =
|
||||
@constraint(model, z_storage[p.name, m.name, instance.time_horizon] == 0)
|
||||
end
|
||||
|
||||
# Global emissions limit
|
||||
eq_emission_limit = _init(model, :eq_emission_limit)
|
||||
for emission in instance.emissions, t in T
|
||||
isfinite(emission.limit[t]) || continue
|
||||
eq_emission_limit[emission.name, t] = @constraint(
|
||||
model,
|
||||
sum(
|
||||
z_em_plant[emission.name, p.name, t] for
|
||||
p in plants if emission.name in keys(p.emissions)
|
||||
) + sum(
|
||||
z_em_tr[emission.name, p1.name, p2.name, m.name, t] for
|
||||
(p1, p2, m) in E if emission.name in keys(m.tr_emissions)
|
||||
) <= emission.limit[t]
|
||||
)
|
||||
end
|
||||
|
||||
if variable_names
|
||||
_set_names!(model)
|
||||
end
|
||||
|
||||
@@ -14,7 +14,7 @@ function fix(x::Float64, v::Float64; force)
|
||||
return abs(x - v) < 1e-6 || error("Value mismatch: $x != $v")
|
||||
end
|
||||
|
||||
function set_name(x::Number, n::String)
|
||||
function set_name(::Number, ::String)
|
||||
# nop
|
||||
end
|
||||
|
||||
@@ -45,3 +45,76 @@ function _set_names!(dict::Dict)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
"""
|
||||
_add_pwl_constraints(model, xvar, yvars, xpts, ypts)
|
||||
|
||||
Add piecewise-linear constraints to a JuMP model for multiple y variables.
|
||||
|
||||
Creates constraints y_i = f_i(x) where each f_i is a piecewise-linear function
|
||||
defined by the breakpoints (xpts, ypts[:, i]).
|
||||
|
||||
# Arguments
|
||||
- `model`: JuMP model
|
||||
- `xvar`: The x variable (JuMP variable)
|
||||
- `yvars`: Vector of y variables (JuMP variables)
|
||||
- `xpts`: Vector of x values for breakpoints (must be in non-decreasing order)
|
||||
- `ypts`: Matrix of y values where ypts[i, j] is the y value for the j-th variable
|
||||
at the i-th breakpoint
|
||||
|
||||
# Example
|
||||
```julia
|
||||
@variable(model, y1)
|
||||
@variable(model, y2)
|
||||
ypts_matrix = [1.5 2.0; 0.0 1.5; 3.0 0.5] # 3 breakpoints, 2 y variables
|
||||
_add_pwl_constraints(model, x, [y1, y2], [0.0, 1.0, 2.0], ypts_matrix, name="multiPWL")
|
||||
```
|
||||
"""
|
||||
function _add_pwl_constraints(model, xvar, yvars, xpts, ypts)
|
||||
# Input validation
|
||||
ypts isa AbstractMatrix || throw(ArgumentError("ypts must be a matrix"))
|
||||
length(xpts) == size(ypts, 1) ||
|
||||
throw(ArgumentError("xpts length must match number of rows in ypts"))
|
||||
length(yvars) == size(ypts, 2) ||
|
||||
throw(ArgumentError("Number of y variables must match number of columns in ypts"))
|
||||
length(xpts) >= 1 || throw(ArgumentError("At least one breakpoint is required"))
|
||||
|
||||
# Check that xpts is increasing
|
||||
for i = 2:length(xpts)
|
||||
xpts[i] > xpts[i-1] || throw(ArgumentError("xpts must be in increasing order"))
|
||||
end
|
||||
|
||||
n_points = length(xpts)
|
||||
n_yvars = length(yvars)
|
||||
|
||||
if n_points == 1
|
||||
# Single point case: y_j = ypts[1,j], x = xpts[1]
|
||||
@constraint(model, xvar == xpts[1])
|
||||
for j = 1:n_yvars
|
||||
@constraint(model, yvars[j] == ypts[1, j])
|
||||
end
|
||||
|
||||
elseif n_points == 2
|
||||
# Two points case: single linear segment for each y variable
|
||||
x1, x2 = xpts[1], xpts[2]
|
||||
|
||||
# Linear relationship for each y variable: y_j = y1_j + slope_j * (x-x1)
|
||||
for j = 1:n_yvars
|
||||
y1, y2 = ypts[1, j], ypts[2, j]
|
||||
slope = (y2 - y1) / (x2 - x1)
|
||||
@constraint(model, yvars[j] == y1 + slope * (xvar - x1))
|
||||
end
|
||||
else
|
||||
# Multiple segments case (3+ points): use SOS2 formulation
|
||||
λ = @variable(model, [1:n_points], lower_bound = 0, upper_bound = 1)
|
||||
@constraint(model, λ in SOS2())
|
||||
@constraint(model, sum(λ) == 1)
|
||||
@constraint(model, xvar == sum(xpts[i] * λ[i] for i = 1:n_points))
|
||||
for j = 1:n_yvars
|
||||
@constraint(model, yvars[j] == sum(ypts[i, j] * λ[i] for i = 1:n_points))
|
||||
end
|
||||
end
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
@@ -15,9 +15,13 @@ function plants_report(model)::DataFrame
|
||||
df."year" = Int[]
|
||||
df."operational?" = Bool[]
|
||||
df."input amount (tonne)" = Float64[]
|
||||
df."stored amount (tonne)" = Float64[]
|
||||
df."processed amount (tonne)" = Float64[]
|
||||
df."opening cost (\$)" = Float64[]
|
||||
df."fixed operating cost (\$)" = Float64[]
|
||||
df."variable operating cost (\$)" = Float64[]
|
||||
df."expansion cost (\$)" = Float64[]
|
||||
df."storage cost (\$)" = Float64[]
|
||||
|
||||
plants = model.ext[:instance].plants
|
||||
T = 1:model.ext[:instance].time_horizon
|
||||
@@ -25,21 +29,36 @@ function plants_report(model)::DataFrame
|
||||
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])
|
||||
processed = value(model[:z_process][p.name, t])
|
||||
|
||||
# Opening cost
|
||||
# Calculate total stored amount across all input materials
|
||||
stored = sum(value(model[:z_storage][p.name, m.name, t]) for m in keys(p.input_mix))
|
||||
|
||||
# Calculate total storage cost
|
||||
storage_cost = sum(
|
||||
p.storage_cost[m][t] * value(model[:z_storage][p.name, m.name, t]) for
|
||||
m in keys(p.storage_cost)
|
||||
)
|
||||
|
||||
var_operating_cost = input * p.capacities[1].var_operating_cost[t]
|
||||
opening_cost = 0
|
||||
curr_capacity = 0
|
||||
expansion_cost = 0
|
||||
fix_operating_cost = 0
|
||||
|
||||
if value(model[:x][p.name, t]) > 0.5 && value(model[:x][p.name, t-1]) < 0.5
|
||||
opening_cost = p.capacities[1].opening_cost[t]
|
||||
end
|
||||
|
||||
# Plant size
|
||||
curr_capacity = 0
|
||||
if operational
|
||||
curr_capacity = p.capacities[1].size
|
||||
curr_expansion = JuMP.value(model[:z_exp][p.name, t])
|
||||
prev_expansion = JuMP.value(model[:z_exp][p.name, t-1])
|
||||
curr_capacity = p.capacities[1].size + curr_expansion
|
||||
expansion_cost = R_expand(p, t) * (curr_expansion - prev_expansion)
|
||||
fix_operating_cost =
|
||||
p.capacities[1].fix_operating_cost[t] + R_fix_exp(p, t) * curr_expansion
|
||||
end
|
||||
|
||||
fix_operating_cost = (operational ? p.capacities[1].fix_operating_cost[t] : 0)
|
||||
var_operating_cost = input * p.capacities[1].var_operating_cost[t]
|
||||
push!(
|
||||
df,
|
||||
Dict(
|
||||
@@ -51,9 +70,53 @@ function plants_report(model)::DataFrame
|
||||
"year" => t,
|
||||
"operational?" => operational,
|
||||
"input amount (tonne)" => _round(input),
|
||||
"stored amount (tonne)" => _round(stored),
|
||||
"processed amount (tonne)" => _round(processed),
|
||||
"opening cost (\$)" => _round(opening_cost),
|
||||
"fixed operating cost (\$)" => _round(fix_operating_cost),
|
||||
"variable operating cost (\$)" => _round(var_operating_cost),
|
||||
"expansion cost (\$)" => _round(expansion_cost),
|
||||
"storage cost (\$)" => _round(storage_cost),
|
||||
),
|
||||
)
|
||||
end
|
||||
return df
|
||||
end
|
||||
|
||||
function plant_inputs_report(model)::DataFrame
|
||||
df = DataFrame()
|
||||
df."plant" = String[]
|
||||
df."latitude" = Float64[]
|
||||
df."longitude" = Float64[]
|
||||
df."input product" = String[]
|
||||
df."year" = Int[]
|
||||
df."amount received (tonne)" = Float64[]
|
||||
df."current storage level (tonne)" = Float64[]
|
||||
df."storage limit (tonne)" = Float64[]
|
||||
df."storage cost (\$)" = Float64[]
|
||||
|
||||
plants = model.ext[:instance].plants
|
||||
T = 1:model.ext[:instance].time_horizon
|
||||
|
||||
for p in plants, m in keys(p.input_mix), t in T
|
||||
amount_received = sum(
|
||||
value(model[:y][src.name, p.name, m.name, t]) for
|
||||
(src, prod) in model.ext[:E_in][p] if prod == m
|
||||
)
|
||||
storage_level = value(model[:z_storage][p.name, m.name, t])
|
||||
storage_cost = p.storage_cost[m][t] * storage_level
|
||||
push!(
|
||||
df,
|
||||
Dict(
|
||||
"plant" => p.name,
|
||||
"latitude" => p.latitude,
|
||||
"longitude" => p.longitude,
|
||||
"input product" => m.name,
|
||||
"year" => t,
|
||||
"amount received (tonne)" => _round(amount_received),
|
||||
"current storage level (tonne)" => _round(storage_level),
|
||||
"storage limit (tonne)" => _round(p.storage_limit[m][t]),
|
||||
"storage cost (\$)" => _round(storage_cost),
|
||||
),
|
||||
)
|
||||
end
|
||||
@@ -97,6 +160,46 @@ function plant_outputs_report(model)::DataFrame
|
||||
return df
|
||||
end
|
||||
|
||||
function plant_emissions_report(model)::DataFrame
|
||||
df = DataFrame()
|
||||
df."plant" = String[]
|
||||
df."latitude" = Float64[]
|
||||
df."longitude" = Float64[]
|
||||
df."emission" = String[]
|
||||
df."year" = Int[]
|
||||
df."processed amount (tonne)" = Float64[]
|
||||
df."emission factor (tonne/tonne)" = Float64[]
|
||||
df."emissions amount (tonne)" = Float64[]
|
||||
|
||||
plants = model.ext[:instance].plants
|
||||
T = 1:model.ext[:instance].time_horizon
|
||||
|
||||
for p in plants, t in T, g in keys(p.emissions)
|
||||
processed_amount = JuMP.value(model[:z_process][p.name, t])
|
||||
processed_amount > 1e-3 || continue
|
||||
emissions = JuMP.value(model[:z_em_plant][g, p.name, t])
|
||||
emission_factor = p.emissions[g][t]
|
||||
push!(
|
||||
df,
|
||||
Dict(
|
||||
"plant" => p.name,
|
||||
"latitude" => p.latitude,
|
||||
"longitude" => p.longitude,
|
||||
"emission" => g,
|
||||
"year" => t,
|
||||
"processed amount (tonne)" => _round(processed_amount),
|
||||
"emission factor (tonne/tonne)" => _round(emission_factor),
|
||||
"emissions amount (tonne)" => _round(emissions),
|
||||
),
|
||||
)
|
||||
end
|
||||
return df
|
||||
end
|
||||
|
||||
write_plants_report(solution, filename) = CSV.write(filename, plants_report(solution))
|
||||
write_plant_inputs_report(solution, filename) =
|
||||
CSV.write(filename, plant_inputs_report(solution))
|
||||
write_plant_outputs_report(solution, filename) =
|
||||
CSV.write(filename, plant_outputs_report(solution))
|
||||
write_plant_emissions_report(solution, filename) =
|
||||
CSV.write(filename, plant_emissions_report(solution))
|
||||
|
||||
@@ -73,7 +73,7 @@ function transportation_emissions_report(model)::DataFrame
|
||||
amount > 1e-3 || continue
|
||||
distance = distances[p1, p2, m]
|
||||
emission_factor = m.tr_emissions[g][t]
|
||||
emissions = value(model[:z_tr_em][g, p1.name, p2.name, m.name, t])
|
||||
emissions = value(model[:z_em_tr][g, p1.name, p2.name, m.name, t])
|
||||
push!(
|
||||
df,
|
||||
Dict(
|
||||
|
||||
2
test/fixtures/boat_example.jl
vendored
2
test/fixtures/boat_example.jl
vendored
@@ -173,7 +173,9 @@ function run_boat_example()
|
||||
mkpath(fixture("boat_example"))
|
||||
write_to_file(model, fixture("boat_example/model.lp"))
|
||||
RELOG.write_plants_report(model, fixture("boat_example/plants.csv"))
|
||||
RELOG.write_plant_inputs_report(model, fixture("boat_example/plant_inputs.csv"))
|
||||
RELOG.write_plant_outputs_report(model, fixture("boat_example/plant_outputs.csv"))
|
||||
RELOG.write_plant_emissions_report(model, fixture("boat_example/plant_emissions.csv"))
|
||||
RELOG.write_centers_report(model, fixture("boat_example/centers.csv"))
|
||||
RELOG.write_center_outputs_report(model, fixture("boat_example/center_outputs.csv"))
|
||||
RELOG.write_transportation_report(model, fixture("boat_example/transportation.csv"))
|
||||
|
||||
14
test/fixtures/boat_example/center_outputs.csv
vendored
14
test/fixtures/boat_example/center_outputs.csv
vendored
@@ -10,10 +10,10 @@ NailFactory (Phoenix),33.448376,-112.074036,Nail,3,1.0,0.0,Inf,1000.0,0.0
|
||||
NailFactory (Phoenix),33.448376,-112.074036,Nail,4,1.0,0.0,Inf,1000.0,0.0
|
||||
NailFactory (Phoenix),33.448376,-112.074036,Nail,5,1.0,0.0,Inf,1000.0,0.0
|
||||
NailFactory (Dallas),32.776664,-96.796988,Nail,1,1.0,0.0,Inf,1000.0,0.0
|
||||
NailFactory (Dallas),32.776664,-96.796988,Nail,2,1.0,-0.0,Inf,1000.0,-0.0
|
||||
NailFactory (Dallas),32.776664,-96.796988,Nail,2,1.0,0.0,Inf,1000.0,0.0
|
||||
NailFactory (Dallas),32.776664,-96.796988,Nail,3,1.0,0.0,Inf,1000.0,0.0
|
||||
NailFactory (Dallas),32.776664,-96.796988,Nail,4,1.0,-0.0,Inf,1000.0,-0.0
|
||||
NailFactory (Dallas),32.776664,-96.796988,Nail,5,1.0,-0.0,Inf,1000.0,-0.0
|
||||
NailFactory (Dallas),32.776664,-96.796988,Nail,4,1.0,0.0,Inf,1000.0,0.0
|
||||
NailFactory (Dallas),32.776664,-96.796988,Nail,5,1.0,0.0,Inf,1000.0,0.0
|
||||
Forest (Chicago),41.881832,-87.623177,Wood,1,100.0,100.0,Inf,0.0,0.0
|
||||
Forest (Chicago),41.881832,-87.623177,Wood,2,100.0,100.0,Inf,0.0,0.0
|
||||
Forest (Chicago),41.881832,-87.623177,Wood,3,100.0,100.0,Inf,0.0,0.0
|
||||
@@ -43,17 +43,17 @@ Retail (Los Angeles),34.052235,-118.243683,UsedBoat,1,0.0,0.0,0.0,0.0,0.0
|
||||
Retail (Los Angeles),34.052235,-118.243683,UsedBoat,2,0.0,0.0,0.0,0.0,0.0
|
||||
Retail (Los Angeles),34.052235,-118.243683,UsedBoat,3,0.0,0.0,0.0,0.0,0.0
|
||||
Retail (Los Angeles),34.052235,-118.243683,UsedBoat,4,0.0,0.0,0.0,0.0,0.0
|
||||
Retail (Los Angeles),34.052235,-118.243683,UsedBoat,5,-0.0,0.0,0.0,-0.0,0.0
|
||||
Retail (Los Angeles),34.052235,-118.243683,UsedBoat,5,0.0,0.0,0.0,0.0,0.0
|
||||
Retail (Houston),29.760427,-95.369804,UsedBoat,1,0.0,0.0,0.0,0.0,0.0
|
||||
Retail (Houston),29.760427,-95.369804,UsedBoat,2,0.0,0.0,0.0,0.0,0.0
|
||||
Retail (Houston),29.760427,-95.369804,UsedBoat,3,0.0,0.0,0.0,0.0,0.0
|
||||
Retail (Houston),29.760427,-95.369804,UsedBoat,4,0.0,0.0,0.0,0.0,0.0
|
||||
Retail (Houston),29.760427,-95.369804,UsedBoat,5,-0.0,0.0,0.0,-0.0,0.0
|
||||
Retail (Houston),29.760427,-95.369804,UsedBoat,5,0.0,0.0,0.0,0.0,0.0
|
||||
Retail (Phoenix),33.448376,-112.074036,UsedBoat,1,0.0,0.0,0.0,0.0,0.0
|
||||
Retail (Phoenix),33.448376,-112.074036,UsedBoat,2,0.0,0.0,0.0,0.0,0.0
|
||||
Retail (Phoenix),33.448376,-112.074036,UsedBoat,3,0.0,0.0,0.0,0.0,0.0
|
||||
Retail (Phoenix),33.448376,-112.074036,UsedBoat,4,-0.0,0.0,0.0,-0.0,0.0
|
||||
Retail (Phoenix),33.448376,-112.074036,UsedBoat,5,-0.0,0.0,0.0,-0.0,0.0
|
||||
Retail (Phoenix),33.448376,-112.074036,UsedBoat,4,0.0,0.0,0.0,0.0,0.0
|
||||
Retail (Phoenix),33.448376,-112.074036,UsedBoat,5,0.0,0.0,0.0,0.0,0.0
|
||||
Retail (Philadelphia),39.952583,-75.165222,UsedBoat,1,0.0,0.0,0.0,0.0,0.0
|
||||
Retail (Philadelphia),39.952583,-75.165222,UsedBoat,2,0.0,0.0,0.0,0.0,0.0
|
||||
Retail (Philadelphia),39.952583,-75.165222,UsedBoat,3,0.0,0.0,0.0,0.0,0.0
|
||||
|
||||
|
6
test/fixtures/boat_example/centers.csv
vendored
6
test/fixtures/boat_example/centers.csv
vendored
@@ -43,16 +43,16 @@ Retail (Los Angeles),34.052235,-118.243683,1,NewBoat,0.0,0.0,125000.0
|
||||
Retail (Los Angeles),34.052235,-118.243683,2,NewBoat,0.0,0.0,125000.0
|
||||
Retail (Los Angeles),34.052235,-118.243683,3,NewBoat,0.0,0.0,125000.0
|
||||
Retail (Los Angeles),34.052235,-118.243683,4,NewBoat,0.0,0.0,125000.0
|
||||
Retail (Los Angeles),34.052235,-118.243683,5,NewBoat,-0.0,0.0,125000.0
|
||||
Retail (Los Angeles),34.052235,-118.243683,5,NewBoat,0.0,0.0,125000.0
|
||||
Retail (Houston),29.760427,-95.369804,1,NewBoat,0.0,0.0,125000.0
|
||||
Retail (Houston),29.760427,-95.369804,2,NewBoat,0.0,0.0,125000.0
|
||||
Retail (Houston),29.760427,-95.369804,3,NewBoat,0.0,0.0,125000.0
|
||||
Retail (Houston),29.760427,-95.369804,4,NewBoat,0.0,0.0,125000.0
|
||||
Retail (Houston),29.760427,-95.369804,5,NewBoat,-0.0,0.0,125000.0
|
||||
Retail (Houston),29.760427,-95.369804,5,NewBoat,0.0,0.0,125000.0
|
||||
Retail (Phoenix),33.448376,-112.074036,1,NewBoat,0.0,0.0,125000.0
|
||||
Retail (Phoenix),33.448376,-112.074036,2,NewBoat,0.0,0.0,125000.0
|
||||
Retail (Phoenix),33.448376,-112.074036,3,NewBoat,0.0,0.0,125000.0
|
||||
Retail (Phoenix),33.448376,-112.074036,4,NewBoat,-0.0,-0.0,125000.0
|
||||
Retail (Phoenix),33.448376,-112.074036,4,NewBoat,0.0,0.0,125000.0
|
||||
Retail (Phoenix),33.448376,-112.074036,5,NewBoat,0.0,0.0,125000.0
|
||||
Retail (Philadelphia),39.952583,-75.165222,1,NewBoat,0.0,0.0,125000.0
|
||||
Retail (Philadelphia),39.952583,-75.165222,2,NewBoat,0.0,0.0,125000.0
|
||||
|
||||
|
11
test/fixtures/boat_example/plant_emissions.csv
vendored
Normal file
11
test/fixtures/boat_example/plant_emissions.csv
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
plant,latitude,longitude,emission,year,processed amount (tonne),emission factor (tonne/tonne),emissions amount (tonne)
|
||||
BoatFactory (Dallas),32.776664,-96.796988,CO2,1,63.15789,5.0,315.78947
|
||||
BoatFactory (Dallas),32.776664,-96.796988,CO2,2,71.46814,5.0,357.34072
|
||||
BoatFactory (Dallas),32.776664,-96.796988,CO2,3,75.8857,5.0,379.42849
|
||||
BoatFactory (Dallas),32.776664,-96.796988,CO2,4,76.90434,5.0,384.52168
|
||||
BoatFactory (Dallas),32.776664,-96.796988,CO2,5,77.27087,5.0,386.35435
|
||||
RecyclingPlant (Dallas),32.776664,-96.796988,CO2,1,6.31579,5.0,31.57895
|
||||
RecyclingPlant (Dallas),32.776664,-96.796988,CO2,2,22.93629,5.0,114.68144
|
||||
RecyclingPlant (Dallas),32.776664,-96.796988,CO2,3,31.7714,5.0,158.85698
|
||||
RecyclingPlant (Dallas),32.776664,-96.796988,CO2,4,33.80867,5.0,169.04336
|
||||
RecyclingPlant (Dallas),32.776664,-96.796988,CO2,5,34.54174,5.0,172.7087
|
||||
|
151
test/fixtures/boat_example/plant_inputs.csv
vendored
Normal file
151
test/fixtures/boat_example/plant_inputs.csv
vendored
Normal file
@@ -0,0 +1,151 @@
|
||||
plant,latitude,longitude,input product,year,amount received (tonne),current storage level (tonne),storage limit (tonne),storage cost ($)
|
||||
BoatFactory (Chicago),41.881832,-87.623177,Wood,1,0.0,0.0,5.0,0.0
|
||||
BoatFactory (Chicago),41.881832,-87.623177,Wood,2,0.0,0.0,5.0,0.0
|
||||
BoatFactory (Chicago),41.881832,-87.623177,Wood,3,0.0,0.0,5.0,0.0
|
||||
BoatFactory (Chicago),41.881832,-87.623177,Wood,4,0.0,0.0,5.0,0.0
|
||||
BoatFactory (Chicago),41.881832,-87.623177,Wood,5,0.0,0.0,5.0,0.0
|
||||
BoatFactory (Chicago),41.881832,-87.623177,Nail,1,0.0,0.0,1.0,0.0
|
||||
BoatFactory (Chicago),41.881832,-87.623177,Nail,2,0.0,0.0,1.0,0.0
|
||||
BoatFactory (Chicago),41.881832,-87.623177,Nail,3,0.0,0.0,1.0,0.0
|
||||
BoatFactory (Chicago),41.881832,-87.623177,Nail,4,0.0,0.0,1.0,0.0
|
||||
BoatFactory (Chicago),41.881832,-87.623177,Nail,5,0.0,0.0,1.0,0.0
|
||||
BoatFactory (New York City),40.712776,-74.005974,Wood,1,0.0,0.0,5.0,0.0
|
||||
BoatFactory (New York City),40.712776,-74.005974,Wood,2,0.0,0.0,5.0,0.0
|
||||
BoatFactory (New York City),40.712776,-74.005974,Wood,3,0.0,0.0,5.0,0.0
|
||||
BoatFactory (New York City),40.712776,-74.005974,Wood,4,0.0,0.0,5.0,0.0
|
||||
BoatFactory (New York City),40.712776,-74.005974,Wood,5,0.0,0.0,5.0,0.0
|
||||
BoatFactory (New York City),40.712776,-74.005974,Nail,1,0.0,0.0,1.0,0.0
|
||||
BoatFactory (New York City),40.712776,-74.005974,Nail,2,0.0,0.0,1.0,0.0
|
||||
BoatFactory (New York City),40.712776,-74.005974,Nail,3,0.0,0.0,1.0,0.0
|
||||
BoatFactory (New York City),40.712776,-74.005974,Nail,4,0.0,0.0,1.0,0.0
|
||||
BoatFactory (New York City),40.712776,-74.005974,Nail,5,0.0,0.0,1.0,0.0
|
||||
BoatFactory (Los Angeles),34.052235,-118.243683,Wood,1,0.0,0.0,5.0,0.0
|
||||
BoatFactory (Los Angeles),34.052235,-118.243683,Wood,2,0.0,0.0,5.0,0.0
|
||||
BoatFactory (Los Angeles),34.052235,-118.243683,Wood,3,0.0,0.0,5.0,0.0
|
||||
BoatFactory (Los Angeles),34.052235,-118.243683,Wood,4,0.0,0.0,5.0,0.0
|
||||
BoatFactory (Los Angeles),34.052235,-118.243683,Wood,5,0.0,0.0,5.0,0.0
|
||||
BoatFactory (Los Angeles),34.052235,-118.243683,Nail,1,0.0,0.0,1.0,0.0
|
||||
BoatFactory (Los Angeles),34.052235,-118.243683,Nail,2,0.0,0.0,1.0,0.0
|
||||
BoatFactory (Los Angeles),34.052235,-118.243683,Nail,3,0.0,0.0,1.0,0.0
|
||||
BoatFactory (Los Angeles),34.052235,-118.243683,Nail,4,0.0,0.0,1.0,0.0
|
||||
BoatFactory (Los Angeles),34.052235,-118.243683,Nail,5,0.0,0.0,1.0,0.0
|
||||
BoatFactory (Houston),29.760427,-95.369804,Wood,1,0.0,0.0,5.0,0.0
|
||||
BoatFactory (Houston),29.760427,-95.369804,Wood,2,0.0,0.0,5.0,0.0
|
||||
BoatFactory (Houston),29.760427,-95.369804,Wood,3,0.0,0.0,5.0,0.0
|
||||
BoatFactory (Houston),29.760427,-95.369804,Wood,4,0.0,0.0,5.0,0.0
|
||||
BoatFactory (Houston),29.760427,-95.369804,Wood,5,0.0,0.0,5.0,0.0
|
||||
BoatFactory (Houston),29.760427,-95.369804,Nail,1,0.0,0.0,1.0,0.0
|
||||
BoatFactory (Houston),29.760427,-95.369804,Nail,2,0.0,0.0,1.0,0.0
|
||||
BoatFactory (Houston),29.760427,-95.369804,Nail,3,0.0,0.0,1.0,0.0
|
||||
BoatFactory (Houston),29.760427,-95.369804,Nail,4,0.0,0.0,1.0,0.0
|
||||
BoatFactory (Houston),29.760427,-95.369804,Nail,5,0.0,0.0,1.0,0.0
|
||||
BoatFactory (Phoenix),33.448376,-112.074036,Wood,1,0.0,0.0,5.0,0.0
|
||||
BoatFactory (Phoenix),33.448376,-112.074036,Wood,2,0.0,0.0,5.0,0.0
|
||||
BoatFactory (Phoenix),33.448376,-112.074036,Wood,3,0.0,0.0,5.0,0.0
|
||||
BoatFactory (Phoenix),33.448376,-112.074036,Wood,4,0.0,0.0,5.0,0.0
|
||||
BoatFactory (Phoenix),33.448376,-112.074036,Wood,5,0.0,0.0,5.0,0.0
|
||||
BoatFactory (Phoenix),33.448376,-112.074036,Nail,1,0.0,0.0,1.0,0.0
|
||||
BoatFactory (Phoenix),33.448376,-112.074036,Nail,2,0.0,0.0,1.0,0.0
|
||||
BoatFactory (Phoenix),33.448376,-112.074036,Nail,3,0.0,0.0,1.0,0.0
|
||||
BoatFactory (Phoenix),33.448376,-112.074036,Nail,4,0.0,0.0,1.0,0.0
|
||||
BoatFactory (Phoenix),33.448376,-112.074036,Nail,5,0.0,0.0,1.0,0.0
|
||||
BoatFactory (Philadelphia),39.952583,-75.165222,Wood,1,0.0,0.0,5.0,0.0
|
||||
BoatFactory (Philadelphia),39.952583,-75.165222,Wood,2,0.0,0.0,5.0,0.0
|
||||
BoatFactory (Philadelphia),39.952583,-75.165222,Wood,3,0.0,0.0,5.0,0.0
|
||||
BoatFactory (Philadelphia),39.952583,-75.165222,Wood,4,0.0,0.0,5.0,0.0
|
||||
BoatFactory (Philadelphia),39.952583,-75.165222,Wood,5,0.0,0.0,5.0,0.0
|
||||
BoatFactory (Philadelphia),39.952583,-75.165222,Nail,1,0.0,0.0,1.0,0.0
|
||||
BoatFactory (Philadelphia),39.952583,-75.165222,Nail,2,0.0,0.0,1.0,0.0
|
||||
BoatFactory (Philadelphia),39.952583,-75.165222,Nail,3,0.0,0.0,1.0,0.0
|
||||
BoatFactory (Philadelphia),39.952583,-75.165222,Nail,4,0.0,0.0,1.0,0.0
|
||||
BoatFactory (Philadelphia),39.952583,-75.165222,Nail,5,0.0,0.0,1.0,0.0
|
||||
BoatFactory (San Antonio),29.424122,-98.493629,Wood,1,0.0,0.0,5.0,0.0
|
||||
BoatFactory (San Antonio),29.424122,-98.493629,Wood,2,0.0,0.0,5.0,0.0
|
||||
BoatFactory (San Antonio),29.424122,-98.493629,Wood,3,0.0,0.0,5.0,0.0
|
||||
BoatFactory (San Antonio),29.424122,-98.493629,Wood,4,0.0,0.0,5.0,0.0
|
||||
BoatFactory (San Antonio),29.424122,-98.493629,Wood,5,0.0,0.0,5.0,0.0
|
||||
BoatFactory (San Antonio),29.424122,-98.493629,Nail,1,0.0,0.0,1.0,0.0
|
||||
BoatFactory (San Antonio),29.424122,-98.493629,Nail,2,0.0,0.0,1.0,0.0
|
||||
BoatFactory (San Antonio),29.424122,-98.493629,Nail,3,0.0,0.0,1.0,0.0
|
||||
BoatFactory (San Antonio),29.424122,-98.493629,Nail,4,0.0,0.0,1.0,0.0
|
||||
BoatFactory (San Antonio),29.424122,-98.493629,Nail,5,0.0,0.0,1.0,0.0
|
||||
BoatFactory (San Diego),32.715736,-117.161087,Wood,1,0.0,0.0,5.0,0.0
|
||||
BoatFactory (San Diego),32.715736,-117.161087,Wood,2,0.0,0.0,5.0,0.0
|
||||
BoatFactory (San Diego),32.715736,-117.161087,Wood,3,0.0,0.0,5.0,0.0
|
||||
BoatFactory (San Diego),32.715736,-117.161087,Wood,4,0.0,0.0,5.0,0.0
|
||||
BoatFactory (San Diego),32.715736,-117.161087,Wood,5,0.0,0.0,5.0,0.0
|
||||
BoatFactory (San Diego),32.715736,-117.161087,Nail,1,0.0,0.0,1.0,0.0
|
||||
BoatFactory (San Diego),32.715736,-117.161087,Nail,2,0.0,0.0,1.0,0.0
|
||||
BoatFactory (San Diego),32.715736,-117.161087,Nail,3,0.0,0.0,1.0,0.0
|
||||
BoatFactory (San Diego),32.715736,-117.161087,Nail,4,0.0,0.0,1.0,0.0
|
||||
BoatFactory (San Diego),32.715736,-117.161087,Nail,5,0.0,0.0,1.0,0.0
|
||||
BoatFactory (Dallas),32.776664,-96.796988,Wood,1,60.0,0.0,5.0,0.0
|
||||
BoatFactory (Dallas),32.776664,-96.796988,Wood,2,67.89474,0.0,5.0,0.0
|
||||
BoatFactory (Dallas),32.776664,-96.796988,Wood,3,72.09141,0.0,5.0,0.0
|
||||
BoatFactory (Dallas),32.776664,-96.796988,Wood,4,73.05912,0.0,5.0,0.0
|
||||
BoatFactory (Dallas),32.776664,-96.796988,Wood,5,73.40733,0.0,5.0,0.0
|
||||
BoatFactory (Dallas),32.776664,-96.796988,Nail,1,3.15789,0.0,1.0,0.0
|
||||
BoatFactory (Dallas),32.776664,-96.796988,Nail,2,3.57341,0.0,1.0,0.0
|
||||
BoatFactory (Dallas),32.776664,-96.796988,Nail,3,3.79428,0.0,1.0,0.0
|
||||
BoatFactory (Dallas),32.776664,-96.796988,Nail,4,3.84522,0.0,1.0,0.0
|
||||
BoatFactory (Dallas),32.776664,-96.796988,Nail,5,3.86354,0.0,1.0,0.0
|
||||
BoatFactory (San Jose),37.338208,-121.886329,Wood,1,0.0,0.0,5.0,0.0
|
||||
BoatFactory (San Jose),37.338208,-121.886329,Wood,2,0.0,0.0,5.0,0.0
|
||||
BoatFactory (San Jose),37.338208,-121.886329,Wood,3,0.0,0.0,5.0,0.0
|
||||
BoatFactory (San Jose),37.338208,-121.886329,Wood,4,0.0,0.0,5.0,0.0
|
||||
BoatFactory (San Jose),37.338208,-121.886329,Wood,5,0.0,0.0,5.0,0.0
|
||||
BoatFactory (San Jose),37.338208,-121.886329,Nail,1,0.0,0.0,1.0,0.0
|
||||
BoatFactory (San Jose),37.338208,-121.886329,Nail,2,0.0,0.0,1.0,0.0
|
||||
BoatFactory (San Jose),37.338208,-121.886329,Nail,3,0.0,0.0,1.0,0.0
|
||||
BoatFactory (San Jose),37.338208,-121.886329,Nail,4,0.0,0.0,1.0,0.0
|
||||
BoatFactory (San Jose),37.338208,-121.886329,Nail,5,0.0,0.0,1.0,0.0
|
||||
RecyclingPlant (Chicago),41.881832,-87.623177,UsedBoat,1,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (Chicago),41.881832,-87.623177,UsedBoat,2,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (Chicago),41.881832,-87.623177,UsedBoat,3,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (Chicago),41.881832,-87.623177,UsedBoat,4,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (Chicago),41.881832,-87.623177,UsedBoat,5,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (New York City),40.712776,-74.005974,UsedBoat,1,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (New York City),40.712776,-74.005974,UsedBoat,2,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (New York City),40.712776,-74.005974,UsedBoat,3,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (New York City),40.712776,-74.005974,UsedBoat,4,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (New York City),40.712776,-74.005974,UsedBoat,5,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (Los Angeles),34.052235,-118.243683,UsedBoat,1,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (Los Angeles),34.052235,-118.243683,UsedBoat,2,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (Los Angeles),34.052235,-118.243683,UsedBoat,3,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (Los Angeles),34.052235,-118.243683,UsedBoat,4,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (Los Angeles),34.052235,-118.243683,UsedBoat,5,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (Houston),29.760427,-95.369804,UsedBoat,1,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (Houston),29.760427,-95.369804,UsedBoat,2,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (Houston),29.760427,-95.369804,UsedBoat,3,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (Houston),29.760427,-95.369804,UsedBoat,4,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (Houston),29.760427,-95.369804,UsedBoat,5,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (Phoenix),33.448376,-112.074036,UsedBoat,1,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (Phoenix),33.448376,-112.074036,UsedBoat,2,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (Phoenix),33.448376,-112.074036,UsedBoat,3,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (Phoenix),33.448376,-112.074036,UsedBoat,4,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (Phoenix),33.448376,-112.074036,UsedBoat,5,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (Philadelphia),39.952583,-75.165222,UsedBoat,1,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (Philadelphia),39.952583,-75.165222,UsedBoat,2,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (Philadelphia),39.952583,-75.165222,UsedBoat,3,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (Philadelphia),39.952583,-75.165222,UsedBoat,4,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (Philadelphia),39.952583,-75.165222,UsedBoat,5,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (San Antonio),29.424122,-98.493629,UsedBoat,1,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (San Antonio),29.424122,-98.493629,UsedBoat,2,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (San Antonio),29.424122,-98.493629,UsedBoat,3,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (San Antonio),29.424122,-98.493629,UsedBoat,4,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (San Antonio),29.424122,-98.493629,UsedBoat,5,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (San Diego),32.715736,-117.161087,UsedBoat,1,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (San Diego),32.715736,-117.161087,UsedBoat,2,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (San Diego),32.715736,-117.161087,UsedBoat,3,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (San Diego),32.715736,-117.161087,UsedBoat,4,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (San Diego),32.715736,-117.161087,UsedBoat,5,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (Dallas),32.776664,-96.796988,UsedBoat,1,6.31579,0.0,0.0,0.0
|
||||
RecyclingPlant (Dallas),32.776664,-96.796988,UsedBoat,2,22.93629,0.0,0.0,0.0
|
||||
RecyclingPlant (Dallas),32.776664,-96.796988,UsedBoat,3,31.7714,0.0,0.0,0.0
|
||||
RecyclingPlant (Dallas),32.776664,-96.796988,UsedBoat,4,33.80867,0.0,0.0,0.0
|
||||
RecyclingPlant (Dallas),32.776664,-96.796988,UsedBoat,5,34.54174,0.0,0.0,0.0
|
||||
RecyclingPlant (San Jose),37.338208,-121.886329,UsedBoat,1,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (San Jose),37.338208,-121.886329,UsedBoat,2,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (San Jose),37.338208,-121.886329,UsedBoat,3,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (San Jose),37.338208,-121.886329,UsedBoat,4,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (San Jose),37.338208,-121.886329,UsedBoat,5,0.0,0.0,0.0,0.0
|
||||
|
4
test/fixtures/boat_example/plant_outputs.csv
vendored
4
test/fixtures/boat_example/plant_outputs.csv
vendored
@@ -50,12 +50,12 @@ BoatFactory (San Jose),37.338208,-121.886329,NewBoat,3,0.0,0.0,0.0,0.0
|
||||
BoatFactory (San Jose),37.338208,-121.886329,NewBoat,4,0.0,0.0,0.0,0.0
|
||||
BoatFactory (San Jose),37.338208,-121.886329,NewBoat,5,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (Chicago),41.881832,-87.623177,Nail,1,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (Chicago),41.881832,-87.623177,Nail,2,-0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (Chicago),41.881832,-87.623177,Nail,2,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (Chicago),41.881832,-87.623177,Nail,3,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (Chicago),41.881832,-87.623177,Nail,4,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (Chicago),41.881832,-87.623177,Nail,5,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (Chicago),41.881832,-87.623177,Wood,1,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (Chicago),41.881832,-87.623177,Wood,2,-0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (Chicago),41.881832,-87.623177,Wood,2,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (Chicago),41.881832,-87.623177,Wood,3,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (Chicago),41.881832,-87.623177,Wood,4,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (Chicago),41.881832,-87.623177,Wood,5,0.0,0.0,0.0,0.0
|
||||
|
||||
|
202
test/fixtures/boat_example/plants.csv
vendored
202
test/fixtures/boat_example/plants.csv
vendored
@@ -1,101 +1,101 @@
|
||||
plant,latitude,longitude,initial capacity,current capacity,year,operational?,input amount (tonne),opening cost ($),fixed operating cost ($),variable operating cost ($)
|
||||
BoatFactory (Chicago),41.881832,-87.623177,0.0,0.0,1,false,0.0,0.0,0.0,0.0
|
||||
BoatFactory (Chicago),41.881832,-87.623177,0.0,0.0,2,false,0.0,0.0,0.0,0.0
|
||||
BoatFactory (Chicago),41.881832,-87.623177,0.0,0.0,3,false,0.0,0.0,0.0,0.0
|
||||
BoatFactory (Chicago),41.881832,-87.623177,0.0,0.0,4,false,0.0,0.0,0.0,0.0
|
||||
BoatFactory (Chicago),41.881832,-87.623177,0.0,0.0,5,false,0.0,0.0,0.0,0.0
|
||||
BoatFactory (New York City),40.712776,-74.005974,0.0,0.0,1,false,0.0,0.0,0.0,0.0
|
||||
BoatFactory (New York City),40.712776,-74.005974,0.0,0.0,2,false,0.0,0.0,0.0,0.0
|
||||
BoatFactory (New York City),40.712776,-74.005974,0.0,0.0,3,false,0.0,0.0,0.0,0.0
|
||||
BoatFactory (New York City),40.712776,-74.005974,0.0,0.0,4,false,0.0,0.0,0.0,0.0
|
||||
BoatFactory (New York City),40.712776,-74.005974,0.0,0.0,5,false,0.0,0.0,0.0,0.0
|
||||
BoatFactory (Los Angeles),34.052235,-118.243683,0.0,0.0,1,false,0.0,0.0,0.0,0.0
|
||||
BoatFactory (Los Angeles),34.052235,-118.243683,0.0,0.0,2,false,0.0,0.0,0.0,0.0
|
||||
BoatFactory (Los Angeles),34.052235,-118.243683,0.0,0.0,3,false,0.0,0.0,0.0,0.0
|
||||
BoatFactory (Los Angeles),34.052235,-118.243683,0.0,0.0,4,false,0.0,0.0,0.0,0.0
|
||||
BoatFactory (Los Angeles),34.052235,-118.243683,0.0,0.0,5,false,0.0,0.0,0.0,0.0
|
||||
BoatFactory (Houston),29.760427,-95.369804,0.0,0.0,1,false,0.0,0.0,0.0,0.0
|
||||
BoatFactory (Houston),29.760427,-95.369804,0.0,0.0,2,false,0.0,0.0,0.0,0.0
|
||||
BoatFactory (Houston),29.760427,-95.369804,0.0,0.0,3,false,0.0,0.0,0.0,0.0
|
||||
BoatFactory (Houston),29.760427,-95.369804,0.0,0.0,4,false,0.0,0.0,0.0,0.0
|
||||
BoatFactory (Houston),29.760427,-95.369804,0.0,0.0,5,false,0.0,0.0,0.0,0.0
|
||||
BoatFactory (Phoenix),33.448376,-112.074036,0.0,0.0,1,false,0.0,0.0,0.0,0.0
|
||||
BoatFactory (Phoenix),33.448376,-112.074036,0.0,0.0,2,false,0.0,0.0,0.0,0.0
|
||||
BoatFactory (Phoenix),33.448376,-112.074036,0.0,0.0,3,false,0.0,0.0,0.0,0.0
|
||||
BoatFactory (Phoenix),33.448376,-112.074036,0.0,0.0,4,false,0.0,0.0,0.0,0.0
|
||||
BoatFactory (Phoenix),33.448376,-112.074036,0.0,0.0,5,false,0.0,0.0,0.0,0.0
|
||||
BoatFactory (Philadelphia),39.952583,-75.165222,0.0,0.0,1,false,0.0,0.0,0.0,0.0
|
||||
BoatFactory (Philadelphia),39.952583,-75.165222,0.0,0.0,2,false,0.0,0.0,0.0,0.0
|
||||
BoatFactory (Philadelphia),39.952583,-75.165222,0.0,0.0,3,false,0.0,0.0,0.0,0.0
|
||||
BoatFactory (Philadelphia),39.952583,-75.165222,0.0,0.0,4,false,0.0,0.0,0.0,0.0
|
||||
BoatFactory (Philadelphia),39.952583,-75.165222,0.0,0.0,5,false,0.0,0.0,0.0,0.0
|
||||
BoatFactory (San Antonio),29.424122,-98.493629,0.0,0.0,1,false,0.0,0.0,0.0,0.0
|
||||
BoatFactory (San Antonio),29.424122,-98.493629,0.0,0.0,2,false,0.0,0.0,0.0,0.0
|
||||
BoatFactory (San Antonio),29.424122,-98.493629,0.0,0.0,3,false,0.0,0.0,0.0,0.0
|
||||
BoatFactory (San Antonio),29.424122,-98.493629,0.0,0.0,4,false,0.0,0.0,0.0,0.0
|
||||
BoatFactory (San Antonio),29.424122,-98.493629,0.0,0.0,5,false,0.0,0.0,0.0,0.0
|
||||
BoatFactory (San Diego),32.715736,-117.161087,0.0,0.0,1,false,0.0,0.0,0.0,0.0
|
||||
BoatFactory (San Diego),32.715736,-117.161087,0.0,0.0,2,false,0.0,0.0,0.0,0.0
|
||||
BoatFactory (San Diego),32.715736,-117.161087,0.0,0.0,3,false,0.0,0.0,0.0,0.0
|
||||
BoatFactory (San Diego),32.715736,-117.161087,0.0,0.0,4,false,0.0,0.0,0.0,0.0
|
||||
BoatFactory (San Diego),32.715736,-117.161087,0.0,0.0,5,false,0.0,0.0,0.0,0.0
|
||||
BoatFactory (Dallas),32.776664,-96.796988,0.0,500.0,1,true,63.15789,100000.0,250000.0,315.78947
|
||||
BoatFactory (Dallas),32.776664,-96.796988,0.0,500.0,2,true,71.46814,0.0,250000.0,357.34072
|
||||
BoatFactory (Dallas),32.776664,-96.796988,0.0,500.0,3,true,75.8857,0.0,250000.0,379.42849
|
||||
BoatFactory (Dallas),32.776664,-96.796988,0.0,500.0,4,true,76.90434,0.0,250000.0,384.52168
|
||||
BoatFactory (Dallas),32.776664,-96.796988,0.0,500.0,5,true,77.27087,0.0,250000.0,386.35435
|
||||
BoatFactory (San Jose),37.338208,-121.886329,0.0,0.0,1,false,0.0,0.0,0.0,0.0
|
||||
BoatFactory (San Jose),37.338208,-121.886329,0.0,0.0,2,false,0.0,0.0,0.0,0.0
|
||||
BoatFactory (San Jose),37.338208,-121.886329,0.0,0.0,3,false,0.0,0.0,0.0,0.0
|
||||
BoatFactory (San Jose),37.338208,-121.886329,0.0,0.0,4,false,0.0,0.0,0.0,0.0
|
||||
BoatFactory (San Jose),37.338208,-121.886329,0.0,0.0,5,false,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (Chicago),41.881832,-87.623177,0.0,0.0,1,false,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (Chicago),41.881832,-87.623177,0.0,0.0,2,false,-0.0,0.0,0.0,-0.0
|
||||
RecyclingPlant (Chicago),41.881832,-87.623177,0.0,0.0,3,false,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (Chicago),41.881832,-87.623177,0.0,0.0,4,false,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (Chicago),41.881832,-87.623177,0.0,0.0,5,false,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (New York City),40.712776,-74.005974,0.0,0.0,1,false,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (New York City),40.712776,-74.005974,0.0,0.0,2,false,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (New York City),40.712776,-74.005974,0.0,0.0,3,false,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (New York City),40.712776,-74.005974,0.0,0.0,4,false,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (New York City),40.712776,-74.005974,0.0,0.0,5,false,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (Los Angeles),34.052235,-118.243683,0.0,0.0,1,false,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (Los Angeles),34.052235,-118.243683,0.0,0.0,2,false,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (Los Angeles),34.052235,-118.243683,0.0,0.0,3,false,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (Los Angeles),34.052235,-118.243683,0.0,0.0,4,false,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (Los Angeles),34.052235,-118.243683,0.0,0.0,5,false,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (Houston),29.760427,-95.369804,0.0,0.0,1,false,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (Houston),29.760427,-95.369804,0.0,0.0,2,false,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (Houston),29.760427,-95.369804,0.0,0.0,3,false,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (Houston),29.760427,-95.369804,0.0,0.0,4,false,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (Houston),29.760427,-95.369804,0.0,0.0,5,false,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (Phoenix),33.448376,-112.074036,0.0,0.0,1,false,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (Phoenix),33.448376,-112.074036,0.0,0.0,2,false,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (Phoenix),33.448376,-112.074036,0.0,0.0,3,false,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (Phoenix),33.448376,-112.074036,0.0,0.0,4,false,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (Phoenix),33.448376,-112.074036,0.0,0.0,5,false,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (Philadelphia),39.952583,-75.165222,0.0,0.0,1,false,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (Philadelphia),39.952583,-75.165222,0.0,0.0,2,false,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (Philadelphia),39.952583,-75.165222,0.0,0.0,3,false,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (Philadelphia),39.952583,-75.165222,0.0,0.0,4,false,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (Philadelphia),39.952583,-75.165222,0.0,0.0,5,false,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (San Antonio),29.424122,-98.493629,0.0,0.0,1,false,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (San Antonio),29.424122,-98.493629,0.0,0.0,2,false,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (San Antonio),29.424122,-98.493629,0.0,0.0,3,false,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (San Antonio),29.424122,-98.493629,0.0,0.0,4,false,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (San Antonio),29.424122,-98.493629,0.0,0.0,5,false,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (San Diego),32.715736,-117.161087,0.0,0.0,1,false,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (San Diego),32.715736,-117.161087,0.0,0.0,2,false,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (San Diego),32.715736,-117.161087,0.0,0.0,3,false,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (San Diego),32.715736,-117.161087,0.0,0.0,4,false,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (San Diego),32.715736,-117.161087,0.0,0.0,5,false,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (Dallas),32.776664,-96.796988,0.0,500.0,1,true,6.31579,500000.0,125000.0,15.78947
|
||||
RecyclingPlant (Dallas),32.776664,-96.796988,0.0,500.0,2,true,22.93629,0.0,125000.0,57.34072
|
||||
RecyclingPlant (Dallas),32.776664,-96.796988,0.0,500.0,3,true,31.7714,0.0,125000.0,79.42849
|
||||
RecyclingPlant (Dallas),32.776664,-96.796988,0.0,500.0,4,true,33.80867,0.0,125000.0,84.52168
|
||||
RecyclingPlant (Dallas),32.776664,-96.796988,0.0,500.0,5,true,34.54174,0.0,125000.0,86.35435
|
||||
RecyclingPlant (San Jose),37.338208,-121.886329,0.0,0.0,1,false,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (San Jose),37.338208,-121.886329,0.0,0.0,2,false,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (San Jose),37.338208,-121.886329,0.0,0.0,3,false,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (San Jose),37.338208,-121.886329,0.0,0.0,4,false,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (San Jose),37.338208,-121.886329,0.0,0.0,5,false,0.0,0.0,0.0,0.0
|
||||
plant,latitude,longitude,initial capacity,current capacity,year,operational?,input amount (tonne),stored amount (tonne),processed amount (tonne),opening cost ($),fixed operating cost ($),variable operating cost ($),expansion cost ($),storage cost ($)
|
||||
BoatFactory (Chicago),41.881832,-87.623177,0.0,0.0,1,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
|
||||
BoatFactory (Chicago),41.881832,-87.623177,0.0,0.0,2,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
|
||||
BoatFactory (Chicago),41.881832,-87.623177,0.0,0.0,3,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
|
||||
BoatFactory (Chicago),41.881832,-87.623177,0.0,0.0,4,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
|
||||
BoatFactory (Chicago),41.881832,-87.623177,0.0,0.0,5,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
|
||||
BoatFactory (New York City),40.712776,-74.005974,0.0,0.0,1,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
|
||||
BoatFactory (New York City),40.712776,-74.005974,0.0,0.0,2,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
|
||||
BoatFactory (New York City),40.712776,-74.005974,0.0,0.0,3,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
|
||||
BoatFactory (New York City),40.712776,-74.005974,0.0,0.0,4,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
|
||||
BoatFactory (New York City),40.712776,-74.005974,0.0,0.0,5,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
|
||||
BoatFactory (Los Angeles),34.052235,-118.243683,0.0,0.0,1,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
|
||||
BoatFactory (Los Angeles),34.052235,-118.243683,0.0,0.0,2,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
|
||||
BoatFactory (Los Angeles),34.052235,-118.243683,0.0,0.0,3,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
|
||||
BoatFactory (Los Angeles),34.052235,-118.243683,0.0,0.0,4,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
|
||||
BoatFactory (Los Angeles),34.052235,-118.243683,0.0,0.0,5,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
|
||||
BoatFactory (Houston),29.760427,-95.369804,0.0,0.0,1,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
|
||||
BoatFactory (Houston),29.760427,-95.369804,0.0,0.0,2,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
|
||||
BoatFactory (Houston),29.760427,-95.369804,0.0,0.0,3,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
|
||||
BoatFactory (Houston),29.760427,-95.369804,0.0,0.0,4,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
|
||||
BoatFactory (Houston),29.760427,-95.369804,0.0,0.0,5,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
|
||||
BoatFactory (Phoenix),33.448376,-112.074036,0.0,0.0,1,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
|
||||
BoatFactory (Phoenix),33.448376,-112.074036,0.0,0.0,2,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
|
||||
BoatFactory (Phoenix),33.448376,-112.074036,0.0,0.0,3,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
|
||||
BoatFactory (Phoenix),33.448376,-112.074036,0.0,0.0,4,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
|
||||
BoatFactory (Phoenix),33.448376,-112.074036,0.0,0.0,5,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
|
||||
BoatFactory (Philadelphia),39.952583,-75.165222,0.0,0.0,1,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
|
||||
BoatFactory (Philadelphia),39.952583,-75.165222,0.0,0.0,2,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
|
||||
BoatFactory (Philadelphia),39.952583,-75.165222,0.0,0.0,3,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
|
||||
BoatFactory (Philadelphia),39.952583,-75.165222,0.0,0.0,4,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
|
||||
BoatFactory (Philadelphia),39.952583,-75.165222,0.0,0.0,5,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
|
||||
BoatFactory (San Antonio),29.424122,-98.493629,0.0,0.0,1,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
|
||||
BoatFactory (San Antonio),29.424122,-98.493629,0.0,0.0,2,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
|
||||
BoatFactory (San Antonio),29.424122,-98.493629,0.0,0.0,3,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
|
||||
BoatFactory (San Antonio),29.424122,-98.493629,0.0,0.0,4,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
|
||||
BoatFactory (San Antonio),29.424122,-98.493629,0.0,0.0,5,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
|
||||
BoatFactory (San Diego),32.715736,-117.161087,0.0,0.0,1,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
|
||||
BoatFactory (San Diego),32.715736,-117.161087,0.0,0.0,2,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
|
||||
BoatFactory (San Diego),32.715736,-117.161087,0.0,0.0,3,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
|
||||
BoatFactory (San Diego),32.715736,-117.161087,0.0,0.0,4,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
|
||||
BoatFactory (San Diego),32.715736,-117.161087,0.0,0.0,5,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
|
||||
BoatFactory (Dallas),32.776664,-96.796988,0.0,500.0,1,true,63.15789,0.0,63.15789,100000.0,250000.0,315.78947,0.0,0.0
|
||||
BoatFactory (Dallas),32.776664,-96.796988,0.0,500.0,2,true,71.46814,0.0,71.46814,0.0,250000.0,357.34072,0.0,0.0
|
||||
BoatFactory (Dallas),32.776664,-96.796988,0.0,500.0,3,true,75.8857,0.0,75.8857,0.0,250000.0,379.42849,0.0,0.0
|
||||
BoatFactory (Dallas),32.776664,-96.796988,0.0,500.0,4,true,76.90434,0.0,76.90434,0.0,250000.0,384.52168,0.0,0.0
|
||||
BoatFactory (Dallas),32.776664,-96.796988,0.0,500.0,5,true,77.27087,0.0,77.27087,0.0,250000.0,386.35435,0.0,0.0
|
||||
BoatFactory (San Jose),37.338208,-121.886329,0.0,0.0,1,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
|
||||
BoatFactory (San Jose),37.338208,-121.886329,0.0,0.0,2,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
|
||||
BoatFactory (San Jose),37.338208,-121.886329,0.0,0.0,3,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
|
||||
BoatFactory (San Jose),37.338208,-121.886329,0.0,0.0,4,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
|
||||
BoatFactory (San Jose),37.338208,-121.886329,0.0,0.0,5,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (Chicago),41.881832,-87.623177,0.0,0.0,1,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (Chicago),41.881832,-87.623177,0.0,0.0,2,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (Chicago),41.881832,-87.623177,0.0,0.0,3,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (Chicago),41.881832,-87.623177,0.0,0.0,4,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (Chicago),41.881832,-87.623177,0.0,0.0,5,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (New York City),40.712776,-74.005974,0.0,0.0,1,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (New York City),40.712776,-74.005974,0.0,0.0,2,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (New York City),40.712776,-74.005974,0.0,0.0,3,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (New York City),40.712776,-74.005974,0.0,0.0,4,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (New York City),40.712776,-74.005974,0.0,0.0,5,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (Los Angeles),34.052235,-118.243683,0.0,0.0,1,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (Los Angeles),34.052235,-118.243683,0.0,0.0,2,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (Los Angeles),34.052235,-118.243683,0.0,0.0,3,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (Los Angeles),34.052235,-118.243683,0.0,0.0,4,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (Los Angeles),34.052235,-118.243683,0.0,0.0,5,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (Houston),29.760427,-95.369804,0.0,0.0,1,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (Houston),29.760427,-95.369804,0.0,0.0,2,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (Houston),29.760427,-95.369804,0.0,0.0,3,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (Houston),29.760427,-95.369804,0.0,0.0,4,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (Houston),29.760427,-95.369804,0.0,0.0,5,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (Phoenix),33.448376,-112.074036,0.0,0.0,1,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (Phoenix),33.448376,-112.074036,0.0,0.0,2,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (Phoenix),33.448376,-112.074036,0.0,0.0,3,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (Phoenix),33.448376,-112.074036,0.0,0.0,4,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (Phoenix),33.448376,-112.074036,0.0,0.0,5,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (Philadelphia),39.952583,-75.165222,0.0,0.0,1,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (Philadelphia),39.952583,-75.165222,0.0,0.0,2,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (Philadelphia),39.952583,-75.165222,0.0,0.0,3,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (Philadelphia),39.952583,-75.165222,0.0,0.0,4,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (Philadelphia),39.952583,-75.165222,0.0,0.0,5,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (San Antonio),29.424122,-98.493629,0.0,0.0,1,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (San Antonio),29.424122,-98.493629,0.0,0.0,2,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (San Antonio),29.424122,-98.493629,0.0,0.0,3,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (San Antonio),29.424122,-98.493629,0.0,0.0,4,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (San Antonio),29.424122,-98.493629,0.0,0.0,5,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (San Diego),32.715736,-117.161087,0.0,0.0,1,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (San Diego),32.715736,-117.161087,0.0,0.0,2,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (San Diego),32.715736,-117.161087,0.0,0.0,3,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (San Diego),32.715736,-117.161087,0.0,0.0,4,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (San Diego),32.715736,-117.161087,0.0,0.0,5,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (Dallas),32.776664,-96.796988,0.0,500.0,1,true,6.31579,0.0,6.31579,500000.0,125000.0,15.78947,0.0,0.0
|
||||
RecyclingPlant (Dallas),32.776664,-96.796988,0.0,500.0,2,true,22.93629,0.0,22.93629,0.0,125000.0,57.34072,0.0,0.0
|
||||
RecyclingPlant (Dallas),32.776664,-96.796988,0.0,500.0,3,true,31.7714,0.0,31.7714,0.0,125000.0,79.42849,0.0,0.0
|
||||
RecyclingPlant (Dallas),32.776664,-96.796988,0.0,500.0,4,true,33.80867,0.0,33.80867,0.0,125000.0,84.52168,0.0,0.0
|
||||
RecyclingPlant (Dallas),32.776664,-96.796988,0.0,500.0,5,true,34.54174,0.0,34.54174,0.0,125000.0,86.35435,0.0,0.0
|
||||
RecyclingPlant (San Jose),37.338208,-121.886329,0.0,0.0,1,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (San Jose),37.338208,-121.886329,0.0,0.0,2,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (San Jose),37.338208,-121.886329,0.0,0.0,3,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (San Jose),37.338208,-121.886329,0.0,0.0,4,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
|
||||
RecyclingPlant (San Jose),37.338208,-121.886329,0.0,0.0,5,false,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
|
||||
|
||||
|
12
test/fixtures/simple.json
vendored
12
test/fixtures/simple.json
vendored
@@ -153,7 +153,17 @@
|
||||
"variable operating cost ($/tonne)": 5.0
|
||||
}
|
||||
],
|
||||
"initial capacity (tonne)": 0
|
||||
"initial capacity (tonne)": 250
|
||||
}
|
||||
},
|
||||
"emissions": {
|
||||
"CO2": {
|
||||
"limit (tonne)": [1000.0, 1100.0, 1200.0, 1300.0],
|
||||
"penalty ($/tonne)": [50.0, 55.0, 60.0, 65.0]
|
||||
},
|
||||
"CH4": {
|
||||
"limit (tonne)": null,
|
||||
"penalty ($/tonne)": 1200.0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ using JuliaFormatter
|
||||
include("instance/parse_test.jl")
|
||||
include("model/build_test.jl")
|
||||
include("model/dist_test.jl")
|
||||
include("model/jumpext_test.jl")
|
||||
include("reports_test.jl")
|
||||
include("../fixtures/boat_example.jl")
|
||||
|
||||
@@ -23,6 +24,7 @@ function runtests()
|
||||
model_build_test()
|
||||
model_dist_test()
|
||||
report_tests()
|
||||
jumpext_test()
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
@@ -56,7 +56,7 @@ function instance_parse_test_1()
|
||||
@test l1.disposal_cost == Dict(p3 => [0, 0, 0, 0], p4 => [0.86, 0.86, 0.86, 0.86])
|
||||
@test l1.disposal_limit ==
|
||||
Dict(p3 => [Inf, Inf, Inf, Inf], p4 => [1000.0, 1000.0, 1000.0, 1000.0])
|
||||
@test l1.initial_capacity == 0
|
||||
@test l1.initial_capacity == 250
|
||||
@test length(l1.capacities) == 2
|
||||
c1 = l1.capacities[1]
|
||||
@test c1.size == 100
|
||||
@@ -68,6 +68,19 @@ function instance_parse_test_1()
|
||||
@test c2.opening_cost == [1000, 1000, 1000, 1000]
|
||||
@test c2.fix_operating_cost == [400, 400, 400, 400]
|
||||
@test c2.var_operating_cost == [5, 5, 5, 5]
|
||||
|
||||
# Emissions
|
||||
@test length(instance.emissions) == 2
|
||||
co2 = instance.emissions[1]
|
||||
@test co2.name == "CO2"
|
||||
@test co2.limit == [1000.0, 1100.0, 1200.0, 1300.0]
|
||||
@test co2.penalty == [50.0, 55.0, 60.0, 65.0]
|
||||
@test instance.emissions_by_name["CO2"] === co2
|
||||
ch4 = instance.emissions[2]
|
||||
@test ch4.name == "CH4"
|
||||
@test ch4.limit == [Inf, Inf, Inf, Inf]
|
||||
@test ch4.penalty == [1200.0, 1200.0, 1200.0, 1200.0]
|
||||
@test instance.emissions_by_name["CH4"] === ch4
|
||||
end
|
||||
|
||||
|
||||
|
||||
@@ -9,7 +9,11 @@ function model_build_test()
|
||||
y = model[:y]
|
||||
z_disp = model[:z_disp]
|
||||
z_input = model[:z_input]
|
||||
z_tr_em = model[:z_tr_em]
|
||||
z_process = model[:z_process]
|
||||
z_storage = model[:z_storage]
|
||||
z_em_tr = model[:z_em_tr]
|
||||
z_em_plant = model[:z_em_plant]
|
||||
z_exp = model[:z_exp]
|
||||
x = model[:x]
|
||||
obj = objective_function(model)
|
||||
# print(model)
|
||||
@@ -26,6 +30,8 @@ function model_build_test()
|
||||
@test obj.terms[z_disp["C1", "P2", 1]] == 0.23
|
||||
@test obj.constant == (
|
||||
150 * 4 * 3 # center operating cost
|
||||
- 300 # initial opening cost
|
||||
- 150 * 1.75 # initial expansion
|
||||
)
|
||||
@test obj.terms[z_disp["L1", "P4", 2]] == 0.86
|
||||
@test obj.terms[x["L1", 1]] == (
|
||||
@@ -45,27 +51,58 @@ function model_build_test()
|
||||
300 # fixed operating cost
|
||||
)
|
||||
|
||||
# Test expansion variables exist and have correct initial values
|
||||
@test z_exp["L1", 0] == 150.0 # initial_capacity (250) - min_capacity (100)
|
||||
@test haskey(z_exp, ("L1", 1))
|
||||
@test haskey(z_exp, ("L1", 2))
|
||||
@test haskey(z_exp, ("L1", 3))
|
||||
@test haskey(z_exp, ("L1", 4))
|
||||
|
||||
# Test expansion costs in objective function
|
||||
# R_expand[1] = (1000 - 300) / (500 - 100) = 1.75
|
||||
# R_expand[2] = (1000 - 400) / (500 - 100) = 1.5
|
||||
# R_fix_exp[1] = (400 - 300) / (500 - 100) = 0.25
|
||||
@test obj.terms[z_exp["L1", 1]] == (
|
||||
+1.75 # expansion cost[1]
|
||||
- 1.5 # expansion cost[2]
|
||||
+ 0.25 # fixed operating cost[1]
|
||||
)
|
||||
|
||||
# Test storage cost in objective function
|
||||
@test obj.terms[z_storage["L1", "P1", 1]] == 0.1 # P1 storage cost
|
||||
@test obj.terms[z_storage["L1", "P2", 1]] == 0.1 # P2 storage cost
|
||||
|
||||
# Variables: Transportation emissions
|
||||
@test haskey(z_tr_em, ("CO2", "L1", "C3", "P4", 1))
|
||||
@test haskey(z_tr_em, ("CH4", "L1", "C3", "P4", 1))
|
||||
@test haskey(z_tr_em, ("CO2", "C2", "L1", "P1", 1))
|
||||
@test haskey(z_tr_em, ("CH4", "C2", "L1", "P1", 1))
|
||||
@test haskey(z_em_tr, ("CO2", "L1", "C3", "P4", 1))
|
||||
@test haskey(z_em_tr, ("CH4", "L1", "C3", "P4", 1))
|
||||
@test haskey(z_em_tr, ("CO2", "C2", "L1", "P1", 1))
|
||||
@test haskey(z_em_tr, ("CH4", "C2", "L1", "P1", 1))
|
||||
|
||||
# Variables: Plant emissions
|
||||
@test haskey(z_em_plant, ("CO2", "L1", 1))
|
||||
@test haskey(z_em_plant, ("CO2", "L1", 2))
|
||||
@test haskey(z_em_plant, ("CO2", "L1", 3))
|
||||
@test haskey(z_em_plant, ("CO2", "L1", 4))
|
||||
|
||||
# Plants: Definition of total plant input
|
||||
@test repr(model[:eq_z_input]["L1", 1]) ==
|
||||
"eq_z_input[L1,1] : -y[C2,L1,P1,1] - y[C1,L1,P2,1] + z_input[L1,1] = 0"
|
||||
|
||||
# Plants: Must meet input mix
|
||||
@test repr(model[:eq_input_mix]["L1", "P1", 1]) ==
|
||||
"eq_input_mix[L1,P1,1] : y[C2,L1,P1,1] - 0.953 z_input[L1,1] = 0"
|
||||
@test repr(model[:eq_input_mix]["L1", "P2", 1]) ==
|
||||
"eq_input_mix[L1,P2,1] : y[C1,L1,P2,1] - 0.047 z_input[L1,1] = 0"
|
||||
# Plants: Definition of total processing amount
|
||||
@test repr(model[:eq_z_process]["L1", 1]) ==
|
||||
"eq_z_process[L1,1] : -z_input[L1,1] + z_storage[L1,P1,1] + z_storage[L1,P2,1] + z_process[L1,1] = 0"
|
||||
|
||||
# Plants: Processing mix must have correct proportion
|
||||
@test repr(model[:eq_process_mix]["L1", "P1", 1]) ==
|
||||
"eq_process_mix[L1,P1,1] : y[C2,L1,P1,1] - z_storage[L1,P1,1] - 0.953 z_process[L1,1] = 0"
|
||||
@test repr(model[:eq_process_mix]["L1", "P2", 1]) ==
|
||||
"eq_process_mix[L1,P2,1] : y[C1,L1,P2,1] - z_storage[L1,P2,1] - 0.047 z_process[L1,1] = 0"
|
||||
|
||||
# Plants: Calculate amount produced
|
||||
@test repr(model[:eq_z_prod]["L1", "P3", 1]) ==
|
||||
"eq_z_prod[L1,P3,1] : z_prod[L1,P3,1] - 0.25 z_input[L1,1] = 0"
|
||||
"eq_z_prod[L1,P3,1] : z_prod[L1,P3,1] - 0.25 z_process[L1,1] = 0"
|
||||
@test repr(model[:eq_z_prod]["L1", "P4", 1]) ==
|
||||
"eq_z_prod[L1,P4,1] : z_prod[L1,P4,1] - 0.12 z_input[L1,1] = 0"
|
||||
"eq_z_prod[L1,P4,1] : z_prod[L1,P4,1] - 0.12 z_process[L1,1] = 0"
|
||||
|
||||
# Plants: Produced material must be sent or disposed
|
||||
@test repr(model[:eq_balance]["L1", "P3", 1]) ==
|
||||
@@ -73,9 +110,13 @@ function model_build_test()
|
||||
@test repr(model[:eq_balance]["L1", "P4", 1]) ==
|
||||
"eq_balance[L1,P4,1] : -y[L1,C3,P4,1] + z_prod[L1,P4,1] - z_disp[L1,P4,1] = 0"
|
||||
|
||||
# Plants: Capacity limit
|
||||
@test repr(model[:eq_capacity]["L1", 1]) ==
|
||||
"eq_capacity[L1,1] : -100 x[L1,1] + z_input[L1,1] ≤ 0"
|
||||
# Plants: Processing limit (capacity constraint)
|
||||
@test repr(model[:eq_process_limit]["L1", 1]) ==
|
||||
"eq_process_limit[L1,1] : -100 x[L1,1] - z_exp[L1,1] + z_process[L1,1] ≤ 0"
|
||||
|
||||
# Plants: Expansion upper bound
|
||||
@test repr(model[:eq_exp_ub]["L1", 1]) ==
|
||||
"eq_exp_ub[L1,1] : -400 x[L1,1] + z_exp[L1,1] ≤ 0"
|
||||
|
||||
# Plants: Disposal limit
|
||||
@test repr(model[:eq_disposal_limit]["L1", "P4", 1]) ==
|
||||
@@ -85,7 +126,13 @@ function model_build_test()
|
||||
# Plants: Plant remains open
|
||||
@test repr(model[:eq_keep_open]["L1", 4]) ==
|
||||
"eq_keep_open[L1,4] : -x[L1,3] + x[L1,4] ≥ 0"
|
||||
@test repr(model[:eq_keep_open]["L1", 1]) == "eq_keep_open[L1,1] : x[L1,1] ≥ 0"
|
||||
@test repr(model[:eq_keep_open]["L1", 1]) == "eq_keep_open[L1,1] : x[L1,1] ≥ 1"
|
||||
|
||||
# Plants: Capacity cannot decrease over time
|
||||
@test repr(model[:eq_capacity_nondecreasing]["L1", 4]) ==
|
||||
"eq_capacity_nondecreasing[L1,4] : -z_exp[L1,3] + z_exp[L1,4] ≥ 0"
|
||||
@test repr(model[:eq_capacity_nondecreasing]["L1", 1]) ==
|
||||
"eq_capacity_nondecreasing[L1,1] : z_exp[L1,1] ≥ 150"
|
||||
|
||||
# Plants: Building period
|
||||
@test ("L1", 1) ∉ keys(model[:eq_building_period])
|
||||
@@ -127,6 +174,49 @@ function model_build_test()
|
||||
@test ("P4", 1) ∉ keys(model[:eq_disposal_limit])
|
||||
|
||||
# Products: Transportation emissions
|
||||
@test repr(model[:eq_tr_em]["CH4", "L1", "C3", "P4", 1]) ==
|
||||
"eq_tr_em[CH4,L1,C3,P4,1] : -0.333354 y[L1,C3,P4,1] + z_tr_em[CH4,L1,C3,P4,1] = 0"
|
||||
@test repr(model[:eq_emission_tr]["CH4", "L1", "C3", "P4", 1]) ==
|
||||
"eq_emission_tr[CH4,L1,C3,P4,1] : -0.333354 y[L1,C3,P4,1] + z_em_tr[CH4,L1,C3,P4,1] = 0"
|
||||
|
||||
# Plants: Plant emissions (updated to use z_process)
|
||||
@test repr(model[:eq_emission_plant]["CO2", "L1", 1]) ==
|
||||
"eq_emission_plant[CO2,L1,1] : -0.1 z_process[L1,1] + z_em_plant[CO2,L1,1] = 0"
|
||||
|
||||
# Objective function: Emissions penalty costs
|
||||
@test obj.terms[z_em_plant["CO2", "L1", 1]] == 50.0 # CO2 penalty at time 1
|
||||
@test obj.terms[z_em_plant["CO2", "L1", 2]] == 55.0 # CO2 penalty at time 2
|
||||
@test obj.terms[z_em_plant["CO2", "L1", 3]] == 60.0 # CO2 penalty at time 3
|
||||
@test obj.terms[z_em_plant["CO2", "L1", 4]] == 65.0 # CO2 penalty at time 4
|
||||
@test obj.terms[z_em_tr["CO2", "L1", "C3", "P4", 1]] == 50.0 # CO2 transportation penalty at time 1
|
||||
@test obj.terms[z_em_tr["CH4", "L1", "C3", "P4", 1]] == 1200.0 # CH4 transportation penalty at time 1
|
||||
|
||||
# Global emissions limit constraints
|
||||
@test repr(model[:eq_emission_limit]["CO2", 1]) ==
|
||||
"eq_emission_limit[CO2,1] : z_em_tr[CO2,C2,L1,P1,1] + z_em_tr[CO2,C2,C1,P1,1] + z_em_tr[CO2,C1,L1,P2,1] + z_em_tr[CO2,L1,C3,P4,1] + z_em_plant[CO2,L1,1] ≤ 1000"
|
||||
@test ("CH4", 1) ∉ keys(model[:eq_emission_limit])
|
||||
|
||||
# Test storage variables exist
|
||||
@test haskey(z_storage, ("L1", "P1", 1))
|
||||
@test haskey(z_storage, ("L1", "P2", 1))
|
||||
@test haskey(z_process, ("L1", 1))
|
||||
@test haskey(z_process, ("L1", 2))
|
||||
@test haskey(z_process, ("L1", 3))
|
||||
@test haskey(z_process, ("L1", 4))
|
||||
|
||||
# Test initial storage values
|
||||
@test z_storage["L1", "P1", 0] == 0
|
||||
@test z_storage["L1", "P2", 0] == 0
|
||||
|
||||
# Test storage limit constraints (P1 has limit of 100, P2 has no limit)
|
||||
@test haskey(model[:eq_storage_limit], ("L1", "P1", 1))
|
||||
@test repr(model[:eq_storage_limit]["L1", "P1", 1]) ==
|
||||
"eq_storage_limit[L1,P1,1] : z_storage[L1,P1,1] ≤ 100"
|
||||
@test ("L1", "P2", 1) ∉ keys(model[:eq_storage_limit]) # P2 has no storage limit
|
||||
|
||||
# Test final storage constraints exist
|
||||
@test haskey(model[:eq_storage_final], ("L1", "P1"))
|
||||
@test haskey(model[:eq_storage_final], ("L1", "P2"))
|
||||
@test repr(model[:eq_storage_final]["L1", "P1"]) ==
|
||||
"eq_storage_final[L1,P1] : z_storage[L1,P1,4] = 0"
|
||||
@test repr(model[:eq_storage_final]["L1", "P2"]) ==
|
||||
"eq_storage_final[L1,P2] : z_storage[L1,P2,4] = 0"
|
||||
end
|
||||
|
||||
144
test/src/model/jumpext_test.jl
Normal file
144
test/src/model/jumpext_test.jl
Normal file
@@ -0,0 +1,144 @@
|
||||
# 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 RELOG
|
||||
using JuMP
|
||||
using HiGHS
|
||||
using Test
|
||||
|
||||
function jumpext_test()
|
||||
jumpext_pwl_single_point()
|
||||
jumpext_pwl_two_points()
|
||||
jumpext_pwl_multiple_points()
|
||||
jumpext_pwl_input_validation()
|
||||
return
|
||||
end
|
||||
|
||||
function jumpext_pwl_single_point()
|
||||
model = Model(HiGHS.Optimizer)
|
||||
set_silent(model)
|
||||
@variable(model, x)
|
||||
@variable(model, y1)
|
||||
@variable(model, y2)
|
||||
xpts = [5.0]
|
||||
ypts = [10.0 20.0]
|
||||
RELOG._add_pwl_constraints(model, x, [y1, y2], xpts, ypts)
|
||||
optimize!(model)
|
||||
@test is_solved_and_feasible(model)
|
||||
@test value(x) ≈ 5.0 atol = 1e-6
|
||||
@test value(y1) ≈ 10.0 atol = 1e-6
|
||||
@test value(y2) ≈ 20.0 atol = 1e-6
|
||||
return
|
||||
end
|
||||
|
||||
function jumpext_pwl_two_points()
|
||||
model = Model(HiGHS.Optimizer)
|
||||
set_silent(model)
|
||||
@variable(model, x)
|
||||
@variable(model, y1)
|
||||
@variable(model, y2)
|
||||
xpts = [0.0, 2.0]
|
||||
ypts = [0.0 10.0; 4.0 6.0]
|
||||
RELOG._add_pwl_constraints(model, x, [y1, y2], xpts, ypts)
|
||||
|
||||
# Test at x = 1
|
||||
JuMP.fix(x, 1.0)
|
||||
optimize!(model)
|
||||
@test is_solved_and_feasible(model)
|
||||
@test value(y1) ≈ 2.0 atol = 1e-6
|
||||
@test value(y2) ≈ 8.0 atol = 1e-6
|
||||
|
||||
# Test at x = 2
|
||||
JuMP.fix(x, 2.0)
|
||||
optimize!(model)
|
||||
@test is_solved_and_feasible(model)
|
||||
@test value(y1) ≈ 4.0 atol = 1e-6
|
||||
@test value(y2) ≈ 6.0 atol = 1e-6
|
||||
return
|
||||
end
|
||||
|
||||
function jumpext_pwl_multiple_points()
|
||||
model = Model(HiGHS.Optimizer)
|
||||
set_silent(model)
|
||||
@variable(model, x)
|
||||
@variable(model, y1)
|
||||
@variable(model, y2)
|
||||
xpts = [0.0, 1.0, 2.0]
|
||||
ypts = [0.0 5.0; 2.0 3.0; 1.0 4.0]
|
||||
RELOG._add_pwl_constraints(model, x, [y1, y2], xpts, ypts)
|
||||
|
||||
# Test at x = 0.5
|
||||
JuMP.fix(x, 0.5)
|
||||
optimize!(model)
|
||||
@test is_solved_and_feasible(model)
|
||||
@test value(y1) ≈ 1.0 atol = 1e-6
|
||||
@test value(y2) ≈ 4.0 atol = 1e-6
|
||||
|
||||
# Test at x = 1
|
||||
JuMP.fix(x, 1.0)
|
||||
optimize!(model)
|
||||
@test is_solved_and_feasible(model)
|
||||
@test value(y1) ≈ 2.0 atol = 1e-6
|
||||
@test value(y2) ≈ 3.0 atol = 1e-6
|
||||
|
||||
# Test at x = 1.5
|
||||
JuMP.fix(x, 1.5)
|
||||
optimize!(model)
|
||||
@test is_solved_and_feasible(model)
|
||||
@test value(y1) ≈ 1.5 atol = 1e-6
|
||||
@test value(y2) ≈ 3.5 atol = 1e-6
|
||||
return
|
||||
end
|
||||
|
||||
function jumpext_pwl_input_validation()
|
||||
model = Model(HiGHS.Optimizer)
|
||||
@variable(model, x)
|
||||
@variable(model, y)
|
||||
|
||||
# Test non-matrix ypts
|
||||
@test_throws ArgumentError RELOG._add_pwl_constraints(model, x, [y], [1.0], [1.0])
|
||||
|
||||
# Test mismatched dimensions
|
||||
@test_throws ArgumentError RELOG._add_pwl_constraints(
|
||||
model,
|
||||
x,
|
||||
[y],
|
||||
[1.0, 2.0],
|
||||
[1.0 2.0],
|
||||
)
|
||||
@test_throws ArgumentError RELOG._add_pwl_constraints(
|
||||
model,
|
||||
x,
|
||||
[y],
|
||||
[1.0],
|
||||
[1.0 2.0; 3.0 4.0],
|
||||
)
|
||||
|
||||
# Test empty breakpoints
|
||||
@test_throws ArgumentError RELOG._add_pwl_constraints(
|
||||
model,
|
||||
x,
|
||||
[y],
|
||||
Float64[],
|
||||
Matrix{Float64}(undef, 0, 1),
|
||||
)
|
||||
|
||||
# Test non-increasing x points
|
||||
@test_throws ArgumentError RELOG._add_pwl_constraints(
|
||||
model,
|
||||
x,
|
||||
[y],
|
||||
[2.0, 1.0],
|
||||
[1.0; 2.0],
|
||||
)
|
||||
@test_throws ArgumentError RELOG._add_pwl_constraints(
|
||||
model,
|
||||
x,
|
||||
[y],
|
||||
[1.0, 1.0],
|
||||
[1.0; 2.0],
|
||||
)
|
||||
|
||||
return
|
||||
end
|
||||
@@ -6,6 +6,7 @@ function report_tests()
|
||||
mkpath("tmp")
|
||||
write_to_file(model, "tmp/model.lp")
|
||||
RELOG.write_plants_report(model, "tmp/plants.csv")
|
||||
RELOG.write_plant_inputs_report(model, "tmp/plant_inputs.csv")
|
||||
RELOG.write_plant_outputs_report(model, "tmp/plant_outputs.csv")
|
||||
RELOG.write_centers_report(model, "tmp/centers.csv")
|
||||
RELOG.write_center_outputs_report(model, "tmp/center_outputs.csv")
|
||||
|
||||
Reference in New Issue
Block a user