diff --git a/src/RELOG.jl b/src/RELOG.jl index 9ba3bb1..82d1d52 100644 --- a/src/RELOG.jl +++ b/src/RELOG.jl @@ -1,5 +1,7 @@ module RELOG +_round(x::Number) = round(x, digits = 5) + include("instance/structs.jl") include("instance/parse.jl") include("model/jumpext.jl") diff --git a/src/model/build.jl b/src/model/build.jl index 99154ab..47d4992 100644 --- a/src/model/build.jl +++ b/src/model/build.jl @@ -119,12 +119,16 @@ function build_model(instance::Instance; optimizer, variable_names::Bool = false # Transportation cost for (p1, p2, m) in E, t in T - add_to_expression!(obj, distances[p1, p2, m], y[p1.name, p2.name, m.name, t]) + add_to_expression!( + obj, + distances[p1, p2, m] * m.tr_cost[t], + y[p1.name, p2.name, m.name, t], + ) end # Center: Revenue for c in centers, (p, m) in E_in[c], t in T - add_to_expression!(obj, c.revenue[t], y[p.name, c.name, m.name, t]) + add_to_expression!(obj, -c.revenue[t], y[p.name, c.name, m.name, t]) end # Center: Collection cost @@ -240,7 +244,8 @@ function build_model(instance::Instance; optimizer, variable_names::Bool = false eq_building_period = _init(model, :eq_building_period) for p in plants, t in T if t ∉ instance.building_period - eq_building_period[p.name, t] = @constraint(model, x[p.name, t] == 0) + eq_building_period[p.name, t] = + @constraint(model, x[p.name, t] - x[p.name, t-1] <= 0) end end diff --git a/src/reports/centers.jl b/src/reports/centers.jl index bbff8c4..4d3e8b8 100644 --- a/src/reports/centers.jl +++ b/src/reports/centers.jl @@ -11,14 +11,35 @@ function centers_report(model)::DataFrame df."year" = Int[] df."input product" = String[] df."input amount (tonne)" = Float64[] + df."revenue (\$)" = Float64[] + df."operating cost (\$)" = Float64[] centers = model.ext[:instance].centers T = 1:model.ext[:instance].time_horizon + E_in = model.ext[:E_in] for c in centers, t in T input_name = (c.input === nothing) ? "" : c.input.name - input = round(value(model[:z_input][c.name, t]), digits = 3) - push!(df, [c.name, t, input_name, input]) + input = value(model[:z_input][c.name, t]) + if isempty(E_in[c]) + revenue = 0 + else + revenue = sum( + c.revenue[t] * value(model[:y][p.name, c.name, m.name, t]) for + (p, m) in E_in[c] + ) + end + push!( + df, + [ + c.name, + t, + input_name, + _round(input), + _round(revenue), + _round(c.operating_cost[t]), + ], + ) end return df end @@ -30,14 +51,37 @@ function center_outputs_report(model)::DataFrame df."year" = Int[] df."amount collected (tonne)" = Float64[] df."amount disposed (tonne)" = Float64[] + df."collection cost (\$)" = Float64[] + df."disposal cost (\$)" = Float64[] centers = model.ext[:instance].centers T = 1:model.ext[:instance].time_horizon + E_out = model.ext[:E_out] for c in centers, m in c.outputs, t in T - collected = round(value(model[:z_collected][c.name, m.name, t]), digits = 3) - disposed = round(value(model[:z_disp][c.name, m.name, t]), digits = 3) - push!(df, [c.name, m.name, t, collected, disposed]) + collected = value(model[:z_collected][c.name, m.name, t]) + disposed = value(model[:z_disp][c.name, m.name, t]) + disposal_cost = c.disposal_cost[m][t] * disposed + if isempty(E_out[c]) + collection_cost = 0 + else + collection_cost = sum( + c.collection_cost[m][t] * value(model[:y][c.name, p.name, m.name, t]) + for (p, m) in E_out[c] + ) + end + push!( + df, + [ + c.name, + m.name, + t, + _round(collected), + _round(disposed), + _round(collection_cost), + _round(disposal_cost), + ], + ) end return df end diff --git a/src/reports/plants.jl b/src/reports/plants.jl index 68cd9c7..e3d3cbe 100644 --- a/src/reports/plants.jl +++ b/src/reports/plants.jl @@ -11,6 +11,9 @@ function plants_report(model)::DataFrame df."year" = Int[] df."operational?" = Bool[] df."input amount (tonne)" = Float64[] + df."opening cost (\$)" = Float64[] + df."fixed operating cost (\$)" = Float64[] + df."variable operating cost (\$)" = Float64[] plants = model.ext[:instance].plants T = 1:model.ext[:instance].time_horizon @@ -18,8 +21,24 @@ 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]) - operational || continue - push!(df, [p.name, t, operational, input]) + opening_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 + 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, + [ + p.name, + t, + operational, + _round(input), + _round(opening_cost), + _round(fix_operating_cost), + _round(var_operating_cost), + ], + ) end return df end @@ -31,6 +50,7 @@ function plant_outputs_report(model)::DataFrame df."year" = Int[] df."amount produced (tonne)" = Float64[] df."amount disposed (tonne)" = Float64[] + df."disposal cost (\$)" = Float64[] plants = model.ext[:instance].plants T = 1:model.ext[:instance].time_horizon @@ -38,8 +58,11 @@ function plant_outputs_report(model)::DataFrame for p in plants, m in keys(p.output), t in T produced = JuMP.value(model[:z_prod][p.name, m.name, t]) disposed = JuMP.value(model[:z_disp][p.name, m.name, t]) - produced > 1e-3 || continue - push!(df, [p.name, m.name, t, produced, disposed]) + disposal_cost = p.disposal_cost[m][t] * disposed + push!( + df, + [p.name, m.name, t, _round(produced), _round(disposed), _round(disposal_cost)], + ) end return df end diff --git a/src/reports/transportation.jl b/src/reports/transportation.jl index 99cee0f..ca98906 100644 --- a/src/reports/transportation.jl +++ b/src/reports/transportation.jl @@ -13,6 +13,9 @@ function transportation_report(model)::DataFrame df."year" = Int[] df."amount sent (tonne)" = Float64[] df."distance (km)" = Float64[] + df."transportation cost (\$)" = Float64[] + df."center revenue (\$)" = Float64[] + df."center collection cost (\$)" = Float64[] E = model.ext[:E] distances = model.ext[:distances] @@ -22,7 +25,29 @@ function transportation_report(model)::DataFrame amount = value(model[:y][p1.name, p2.name, m.name, t]) amount > 1e-3 || continue distance = distances[p1, p2, m] - push!(df, [p1.name, p2.name, m.name, t, amount, distance]) + tr_cost = distance * amount * m.tr_cost[t] + revenue = 0 + if isa(p2, Center) + revenue = p2.revenue[t] * amount + end + collection_cost = 0 + if isa(p1, Center) + collection_cost = p1.collection_cost[m][t] * amount + end + push!( + df, + [ + p1.name, + p2.name, + m.name, + t, + _round(amount), + _round(distance), + _round(tr_cost), + _round(revenue), + _round(collection_cost), + ], + ) end return df end diff --git a/test/fixtures/boat_example.ipynb b/test/fixtures/boat_example.ipynb index 769462f..777752b 100644 --- a/test/fixtures/boat_example.ipynb +++ b/test/fixtures/boat_example.ipynb @@ -2,59 +2,33 @@ "cells": [ { "cell_type": "code", - "execution_count": 67, + "execution_count": 115, "metadata": {}, "outputs": [], "source": [ "import json\n", "\n", - "# cities_a = {\n", - "# \"Chicago\": [41.881832, -87.623177],\n", - "# \"New York City\": [40.712776, -74.005974],\n", - "# \"Los Angeles\": [34.052235, -118.243683],\n", - "# \"Houston\": [29.760427, -95.369804],\n", - "# \"Phoenix\": [33.448376, -112.074036],\n", - "# \"Philadelphia\": [39.952583, -75.165222],\n", - "# \"San Antonio\": [29.424122, -98.493629],\n", - "# \"San Diego\": [32.715736, -117.161087],\n", - "# \"Dallas\": [32.776664, -96.796988],\n", - "# \"San Jose\": [37.338208, -121.886329],\n", - "# \"Austin\": [30.267153, -97.743061],\n", - "# \"Jacksonville\": [30.332184, -81.655651],\n", - "# \"Fort Worth\": [32.755488, -97.330766],\n", - "# \"Columbus\": [39.961176, -82.998794],\n", - "# \"Charlotte\": [35.227087, -80.843127],\n", - "# \"Indianapolis\": [39.768403, -86.158068],\n", - "# \"San Francisco\": [37.774929, -122.419416],\n", - "# \"Seattle\": [47.606209, -122.332071],\n", - "# \"Denver\": [39.739236, -104.990251],\n", - "# \"Washington D.C.\": [38.907192, -77.036871],\n", - "# \"Nashville\": [36.162664, -86.781602],\n", - "# \"Detroit\": [42.331427, -83.045754],\n", - "# \"Oklahoma City\": [35.467560, -97.516428],\n", - "# \"Portland\": [45.505106, -122.675026],\n", - "# \"Las Vegas\": [36.169941, -115.139830],\n", - "# }\n", - "\n", - "# cities_b = {\n", - "# \"Chicago\": [41.881832, -87.623177],\n", - "# \"Phoenix\": [33.448376, -112.074036],\n", - "# \"Dallas\": [32.776664, -96.796988],\n", - "# \"San Jose\": [37.338208, -121.886329],\n", - "# \"Seattle\": [47.606209, -122.332071],\n", - "# \"Las Vegas\": [36.169941, -115.139830],\n", - "# }\n", - "\n", "cities_a = {\n", " \"Chicago\": [41.881832, -87.623177],\n", + " \"New York City\": [40.712776, -74.005974],\n", + " \"Los Angeles\": [34.052235, -118.243683],\n", + " \"Houston\": [29.760427, -95.369804],\n", + " \"Phoenix\": [33.448376, -112.074036],\n", + " \"Philadelphia\": [39.952583, -75.165222],\n", + " \"San Antonio\": [29.424122, -98.493629],\n", + " \"San Diego\": [32.715736, -117.161087],\n", + " \"Dallas\": [32.776664, -96.796988],\n", + " \"San Jose\": [37.338208, -121.886329],\n", "}\n", "\n", "cities_b = {\n", " \"Chicago\": [41.881832, -87.623177],\n", + " \"Phoenix\": [33.448376, -112.074036],\n", + " \"Dallas\": [32.776664, -96.796988],\n", "}\n", "\n", "parameters = {\n", - " \"time horizon (years)\": 1,\n", + " \"time horizon (years)\": 5,\n", " \"building period (years)\": [1],\n", " \"distance metric\": \"Euclidean\",\n", "}\n", @@ -67,7 +41,7 @@ " \"revenue ($/tonne)\": None,\n", " \"collection cost ($/tonne)\": {\"Nail\": 1000},\n", " \"operating cost ($)\": 0,\n", - " \"disposal limit (tonne)\": {\"Nail\": 0},\n", + " \"disposal limit (tonne)\": {\"Nail\": None},\n", " \"disposal cost ($/tonne)\": {\"Nail\": 0},\n", "}\n", "\n", @@ -79,7 +53,7 @@ " \"revenue ($/tonne)\": None,\n", " \"collection cost ($/tonne)\": {\"Wood\": 250},\n", " \"operating cost ($)\": 0,\n", - " \"disposal limit (tonne)\": {\"Wood\": 0},\n", + " \"disposal limit (tonne)\": {\"Wood\": None},\n", " \"disposal cost ($/tonne)\": {\"Wood\": 0},\n", "}\n", "\n", @@ -88,10 +62,10 @@ " \"outputs\": [\"UsedBoat\"],\n", " \"fixed output (tonne)\": {\"UsedBoat\": 0},\n", " \"variable output (tonne/tonne)\": {\"UsedBoat\": [0.10, 0.25, 0.10]},\n", - " \"revenue ($/tonne)\": 300_000,\n", + " \"revenue ($/tonne)\": 12_000,\n", " \"collection cost ($/tonne)\": {\"UsedBoat\": 100},\n", " \"operating cost ($)\": 125_000,\n", - " \"disposal limit (tonne)\": {\"UsedBoat\": 0},\n", + " \"disposal limit (tonne)\": {\"UsedBoat\": None},\n", " \"disposal cost ($/tonne)\": {\"UsedBoat\": 0},\n", "}\n", "\n", @@ -123,15 +97,15 @@ " },\n", " \"capacities\": [\n", " {\n", - " \"size (tonne)\": 200,\n", - " \"opening cost ($)\": 10_000,\n", - " \"fixed operating cost ($)\": 1_000,\n", + " \"size (tonne)\": 500,\n", + " \"opening cost ($)\": 1_000_000,\n", + " \"fixed operating cost ($)\": 250_000,\n", " \"variable operating cost ($/tonne)\": 5,\n", " },\n", " {\n", - " \"size (tonne)\": 500,\n", - " \"opening cost ($)\": 20_000,\n", - " \"fixed operating cost ($)\": 2_000,\n", + " \"size (tonne)\": 1000,\n", + " \"opening cost ($)\": 2_000_000,\n", + " \"fixed operating cost ($)\": 500_000,\n", " \"variable operating cost ($/tonne)\": 5,\n", " },\n", " ],\n", @@ -155,16 +129,15 @@ " \"disposal limit (tonne)\": {\"Nail\": 0, \"Wood\": 0},\n", " \"capacities\": [\n", " {\n", - " \"size (tonne)\": 50,\n", - " \"opening cost ($)\": 5_000,\n", - " \"fixed operating cost ($)\": 500,\n", + " \"size (tonne)\": 500,\n", + " \"opening cost ($)\": 500_000,\n", + " \"fixed operating cost ($)\": 125_000,\n", " \"variable operating cost ($/tonne)\": 2.5,\n", " },\n", " {\n", - " \"size (tonne)\": 500,\n", - " \"opening cost ($)\": 10_000,\n", - " \n", - " \"fixed operating cost ($)\": 1_000,\n", + " \"size (tonne)\": 1000,\n", + " \"opening cost ($)\": 1_000_000,\n", + " \"fixed operating cost ($)\": 250_000,\n", " \"variable operating cost ($/tonne)\": 2.5,\n", " },\n", " ],\n", @@ -174,7 +147,7 @@ }, { "cell_type": "code", - "execution_count": 68, + "execution_count": 116, "metadata": {}, "outputs": [], "source": [ @@ -200,7 +173,8 @@ " \"longitude (deg)\": city_location[1],\n", " }\n", " for (city_name, city_location) in cities_b.items()\n", - " } | {\n", + " }\n", + " | {\n", " f\"Retail ({city_name})\": {\n", " **retail,\n", " \"latitude (deg)\": city_location[0],\n", @@ -217,7 +191,8 @@ " \"longitude (deg)\": city_location[1],\n", " }\n", " for (city_name, city_location) in cities_a.items()\n", - " } | {\n", + " }\n", + " | {\n", " f\"RecyclingPlant ({city_name})\": {\n", " **recycling_plant,\n", " \"latitude (deg)\": city_location[0],\n", diff --git a/test/fixtures/boat_example.json b/test/fixtures/boat_example.json index 4a2fdfc..df7736b 100644 --- a/test/fixtures/boat_example.json +++ b/test/fixtures/boat_example.json @@ -1,6 +1,6 @@ { "parameters": { - "time horizon (years)": 1, + "time horizon (years)": 5, "building period (years)": [ 1 ], @@ -54,114 +54,1206 @@ }, "operating cost ($)": 0, "disposal limit (tonne)": { + "Nail": null + }, + "disposal cost ($/tonne)": { + "Nail": 0 + }, + "latitude (deg)": 41.881832, + "longitude (deg)": -87.623177 + }, + "NailFactory (Phoenix)": { + "input": null, + "outputs": [ + "Nail" + ], + "fixed output (tonne)": { + "Nail": 5 + }, + "variable output (tonne/tonne)": { + "Nail": 0 + }, + "revenue ($/tonne)": null, + "collection cost ($/tonne)": { + "Nail": 1000 + }, + "operating cost ($)": 0, + "disposal limit (tonne)": { + "Nail": null + }, + "disposal cost ($/tonne)": { + "Nail": 0 + }, + "latitude (deg)": 33.448376, + "longitude (deg)": -112.074036 + }, + "NailFactory (Dallas)": { + "input": null, + "outputs": [ + "Nail" + ], + "fixed output (tonne)": { + "Nail": 5 + }, + "variable output (tonne/tonne)": { + "Nail": 0 + }, + "revenue ($/tonne)": null, + "collection cost ($/tonne)": { + "Nail": 1000 + }, + "operating cost ($)": 0, + "disposal limit (tonne)": { + "Nail": null + }, + "disposal cost ($/tonne)": { "Nail": 0 }, + "latitude (deg)": 32.776664, + "longitude (deg)": -96.796988 + }, + "Forest (Chicago)": { + "input": null, + "outputs": [ + "Wood" + ], + "fixed output (tonne)": { + "Wood": 95 + }, + "variable output (tonne/tonne)": { + "Wood": 0 + }, + "revenue ($/tonne)": null, + "collection cost ($/tonne)": { + "Wood": 250 + }, + "operating cost ($)": 0, + "disposal limit (tonne)": { + "Wood": null + }, + "disposal cost ($/tonne)": { + "Wood": 0 + }, + "latitude (deg)": 41.881832, + "longitude (deg)": -87.623177 + }, + "Forest (Phoenix)": { + "input": null, + "outputs": [ + "Wood" + ], + "fixed output (tonne)": { + "Wood": 95 + }, + "variable output (tonne/tonne)": { + "Wood": 0 + }, + "revenue ($/tonne)": null, + "collection cost ($/tonne)": { + "Wood": 250 + }, + "operating cost ($)": 0, + "disposal limit (tonne)": { + "Wood": null + }, + "disposal cost ($/tonne)": { + "Wood": 0 + }, + "latitude (deg)": 33.448376, + "longitude (deg)": -112.074036 + }, + "Forest (Dallas)": { + "input": null, + "outputs": [ + "Wood" + ], + "fixed output (tonne)": { + "Wood": 95 + }, + "variable output (tonne/tonne)": { + "Wood": 0 + }, + "revenue ($/tonne)": null, + "collection cost ($/tonne)": { + "Wood": 250 + }, + "operating cost ($)": 0, + "disposal limit (tonne)": { + "Wood": null + }, + "disposal cost ($/tonne)": { + "Wood": 0 + }, + "latitude (deg)": 32.776664, + "longitude (deg)": -96.796988 + }, + "Retail (Chicago)": { + "input": "NewBoat", + "outputs": [ + "UsedBoat" + ], + "fixed output (tonne)": { + "UsedBoat": 0 + }, + "variable output (tonne/tonne)": { + "UsedBoat": [ + 0.1, + 0.25, + 0.1 + ] + }, + "revenue ($/tonne)": 12000, + "collection cost ($/tonne)": { + "UsedBoat": 100 + }, + "operating cost ($)": 125000, + "disposal limit (tonne)": { + "UsedBoat": null + }, + "disposal cost ($/tonne)": { + "UsedBoat": 0 + }, + "latitude (deg)": 41.881832, + "longitude (deg)": -87.623177 + }, + "Retail (New York City)": { + "input": "NewBoat", + "outputs": [ + "UsedBoat" + ], + "fixed output (tonne)": { + "UsedBoat": 0 + }, + "variable output (tonne/tonne)": { + "UsedBoat": [ + 0.1, + 0.25, + 0.1 + ] + }, + "revenue ($/tonne)": 12000, + "collection cost ($/tonne)": { + "UsedBoat": 100 + }, + "operating cost ($)": 125000, + "disposal limit (tonne)": { + "UsedBoat": null + }, + "disposal cost ($/tonne)": { + "UsedBoat": 0 + }, + "latitude (deg)": 40.712776, + "longitude (deg)": -74.005974 + }, + "Retail (Los Angeles)": { + "input": "NewBoat", + "outputs": [ + "UsedBoat" + ], + "fixed output (tonne)": { + "UsedBoat": 0 + }, + "variable output (tonne/tonne)": { + "UsedBoat": [ + 0.1, + 0.25, + 0.1 + ] + }, + "revenue ($/tonne)": 12000, + "collection cost ($/tonne)": { + "UsedBoat": 100 + }, + "operating cost ($)": 125000, + "disposal limit (tonne)": { + "UsedBoat": null + }, + "disposal cost ($/tonne)": { + "UsedBoat": 0 + }, + "latitude (deg)": 34.052235, + "longitude (deg)": -118.243683 + }, + "Retail (Houston)": { + "input": "NewBoat", + "outputs": [ + "UsedBoat" + ], + "fixed output (tonne)": { + "UsedBoat": 0 + }, + "variable output (tonne/tonne)": { + "UsedBoat": [ + 0.1, + 0.25, + 0.1 + ] + }, + "revenue ($/tonne)": 12000, + "collection cost ($/tonne)": { + "UsedBoat": 100 + }, + "operating cost ($)": 125000, + "disposal limit (tonne)": { + "UsedBoat": null + }, + "disposal cost ($/tonne)": { + "UsedBoat": 0 + }, + "latitude (deg)": 29.760427, + "longitude (deg)": -95.369804 + }, + "Retail (Phoenix)": { + "input": "NewBoat", + "outputs": [ + "UsedBoat" + ], + "fixed output (tonne)": { + "UsedBoat": 0 + }, + "variable output (tonne/tonne)": { + "UsedBoat": [ + 0.1, + 0.25, + 0.1 + ] + }, + "revenue ($/tonne)": 12000, + "collection cost ($/tonne)": { + "UsedBoat": 100 + }, + "operating cost ($)": 125000, + "disposal limit (tonne)": { + "UsedBoat": null + }, + "disposal cost ($/tonne)": { + "UsedBoat": 0 + }, + "latitude (deg)": 33.448376, + "longitude (deg)": -112.074036 + }, + "Retail (Philadelphia)": { + "input": "NewBoat", + "outputs": [ + "UsedBoat" + ], + "fixed output (tonne)": { + "UsedBoat": 0 + }, + "variable output (tonne/tonne)": { + "UsedBoat": [ + 0.1, + 0.25, + 0.1 + ] + }, + "revenue ($/tonne)": 12000, + "collection cost ($/tonne)": { + "UsedBoat": 100 + }, + "operating cost ($)": 125000, + "disposal limit (tonne)": { + "UsedBoat": null + }, + "disposal cost ($/tonne)": { + "UsedBoat": 0 + }, + "latitude (deg)": 39.952583, + "longitude (deg)": -75.165222 + }, + "Retail (San Antonio)": { + "input": "NewBoat", + "outputs": [ + "UsedBoat" + ], + "fixed output (tonne)": { + "UsedBoat": 0 + }, + "variable output (tonne/tonne)": { + "UsedBoat": [ + 0.1, + 0.25, + 0.1 + ] + }, + "revenue ($/tonne)": 12000, + "collection cost ($/tonne)": { + "UsedBoat": 100 + }, + "operating cost ($)": 125000, + "disposal limit (tonne)": { + "UsedBoat": null + }, + "disposal cost ($/tonne)": { + "UsedBoat": 0 + }, + "latitude (deg)": 29.424122, + "longitude (deg)": -98.493629 + }, + "Retail (San Diego)": { + "input": "NewBoat", + "outputs": [ + "UsedBoat" + ], + "fixed output (tonne)": { + "UsedBoat": 0 + }, + "variable output (tonne/tonne)": { + "UsedBoat": [ + 0.1, + 0.25, + 0.1 + ] + }, + "revenue ($/tonne)": 12000, + "collection cost ($/tonne)": { + "UsedBoat": 100 + }, + "operating cost ($)": 125000, + "disposal limit (tonne)": { + "UsedBoat": null + }, + "disposal cost ($/tonne)": { + "UsedBoat": 0 + }, + "latitude (deg)": 32.715736, + "longitude (deg)": -117.161087 + }, + "Retail (Dallas)": { + "input": "NewBoat", + "outputs": [ + "UsedBoat" + ], + "fixed output (tonne)": { + "UsedBoat": 0 + }, + "variable output (tonne/tonne)": { + "UsedBoat": [ + 0.1, + 0.25, + 0.1 + ] + }, + "revenue ($/tonne)": 12000, + "collection cost ($/tonne)": { + "UsedBoat": 100 + }, + "operating cost ($)": 125000, + "disposal limit (tonne)": { + "UsedBoat": null + }, + "disposal cost ($/tonne)": { + "UsedBoat": 0 + }, + "latitude (deg)": 32.776664, + "longitude (deg)": -96.796988 + }, + "Retail (San Jose)": { + "input": "NewBoat", + "outputs": [ + "UsedBoat" + ], + "fixed output (tonne)": { + "UsedBoat": 0 + }, + "variable output (tonne/tonne)": { + "UsedBoat": [ + 0.1, + 0.25, + 0.1 + ] + }, + "revenue ($/tonne)": 12000, + "collection cost ($/tonne)": { + "UsedBoat": 100 + }, + "operating cost ($)": 125000, + "disposal limit (tonne)": { + "UsedBoat": null + }, + "disposal cost ($/tonne)": { + "UsedBoat": 0 + }, + "latitude (deg)": 37.338208, + "longitude (deg)": -121.886329 + } + }, + "plants": { + "BoatFactory (Chicago)": { + "input mix (%)": { + "Wood": 95, + "Nail": 5 + }, + "output (tonne)": { + "NewBoat": 1.0 + }, + "processing emissions (tonne)": { + "CO2": 5 + }, + "storage cost ($/tonne)": { + "Wood": 500, + "Nail": 200 + }, + "storage limit (tonne)": { + "Wood": 5, + "Nail": 1 + }, + "disposal cost ($/tonne)": { + "NewBoat": 0 + }, + "disposal limit (tonne)": { + "NewBoat": 0 + }, + "capacities": [ + { + "size (tonne)": 500, + "opening cost ($)": 1000000, + "fixed operating cost ($)": 250000, + "variable operating cost ($/tonne)": 5 + }, + { + "size (tonne)": 1000, + "opening cost ($)": 2000000, + "fixed operating cost ($)": 500000, + "variable operating cost ($/tonne)": 5 + } + ], + "initial capacity (tonne)": 0, + "latitude (deg)": 41.881832, + "longitude (deg)": -87.623177 + }, + "BoatFactory (New York City)": { + "input mix (%)": { + "Wood": 95, + "Nail": 5 + }, + "output (tonne)": { + "NewBoat": 1.0 + }, + "processing emissions (tonne)": { + "CO2": 5 + }, + "storage cost ($/tonne)": { + "Wood": 500, + "Nail": 200 + }, + "storage limit (tonne)": { + "Wood": 5, + "Nail": 1 + }, + "disposal cost ($/tonne)": { + "NewBoat": 0 + }, + "disposal limit (tonne)": { + "NewBoat": 0 + }, + "capacities": [ + { + "size (tonne)": 500, + "opening cost ($)": 1000000, + "fixed operating cost ($)": 250000, + "variable operating cost ($/tonne)": 5 + }, + { + "size (tonne)": 1000, + "opening cost ($)": 2000000, + "fixed operating cost ($)": 500000, + "variable operating cost ($/tonne)": 5 + } + ], + "initial capacity (tonne)": 0, + "latitude (deg)": 40.712776, + "longitude (deg)": -74.005974 + }, + "BoatFactory (Los Angeles)": { + "input mix (%)": { + "Wood": 95, + "Nail": 5 + }, + "output (tonne)": { + "NewBoat": 1.0 + }, + "processing emissions (tonne)": { + "CO2": 5 + }, + "storage cost ($/tonne)": { + "Wood": 500, + "Nail": 200 + }, + "storage limit (tonne)": { + "Wood": 5, + "Nail": 1 + }, + "disposal cost ($/tonne)": { + "NewBoat": 0 + }, + "disposal limit (tonne)": { + "NewBoat": 0 + }, + "capacities": [ + { + "size (tonne)": 500, + "opening cost ($)": 1000000, + "fixed operating cost ($)": 250000, + "variable operating cost ($/tonne)": 5 + }, + { + "size (tonne)": 1000, + "opening cost ($)": 2000000, + "fixed operating cost ($)": 500000, + "variable operating cost ($/tonne)": 5 + } + ], + "initial capacity (tonne)": 0, + "latitude (deg)": 34.052235, + "longitude (deg)": -118.243683 + }, + "BoatFactory (Houston)": { + "input mix (%)": { + "Wood": 95, + "Nail": 5 + }, + "output (tonne)": { + "NewBoat": 1.0 + }, + "processing emissions (tonne)": { + "CO2": 5 + }, + "storage cost ($/tonne)": { + "Wood": 500, + "Nail": 200 + }, + "storage limit (tonne)": { + "Wood": 5, + "Nail": 1 + }, + "disposal cost ($/tonne)": { + "NewBoat": 0 + }, + "disposal limit (tonne)": { + "NewBoat": 0 + }, + "capacities": [ + { + "size (tonne)": 500, + "opening cost ($)": 1000000, + "fixed operating cost ($)": 250000, + "variable operating cost ($/tonne)": 5 + }, + { + "size (tonne)": 1000, + "opening cost ($)": 2000000, + "fixed operating cost ($)": 500000, + "variable operating cost ($/tonne)": 5 + } + ], + "initial capacity (tonne)": 0, + "latitude (deg)": 29.760427, + "longitude (deg)": -95.369804 + }, + "BoatFactory (Phoenix)": { + "input mix (%)": { + "Wood": 95, + "Nail": 5 + }, + "output (tonne)": { + "NewBoat": 1.0 + }, + "processing emissions (tonne)": { + "CO2": 5 + }, + "storage cost ($/tonne)": { + "Wood": 500, + "Nail": 200 + }, + "storage limit (tonne)": { + "Wood": 5, + "Nail": 1 + }, + "disposal cost ($/tonne)": { + "NewBoat": 0 + }, + "disposal limit (tonne)": { + "NewBoat": 0 + }, + "capacities": [ + { + "size (tonne)": 500, + "opening cost ($)": 1000000, + "fixed operating cost ($)": 250000, + "variable operating cost ($/tonne)": 5 + }, + { + "size (tonne)": 1000, + "opening cost ($)": 2000000, + "fixed operating cost ($)": 500000, + "variable operating cost ($/tonne)": 5 + } + ], + "initial capacity (tonne)": 0, + "latitude (deg)": 33.448376, + "longitude (deg)": -112.074036 + }, + "BoatFactory (Philadelphia)": { + "input mix (%)": { + "Wood": 95, + "Nail": 5 + }, + "output (tonne)": { + "NewBoat": 1.0 + }, + "processing emissions (tonne)": { + "CO2": 5 + }, + "storage cost ($/tonne)": { + "Wood": 500, + "Nail": 200 + }, + "storage limit (tonne)": { + "Wood": 5, + "Nail": 1 + }, + "disposal cost ($/tonne)": { + "NewBoat": 0 + }, + "disposal limit (tonne)": { + "NewBoat": 0 + }, + "capacities": [ + { + "size (tonne)": 500, + "opening cost ($)": 1000000, + "fixed operating cost ($)": 250000, + "variable operating cost ($/tonne)": 5 + }, + { + "size (tonne)": 1000, + "opening cost ($)": 2000000, + "fixed operating cost ($)": 500000, + "variable operating cost ($/tonne)": 5 + } + ], + "initial capacity (tonne)": 0, + "latitude (deg)": 39.952583, + "longitude (deg)": -75.165222 + }, + "BoatFactory (San Antonio)": { + "input mix (%)": { + "Wood": 95, + "Nail": 5 + }, + "output (tonne)": { + "NewBoat": 1.0 + }, + "processing emissions (tonne)": { + "CO2": 5 + }, + "storage cost ($/tonne)": { + "Wood": 500, + "Nail": 200 + }, + "storage limit (tonne)": { + "Wood": 5, + "Nail": 1 + }, + "disposal cost ($/tonne)": { + "NewBoat": 0 + }, + "disposal limit (tonne)": { + "NewBoat": 0 + }, + "capacities": [ + { + "size (tonne)": 500, + "opening cost ($)": 1000000, + "fixed operating cost ($)": 250000, + "variable operating cost ($/tonne)": 5 + }, + { + "size (tonne)": 1000, + "opening cost ($)": 2000000, + "fixed operating cost ($)": 500000, + "variable operating cost ($/tonne)": 5 + } + ], + "initial capacity (tonne)": 0, + "latitude (deg)": 29.424122, + "longitude (deg)": -98.493629 + }, + "BoatFactory (San Diego)": { + "input mix (%)": { + "Wood": 95, + "Nail": 5 + }, + "output (tonne)": { + "NewBoat": 1.0 + }, + "processing emissions (tonne)": { + "CO2": 5 + }, + "storage cost ($/tonne)": { + "Wood": 500, + "Nail": 200 + }, + "storage limit (tonne)": { + "Wood": 5, + "Nail": 1 + }, + "disposal cost ($/tonne)": { + "NewBoat": 0 + }, + "disposal limit (tonne)": { + "NewBoat": 0 + }, + "capacities": [ + { + "size (tonne)": 500, + "opening cost ($)": 1000000, + "fixed operating cost ($)": 250000, + "variable operating cost ($/tonne)": 5 + }, + { + "size (tonne)": 1000, + "opening cost ($)": 2000000, + "fixed operating cost ($)": 500000, + "variable operating cost ($/tonne)": 5 + } + ], + "initial capacity (tonne)": 0, + "latitude (deg)": 32.715736, + "longitude (deg)": -117.161087 + }, + "BoatFactory (Dallas)": { + "input mix (%)": { + "Wood": 95, + "Nail": 5 + }, + "output (tonne)": { + "NewBoat": 1.0 + }, + "processing emissions (tonne)": { + "CO2": 5 + }, + "storage cost ($/tonne)": { + "Wood": 500, + "Nail": 200 + }, + "storage limit (tonne)": { + "Wood": 5, + "Nail": 1 + }, + "disposal cost ($/tonne)": { + "NewBoat": 0 + }, + "disposal limit (tonne)": { + "NewBoat": 0 + }, + "capacities": [ + { + "size (tonne)": 500, + "opening cost ($)": 1000000, + "fixed operating cost ($)": 250000, + "variable operating cost ($/tonne)": 5 + }, + { + "size (tonne)": 1000, + "opening cost ($)": 2000000, + "fixed operating cost ($)": 500000, + "variable operating cost ($/tonne)": 5 + } + ], + "initial capacity (tonne)": 0, + "latitude (deg)": 32.776664, + "longitude (deg)": -96.796988 + }, + "BoatFactory (San Jose)": { + "input mix (%)": { + "Wood": 95, + "Nail": 5 + }, + "output (tonne)": { + "NewBoat": 1.0 + }, + "processing emissions (tonne)": { + "CO2": 5 + }, + "storage cost ($/tonne)": { + "Wood": 500, + "Nail": 200 + }, + "storage limit (tonne)": { + "Wood": 5, + "Nail": 1 + }, + "disposal cost ($/tonne)": { + "NewBoat": 0 + }, + "disposal limit (tonne)": { + "NewBoat": 0 + }, + "capacities": [ + { + "size (tonne)": 500, + "opening cost ($)": 1000000, + "fixed operating cost ($)": 250000, + "variable operating cost ($/tonne)": 5 + }, + { + "size (tonne)": 1000, + "opening cost ($)": 2000000, + "fixed operating cost ($)": 500000, + "variable operating cost ($/tonne)": 5 + } + ], + "initial capacity (tonne)": 0, + "latitude (deg)": 37.338208, + "longitude (deg)": -121.886329 + }, + "RecyclingPlant (Chicago)": { + "input mix (%)": { + "UsedBoat": 100 + }, + "output (tonne)": { + "Nail": 0.025, + "Wood": 0.475 + }, + "processing emissions (tonne)": { + "CO2": 5 + }, + "storage cost ($/tonne)": { + "UsedBoat": 0 + }, + "storage limit (tonne)": { + "UsedBoat": 0 + }, + "disposal cost ($/tonne)": { + "Nail": 0, + "Wood": 0 + }, + "disposal limit (tonne)": { + "Nail": 0, + "Wood": 0 + }, + "capacities": [ + { + "size (tonne)": 500, + "opening cost ($)": 500000, + "fixed operating cost ($)": 125000, + "variable operating cost ($/tonne)": 2.5 + }, + { + "size (tonne)": 1000, + "opening cost ($)": 1000000, + "fixed operating cost ($)": 250000, + "variable operating cost ($/tonne)": 2.5 + } + ], + "initial capacity (tonne)": 0, + "latitude (deg)": 41.881832, + "longitude (deg)": -87.623177 + }, + "RecyclingPlant (New York City)": { + "input mix (%)": { + "UsedBoat": 100 + }, + "output (tonne)": { + "Nail": 0.025, + "Wood": 0.475 + }, + "processing emissions (tonne)": { + "CO2": 5 + }, + "storage cost ($/tonne)": { + "UsedBoat": 0 + }, + "storage limit (tonne)": { + "UsedBoat": 0 + }, + "disposal cost ($/tonne)": { + "Nail": 0, + "Wood": 0 + }, + "disposal limit (tonne)": { + "Nail": 0, + "Wood": 0 + }, + "capacities": [ + { + "size (tonne)": 500, + "opening cost ($)": 500000, + "fixed operating cost ($)": 125000, + "variable operating cost ($/tonne)": 2.5 + }, + { + "size (tonne)": 1000, + "opening cost ($)": 1000000, + "fixed operating cost ($)": 250000, + "variable operating cost ($/tonne)": 2.5 + } + ], + "initial capacity (tonne)": 0, + "latitude (deg)": 40.712776, + "longitude (deg)": -74.005974 + }, + "RecyclingPlant (Los Angeles)": { + "input mix (%)": { + "UsedBoat": 100 + }, + "output (tonne)": { + "Nail": 0.025, + "Wood": 0.475 + }, + "processing emissions (tonne)": { + "CO2": 5 + }, + "storage cost ($/tonne)": { + "UsedBoat": 0 + }, + "storage limit (tonne)": { + "UsedBoat": 0 + }, "disposal cost ($/tonne)": { - "Nail": 0 + "Nail": 0, + "Wood": 0 }, - "latitude (deg)": 41.881832, - "longitude (deg)": -87.623177 - }, - "Forest (Chicago)": { - "input": null, - "outputs": [ - "Wood" + "disposal limit (tonne)": { + "Nail": 0, + "Wood": 0 + }, + "capacities": [ + { + "size (tonne)": 500, + "opening cost ($)": 500000, + "fixed operating cost ($)": 125000, + "variable operating cost ($/tonne)": 2.5 + }, + { + "size (tonne)": 1000, + "opening cost ($)": 1000000, + "fixed operating cost ($)": 250000, + "variable operating cost ($/tonne)": 2.5 + } ], - "fixed output (tonne)": { - "Wood": 95 + "initial capacity (tonne)": 0, + "latitude (deg)": 34.052235, + "longitude (deg)": -118.243683 + }, + "RecyclingPlant (Houston)": { + "input mix (%)": { + "UsedBoat": 100 }, - "variable output (tonne/tonne)": { - "Wood": 0 + "output (tonne)": { + "Nail": 0.025, + "Wood": 0.475 }, - "revenue ($/tonne)": null, - "collection cost ($/tonne)": { - "Wood": 250 + "processing emissions (tonne)": { + "CO2": 5 + }, + "storage cost ($/tonne)": { + "UsedBoat": 0 + }, + "storage limit (tonne)": { + "UsedBoat": 0 + }, + "disposal cost ($/tonne)": { + "Nail": 0, + "Wood": 0 }, - "operating cost ($)": 0, "disposal limit (tonne)": { + "Nail": 0, "Wood": 0 }, + "capacities": [ + { + "size (tonne)": 500, + "opening cost ($)": 500000, + "fixed operating cost ($)": 125000, + "variable operating cost ($/tonne)": 2.5 + }, + { + "size (tonne)": 1000, + "opening cost ($)": 1000000, + "fixed operating cost ($)": 250000, + "variable operating cost ($/tonne)": 2.5 + } + ], + "initial capacity (tonne)": 0, + "latitude (deg)": 29.760427, + "longitude (deg)": -95.369804 + }, + "RecyclingPlant (Phoenix)": { + "input mix (%)": { + "UsedBoat": 100 + }, + "output (tonne)": { + "Nail": 0.025, + "Wood": 0.475 + }, + "processing emissions (tonne)": { + "CO2": 5 + }, + "storage cost ($/tonne)": { + "UsedBoat": 0 + }, + "storage limit (tonne)": { + "UsedBoat": 0 + }, "disposal cost ($/tonne)": { + "Nail": 0, "Wood": 0 }, - "latitude (deg)": 41.881832, - "longitude (deg)": -87.623177 - }, - "Retail (Chicago)": { - "input": "NewBoat", - "outputs": [ - "UsedBoat" + "disposal limit (tonne)": { + "Nail": 0, + "Wood": 0 + }, + "capacities": [ + { + "size (tonne)": 500, + "opening cost ($)": 500000, + "fixed operating cost ($)": 125000, + "variable operating cost ($/tonne)": 2.5 + }, + { + "size (tonne)": 1000, + "opening cost ($)": 1000000, + "fixed operating cost ($)": 250000, + "variable operating cost ($/tonne)": 2.5 + } ], - "fixed output (tonne)": { + "initial capacity (tonne)": 0, + "latitude (deg)": 33.448376, + "longitude (deg)": -112.074036 + }, + "RecyclingPlant (Philadelphia)": { + "input mix (%)": { + "UsedBoat": 100 + }, + "output (tonne)": { + "Nail": 0.025, + "Wood": 0.475 + }, + "processing emissions (tonne)": { + "CO2": 5 + }, + "storage cost ($/tonne)": { "UsedBoat": 0 }, - "variable output (tonne/tonne)": { - "UsedBoat": [ - 0.1, - 0.25, - 0.1 - ] + "storage limit (tonne)": { + "UsedBoat": 0 }, - "revenue ($/tonne)": 300000, - "collection cost ($/tonne)": { - "UsedBoat": 100 + "disposal cost ($/tonne)": { + "Nail": 0, + "Wood": 0 }, - "operating cost ($)": 125000, "disposal limit (tonne)": { + "Nail": 0, + "Wood": 0 + }, + "capacities": [ + { + "size (tonne)": 500, + "opening cost ($)": 500000, + "fixed operating cost ($)": 125000, + "variable operating cost ($/tonne)": 2.5 + }, + { + "size (tonne)": 1000, + "opening cost ($)": 1000000, + "fixed operating cost ($)": 250000, + "variable operating cost ($/tonne)": 2.5 + } + ], + "initial capacity (tonne)": 0, + "latitude (deg)": 39.952583, + "longitude (deg)": -75.165222 + }, + "RecyclingPlant (San Antonio)": { + "input mix (%)": { + "UsedBoat": 100 + }, + "output (tonne)": { + "Nail": 0.025, + "Wood": 0.475 + }, + "processing emissions (tonne)": { + "CO2": 5 + }, + "storage cost ($/tonne)": { "UsedBoat": 0 }, - "disposal cost ($/tonne)": { + "storage limit (tonne)": { "UsedBoat": 0 }, - "latitude (deg)": 41.881832, - "longitude (deg)": -87.623177 - } - }, - "plants": { - "BoatFactory (Chicago)": { + "disposal cost ($/tonne)": { + "Nail": 0, + "Wood": 0 + }, + "disposal limit (tonne)": { + "Nail": 0, + "Wood": 0 + }, + "capacities": [ + { + "size (tonne)": 500, + "opening cost ($)": 500000, + "fixed operating cost ($)": 125000, + "variable operating cost ($/tonne)": 2.5 + }, + { + "size (tonne)": 1000, + "opening cost ($)": 1000000, + "fixed operating cost ($)": 250000, + "variable operating cost ($/tonne)": 2.5 + } + ], + "initial capacity (tonne)": 0, + "latitude (deg)": 29.424122, + "longitude (deg)": -98.493629 + }, + "RecyclingPlant (San Diego)": { "input mix (%)": { - "Wood": 95, - "Nail": 5 + "UsedBoat": 100 }, "output (tonne)": { - "NewBoat": 1.0 + "Nail": 0.025, + "Wood": 0.475 }, "processing emissions (tonne)": { "CO2": 5 }, "storage cost ($/tonne)": { - "Wood": 500, - "Nail": 200 + "UsedBoat": 0 }, "storage limit (tonne)": { - "Wood": 5, - "Nail": 1 + "UsedBoat": 0 }, "disposal cost ($/tonne)": { - "NewBoat": 0 + "Nail": 0, + "Wood": 0 }, "disposal limit (tonne)": { - "NewBoat": 0 + "Nail": 0, + "Wood": 0 }, "capacities": [ { - "size (tonne)": 200, - "opening cost ($)": 10000, - "fixed operating cost ($)": 1000, - "variable operating cost ($/tonne)": 5 + "size (tonne)": 500, + "opening cost ($)": 500000, + "fixed operating cost ($)": 125000, + "variable operating cost ($/tonne)": 2.5 }, { - "size (tonne)": 500, - "opening cost ($)": 20000, - "fixed operating cost ($)": 2000, - "variable operating cost ($/tonne)": 5 + "size (tonne)": 1000, + "opening cost ($)": 1000000, + "fixed operating cost ($)": 250000, + "variable operating cost ($/tonne)": 2.5 } ], "initial capacity (tonne)": 0, - "latitude (deg)": 41.881832, - "longitude (deg)": -87.623177 + "latitude (deg)": 32.715736, + "longitude (deg)": -117.161087 }, - "RecyclingPlant (Chicago)": { + "RecyclingPlant (Dallas)": { "input mix (%)": { "UsedBoat": 100 }, @@ -188,21 +1280,64 @@ }, "capacities": [ { - "size (tonne)": 50, - "opening cost ($)": 5000, - "fixed operating cost ($)": 500, + "size (tonne)": 500, + "opening cost ($)": 500000, + "fixed operating cost ($)": 125000, "variable operating cost ($/tonne)": 2.5 }, + { + "size (tonne)": 1000, + "opening cost ($)": 1000000, + "fixed operating cost ($)": 250000, + "variable operating cost ($/tonne)": 2.5 + } + ], + "initial capacity (tonne)": 0, + "latitude (deg)": 32.776664, + "longitude (deg)": -96.796988 + }, + "RecyclingPlant (San Jose)": { + "input mix (%)": { + "UsedBoat": 100 + }, + "output (tonne)": { + "Nail": 0.025, + "Wood": 0.475 + }, + "processing emissions (tonne)": { + "CO2": 5 + }, + "storage cost ($/tonne)": { + "UsedBoat": 0 + }, + "storage limit (tonne)": { + "UsedBoat": 0 + }, + "disposal cost ($/tonne)": { + "Nail": 0, + "Wood": 0 + }, + "disposal limit (tonne)": { + "Nail": 0, + "Wood": 0 + }, + "capacities": [ { "size (tonne)": 500, - "opening cost ($)": 10000, - "fixed operating cost ($)": 1000, + "opening cost ($)": 500000, + "fixed operating cost ($)": 125000, + "variable operating cost ($/tonne)": 2.5 + }, + { + "size (tonne)": 1000, + "opening cost ($)": 1000000, + "fixed operating cost ($)": 250000, "variable operating cost ($/tonne)": 2.5 } ], "initial capacity (tonne)": 0, - "latitude (deg)": 41.881832, - "longitude (deg)": -87.623177 + "latitude (deg)": 37.338208, + "longitude (deg)": -121.886329 } } } \ No newline at end of file diff --git a/test/src/model/build_test.jl b/test/src/model/build_test.jl index b95f7a3..137bfae 100644 --- a/test/src/model/build_test.jl +++ b/test/src/model/build_test.jl @@ -14,11 +14,11 @@ function model_build_test() # print(model) @test obj.terms[y["L1", "C3", "P4", 1]] == ( - 111.118 + # transportation - 12.0 # revenue + 111.118 * 0.015 # transportation + - 12.0 # revenue ) @test obj.terms[y["C1", "L1", "P2", 4]] == ( - 333.262 + # transportation + 333.262 * 0.015 + # transportation 0.25 + # center collection cost 5.0 # plant operating cost ) @@ -83,7 +83,7 @@ function model_build_test() # Plants: Building period @test ("L1", 1) ∉ keys(model[:eq_building_period]) @test repr(model[:eq_building_period]["L1", 2]) == - "eq_building_period[L1,2] : x[L1,2] = 0" + "eq_building_period[L1,2] : -x[L1,1] + x[L1,2] ≤ 0" # Centers: Definition of total center input @test repr(model[:eq_z_input]["C1", 1]) ==