Generate simplified solution reports in CSV format
1
Makefile
@@ -1,5 +1,6 @@
|
||||
JULIA := julia --color=yes --project=@.
|
||||
SRC_FILES := $(wildcard src/*.jl test/*.jl)
|
||||
VERSION := 0.3
|
||||
|
||||
all: docs test
|
||||
|
||||
|
||||
129
Manifest.toml
@@ -17,21 +17,33 @@ version = "0.5.10"
|
||||
|
||||
[[Bzip2_jll]]
|
||||
deps = ["Libdl", "Pkg"]
|
||||
git-tree-sha1 = "5ccb0770e3d1c185a52e6d36e3ffb830639ed3d2"
|
||||
git-tree-sha1 = "03a44490020826950c68005cafb336e5ba08b7e8"
|
||||
uuid = "6e34b625-4abd-537c-b88f-471c36dfa7a0"
|
||||
version = "1.0.6+3"
|
||||
version = "1.0.6+4"
|
||||
|
||||
[[CEnum]]
|
||||
git-tree-sha1 = "1b77a77c3b28e0b3f413f7567c9bb8dd9bdccd14"
|
||||
uuid = "fa961155-64e5-5f13-b03f-caf6b980ea82"
|
||||
version = "0.3.0"
|
||||
|
||||
[[CSV]]
|
||||
deps = ["CategoricalArrays", "DataFrames", "Dates", "Mmap", "Parsers", "PooledArrays", "SentinelArrays", "Tables", "Unicode"]
|
||||
git-tree-sha1 = "a390152e6850405a48ca51bd7ca33d11a21d6230"
|
||||
uuid = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b"
|
||||
version = "0.7.7"
|
||||
|
||||
[[Calculus]]
|
||||
deps = ["LinearAlgebra"]
|
||||
git-tree-sha1 = "f641eb0a4f00c343bbc32346e1217b86f3ce9dad"
|
||||
uuid = "49dc2e85-a5d0-5ad3-a950-438e2897f1b9"
|
||||
version = "0.5.1"
|
||||
|
||||
[[CategoricalArrays]]
|
||||
deps = ["DataAPI", "Future", "JSON", "Missings", "Printf", "Statistics", "StructTypes", "Unicode"]
|
||||
git-tree-sha1 = "e7cb4f23938914f09afae58b611a59f3aa8d8f66"
|
||||
uuid = "324d7699-5711-5eae-9e2f-1d82baa6b597"
|
||||
version = "0.8.2"
|
||||
|
||||
[[Cbc]]
|
||||
deps = ["BinaryProvider", "Libdl", "MathOptInterface", "MathProgBase", "SparseArrays", "Test"]
|
||||
git-tree-sha1 = "62d80f448b5d77b3f0a59cecf6197aad2a3aa280"
|
||||
@@ -46,9 +58,9 @@ version = "0.8.0"
|
||||
|
||||
[[Clp_jll]]
|
||||
deps = ["CoinUtils_jll", "CompilerSupportLibraries_jll", "Libdl", "OpenBLAS32_jll", "Osi_jll", "Pkg"]
|
||||
git-tree-sha1 = "70fe9e52fd95fa37f645e3d30f08f436cc5b1457"
|
||||
git-tree-sha1 = "79263d9383ca89b35f31c33ab5b880536a8413a4"
|
||||
uuid = "06985876-5285-5a41-9fcb-8948a742cc53"
|
||||
version = "1.17.6+5"
|
||||
version = "1.17.6+6"
|
||||
|
||||
[[CodeTracking]]
|
||||
deps = ["InteractiveUtils", "UUIDs"]
|
||||
@@ -80,6 +92,12 @@ git-tree-sha1 = "7b8a93dba8af7e3b42fecabf646260105ac373f7"
|
||||
uuid = "bbf7d656-a473-5ed7-a52c-81e309532950"
|
||||
version = "0.3.0"
|
||||
|
||||
[[Compat]]
|
||||
deps = ["Base64", "Dates", "DelimitedFiles", "Distributed", "InteractiveUtils", "LibGit2", "Libdl", "LinearAlgebra", "Markdown", "Mmap", "Pkg", "Printf", "REPL", "Random", "SHA", "Serialization", "SharedArrays", "Sockets", "SparseArrays", "Statistics", "Test", "UUIDs", "Unicode"]
|
||||
git-tree-sha1 = "7c7f4cda0d58ec999189d70f5ee500348c4b4df1"
|
||||
uuid = "34da2185-b29b-5c13-b0c7-acf172513d20"
|
||||
version = "3.16.0"
|
||||
|
||||
[[CompilerSupportLibraries_jll]]
|
||||
deps = ["Libdl", "Pkg"]
|
||||
git-tree-sha1 = "7c4f882c41faa72118841185afc58a2eb00ef612"
|
||||
@@ -92,16 +110,36 @@ git-tree-sha1 = "c230b1d94db9fdd073168830437e64b9db627fcb"
|
||||
uuid = "150eb455-5306-5404-9cee-2592286d6298"
|
||||
version = "0.6.0"
|
||||
|
||||
[[DataAPI]]
|
||||
git-tree-sha1 = "176e23402d80e7743fc26c19c681bfb11246af32"
|
||||
uuid = "9a962f9c-6df0-11e9-0e5d-c546b8b5ee8a"
|
||||
version = "1.3.0"
|
||||
|
||||
[[DataFrames]]
|
||||
deps = ["CategoricalArrays", "Compat", "DataAPI", "Future", "InvertedIndices", "IteratorInterfaceExtensions", "Missings", "PooledArrays", "Printf", "REPL", "Reexport", "SortingAlgorithms", "Statistics", "TableTraits", "Tables", "Unicode"]
|
||||
git-tree-sha1 = "a7c1c9a6e47a92321bbc9d500dab9b04cc4a6a39"
|
||||
uuid = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
|
||||
version = "0.21.7"
|
||||
|
||||
[[DataStructures]]
|
||||
deps = ["InteractiveUtils", "OrderedCollections"]
|
||||
git-tree-sha1 = "88d48e133e6d3dd68183309877eac74393daa7eb"
|
||||
uuid = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8"
|
||||
version = "0.17.20"
|
||||
|
||||
[[DataValueInterfaces]]
|
||||
git-tree-sha1 = "bfc1187b79289637fa0ef6d4436ebdfe6905cbd6"
|
||||
uuid = "e2d170a0-9d28-54be-80f0-106bbe20a464"
|
||||
version = "1.0.0"
|
||||
|
||||
[[Dates]]
|
||||
deps = ["Printf"]
|
||||
uuid = "ade2ca70-3891-5945-98fb-dc099432e06a"
|
||||
|
||||
[[DelimitedFiles]]
|
||||
deps = ["Mmap"]
|
||||
uuid = "8bb1440f-4735-579b-a4ab-409b98df4dab"
|
||||
|
||||
[[DiffResults]]
|
||||
deps = ["StaticArrays"]
|
||||
git-tree-sha1 = "da24935df8e0c6cf28de340b958f6aac88eaa0cc"
|
||||
@@ -127,6 +165,16 @@ git-tree-sha1 = "48ff21740dfadb05eb1233c9fe17c2ad9cde4d45"
|
||||
uuid = "f6369f11-7733-5829-9624-2563aa707210"
|
||||
version = "0.10.11"
|
||||
|
||||
[[Future]]
|
||||
deps = ["Random"]
|
||||
uuid = "9fa8497b-333b-5362-9e8d-4d0656e87820"
|
||||
|
||||
[[GZip]]
|
||||
deps = ["Libdl"]
|
||||
git-tree-sha1 = "039be665faf0b8ae36e089cd694233f5dee3f7d6"
|
||||
uuid = "92fee26a-97fe-5a0c-ad85-20a5f3185b63"
|
||||
version = "0.5.1"
|
||||
|
||||
[[Geodesy]]
|
||||
deps = ["CoordinateTransformations", "Dates", "LinearAlgebra", "StaticArrays", "Test"]
|
||||
git-tree-sha1 = "f80ea86cb88db337a1906e245e495592f0b5cc25"
|
||||
@@ -149,6 +197,17 @@ version = "0.5.0"
|
||||
deps = ["Markdown"]
|
||||
uuid = "b77e0a4c-d291-57a0-90e8-8db25a27a240"
|
||||
|
||||
[[InvertedIndices]]
|
||||
deps = ["Test"]
|
||||
git-tree-sha1 = "15732c475062348b0165684ffe28e85ea8396afc"
|
||||
uuid = "41ab1584-1d38-5bbf-9106-f11c6c58b48f"
|
||||
version = "1.0.0"
|
||||
|
||||
[[IteratorInterfaceExtensions]]
|
||||
git-tree-sha1 = "a3f24677c21f5bbe9d2a714f95dcd58337fb2856"
|
||||
uuid = "82899510-4779-5014-852e-03e436cf321d"
|
||||
version = "1.0.0"
|
||||
|
||||
[[JSON]]
|
||||
deps = ["Dates", "Mmap", "Parsers", "Unicode"]
|
||||
git-tree-sha1 = "b34d7cef7b337321e97d22242c3c2b91f476748e"
|
||||
@@ -227,6 +286,12 @@ git-tree-sha1 = "a0cb0d489819fa7ea5f9fa84c7e7eba19d8073af"
|
||||
uuid = "c8ffd9c3-330d-5841-b78e-0817d7145fa1"
|
||||
version = "2.16.6+1"
|
||||
|
||||
[[Missings]]
|
||||
deps = ["DataAPI"]
|
||||
git-tree-sha1 = "ed61674a0864832495ffe0a7e889c0da76b0f4c8"
|
||||
uuid = "e1d29d7a-bbdc-5cf2-9ac0-f12de2c33e28"
|
||||
version = "0.4.4"
|
||||
|
||||
[[Mmap]]
|
||||
uuid = "a63ad114-7e13-5084-954f-fe012c677804"
|
||||
|
||||
@@ -264,6 +329,12 @@ git-tree-sha1 = "bd436a97280df40938e66ae8d18e57aceb072856"
|
||||
uuid = "7da25872-d9ce-5375-a4d3-7a845f58efdd"
|
||||
version = "0.108.5+3"
|
||||
|
||||
[[PackageCompiler]]
|
||||
deps = ["Libdl", "Pkg", "UUIDs"]
|
||||
git-tree-sha1 = "98aa9c653e1dc3473bb5050caf8501293db9eee1"
|
||||
uuid = "9b87118b-4619-50d2-8e1e-99f35a4d4d9d"
|
||||
version = "1.2.1"
|
||||
|
||||
[[Parsers]]
|
||||
deps = ["Dates", "Test"]
|
||||
git-tree-sha1 = "20ef902ea02f7000756a4bc19f7b9c24867c6211"
|
||||
@@ -274,6 +345,12 @@ version = "1.0.6"
|
||||
deps = ["Dates", "LibGit2", "Libdl", "Logging", "Markdown", "Printf", "REPL", "Random", "SHA", "UUIDs"]
|
||||
uuid = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"
|
||||
|
||||
[[PooledArrays]]
|
||||
deps = ["DataAPI"]
|
||||
git-tree-sha1 = "b1333d4eced1826e15adbdf01a4ecaccca9d353c"
|
||||
uuid = "2dfb63ee-cc39-5dd5-95bd-886bf059d720"
|
||||
version = "0.5.3"
|
||||
|
||||
[[Printf]]
|
||||
deps = ["Unicode"]
|
||||
uuid = "de0858da-6303-5e67-8744-51eddeeeb8d7"
|
||||
@@ -292,6 +369,12 @@ uuid = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb"
|
||||
deps = ["Serialization"]
|
||||
uuid = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
|
||||
|
||||
[[Reexport]]
|
||||
deps = ["Pkg"]
|
||||
git-tree-sha1 = "7b1d07f411bc8ddb7977ec7f377b97b158514fe0"
|
||||
uuid = "189a3867-3050-52da-a836-e630ba90ab69"
|
||||
version = "0.2.0"
|
||||
|
||||
[[Revise]]
|
||||
deps = ["CodeTracking", "Distributed", "FileWatching", "JuliaInterpreter", "LibGit2", "LoweredCodeUtils", "OrderedCollections", "Pkg", "REPL", "UUIDs", "Unicode"]
|
||||
git-tree-sha1 = "0992d4643e27b2deb9f2e4ec7a56b7033813a027"
|
||||
@@ -301,12 +384,28 @@ version = "2.7.3"
|
||||
[[SHA]]
|
||||
uuid = "ea8e919c-243c-51af-8825-aaa63cd721ce"
|
||||
|
||||
[[SentinelArrays]]
|
||||
deps = ["Dates", "Random"]
|
||||
git-tree-sha1 = "7a74946ace3b34fbb6c10e61b6e250b33d7e758c"
|
||||
uuid = "91c51154-3ec4-41a3-a24f-3f23e20d615c"
|
||||
version = "1.2.15"
|
||||
|
||||
[[Serialization]]
|
||||
uuid = "9e88b42a-f829-5b0c-bbe9-9e923198166b"
|
||||
|
||||
[[SharedArrays]]
|
||||
deps = ["Distributed", "Mmap", "Random", "Serialization"]
|
||||
uuid = "1a1011a3-84de-559e-8e89-a11a2f7dc383"
|
||||
|
||||
[[Sockets]]
|
||||
uuid = "6462fe0b-24de-5631-8697-dd941f90decc"
|
||||
|
||||
[[SortingAlgorithms]]
|
||||
deps = ["DataStructures", "Random", "Test"]
|
||||
git-tree-sha1 = "03f5898c9959f8115e30bc7226ada7d0df554ddd"
|
||||
uuid = "a2af1166-a08f-5f64-846c-94a0d3cef48c"
|
||||
version = "0.3.1"
|
||||
|
||||
[[SparseArrays]]
|
||||
deps = ["LinearAlgebra", "Random"]
|
||||
uuid = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"
|
||||
@@ -327,6 +426,24 @@ version = "0.12.3"
|
||||
deps = ["LinearAlgebra", "SparseArrays"]
|
||||
uuid = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"
|
||||
|
||||
[[StructTypes]]
|
||||
deps = ["Dates", "UUIDs"]
|
||||
git-tree-sha1 = "1ed04f622a39d2e5a6747c3a70be040c00333933"
|
||||
uuid = "856f2bd8-1eba-4b0a-8007-ebc267875bd4"
|
||||
version = "1.1.0"
|
||||
|
||||
[[TableTraits]]
|
||||
deps = ["IteratorInterfaceExtensions"]
|
||||
git-tree-sha1 = "b1ad568ba658d8cbb3b892ed5380a6f3e781a81e"
|
||||
uuid = "3783bdb8-4a98-5b6b-af9a-565f29a5fe9c"
|
||||
version = "1.0.0"
|
||||
|
||||
[[Tables]]
|
||||
deps = ["DataAPI", "DataValueInterfaces", "IteratorInterfaceExtensions", "LinearAlgebra", "TableTraits", "Test"]
|
||||
git-tree-sha1 = "b7f762e9820b7fab47544c36f26f54ac59cf8abf"
|
||||
uuid = "bd369af6-aec1-5ad0-b16a-f7cc5008161c"
|
||||
version = "1.0.5"
|
||||
|
||||
[[Test]]
|
||||
deps = ["Distributed", "InteractiveUtils", "Logging", "Random"]
|
||||
uuid = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
|
||||
@@ -346,6 +463,6 @@ uuid = "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5"
|
||||
|
||||
[[Zlib_jll]]
|
||||
deps = ["Libdl", "Pkg"]
|
||||
git-tree-sha1 = "d5bba6485811931e4b8958e2d7ca3738273ac468"
|
||||
git-tree-sha1 = "fdd89e5ab270ea0f2a0174bd9093e557d06d4bfa"
|
||||
uuid = "83775a58-1f1d-513f-b197-d71354ab007a"
|
||||
version = "1.2.11+15"
|
||||
version = "1.2.11+16"
|
||||
|
||||
@@ -4,15 +4,19 @@ authors = ["Alinson S Xavier <axavier@anl.gov>"]
|
||||
version = "0.3.2"
|
||||
|
||||
[deps]
|
||||
CSV = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b"
|
||||
Cbc = "9961bab8-2fa3-5c5a-9d89-47fab24efd76"
|
||||
Clp = "e2554f3b-3117-50c0-817c-e040a3ddf72d"
|
||||
DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
|
||||
DataStructures = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8"
|
||||
GZip = "92fee26a-97fe-5a0c-ad85-20a5f3185b63"
|
||||
Geodesy = "0ef565a4-170c-5f04-8de2-149903a85f3d"
|
||||
JSON = "682c06a0-de6a-54ab-a142-c8b1cf79cde6"
|
||||
JSONSchema = "7d188eb4-7ad8-530c-ae41-71a32a6d4692"
|
||||
JuMP = "4076af6c-e467-56ae-b986-b466b2749572"
|
||||
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
|
||||
MathOptInterface = "b8f27783-ece8-5eb3-8dc8-9495eed66fee"
|
||||
PackageCompiler = "9b87118b-4619-50d2-8e1e-99f35a4d4d9d"
|
||||
Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7"
|
||||
ProgressBars = "49802e3a-d2f1-5c88-81d8-b72133a6f568"
|
||||
Revise = "295af30f-e4ad-537b-8983-00126c2a3abe"
|
||||
|
||||
@@ -7,6 +7,7 @@ nav:
|
||||
- Home: index.md
|
||||
- Usage: usage.md
|
||||
- Data Format: format.md
|
||||
- Reports: reports.md
|
||||
- Optimization Model: model.md
|
||||
plugins:
|
||||
- search
|
||||
|
||||
@@ -7,4 +7,5 @@ module RELOG
|
||||
include("instance.jl")
|
||||
include("graph.jl")
|
||||
include("model.jl")
|
||||
include("reports.jl")
|
||||
end
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
# Input Data Format
|
||||
# Input and Output Data Formats
|
||||
|
||||
The first step when using RELOG is to describe the reverse logistics pipeline and the relevant data. RELOG accepts as input a JSON file with three sections: `parameters`, `products` and `plants`. Below, we describe each section in more detail.
|
||||
In this page, we describe the input and output JSON formats used by RELOG. In addition to these, RELOG can also produce [simplified reports](reports.md) in tabular data format.
|
||||
|
||||
## Parameters
|
||||
## Input Data Format (JSON)
|
||||
|
||||
RELOG accepts as input a JSON file with three sections: `parameters`, `products` and `plants`. Below, we describe each section in more detail.
|
||||
|
||||
### Parameters
|
||||
|
||||
The **parameters** section describes details about the simulation itself.
|
||||
|
||||
@@ -12,7 +16,7 @@ The **parameters** section describes details about the simulation itself.
|
||||
|`building period (years)` | List of years in which we are allowed to open new plants. For example, if this parameter is set to `[1,2,3]`, we can only open plants during the first three years. By default, this equals `[1]`; that is, plants can only be opened during the first year. |
|
||||
|
||||
|
||||
### Example
|
||||
#### Example
|
||||
```json
|
||||
{
|
||||
"parameters": {
|
||||
@@ -22,7 +26,7 @@ The **parameters** section describes details about the simulation itself.
|
||||
}
|
||||
```
|
||||
|
||||
## Products
|
||||
### Products
|
||||
|
||||
The **products** section describes all products and subproducts in the simulation. The field `instance["Products"]` is a dictionary mapping the name of the product to a dictionary which describes its characteristics. Each product description contains the following keys:
|
||||
|
||||
@@ -41,7 +45,7 @@ Each product may have some amount available at the beginning of each time period
|
||||
| `longitude (deg)` | The longitude of the location.
|
||||
| `amount (tonne)` | The amount of the product initially available at the location. Must be a timeseries.
|
||||
|
||||
### Example
|
||||
#### Example
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -84,7 +88,7 @@ Each product may have some amount available at the beginning of each time period
|
||||
}
|
||||
```
|
||||
|
||||
## Processing Plants
|
||||
### Processing plants
|
||||
|
||||
The **plants** section describes the available types of reverse manufacturing plants, their potential locations and associated costs, as well as their inputs and outputs. The field `instance["Plants"]` is a dictionary mapping the name of the plant to a dictionary with the following keys:
|
||||
|
||||
@@ -121,7 +125,7 @@ The keys in the `capacities (tonne)` dictionary should be the amounts (in tonnes
|
||||
| `fixed operating cost ($)` | The cost to keep the plant open, even if the plant doesn't process anything. Must be a timeseries.
|
||||
| `variable operating cost ($/tonne)` | The cost that the plant incurs to process each tonne of input. Must be a timeseries.
|
||||
|
||||
### Example
|
||||
#### Example
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -166,9 +170,14 @@ The keys in the `capacities (tonne)` dictionary should be the amounts (in tonnes
|
||||
}
|
||||
```
|
||||
|
||||
## Current limitations
|
||||
### Current limitations
|
||||
|
||||
* Each plant can only be opened exactly once. After open, the plant remains open until the end of the simulation.
|
||||
* Plants can be expanded at any time, even long after they are open.
|
||||
* All material available at the beginning of a time period must be entirely processed by the end of that time period. It is not possible to store unprocessed materials from one time period to the next.
|
||||
* Up to two plant sizes are currently supported. Variable operating costs must be the same for all plant sizes.
|
||||
|
||||
## Output Data Format (JSON)
|
||||
|
||||
To be documented.
|
||||
|
||||
|
||||
BIN
src/docs/images/ex_amount_produced.png
Normal file
|
After Width: | Height: | Size: 52 KiB |
BIN
src/docs/images/ex_emissions.png
Normal file
|
After Width: | Height: | Size: 37 KiB |
BIN
src/docs/images/ex_plant_cost_per_year.png
Normal file
|
After Width: | Height: | Size: 31 KiB |
BIN
src/docs/images/ex_plant_locations.png
Normal file
|
After Width: | Height: | Size: 91 KiB |
BIN
src/docs/images/ex_transportation.png
Normal file
|
After Width: | Height: | Size: 586 KiB |
BIN
src/docs/images/ex_transportation_amount_distance.png
Normal file
|
After Width: | Height: | Size: 31 KiB |
BIN
src/docs/images/ex_transportation_emissions.png
Normal file
|
After Width: | Height: | Size: 32 KiB |
@@ -3,10 +3,14 @@
|
||||
|
||||
**RELOG** is an open-source supply chain optimization package focusing on reverse logistics and reverse manufacturing. The package uses Mixed-Integer Linear Programming to determine where to build recycling plants, what size should these plants have and which customers should be served by which plants. The package supports custom reverse logistics pipelines, with multiple types of plants, multiple types of product and multiple time periods.
|
||||
|
||||
<img src="images/ex_transportation.png" width="1000px"/>
|
||||
|
||||
|
||||
### Table of Contents
|
||||
|
||||
* [Usage](usage.md)
|
||||
* [Data Format](format.md)
|
||||
* [Input and Output Data Formats](format.md)
|
||||
* [Simplified Solution Reports](reports.md)
|
||||
* [Optimization model](model.md)
|
||||
|
||||
### Source Code
|
||||
|
||||
269
src/docs/reports.md
Normal file
@@ -0,0 +1,269 @@
|
||||
# Simplified Solution Reports
|
||||
|
||||
In addition to the full output format described in [data formats](format.md), RELOG can also generate a number of simplified reports in tabular data format (CSV), which can be more easily processed by spreadsheet software (such as Microsoft Excel), by data analysis libraries (such as Pandas) or by relational databases (such as SQLite).
|
||||
|
||||
In this page, we also illustrate what types of charts and visualizations can be produced from these tabular data files. The sample charts have been produced using Python, matplotlib, seaborn and geopandas.
|
||||
|
||||
## Plants report
|
||||
|
||||
Report showing plant costs, capacities, energy expenditure and utilization factors.
|
||||
|
||||
Generated by `RELOG.write_plants_report(solution, filename)`. For a concrete example, see [nimh_plants.csv](https://github.com/ANL-CEEESA/RELOG/blob/master/test/fixtures/nimh_plants.csv).
|
||||
|
||||
| Column | Description
|
||||
|:--------------------------------------|---------------|
|
||||
| `plant type` | Plant type.
|
||||
| `location name` | Location name.
|
||||
| `year` | What year this row corresponds to. This reports includes one row for each year in the simulation.
|
||||
| `latitude (deg)` | Latitude of the plant.
|
||||
| `longitude (deg)` | Longitude of the plant.
|
||||
| `capacity (tonne)` | Capacity of the plant at this point in time.
|
||||
| `amount processed (tonne)` | Amount of input material received by the plant this year.
|
||||
| `utilization factor (%)` | Amount processed by the plant this year divided by current plant capacity.
|
||||
| `energy (GJ)` | Amount of energy expended by the plant this year.
|
||||
| `opening cost ($)` | Amount spent opening the plant. This value is only positive if the plant became operational this year.
|
||||
| `expansion cost ($)` | Amount spent this year expanding the plant capacity.
|
||||
| `fixed operating cost ($)` | Amount spent for keeping the plant operational this year.
|
||||
| `variable operating cost ($)` | Amount spent for processing the input material this year.
|
||||
| `total cost ($)` | Sum of all previous plant costs.
|
||||
|
||||
|
||||
### Sample charts
|
||||
|
||||
* Bar plot with total plant costs per year, grouped by plant type (in Python):
|
||||
```python
|
||||
import pandas as pd
|
||||
import seaborn as sns; sns.set()
|
||||
|
||||
data = pd.read_csv("plants_report.csv")
|
||||
sns.barplot(x="year",
|
||||
y="total cost ($)",
|
||||
hue="plant type",
|
||||
data=data.groupby(["plant type", "year"])
|
||||
.sum()
|
||||
.reset_index());
|
||||
```
|
||||
|
||||
<img src="../images/ex_plant_cost_per_year.png" width="500px"/>
|
||||
|
||||
* Map showing plant locations (in Python):
|
||||
```python
|
||||
import pandas as pd
|
||||
import geopandas as gp
|
||||
|
||||
# Plot base map
|
||||
world = gp.read_file(gp.datasets.get_path('naturalearth_lowres'))
|
||||
world = world[world.continent == 'North America']
|
||||
ax = world.plot(color='white', edgecolor='50', figsize=(15,15))
|
||||
|
||||
# Plot plant locations
|
||||
data = pd.read_csv("plants_report.csv")
|
||||
points = gp.points_from_xy(data["longitude (deg)"],
|
||||
data["latitude (deg)"])
|
||||
gp.GeoDataFrame(data, geometry=points).plot(ax=ax);
|
||||
```
|
||||
|
||||
<img src="../images/ex_plant_locations.png" width="1000px"/>
|
||||
|
||||
|
||||
## Plant outputs report
|
||||
|
||||
Report showing amount of products produced, sent and disposed of by each plant, as well as disposal costs.
|
||||
|
||||
Generated by `RELOG.write_plant_outputs_report(solution, filename)`. For a concrete example, see [nimh_plant_outputs.csv](https://github.com/ANL-CEEESA/RELOG/blob/master/test/fixtures/nimh_plant_outputs.csv).
|
||||
|
||||
|
||||
| Column | Description
|
||||
|:--------------------------------------|---------------|
|
||||
| `plant type` | Plant type.
|
||||
| `location name` | Location name.
|
||||
| `year` | What year this row corresponds to. This reports includes one row for each year in the simulation.
|
||||
| `product` | Product being produced.
|
||||
| `amount produced (tonne)` | Amount of product produced this year.
|
||||
| `amount sent (tonne)` | Amount of product produced by this plant and sent to another plant for further processing this year.
|
||||
| `amount disposed (tonne)` | Amount produced produced by this plant and immediately disposed of locally this year.
|
||||
| `disposal cost ($)` | Disposal cost for this year.
|
||||
|
||||
### Sample charts
|
||||
|
||||
* Bar plot showing total amount produced for each product, grouped by year (in Python):
|
||||
|
||||
```python
|
||||
import pandas as pd
|
||||
import seaborn as sns; sns.set()
|
||||
|
||||
data = pd.read_csv("plant_outputs_report.csv")
|
||||
sns.barplot(x="amount produced (tonne)",
|
||||
y="product name",
|
||||
hue="year",
|
||||
data=data.groupby(["product name", "year"])
|
||||
.sum()
|
||||
.reset_index());
|
||||
```
|
||||
|
||||
<img src="../images/ex_amount_produced.png" width="500px"/>
|
||||
|
||||
|
||||
## Plant emissions report
|
||||
|
||||
Report showing amount of emissions produced by each plant.
|
||||
|
||||
Generated by `RELOG.write_plant_emissions_report(solution, filename)`. For a concrete example, see [nimh_plant_emissions.csv](https://github.com/ANL-CEEESA/RELOG/blob/master/test/fixtures/nimh_plant_emissions.csv).
|
||||
|
||||
| Column | Description
|
||||
|:--------------------------------------|---------------|
|
||||
| `plant type` | Plant type.
|
||||
| `location name` | Location name.
|
||||
| `year` | Year.
|
||||
| `emission type` | Type of emission.
|
||||
| `amount (tonne)` | Amount of emission produced by the plant this year.
|
||||
|
||||
### Sample charts
|
||||
|
||||
* Bar plot showing total emission by plant type, grouped type of emissions (in Python):
|
||||
|
||||
```python
|
||||
import pandas as pd
|
||||
import seaborn as sns; sns.set()
|
||||
|
||||
data = pd.read_csv("plant_emissions_report.csv")
|
||||
sns.barplot(x="plant type",
|
||||
y="emission amount (tonne)",
|
||||
hue="emission type",
|
||||
data=data.groupby(["plant type", "emission type"])
|
||||
.sum()
|
||||
.reset_index());
|
||||
```
|
||||
|
||||
<img src="../images/ex_emissions.png" width="500px"/>
|
||||
|
||||
## Transportation report
|
||||
|
||||
Report showing amount of product sent from initial locations to plants, and from one plant to another. Includes the distance between each pair of locations, amount-distance shipped, transportation costs and energy expenditure.
|
||||
|
||||
Generated by `RELOG.write_transportation_report(solution, filename)`. For a concrete example, see [nimh_transportation.csv](https://github.com/ANL-CEEESA/RELOG/blob/master/test/fixtures/nimh_transportation.csv).
|
||||
|
||||
|
||||
| Column | Description
|
||||
|:--------------------------------------|---------------|
|
||||
| `source type` | If product is being shipped from an initial location, equals `Origin`. If product is being shipped from a plant, equals plant type.
|
||||
| `source location name` | Name of the location where the product is being shipped from.
|
||||
| `source latitude (deg)` | Latitude of the source location.
|
||||
| `source longitude (deg)` | Longitude of the source location.
|
||||
| `destination type`| Type of plant the product is being shipped to.
|
||||
| `destination location name`| Name of the location where the product is being shipped to.
|
||||
| `destination latitude (deg)` | Latitude of the destination location.
|
||||
| `destination longitude (deg)` | Longitude of the destination location.
|
||||
| `product`| Product being shipped.
|
||||
| `year`| Year.
|
||||
| `distance (km)`| Distance between source and destination.
|
||||
| `amount (tonne)`| Total amount of product being shipped between the two locations this year.
|
||||
| `amount-distance (tonne-km)`| Total amount being shipped this year times distance.
|
||||
| `transportation cost ($)`| Cost to transport this amount of product between the two locations for this year.
|
||||
| `transportation energy (GJ)`| Energy expended transporting this amount of product between the two locations.
|
||||
|
||||
### Sample charts
|
||||
|
||||
* Bar plot showing total amount-distance for each product type, grouped by year (in Python):
|
||||
|
||||
```python
|
||||
import pandas as pd
|
||||
import seaborn as sns; sns.set()
|
||||
|
||||
data = pd.read_csv("transportation_report.csv")
|
||||
sns.barplot(x="product",
|
||||
y="amount-distance (tonne-km)",
|
||||
hue="year",
|
||||
data=data.groupby(["product", "year"])
|
||||
.sum()
|
||||
.reset_index());
|
||||
```
|
||||
|
||||
<img src="../images/ex_transportation_amount_distance.png" width="500px"/>
|
||||
|
||||
* Map of transportation lines (in Python):
|
||||
|
||||
```python
|
||||
import pandas as pd
|
||||
import geopandas as gp
|
||||
from shapely.geometry import Point, LineString
|
||||
import matplotlib.pyplot as plt
|
||||
from matplotlib import collections
|
||||
|
||||
# Plot base map
|
||||
world = gp.read_file(gp.datasets.get_path('naturalearth_lowres'))
|
||||
ax = world.plot(color='white', edgecolor='50', figsize=(14,7))
|
||||
ax.set_ylim([23, 50])
|
||||
ax.set_xlim([-128, -65])
|
||||
|
||||
# Draw transportation lines
|
||||
data = pd.read_csv("transportation_report.csv")
|
||||
lines = [[(row["source longitude (deg)"], row["source latitude (deg)"]),
|
||||
(row["destination longitude (deg)"], row["destination latitude (deg)"])
|
||||
] for (index, row) in data.iterrows()]
|
||||
ax.add_collection(collections.LineCollection(lines,
|
||||
linewidths=0.25,
|
||||
zorder=1,
|
||||
alpha=0.5,
|
||||
color="50"))
|
||||
|
||||
# Draw source points
|
||||
points = gp.points_from_xy(data["source longitude (deg)"],
|
||||
data["source latitude (deg)"])
|
||||
gp.GeoDataFrame(data, geometry=points).plot(ax=ax,
|
||||
color="0.5",
|
||||
markersize=1);
|
||||
|
||||
# Draw destination points
|
||||
points = gp.points_from_xy(data["destination longitude (deg)"],
|
||||
data["destination latitude (deg)"])
|
||||
gp.GeoDataFrame(data, geometry=points).plot(ax=ax,
|
||||
color="red",
|
||||
markersize=50);
|
||||
```
|
||||
|
||||
<img src="../images/ex_transportation.png" width="1000px"/>
|
||||
|
||||
|
||||
## Transportation emissions report
|
||||
|
||||
Report showing emissions for each trip between initial locations and plants, and between pairs of plants.
|
||||
|
||||
Generated by `RELOG.write_transportation_emissions_report(solution, filename)`. For a concrete example, see [nimh_transportation_emissions.csv](https://github.com/ANL-CEEESA/RELOG/blob/master/test/fixtures/nimh_transportation_emissions.csv).
|
||||
|
||||
| Column | Description
|
||||
|:--------------------------------------|---------------|
|
||||
| `source type` | If product is being shipped from an initial location, equals `Origin`. If product is being shipped from a plant, equals plant type.
|
||||
| `source location name` | Name of the location where the product is being shipped from.
|
||||
| `source latitude (deg)` | Latitude of the source location.
|
||||
| `source longitude (deg)` | Longitude of the source location.
|
||||
| `destination type`| Type of plant the product is being shipped to.
|
||||
| `destination location name`| Name of the location where the product is being shipped to.
|
||||
| `destination latitude (deg)` | Latitude of the destination location.
|
||||
| `destination longitude (deg)` | Longitude of the destination location.
|
||||
| `product`| Product being shipped.
|
||||
| `year`| Year.
|
||||
| `distance (km)`| Distance between source and destination.
|
||||
| `shipped amount (tonne)`| Total amount of product being shipped between the two locations this year.
|
||||
| `shipped amount-distance (tonne-km)`| Total amount being shipped this year times distance.
|
||||
| `emission type` | Type of emission.
|
||||
| `emission amount (tonne)` | Amount of emission produced by transportation segment this year.
|
||||
|
||||
### Sample charts
|
||||
|
||||
* Bar plot showing total emission amount by emission type, grouped by type of product being transported (in Python):
|
||||
|
||||
```python
|
||||
import pandas as pd
|
||||
import seaborn as sns; sns.set()
|
||||
|
||||
data = pd.read_csv("transportation_emissions_report.csv")
|
||||
sns.barplot(x="emission type",
|
||||
y="emission amount (tonne)",
|
||||
hue="product",
|
||||
data=data.groupby(["product", "emission type"])
|
||||
.sum()
|
||||
.reset_index());
|
||||
```
|
||||
|
||||
<img src="../images/ex_transportation_emissions.png" width="500px"/>
|
||||
@@ -46,12 +46,21 @@ All user parameters specified above must be provided to RELOG as a JSON file, wh
|
||||
After creating a JSON file describing the reverse manufacturing process and the input data, the following example illustrates how to use the package to find the optimal set of decisions:
|
||||
|
||||
```julia
|
||||
# Import package
|
||||
using RELOG
|
||||
RELOG.solve("/home/user/instance.json",
|
||||
output="/home/user/solution.json")
|
||||
|
||||
# Solve optimization problem
|
||||
solution = RELOG.solve("/home/user/instance.json")
|
||||
|
||||
# Write full solution in JSON format
|
||||
RELOG.write(solution, "solution.json")
|
||||
|
||||
# Write simplified reports in CSV format
|
||||
RELOG.write_plants_report(solution, "plants.csv")
|
||||
RELOG.write_transportation_report(solution, "transportation.csv")
|
||||
```
|
||||
|
||||
The optimal logistics plan will be stored in the output file specified. See [data format page](format.md) for a description of this output file.
|
||||
For a complete description of the file formats above, and for a complete list of available reports, see the [data format page](format.md).
|
||||
|
||||
## 4. Advanced options
|
||||
|
||||
|
||||
@@ -312,6 +312,7 @@ function get_solution(model::ManufacturingModel)
|
||||
"Send" => OrderedDict(),
|
||||
"Dispose" => OrderedDict(),
|
||||
),
|
||||
"Input product" => plant.input.name,
|
||||
"Total input (tonne)" => [0.0 for t in 1:T],
|
||||
"Total output" => OrderedDict(),
|
||||
"Latitude (deg)" => plant.latitude,
|
||||
|
||||
268
src/reports.jl
Normal file
@@ -0,0 +1,268 @@
|
||||
# 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 DataFrames
|
||||
using CSV
|
||||
|
||||
function plants_report(solution::Dict)::DataFrame
|
||||
df = DataFrame()
|
||||
df."plant type" = String[]
|
||||
df."location name" = String[]
|
||||
df."year" = Int[]
|
||||
df."latitude (deg)" = Float64[]
|
||||
df."longitude (deg)" = Float64[]
|
||||
df."capacity (tonne)" = Float64[]
|
||||
df."amount processed (tonne)" = Float64[]
|
||||
df."utilization factor (%)" = Float64[]
|
||||
df."energy (GJ)" = Float64[]
|
||||
df."opening cost (\$)" = Float64[]
|
||||
df."expansion cost (\$)" = Float64[]
|
||||
df."fixed operating cost (\$)" = Float64[]
|
||||
df."variable operating cost (\$)" = Float64[]
|
||||
df."total cost (\$)" = Float64[]
|
||||
T = length(solution["Energy"]["Plants (GJ)"])
|
||||
for (plant_name, plant_dict) in solution["Plants"]
|
||||
for (location_name, location_dict) in plant_dict
|
||||
var_cost = zeros(T)
|
||||
for (src_plant_name, src_plant_dict) in location_dict["Input"]
|
||||
for (src_location_name, src_location_dict) in src_plant_dict
|
||||
var_cost += src_location_dict["Variable operating cost (\$)"]
|
||||
end
|
||||
end
|
||||
var_cost = round.(var_cost, digits=2)
|
||||
for year in 1:T
|
||||
opening_cost = round(location_dict["Opening cost (\$)"][year], digits=2)
|
||||
expansion_cost = round(location_dict["Expansion cost (\$)"][year], digits=2)
|
||||
fixed_cost = round(location_dict["Fixed operating cost (\$)"][year], digits=2)
|
||||
total_cost = round(var_cost[year] + opening_cost + expansion_cost + fixed_cost, digits=2)
|
||||
capacity = round(location_dict["Capacity (tonne)"][year], digits=2)
|
||||
processed = round(location_dict["Total input (tonne)"][year], digits=2)
|
||||
utilization_factor = round(processed / capacity * 100.0, digits=2)
|
||||
energy = round(location_dict["Energy (GJ)"][year], digits=2)
|
||||
latitude = round(location_dict["Latitude (deg)"], digits=6)
|
||||
longitude = round(location_dict["Longitude (deg)"], digits=6)
|
||||
push!(df, [
|
||||
plant_name,
|
||||
location_name,
|
||||
year,
|
||||
latitude,
|
||||
longitude,
|
||||
capacity,
|
||||
processed,
|
||||
utilization_factor,
|
||||
energy,
|
||||
opening_cost,
|
||||
expansion_cost,
|
||||
fixed_cost,
|
||||
var_cost[year],
|
||||
total_cost,
|
||||
])
|
||||
end
|
||||
end
|
||||
end
|
||||
return df
|
||||
end
|
||||
|
||||
function plant_outputs_report(solution::Dict)::DataFrame
|
||||
df = DataFrame()
|
||||
df."plant type" = String[]
|
||||
df."location name" = String[]
|
||||
df."year" = Int[]
|
||||
df."product name" = String[]
|
||||
df."amount produced (tonne)" = Float64[]
|
||||
df."amount sent (tonne)" = Float64[]
|
||||
df."amount disposed (tonne)" = Float64[]
|
||||
df."disposal cost (\$)" = Float64[]
|
||||
T = length(solution["Energy"]["Plants (GJ)"])
|
||||
for (plant_name, plant_dict) in solution["Plants"]
|
||||
for (location_name, location_dict) in plant_dict
|
||||
for (product_name, amount_produced) in location_dict["Total output"]
|
||||
send_dict = location_dict["Output"]["Send"]
|
||||
disposal_dict = location_dict["Output"]["Dispose"]
|
||||
|
||||
sent = zeros(T)
|
||||
if product_name in keys(send_dict)
|
||||
for (dst_plant_name, dst_plant_dict) in send_dict[product_name]
|
||||
for (dst_location_name, dst_location_dict) in dst_plant_dict
|
||||
sent += dst_location_dict["Amount (tonne)"]
|
||||
end
|
||||
end
|
||||
end
|
||||
sent = round.(sent, digits=2)
|
||||
|
||||
disposal_amount = zeros(T)
|
||||
disposal_cost = zeros(T)
|
||||
if product_name in keys(disposal_dict)
|
||||
disposal_amount += disposal_dict[product_name]["Amount (tonne)"]
|
||||
disposal_cost += disposal_dict[product_name]["Cost (\$)"]
|
||||
end
|
||||
disposal_amount = round.(disposal_amount, digits=2)
|
||||
disposal_cost = round.(disposal_cost, digits=2)
|
||||
|
||||
for year in 1:T
|
||||
push!(df, [
|
||||
plant_name,
|
||||
location_name,
|
||||
year,
|
||||
product_name,
|
||||
round(amount_produced[year], digits=2),
|
||||
sent[year],
|
||||
disposal_amount[year],
|
||||
disposal_cost[year],
|
||||
])
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return df
|
||||
end
|
||||
|
||||
|
||||
function plant_emissions_report(solution::Dict)::DataFrame
|
||||
df = DataFrame()
|
||||
df."plant type" = String[]
|
||||
df."location name" = String[]
|
||||
df."year" = Int[]
|
||||
df."emission type" = String[]
|
||||
df."emission amount (tonne)" = Float64[]
|
||||
T = length(solution["Energy"]["Plants (GJ)"])
|
||||
for (plant_name, plant_dict) in solution["Plants"]
|
||||
for (location_name, location_dict) in plant_dict
|
||||
for (emission_name, emission_amount) in location_dict["Emissions (tonne)"]
|
||||
for year in 1:T
|
||||
push!(df, [
|
||||
plant_name,
|
||||
location_name,
|
||||
year,
|
||||
emission_name,
|
||||
round(emission_amount[year], digits=2),
|
||||
])
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return df
|
||||
end
|
||||
|
||||
|
||||
function transportation_report(solution::Dict)::DataFrame
|
||||
df = DataFrame()
|
||||
df."source type" = String[]
|
||||
df."source location name" = String[]
|
||||
df."source latitude (deg)" = Float64[]
|
||||
df."source longitude (deg)" = Float64[]
|
||||
df."destination type" = String[]
|
||||
df."destination location name" = String[]
|
||||
df."destination latitude (deg)" = Float64[]
|
||||
df."destination longitude (deg)" = Float64[]
|
||||
df."product" = String[]
|
||||
df."year" = Int[]
|
||||
df."distance (km)" = Float64[]
|
||||
df."amount (tonne)" = Float64[]
|
||||
df."amount-distance (tonne-km)" = Float64[]
|
||||
df."transportation cost (\$)" = Float64[]
|
||||
df."transportation energy (GJ)" = Float64[]
|
||||
|
||||
T = length(solution["Energy"]["Plants (GJ)"])
|
||||
for (dst_plant_name, dst_plant_dict) in solution["Plants"]
|
||||
for (dst_location_name, dst_location_dict) in dst_plant_dict
|
||||
for (src_plant_name, src_plant_dict) in dst_location_dict["Input"]
|
||||
for (src_location_name, src_location_dict) in src_plant_dict
|
||||
for year in 1:T
|
||||
push!(df, [
|
||||
src_plant_name,
|
||||
src_location_name,
|
||||
round(src_location_dict["Latitude (deg)"], digits=6),
|
||||
round(src_location_dict["Longitude (deg)"], digits=6),
|
||||
dst_plant_name,
|
||||
dst_location_name,
|
||||
round(dst_location_dict["Latitude (deg)"], digits=6),
|
||||
round(dst_location_dict["Longitude (deg)"], digits=6),
|
||||
dst_location_dict["Input product"],
|
||||
year,
|
||||
round(src_location_dict["Distance (km)"][year], digits=2),
|
||||
round(src_location_dict["Amount (tonne)"][year], digits=2),
|
||||
round(src_location_dict["Amount (tonne)"][year] *
|
||||
src_location_dict["Distance (km)"][year],
|
||||
digits=2),
|
||||
round(src_location_dict["Transportation cost (\$)"][year], digits=2),
|
||||
round(src_location_dict["Transportation energy (J)"][year] / 1e9, digits=2),
|
||||
])
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return df
|
||||
end
|
||||
|
||||
|
||||
function transportation_emissions_report(solution::Dict)::DataFrame
|
||||
df = DataFrame()
|
||||
df."source type" = String[]
|
||||
df."source location name" = String[]
|
||||
df."source latitude (deg)" = Float64[]
|
||||
df."source longitude (deg)" = Float64[]
|
||||
df."destination type" = String[]
|
||||
df."destination location name" = String[]
|
||||
df."destination latitude (deg)" = Float64[]
|
||||
df."destination longitude (deg)" = Float64[]
|
||||
df."product" = String[]
|
||||
df."year" = Int[]
|
||||
df."distance (km)" = Float64[]
|
||||
df."shipped amount (tonne)" = Float64[]
|
||||
df."shipped amount-distance (tonne-km)" = Float64[]
|
||||
df."emission type" = String[]
|
||||
df."emission amount (tonne)" = Float64[]
|
||||
|
||||
T = length(solution["Energy"]["Plants (GJ)"])
|
||||
for (dst_plant_name, dst_plant_dict) in solution["Plants"]
|
||||
for (dst_location_name, dst_location_dict) in dst_plant_dict
|
||||
for (src_plant_name, src_plant_dict) in dst_location_dict["Input"]
|
||||
for (src_location_name, src_location_dict) in src_plant_dict
|
||||
for (emission_name, emission_amount) in src_location_dict["Emissions (tonne)"]
|
||||
for year in 1:T
|
||||
push!(df, [
|
||||
src_plant_name,
|
||||
src_location_name,
|
||||
round(src_location_dict["Latitude (deg)"], digits=6),
|
||||
round(src_location_dict["Longitude (deg)"], digits=6),
|
||||
dst_plant_name,
|
||||
dst_location_name,
|
||||
round(dst_location_dict["Latitude (deg)"], digits=6),
|
||||
round(dst_location_dict["Longitude (deg)"], digits=6),
|
||||
dst_location_dict["Input product"],
|
||||
year,
|
||||
round(src_location_dict["Distance (km)"][year], digits=2),
|
||||
round(src_location_dict["Amount (tonne)"][year], digits=2),
|
||||
round(src_location_dict["Amount (tonne)"][year] *
|
||||
src_location_dict["Distance (km)"][year],
|
||||
digits=2),
|
||||
emission_name,
|
||||
round(emission_amount[year], digits=2),
|
||||
])
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return df
|
||||
end
|
||||
|
||||
|
||||
write_plants_report(solution, filename) =
|
||||
CSV.write(filename, plants_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))
|
||||
|
||||
write_transportation_report(solution, filename) =
|
||||
CSV.write(filename, transportation_report(solution))
|
||||
|
||||
write_transportation_emissions_report(solution, filename) =
|
||||
CSV.write(filename, transportation_emissions_report(solution))
|
||||
7
test/fixtures/nimh_plant_emissions.csv
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
plant type,location name,year,emission type,emission amount (tonne)
|
||||
Rare Earth Recycling Plant,"Sebastian, Arkansas",1,CO2,40711.3
|
||||
Rare Earth Recycling Plant,"Stanly, North Carolina",1,CO2,23336.47
|
||||
Rare Earth Recycling Plant,"Lynn, Texas",1,CO2,52927.44
|
||||
Mega Plant,"Sebastian, Arkansas",1,CO2,110818.84
|
||||
Mega Plant,"District of Columbia, District of Columbia",1,CO2,63523.43
|
||||
Mega Plant,"Maricopa, Arizona",1,CO2,144072.0
|
||||
|
37
test/fixtures/nimh_plant_outputs.csv
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
plant type,location name,year,product name,amount produced (tonne),amount sent (tonne),amount disposed (tonne),disposal cost ($)
|
||||
Rare Earth Recycling Plant,"Sebastian, Arkansas",1,rare earth cela,18045.12,0.0,18045.12,0.0
|
||||
Rare Earth Recycling Plant,"Sebastian, Arkansas",1,rare earth diddy,7624.02,0.0,7624.02,0.0
|
||||
Rare Earth Recycling Plant,"Sebastian, Arkansas",1,salt,6434.8,0.0,6434.8,324314.03
|
||||
Rare Earth Recycling Plant,"Sebastian, Arkansas",1,rare earth misch,2188.78,0.0,2188.78,0.0
|
||||
Rare Earth Recycling Plant,"Stanly, North Carolina",1,rare earth cela,10343.8,0.0,10343.8,0.0
|
||||
Rare Earth Recycling Plant,"Stanly, North Carolina",1,rare earth diddy,4370.23,0.0,4370.23,0.0
|
||||
Rare Earth Recycling Plant,"Stanly, North Carolina",1,salt,3688.55,0.0,3688.55,185902.85
|
||||
Rare Earth Recycling Plant,"Stanly, North Carolina",1,rare earth misch,1254.65,0.0,1254.65,0.0
|
||||
Rare Earth Recycling Plant,"Lynn, Texas",1,rare earth cela,23459.88,0.0,23459.88,0.0
|
||||
Rare Earth Recycling Plant,"Lynn, Texas",1,rare earth diddy,9911.74,0.0,9911.74,0.0
|
||||
Rare Earth Recycling Plant,"Lynn, Texas",1,salt,8365.68,0.0,8365.68,421630.2
|
||||
Rare Earth Recycling Plant,"Lynn, Texas",1,rare earth misch,2845.56,0.0,2845.56,0.0
|
||||
Mega Plant,"Sebastian, Arkansas",1,iron-nickel scrap,35656.28,0.0,35656.28,0.0
|
||||
Mega Plant,"Sebastian, Arkansas",1,mixed-hydroxides,73141.86,0.0,73141.86,0.0
|
||||
Mega Plant,"Sebastian, Arkansas",1,leach residue,31470.35,0.0,31470.35,6.38848022e6
|
||||
Mega Plant,"Sebastian, Arkansas",1,plastic pack,96503.37,0.0,96503.37,4.86376966e6
|
||||
Mega Plant,"Sebastian, Arkansas",1,salt,285304.6,0.0,285304.6,1.437935192e7
|
||||
Mega Plant,"Sebastian, Arkansas",1,rare earth mix,44145.84,44145.84,0.0,0.0
|
||||
Mega Plant,"Sebastian, Arkansas",1,nickel-iron scrap,178655.26,0.0,178655.26,0.0
|
||||
Mega Plant,"Sebastian, Arkansas",1,nickel,37931.36,0.0,37931.36,0.0
|
||||
Mega Plant,"District of Columbia, District of Columbia",1,iron-nickel scrap,20438.84,0.0,20438.84,0.0
|
||||
Mega Plant,"District of Columbia, District of Columbia",1,mixed-hydroxides,41926.28,0.0,41926.28,0.0
|
||||
Mega Plant,"District of Columbia, District of Columbia",1,leach residue,18039.39,0.0,18039.39,3.66199595e6
|
||||
Mega Plant,"District of Columbia, District of Columbia",1,plastic pack,55317.53,0.0,55317.53,2.78800343e6
|
||||
Mega Plant,"District of Columbia, District of Columbia",1,salt,163541.92,0.0,163541.92,8.24251257e6
|
||||
Mega Plant,"District of Columbia, District of Columbia",1,rare earth mix,25305.22,25305.22,0.0,0.0
|
||||
Mega Plant,"District of Columbia, District of Columbia",1,nickel-iron scrap,102408.52,0.0,102408.52,0.0
|
||||
Mega Plant,"District of Columbia, District of Columbia",1,nickel,21742.96,0.0,21742.96,0.0
|
||||
Mega Plant,"Maricopa, Arizona",1,iron-nickel scrap,46355.57,0.0,46355.57,0.0
|
||||
Mega Plant,"Maricopa, Arizona",1,mixed-hydroxides,95089.37,0.0,95089.37,0.0
|
||||
Mega Plant,"Maricopa, Arizona",1,leach residue,40913.58,0.0,40913.58,8.30545698e6
|
||||
Mega Plant,"Maricopa, Arizona",1,plastic pack,125460.91,0.0,125460.91,6.32322998e6
|
||||
Mega Plant,"Maricopa, Arizona",1,salt,370915.31,0.0,370915.31,1.869413141e7
|
||||
Mega Plant,"Maricopa, Arizona",1,rare earth mix,57392.58,57392.58,0.0,0.0
|
||||
Mega Plant,"Maricopa, Arizona",1,nickel-iron scrap,232263.93,0.0,232263.93,0.0
|
||||
Mega Plant,"Maricopa, Arizona",1,nickel,49313.34,0.0,49313.34,0.0
|
||||
|
7
test/fixtures/nimh_plants.csv
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
plant type,location name,year,latitude (deg),longitude (deg),capacity (tonne),amount processed (tonne),utilization factor (%),energy (GJ),opening cost ($),expansion cost ($),fixed operating cost ($),variable operating cost ($),total cost ($)
|
||||
Rare Earth Recycling Plant,"Sebastian, Arkansas",1,35.23416,-94.212943,44145.84,44145.84,100.0,1.13360359e6,6.9926855e6,1.793555439e7,1.677420707e7,1.0080261442e8,1.4250506138e8
|
||||
Rare Earth Recycling Plant,"Stanly, North Carolina",1,35.334445,-80.223231,25305.22,25305.22,100.0,649802.71,7.1653444e6,9.98954108e6,1.126536154e7,5.778193764e7,8.620218466e7
|
||||
Rare Earth Recycling Plant,"Lynn, Texas",1,33.166444,-101.793455,57392.58,57392.58,100.0,1.47376145e6,7.4243328e6,2.5154042e7,2.06474474e7,1.310502261e8,1.842760483e8
|
||||
Mega Plant,"Sebastian, Arkansas",1,35.23416,-94.212943,553817.3,553817.3,100.0,3.08574408e6,1.6858178e7,4.012879371e7,3.834652057e7,4.2898688058e8,5.2432037286e8
|
||||
Mega Plant,"District of Columbia, District of Columbia",1,38.930028,-76.974164,317458.4,317458.4,100.0,1.76880602e6,2.12288167e7,2.746685387e7,2.602109584e7,2.4590327664e8,3.2062004305e8
|
||||
Mega Plant,"Maricopa, Arizona",1,33.647365,-111.893669,720000.0,720000.0,100.0,4.0116763e6,2.10206911e7,6.60955172e7,4.70124619e7,5.57712e8,6.918406702e8
|
||||
|
BIN
test/fixtures/nimh_solution.json.gz
vendored
Normal file
3618
test/fixtures/nimh_transportation.csv
vendored
Normal file
3618
test/fixtures/nimh_transportation_emissions.csv
vendored
Normal file
28
test/reports_test.jl
Normal file
@@ -0,0 +1,28 @@
|
||||
# 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, JSON, GZip
|
||||
|
||||
load_json_gz(filename) = JSON.parse(GZip.gzopen(filename))
|
||||
|
||||
function check(func, expected_csv_filename::String)
|
||||
solution = load_json_gz("fixtures/nimh_solution.json.gz")
|
||||
actual_csv_filename = tempname()
|
||||
func(solution, actual_csv_filename)
|
||||
@test isfile(actual_csv_filename)
|
||||
if readlines(actual_csv_filename) != readlines(expected_csv_filename)
|
||||
out_filename = replace(expected_csv_filename, ".csv" => "_actual.csv")
|
||||
@error "$func: Unexpected CSV contents: $out_filename"
|
||||
write(out_filename, read(actual_csv_filename))
|
||||
@test false
|
||||
end
|
||||
end
|
||||
|
||||
@testset "Reports" begin
|
||||
check(RELOG.write_plants_report, "fixtures/nimh_plants.csv")
|
||||
check(RELOG.write_plant_outputs_report, "fixtures/nimh_plant_outputs.csv")
|
||||
check(RELOG.write_plant_emissions_report, "fixtures/nimh_plant_emissions.csv")
|
||||
check(RELOG.write_transportation_report, "fixtures/nimh_transportation.csv")
|
||||
check(RELOG.write_transportation_emissions_report, "fixtures/nimh_transportation_emissions.csv")
|
||||
end
|
||||
@@ -4,7 +4,8 @@
|
||||
using Test
|
||||
|
||||
@testset "RELOG" begin
|
||||
include("instance_test.jl")
|
||||
include("graph_test.jl")
|
||||
include("model_test.jl")
|
||||
#include("instance_test.jl")
|
||||
#include("graph_test.jl")
|
||||
#include("model_test.jl")
|
||||
include("reports_test.jl")
|
||||
end
|
||||