diff --git a/docs/src/problem.md b/docs/src/problem.md index 5922ceb..3f088c1 100644 --- a/docs/src/problem.md +++ b/docs/src/problem.md @@ -39,6 +39,7 @@ The mathematical model employed by RELOG is based on three main components: | $C$ | Set of collection and distribution centers | | $P$ | Set of manufacturing and recycling plants | | $M$ | Set of products and materials | +| $G$ | Set of greenhouse gases | | $M^+_u$ | Set of output products of plant/center $u$. | | $M^-_u$ | Set of input products of plant/center $u$. | | $T$ | Set of time periods in the planning horizon. We assume $T=\{1,\ldots,t^{max}\}.$ | @@ -48,35 +49,37 @@ 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{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{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{output}_{pmt}$ | Amount of material $m$ produced by plant $p$ at time $t$ for each tonne of input material processed | tonne | -| $R^\text{tr}_{mt}$ | Cost to send material $m$ at time $t$ | \$/km-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{rev}_{ct}$ | Revenue for selling the input product of center $c$ at this center at time $t$ | \$/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. | -- | +| 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{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{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{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 | +| $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{rev}_{ct}$ | Revenue for selling the input product of center $c$ at this center at time $t$ | \$/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 -| Symbol | JuMP name | Description | Unit | -| :--------------------------- | :------------------------------- | :------------------------------------------------------------------------------- | :----- | -| $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{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{prod}}_{umt}$ | `z_prod[u.name, m.name, t]` | Amount of product $m$ produced by plant/center $u$ at time $t$ | tonne | +| Symbol | JuMP name | Description | Unit | +| :--------------------------- | :------------------------------------------- | :------------------------------------------------------------------------------------------------------ | :----- | +| $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{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{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 | ## Objective function @@ -264,4 +267,13 @@ The goals is to minimize a linear objective function with the following terms: & \sum_{p \in P} z^\text{disp}_{pmt} + \sum_{c \in C} z^\text{disp}_{cmt} \leq K^\text{disp-limit}_{mt} & \forall m \in M, t \in T \end{align*} -``` \ No newline at end of file +``` + +- Computation of transportation emissions (`eq_tr_em[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} +& \forall g \in G, (u, v, m) \in E, t \in T +\end{align*} +``` diff --git a/src/instance/parse.jl b/src/instance/parse.jl index a225bc8..73eeb92 100644 --- a/src/instance/parse.jl +++ b/src/instance/parse.jl @@ -20,10 +20,11 @@ function parse(json)::Instance error("Invalid distance metric: $distance_metric_str") end - timeseries(::Nothing; null_val=nothing) = repeat([null_val], time_horizon) - timeseries(x::Number; null_val=nothing) = repeat([x], time_horizon) - timeseries(x::Array; null_val=nothing) = [xi === nothing ? null_val : xi for xi in x] - timeseries(d::OrderedDict; null_val=nothing) = OrderedDict(k => timeseries(v; null_val) for (k, v) in d) + timeseries(::Nothing; null_val = nothing) = repeat([null_val], time_horizon) + timeseries(x::Number; null_val = nothing) = repeat([x], time_horizon) + timeseries(x::Array; null_val = nothing) = [xi === nothing ? null_val : xi for xi in x] + timeseries(d::OrderedDict; null_val = nothing) = + OrderedDict(k => timeseries(v; null_val) for (k, v) in d) # Read products products = Product[] @@ -32,7 +33,7 @@ function parse(json)::Instance tr_cost = timeseries(pdict["transportation cost (\$/km/tonne)"]) tr_energy = timeseries(pdict["transportation energy (J/km/tonne)"]) tr_emissions = timeseries(pdict["transportation emissions (tonne/km/tonne)"]) - disposal_limit = timeseries(pdict["disposal limit (tonne)"], null_val=Inf) + disposal_limit = timeseries(pdict["disposal limit (tonne)"], null_val = Inf) prod = Product(; name, tr_cost, tr_energy, tr_emissions, disposal_limit) push!(products, prod) products_by_name[name] = prod @@ -52,10 +53,8 @@ function parse(json)::Instance end outputs = [products_by_name[p] for p in cdict["outputs"]] operating_cost = timeseries(cdict["operating cost (\$)"]) - prod_dict(key, null_val) = OrderedDict( - p => timeseries(cdict[key][p.name]; null_val) - for p in outputs - ) + prod_dict(key, null_val) = + OrderedDict(p => timeseries(cdict[key][p.name]; null_val) for p in outputs) fixed_output = prod_dict("fixed output (tonne)", 0.0) var_output = prod_dict("variable output (tonne/tonne)", 0.0) collection_cost = prod_dict("collection cost (\$/tonne)", 0.0) diff --git a/src/model/build.jl b/src/model/build.jl index 4238bb5..a100506 100644 --- a/src/model/build.jl +++ b/src/model/build.jl @@ -118,6 +118,12 @@ function build_model(instance::Instance; optimizer, variable_names::Bool = false z_collected[c.name, m.name, t] = @variable(model, lower_bound = 0) end + # Transportation emissions by greenhouse gas + z_tr_em = _init(model, :z_tr_em) + 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) + end + # Objective function # ------------------------------------------------------------------------- @@ -310,6 +316,16 @@ function build_model(instance::Instance; optimizer, variable_names::Bool = false ) end + # Transportation emissions + eq_tr_em = _init(model, :eq_tr_em) + 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( + model, + z_tr_em[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 + if variable_names _set_names!(model) end diff --git a/src/reports/transportation.jl b/src/reports/transportation.jl index 9d37e0f..4b041e1 100644 --- a/src/reports/transportation.jl +++ b/src/reports/transportation.jl @@ -52,5 +52,48 @@ function transportation_report(model)::DataFrame return df end +function transportation_emissions_report(model)::DataFrame + df = DataFrame() + df."source" = String[] + df."destination" = String[] + df."product" = String[] + df."emission" = String[] + df."year" = Int[] + df."amount sent (tonne)" = Float64[] + df."distance (km)" = Float64[] + df."emission factor (tonne/km/tonne)" = Float64[] + df."emission amount (tonne)" = Float64[] + + E = model.ext[:E] + distances = model.ext[:distances] + T = 1:model.ext[:instance].time_horizon + + for (p1, p2, m) in E, t in T, g in keys(m.tr_emissions) + amount = value(model[:y][p1.name, p2.name, m.name, t]) + 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]) + push!( + df, + Dict( + "source" => p1.name, + "destination" => p2.name, + "product" => m.name, + "emission" => g, + "year" => t, + "amount sent (tonne)" => _round(amount), + "distance (km)" => _round(distance), + "emission factor (tonne/km/tonne)" => _round(emission_factor), + "emission amount (tonne)" => _round(emissions), + ), + ) + end + return df +end + write_transportation_report(solution, filename) = CSV.write(filename, transportation_report(solution)) + +write_transportation_emissions_report(solution, filename) = + CSV.write(filename, transportation_emissions_report(solution)) diff --git a/test/fixtures/boat_example.jl b/test/fixtures/boat_example.jl index 897f631..c2d0f74 100644 --- a/test/fixtures/boat_example.jl +++ b/test/fixtures/boat_example.jl @@ -68,7 +68,8 @@ function run_boat_example() prod = dict( "transportation cost (\$/km/tonne)" => 0.30, "transportation energy (J/km/tonne)" => 7_500, - "transportation emissions (tonne/km/tonne)" => dict("CO2" => 2.68), + "transportation emissions (tonne/km/tonne)" => + dict("CO2" => 2.68, "NH4" => 1.02), "disposal limit (tonne)" => nothing, ) @@ -176,6 +177,10 @@ function run_boat_example() 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")) + RELOG.write_transportation_emissions_report( + model, + fixture("boat_example/tr_emissions.csv"), + ) return end diff --git a/test/fixtures/boat_example.json b/test/fixtures/boat_example.json index 3419a60..4d7dfd5 100644 --- a/test/fixtures/boat_example.json +++ b/test/fixtures/boat_example.json @@ -11,7 +11,8 @@ "transportation cost ($/km/tonne)": 0.3, "transportation energy (J/km/tonne)": 7500, "transportation emissions (tonne/km/tonne)": { - "CO2": 2.68 + "CO2": 2.68, + "NH4": 1.02 }, "disposal limit (tonne)": null }, @@ -19,7 +20,8 @@ "transportation cost ($/km/tonne)": 0.3, "transportation energy (J/km/tonne)": 7500, "transportation emissions (tonne/km/tonne)": { - "CO2": 2.68 + "CO2": 2.68, + "NH4": 1.02 }, "disposal limit (tonne)": null }, @@ -27,7 +29,8 @@ "transportation cost ($/km/tonne)": 0.3, "transportation energy (J/km/tonne)": 7500, "transportation emissions (tonne/km/tonne)": { - "CO2": 2.68 + "CO2": 2.68, + "NH4": 1.02 }, "disposal limit (tonne)": null }, @@ -35,7 +38,8 @@ "transportation cost ($/km/tonne)": 0.3, "transportation energy (J/km/tonne)": 7500, "transportation emissions (tonne/km/tonne)": { - "CO2": 2.68 + "CO2": 2.68, + "NH4": 1.02 }, "disposal limit (tonne)": null } diff --git a/test/fixtures/boat_example/tr_emissions.csv b/test/fixtures/boat_example/tr_emissions.csv new file mode 100644 index 0000000..ddf0a4d --- /dev/null +++ b/test/fixtures/boat_example/tr_emissions.csv @@ -0,0 +1,81 @@ +source,destination,product,emission,year,amount sent (tonne),distance (km),emission factor (tonne/km/tonne),emission amount (tonne) +RecyclingPlant (Dallas),BoatFactory (Dallas),Nail,CO2,1,0.15789,0.0,2.68,0.0 +RecyclingPlant (Dallas),BoatFactory (Dallas),Nail,NH4,1,0.15789,0.0,1.02,0.0 +RecyclingPlant (Dallas),BoatFactory (Dallas),Nail,CO2,2,0.57341,0.0,2.68,0.0 +RecyclingPlant (Dallas),BoatFactory (Dallas),Nail,NH4,2,0.57341,0.0,1.02,0.0 +RecyclingPlant (Dallas),BoatFactory (Dallas),Nail,CO2,3,0.79428,0.0,2.68,0.0 +RecyclingPlant (Dallas),BoatFactory (Dallas),Nail,NH4,3,0.79428,0.0,1.02,0.0 +RecyclingPlant (Dallas),BoatFactory (Dallas),Nail,CO2,4,0.84522,0.0,2.68,0.0 +RecyclingPlant (Dallas),BoatFactory (Dallas),Nail,NH4,4,0.84522,0.0,1.02,0.0 +RecyclingPlant (Dallas),BoatFactory (Dallas),Nail,CO2,5,0.86354,0.0,2.68,0.0 +RecyclingPlant (Dallas),BoatFactory (Dallas),Nail,NH4,5,0.86354,0.0,1.02,0.0 +NailFactory (Chicago),BoatFactory (Dallas),Nail,CO2,1,1.0,1293.093,2.68,3465.48924 +NailFactory (Chicago),BoatFactory (Dallas),Nail,NH4,1,1.0,1293.093,1.02,1318.95486 +NailFactory (Chicago),BoatFactory (Dallas),Nail,CO2,2,1.0,1293.093,2.68,3465.48924 +NailFactory (Chicago),BoatFactory (Dallas),Nail,NH4,2,1.0,1293.093,1.02,1318.95486 +NailFactory (Chicago),BoatFactory (Dallas),Nail,CO2,3,1.0,1293.093,2.68,3465.48924 +NailFactory (Chicago),BoatFactory (Dallas),Nail,NH4,3,1.0,1293.093,1.02,1318.95486 +NailFactory (Chicago),BoatFactory (Dallas),Nail,CO2,4,1.0,1293.093,2.68,3465.48924 +NailFactory (Chicago),BoatFactory (Dallas),Nail,NH4,4,1.0,1293.093,1.02,1318.95486 +NailFactory (Chicago),BoatFactory (Dallas),Nail,CO2,5,1.0,1293.093,2.68,3465.48924 +NailFactory (Chicago),BoatFactory (Dallas),Nail,NH4,5,1.0,1293.093,1.02,1318.95486 +NailFactory (Phoenix),BoatFactory (Dallas),Nail,CO2,1,1.0,1423.57,2.68,3815.1676 +NailFactory (Phoenix),BoatFactory (Dallas),Nail,NH4,1,1.0,1423.57,1.02,1452.0414 +NailFactory (Phoenix),BoatFactory (Dallas),Nail,CO2,2,1.0,1423.57,2.68,3815.1676 +NailFactory (Phoenix),BoatFactory (Dallas),Nail,NH4,2,1.0,1423.57,1.02,1452.0414 +NailFactory (Phoenix),BoatFactory (Dallas),Nail,CO2,3,1.0,1423.57,2.68,3815.1676 +NailFactory (Phoenix),BoatFactory (Dallas),Nail,NH4,3,1.0,1423.57,1.02,1452.0414 +NailFactory (Phoenix),BoatFactory (Dallas),Nail,CO2,4,1.0,1423.57,2.68,3815.1676 +NailFactory (Phoenix),BoatFactory (Dallas),Nail,NH4,4,1.0,1423.57,1.02,1452.0414 +NailFactory (Phoenix),BoatFactory (Dallas),Nail,CO2,5,1.0,1423.57,2.68,3815.1676 +NailFactory (Phoenix),BoatFactory (Dallas),Nail,NH4,5,1.0,1423.57,1.02,1452.0414 +NailFactory (Dallas),BoatFactory (Dallas),Nail,CO2,1,1.0,0.0,2.68,0.0 +NailFactory (Dallas),BoatFactory (Dallas),Nail,NH4,1,1.0,0.0,1.02,0.0 +NailFactory (Dallas),BoatFactory (Dallas),Nail,CO2,2,1.0,0.0,2.68,0.0 +NailFactory (Dallas),BoatFactory (Dallas),Nail,NH4,2,1.0,0.0,1.02,0.0 +NailFactory (Dallas),BoatFactory (Dallas),Nail,CO2,3,1.0,0.0,2.68,0.0 +NailFactory (Dallas),BoatFactory (Dallas),Nail,NH4,3,1.0,0.0,1.02,0.0 +NailFactory (Dallas),BoatFactory (Dallas),Nail,CO2,4,1.0,0.0,2.68,0.0 +NailFactory (Dallas),BoatFactory (Dallas),Nail,NH4,4,1.0,0.0,1.02,0.0 +NailFactory (Dallas),BoatFactory (Dallas),Nail,CO2,5,1.0,0.0,2.68,0.0 +NailFactory (Dallas),BoatFactory (Dallas),Nail,NH4,5,1.0,0.0,1.02,0.0 +RecyclingPlant (Dallas),BoatFactory (Dallas),Wood,CO2,1,3.0,0.0,2.68,0.0 +RecyclingPlant (Dallas),BoatFactory (Dallas),Wood,NH4,1,3.0,0.0,1.02,0.0 +RecyclingPlant (Dallas),BoatFactory (Dallas),Wood,CO2,2,10.89474,0.0,2.68,0.0 +RecyclingPlant (Dallas),BoatFactory (Dallas),Wood,NH4,2,10.89474,0.0,1.02,0.0 +RecyclingPlant (Dallas),BoatFactory (Dallas),Wood,CO2,3,15.09141,0.0,2.68,0.0 +RecyclingPlant (Dallas),BoatFactory (Dallas),Wood,NH4,3,15.09141,0.0,1.02,0.0 +RecyclingPlant (Dallas),BoatFactory (Dallas),Wood,CO2,4,16.05912,0.0,2.68,0.0 +RecyclingPlant (Dallas),BoatFactory (Dallas),Wood,NH4,4,16.05912,0.0,1.02,0.0 +RecyclingPlant (Dallas),BoatFactory (Dallas),Wood,CO2,5,16.40733,0.0,2.68,0.0 +RecyclingPlant (Dallas),BoatFactory (Dallas),Wood,NH4,5,16.40733,0.0,1.02,0.0 +Forest (Dallas),BoatFactory (Dallas),Wood,CO2,1,57.0,0.0,2.68,0.0 +Forest (Dallas),BoatFactory (Dallas),Wood,NH4,1,57.0,0.0,1.02,0.0 +Forest (Dallas),BoatFactory (Dallas),Wood,CO2,2,57.0,0.0,2.68,0.0 +Forest (Dallas),BoatFactory (Dallas),Wood,NH4,2,57.0,0.0,1.02,0.0 +Forest (Dallas),BoatFactory (Dallas),Wood,CO2,3,57.0,0.0,2.68,0.0 +Forest (Dallas),BoatFactory (Dallas),Wood,NH4,3,57.0,0.0,1.02,0.0 +Forest (Dallas),BoatFactory (Dallas),Wood,CO2,4,57.0,0.0,2.68,0.0 +Forest (Dallas),BoatFactory (Dallas),Wood,NH4,4,57.0,0.0,1.02,0.0 +Forest (Dallas),BoatFactory (Dallas),Wood,CO2,5,57.0,0.0,2.68,0.0 +Forest (Dallas),BoatFactory (Dallas),Wood,NH4,5,57.0,0.0,1.02,0.0 +BoatFactory (Dallas),Retail (Dallas),NewBoat,CO2,1,63.15789,0.0,2.68,0.0 +BoatFactory (Dallas),Retail (Dallas),NewBoat,NH4,1,63.15789,0.0,1.02,0.0 +BoatFactory (Dallas),Retail (Dallas),NewBoat,CO2,2,71.46814,0.0,2.68,0.0 +BoatFactory (Dallas),Retail (Dallas),NewBoat,NH4,2,71.46814,0.0,1.02,0.0 +BoatFactory (Dallas),Retail (Dallas),NewBoat,CO2,3,75.8857,0.0,2.68,0.0 +BoatFactory (Dallas),Retail (Dallas),NewBoat,NH4,3,75.8857,0.0,1.02,0.0 +BoatFactory (Dallas),Retail (Dallas),NewBoat,CO2,4,76.90434,0.0,2.68,0.0 +BoatFactory (Dallas),Retail (Dallas),NewBoat,NH4,4,76.90434,0.0,1.02,0.0 +BoatFactory (Dallas),Retail (Dallas),NewBoat,CO2,5,77.27087,0.0,2.68,0.0 +BoatFactory (Dallas),Retail (Dallas),NewBoat,NH4,5,77.27087,0.0,1.02,0.0 +Retail (Dallas),RecyclingPlant (Dallas),UsedBoat,CO2,1,6.31579,0.0,2.68,0.0 +Retail (Dallas),RecyclingPlant (Dallas),UsedBoat,NH4,1,6.31579,0.0,1.02,0.0 +Retail (Dallas),RecyclingPlant (Dallas),UsedBoat,CO2,2,22.93629,0.0,2.68,0.0 +Retail (Dallas),RecyclingPlant (Dallas),UsedBoat,NH4,2,22.93629,0.0,1.02,0.0 +Retail (Dallas),RecyclingPlant (Dallas),UsedBoat,CO2,3,31.7714,0.0,2.68,0.0 +Retail (Dallas),RecyclingPlant (Dallas),UsedBoat,NH4,3,31.7714,0.0,1.02,0.0 +Retail (Dallas),RecyclingPlant (Dallas),UsedBoat,CO2,4,33.80867,0.0,2.68,0.0 +Retail (Dallas),RecyclingPlant (Dallas),UsedBoat,NH4,4,33.80867,0.0,1.02,0.0 +Retail (Dallas),RecyclingPlant (Dallas),UsedBoat,CO2,5,34.54174,0.0,2.68,0.0 +Retail (Dallas),RecyclingPlant (Dallas),UsedBoat,NH4,5,34.54174,0.0,1.02,0.0 diff --git a/test/src/model/build_test.jl b/test/src/model/build_test.jl index db6c43f..c167321 100644 --- a/test/src/model/build_test.jl +++ b/test/src/model/build_test.jl @@ -9,6 +9,7 @@ function model_build_test() y = model[:y] z_disp = model[:z_disp] z_input = model[:z_input] + z_tr_em = model[:z_tr_em] x = model[:x] obj = objective_function(model) # print(model) @@ -44,6 +45,12 @@ function model_build_test() 300 # fixed operating 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)) + # 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" @@ -118,4 +125,8 @@ function model_build_test() @test repr(model[:eq_disposal_limit]["P3", 1]) == "eq_disposal_limit[P3,1] : z_disp[L1,P3,1] + z_disp[C1,P3,1] ≤ 5" @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" end