mirror of https://github.com/ANL-CEEESA/RELOG.git
Compare commits
No commits in common. 'f74713185df61a422b44e70e777c215e28ec630f' and '18f963836d511674e5cde43e525bb8c8eb510c78' have entirely different histories.
f74713185d
...
18f963836d
@ -1,4 +0,0 @@
|
||||
build
|
||||
jobs
|
||||
relog-web/node_modules
|
||||
relog-web/build
|
@ -1,27 +0,0 @@
|
||||
name: Lint
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: julia-actions/setup-julia@latest
|
||||
with:
|
||||
version: '1'
|
||||
- uses: actions/checkout@v1
|
||||
- name: Format check
|
||||
shell: julia --color=yes {0}
|
||||
run: |
|
||||
using Pkg
|
||||
Pkg.add(PackageSpec(name="JuliaFormatter", version="1"))
|
||||
using JuliaFormatter
|
||||
format("src", verbose=true)
|
||||
format("test/src", verbose=true)
|
||||
out = String(read(Cmd(`git diff`)))
|
||||
if isempty(out)
|
||||
exit(0)
|
||||
end
|
||||
@error "Some files have not been formatted !!!"
|
||||
write(stdout, out)
|
||||
exit(1)
|
@ -1,15 +0,0 @@
|
||||
name: TagBot
|
||||
on:
|
||||
issue_comment:
|
||||
types:
|
||||
- created
|
||||
workflow_dispatch:
|
||||
jobs:
|
||||
TagBot:
|
||||
if: github.event_name == 'workflow_dispatch' || github.actor == 'JuliaTagBot'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: JuliaRegistries/TagBot@v1
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
ssh: ${{ secrets.DOCUMENTER_KEY }}
|
@ -1,35 +0,0 @@
|
||||
name: Build & Test
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
schedule:
|
||||
- cron: '45 10 * * *'
|
||||
jobs:
|
||||
test:
|
||||
name: Julia ${{ matrix.version }} - ${{ matrix.os }} - ${{ matrix.arch }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
version: ['1.6', '1.7', '1.8']
|
||||
os:
|
||||
- ubuntu-latest
|
||||
arch:
|
||||
- x64
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: julia-actions/setup-julia@v1
|
||||
with:
|
||||
version: ${{ matrix.version }}
|
||||
arch: ${{ matrix.arch }}
|
||||
- name: Run tests
|
||||
shell: julia --color=yes --project=test {0}
|
||||
run: |
|
||||
using Pkg
|
||||
Pkg.develop(path=".")
|
||||
Pkg.update()
|
||||
using RELOGT
|
||||
try
|
||||
runtests()
|
||||
catch
|
||||
exit(1)
|
||||
end
|
@ -1,28 +0,0 @@
|
||||
{
|
||||
"creators": [
|
||||
{
|
||||
"orcid": "0000-0002-5022-9802",
|
||||
"affiliation": "Argonne National Laboratory",
|
||||
"name": "Santos Xavier, Alinson"
|
||||
},
|
||||
{
|
||||
"orcid": "0000-0002-3426-9425",
|
||||
"affiliation": "Argonne National Laboratory",
|
||||
"name": "Iloeje, Chukwunwike"
|
||||
},
|
||||
{
|
||||
"affiliation": "Argonne National Laboratory",
|
||||
"name": "Atkins, John"
|
||||
},
|
||||
{
|
||||
"affiliation": "Argonne National Laboratory",
|
||||
"name": "Sun, Kyle"
|
||||
},
|
||||
{
|
||||
"affiliation": "Argonne National Laboratory",
|
||||
"name": "Gallier, Audrey"
|
||||
}
|
||||
],
|
||||
"title": "RELOG: Reverse Logistics Optimization",
|
||||
"description": "<b>RELOG</b> is a supply chain optimization package focusing on reverse logistics and reverse manufacturing. For example, the package can be used to determine where to build recycling plants, what sizes should they have and which customers should be served by which plants. The package supports customized reverse logistics pipelines, with multiple types of plants, multiple types of product and multiple time periods."
|
||||
}
|
@ -0,0 +1,608 @@
|
||||
# This file is machine-generated - editing it directly is not advised
|
||||
|
||||
julia_version = "1.9.0"
|
||||
manifest_format = "2.0"
|
||||
project_hash = "6050446040717864eaea84cf3a5f066d959d36dd"
|
||||
|
||||
[[deps.ArgTools]]
|
||||
uuid = "0dad84c5-d112-42e6-8d28-ef12dabb789f"
|
||||
version = "1.1.1"
|
||||
|
||||
[[deps.Artifacts]]
|
||||
uuid = "56f22d72-fd6d-98f1-02f0-08ddc0907c33"
|
||||
|
||||
[[deps.Base64]]
|
||||
uuid = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"
|
||||
|
||||
[[deps.BenchmarkTools]]
|
||||
deps = ["JSON", "Logging", "Printf", "Profile", "Statistics", "UUIDs"]
|
||||
git-tree-sha1 = "f1f03a9fa24271160ed7e73051fba3c1a759b53f"
|
||||
uuid = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf"
|
||||
version = "1.4.0"
|
||||
|
||||
[[deps.Bzip2_jll]]
|
||||
deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"]
|
||||
git-tree-sha1 = "9e2a6b69137e6969bab0152632dcb3bc108c8bdd"
|
||||
uuid = "6e34b625-4abd-537c-b88f-471c36dfa7a0"
|
||||
version = "1.0.8+1"
|
||||
|
||||
[[deps.CRC]]
|
||||
git-tree-sha1 = "b7ba7f0d727433c961909b329c4d2263268da4c9"
|
||||
uuid = "44b605c4-b955-5f2b-9b6d-d2bd01d3d205"
|
||||
version = "4.0.0"
|
||||
|
||||
[[deps.CSV]]
|
||||
deps = ["CodecZlib", "Dates", "FilePathsBase", "InlineStrings", "Mmap", "Parsers", "PooledArrays", "PrecompileTools", "SentinelArrays", "Tables", "Unicode", "WeakRefStrings", "WorkerUtilities"]
|
||||
git-tree-sha1 = "679e69c611fff422038e9e21e270c4197d49d918"
|
||||
uuid = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b"
|
||||
version = "0.10.12"
|
||||
|
||||
[[deps.CodeTracking]]
|
||||
deps = ["InteractiveUtils", "UUIDs"]
|
||||
git-tree-sha1 = "c0216e792f518b39b22212127d4a84dc31e4e386"
|
||||
uuid = "da1fd8a2-8d9e-5ec2-8556-3022fb5608a2"
|
||||
version = "1.3.5"
|
||||
|
||||
[[deps.CodecBzip2]]
|
||||
deps = ["Bzip2_jll", "Libdl", "TranscodingStreams"]
|
||||
git-tree-sha1 = "9b1ca1aa6ce3f71b3d1840c538a8210a043625eb"
|
||||
uuid = "523fee87-0ab8-5b00-afb7-3ecf72e48cfd"
|
||||
version = "0.8.2"
|
||||
|
||||
[[deps.CodecZlib]]
|
||||
deps = ["TranscodingStreams", "Zlib_jll"]
|
||||
git-tree-sha1 = "59939d8a997469ee05c4b4944560a820f9ba0d73"
|
||||
uuid = "944b1d66-785c-5afd-91f1-9de20f533193"
|
||||
version = "0.7.4"
|
||||
|
||||
[[deps.CommonSubexpressions]]
|
||||
deps = ["MacroTools", "Test"]
|
||||
git-tree-sha1 = "7b8a93dba8af7e3b42fecabf646260105ac373f7"
|
||||
uuid = "bbf7d656-a473-5ed7-a52c-81e309532950"
|
||||
version = "0.3.0"
|
||||
|
||||
[[deps.Compat]]
|
||||
deps = ["TOML", "UUIDs"]
|
||||
git-tree-sha1 = "c955881e3c981181362ae4088b35995446298b80"
|
||||
uuid = "34da2185-b29b-5c13-b0c7-acf172513d20"
|
||||
version = "4.14.0"
|
||||
weakdeps = ["Dates", "LinearAlgebra"]
|
||||
|
||||
[deps.Compat.extensions]
|
||||
CompatLinearAlgebraExt = "LinearAlgebra"
|
||||
|
||||
[[deps.CompilerSupportLibraries_jll]]
|
||||
deps = ["Artifacts", "Libdl"]
|
||||
uuid = "e66e0078-7015-5450-92f7-15fbd957f2ae"
|
||||
version = "1.0.2+0"
|
||||
|
||||
[[deps.CoordinateTransformations]]
|
||||
deps = ["LinearAlgebra", "StaticArrays"]
|
||||
git-tree-sha1 = "f9d7112bfff8a19a3a4ea4e03a8e6a91fe8456bf"
|
||||
uuid = "150eb455-5306-5404-9cee-2592286d6298"
|
||||
version = "0.6.3"
|
||||
|
||||
[[deps.Crayons]]
|
||||
git-tree-sha1 = "249fe38abf76d48563e2f4556bebd215aa317e15"
|
||||
uuid = "a8cc5b0e-0ffa-5ad4-8c14-923d3ee1735f"
|
||||
version = "4.1.1"
|
||||
|
||||
[[deps.DataAPI]]
|
||||
git-tree-sha1 = "abe83f3a2f1b857aac70ef8b269080af17764bbe"
|
||||
uuid = "9a962f9c-6df0-11e9-0e5d-c546b8b5ee8a"
|
||||
version = "1.16.0"
|
||||
|
||||
[[deps.DataFrames]]
|
||||
deps = ["Compat", "DataAPI", "DataStructures", "Future", "InlineStrings", "InvertedIndices", "IteratorInterfaceExtensions", "LinearAlgebra", "Markdown", "Missings", "PooledArrays", "PrecompileTools", "PrettyTables", "Printf", "REPL", "Random", "Reexport", "SentinelArrays", "SortingAlgorithms", "Statistics", "TableTraits", "Tables", "Unicode"]
|
||||
git-tree-sha1 = "04c738083f29f86e62c8afc341f0967d8717bdb8"
|
||||
uuid = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
|
||||
version = "1.6.1"
|
||||
|
||||
[[deps.DataStructures]]
|
||||
deps = ["Compat", "InteractiveUtils", "OrderedCollections"]
|
||||
git-tree-sha1 = "1fb174f0d48fe7d142e1109a10636bc1d14f5ac2"
|
||||
uuid = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8"
|
||||
version = "0.18.17"
|
||||
|
||||
[[deps.DataValueInterfaces]]
|
||||
git-tree-sha1 = "bfc1187b79289637fa0ef6d4436ebdfe6905cbd6"
|
||||
uuid = "e2d170a0-9d28-54be-80f0-106bbe20a464"
|
||||
version = "1.0.0"
|
||||
|
||||
[[deps.Dates]]
|
||||
deps = ["Printf"]
|
||||
uuid = "ade2ca70-3891-5945-98fb-dc099432e06a"
|
||||
|
||||
[[deps.DiffResults]]
|
||||
deps = ["StaticArraysCore"]
|
||||
git-tree-sha1 = "782dd5f4561f5d267313f23853baaaa4c52ea621"
|
||||
uuid = "163ba53b-c6d8-5494-b064-1a9d43ac40c5"
|
||||
version = "1.1.0"
|
||||
|
||||
[[deps.DiffRules]]
|
||||
deps = ["IrrationalConstants", "LogExpFunctions", "NaNMath", "Random", "SpecialFunctions"]
|
||||
git-tree-sha1 = "23163d55f885173722d1e4cf0f6110cdbaf7e272"
|
||||
uuid = "b552c78f-8df3-52c6-915a-8e097449b14b"
|
||||
version = "1.15.1"
|
||||
|
||||
[[deps.Distances]]
|
||||
deps = ["LinearAlgebra", "Statistics", "StatsAPI"]
|
||||
git-tree-sha1 = "66c4c81f259586e8f002eacebc177e1fb06363b0"
|
||||
uuid = "b4f34e82-e78d-54a5-968a-f98e89d6e8f7"
|
||||
version = "0.10.11"
|
||||
|
||||
[deps.Distances.extensions]
|
||||
DistancesChainRulesCoreExt = "ChainRulesCore"
|
||||
DistancesSparseArraysExt = "SparseArrays"
|
||||
|
||||
[deps.Distances.weakdeps]
|
||||
ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4"
|
||||
SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"
|
||||
|
||||
[[deps.Distributed]]
|
||||
deps = ["Random", "Serialization", "Sockets"]
|
||||
uuid = "8ba89e20-285c-5b6f-9357-94700520ee1b"
|
||||
|
||||
[[deps.DocStringExtensions]]
|
||||
deps = ["LibGit2"]
|
||||
git-tree-sha1 = "2fb1e02f2b635d0845df5d7c167fec4dd739b00d"
|
||||
uuid = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae"
|
||||
version = "0.9.3"
|
||||
|
||||
[[deps.Downloads]]
|
||||
deps = ["ArgTools", "FileWatching", "LibCURL", "NetworkOptions"]
|
||||
uuid = "f43a241f-c20a-4ad4-852c-f6b1247861c6"
|
||||
version = "1.6.0"
|
||||
|
||||
[[deps.FilePathsBase]]
|
||||
deps = ["Compat", "Dates", "Mmap", "Printf", "Test", "UUIDs"]
|
||||
git-tree-sha1 = "9f00e42f8d99fdde64d40c8ea5d14269a2e2c1aa"
|
||||
uuid = "48062228-2e41-5def-b9a4-89aafe57970f"
|
||||
version = "0.9.21"
|
||||
|
||||
[[deps.FileWatching]]
|
||||
uuid = "7b1f6079-737a-58dc-b8bc-7a2ca5c1b5ee"
|
||||
|
||||
[[deps.ForwardDiff]]
|
||||
deps = ["CommonSubexpressions", "DiffResults", "DiffRules", "LinearAlgebra", "LogExpFunctions", "NaNMath", "Preferences", "Printf", "Random", "SpecialFunctions"]
|
||||
git-tree-sha1 = "cf0fe81336da9fb90944683b8c41984b08793dad"
|
||||
uuid = "f6369f11-7733-5829-9624-2563aa707210"
|
||||
version = "0.10.36"
|
||||
weakdeps = ["StaticArrays"]
|
||||
|
||||
[deps.ForwardDiff.extensions]
|
||||
ForwardDiffStaticArraysExt = "StaticArrays"
|
||||
|
||||
[[deps.Future]]
|
||||
deps = ["Random"]
|
||||
uuid = "9fa8497b-333b-5362-9e8d-4d0656e87820"
|
||||
|
||||
[[deps.Geodesy]]
|
||||
deps = ["CoordinateTransformations", "Dates", "LinearAlgebra", "StaticArrays"]
|
||||
git-tree-sha1 = "ed98a4429bf0a033ccc5e036120181dd52f06d31"
|
||||
uuid = "0ef565a4-170c-5f04-8de2-149903a85f3d"
|
||||
version = "1.1.0"
|
||||
|
||||
[[deps.Gurobi]]
|
||||
deps = ["LazyArtifacts", "Libdl", "MathOptInterface"]
|
||||
git-tree-sha1 = "5995b72d385235f3fe55f8f0c4ad61049f867814"
|
||||
uuid = "2e9cd046-0924-5485-92f1-d5272153d98b"
|
||||
version = "1.2.1"
|
||||
|
||||
[[deps.InlineStrings]]
|
||||
deps = ["Parsers"]
|
||||
git-tree-sha1 = "9cc2baf75c6d09f9da536ddf58eb2f29dedaf461"
|
||||
uuid = "842dd82b-1e85-43dc-bf29-5d0ee9dffc48"
|
||||
version = "1.4.0"
|
||||
|
||||
[[deps.InteractiveUtils]]
|
||||
deps = ["Markdown"]
|
||||
uuid = "b77e0a4c-d291-57a0-90e8-8db25a27a240"
|
||||
|
||||
[[deps.InvertedIndices]]
|
||||
git-tree-sha1 = "0dc7b50b8d436461be01300fd8cd45aa0274b038"
|
||||
uuid = "41ab1584-1d38-5bbf-9106-f11c6c58b48f"
|
||||
version = "1.3.0"
|
||||
|
||||
[[deps.IrrationalConstants]]
|
||||
git-tree-sha1 = "630b497eafcc20001bba38a4651b327dcfc491d2"
|
||||
uuid = "92d709cd-6900-40b7-9082-c6be49f344b6"
|
||||
version = "0.2.2"
|
||||
|
||||
[[deps.IteratorInterfaceExtensions]]
|
||||
git-tree-sha1 = "a3f24677c21f5bbe9d2a714f95dcd58337fb2856"
|
||||
uuid = "82899510-4779-5014-852e-03e436cf321d"
|
||||
version = "1.0.0"
|
||||
|
||||
[[deps.JLLWrappers]]
|
||||
deps = ["Artifacts", "Preferences"]
|
||||
git-tree-sha1 = "7e5d6779a1e09a36db2a7b6cff50942a0a7d0fca"
|
||||
uuid = "692b3bcd-3c85-4b1f-b108-f13ce0eb3210"
|
||||
version = "1.5.0"
|
||||
|
||||
[[deps.JSON]]
|
||||
deps = ["Dates", "Mmap", "Parsers", "Unicode"]
|
||||
git-tree-sha1 = "31e996f0a15c7b280ba9f76636b3ff9e2ae58c9a"
|
||||
uuid = "682c06a0-de6a-54ab-a142-c8b1cf79cde6"
|
||||
version = "0.21.4"
|
||||
|
||||
[[deps.JuMP]]
|
||||
deps = ["LinearAlgebra", "MacroTools", "MathOptInterface", "MutableArithmetics", "OrderedCollections", "PrecompileTools", "Printf", "SparseArrays"]
|
||||
git-tree-sha1 = "4e44cff1595c6c02cdbca4e87ce376e63c33a584"
|
||||
uuid = "4076af6c-e467-56ae-b986-b466b2749572"
|
||||
version = "1.20.0"
|
||||
|
||||
[deps.JuMP.extensions]
|
||||
JuMPDimensionalDataExt = "DimensionalData"
|
||||
|
||||
[deps.JuMP.weakdeps]
|
||||
DimensionalData = "0703355e-b756-11e9-17c0-8b28908087d0"
|
||||
|
||||
[[deps.JuliaInterpreter]]
|
||||
deps = ["CodeTracking", "InteractiveUtils", "Random", "UUIDs"]
|
||||
git-tree-sha1 = "7b762d81887160169ddfc93a47e5fd7a6a3e78ef"
|
||||
uuid = "aa1ae85d-cabe-5617-a682-6adf51b2e16a"
|
||||
version = "0.9.29"
|
||||
|
||||
[[deps.LaTeXStrings]]
|
||||
git-tree-sha1 = "50901ebc375ed41dbf8058da26f9de442febbbec"
|
||||
uuid = "b964fa9f-0449-5b57-a5c2-d3ea65f4040f"
|
||||
version = "1.3.1"
|
||||
|
||||
[[deps.LazyArtifacts]]
|
||||
deps = ["Artifacts", "Pkg"]
|
||||
uuid = "4af54fe1-eca0-43a8-85a7-787d91b784e3"
|
||||
|
||||
[[deps.LibCURL]]
|
||||
deps = ["LibCURL_jll", "MozillaCACerts_jll"]
|
||||
uuid = "b27032c2-a3e7-50c8-80cd-2d36dbcbfd21"
|
||||
version = "0.6.3"
|
||||
|
||||
[[deps.LibCURL_jll]]
|
||||
deps = ["Artifacts", "LibSSH2_jll", "Libdl", "MbedTLS_jll", "Zlib_jll", "nghttp2_jll"]
|
||||
uuid = "deac9b47-8bc7-5906-a0fe-35ac56dc84c0"
|
||||
version = "7.84.0+0"
|
||||
|
||||
[[deps.LibGit2]]
|
||||
deps = ["Base64", "NetworkOptions", "Printf", "SHA"]
|
||||
uuid = "76f85450-5226-5b5a-8eaa-529ad045b433"
|
||||
|
||||
[[deps.LibSSH2_jll]]
|
||||
deps = ["Artifacts", "Libdl", "MbedTLS_jll"]
|
||||
uuid = "29816b5a-b9ab-546f-933c-edad1886dfa8"
|
||||
version = "1.10.2+0"
|
||||
|
||||
[[deps.Libdl]]
|
||||
uuid = "8f399da3-3557-5675-b5ff-fb832c97cbdb"
|
||||
|
||||
[[deps.LinearAlgebra]]
|
||||
deps = ["Libdl", "OpenBLAS_jll", "libblastrampoline_jll"]
|
||||
uuid = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
|
||||
|
||||
[[deps.LogExpFunctions]]
|
||||
deps = ["DocStringExtensions", "IrrationalConstants", "LinearAlgebra"]
|
||||
git-tree-sha1 = "18144f3e9cbe9b15b070288eef858f71b291ce37"
|
||||
uuid = "2ab3a3ac-af41-5b50-aa03-7779005ae688"
|
||||
version = "0.3.27"
|
||||
|
||||
[deps.LogExpFunctions.extensions]
|
||||
LogExpFunctionsChainRulesCoreExt = "ChainRulesCore"
|
||||
LogExpFunctionsChangesOfVariablesExt = "ChangesOfVariables"
|
||||
LogExpFunctionsInverseFunctionsExt = "InverseFunctions"
|
||||
|
||||
[deps.LogExpFunctions.weakdeps]
|
||||
ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4"
|
||||
ChangesOfVariables = "9e997f8a-9a97-42d5-a9f1-ce6bfc15e2c0"
|
||||
InverseFunctions = "3587e190-3f89-42d0-90ee-14403ec27112"
|
||||
|
||||
[[deps.Logging]]
|
||||
uuid = "56ddb016-857b-54e1-b83d-db4d58db5568"
|
||||
|
||||
[[deps.LoweredCodeUtils]]
|
||||
deps = ["JuliaInterpreter"]
|
||||
git-tree-sha1 = "31e27f0b0bf0df3e3e951bfcc43fe8c730a219f6"
|
||||
uuid = "6f1432cf-f94c-5a45-995e-cdbf5db27b0b"
|
||||
version = "2.4.5"
|
||||
|
||||
[[deps.MacroTools]]
|
||||
deps = ["Markdown", "Random"]
|
||||
git-tree-sha1 = "2fa9ee3e63fd3a4f7a9a4f4744a52f4856de82df"
|
||||
uuid = "1914dd2f-81c6-5fcd-8719-6d5c9610ff09"
|
||||
version = "0.5.13"
|
||||
|
||||
[[deps.Markdown]]
|
||||
deps = ["Base64"]
|
||||
uuid = "d6f4376e-aef5-505a-96c1-9c027394607a"
|
||||
|
||||
[[deps.MathOptInterface]]
|
||||
deps = ["BenchmarkTools", "CodecBzip2", "CodecZlib", "DataStructures", "ForwardDiff", "JSON", "LinearAlgebra", "MutableArithmetics", "NaNMath", "OrderedCollections", "PrecompileTools", "Printf", "SparseArrays", "SpecialFunctions", "Test", "Unicode"]
|
||||
git-tree-sha1 = "e8b98c868029d007102dc5f98986c81f33b0ec37"
|
||||
uuid = "b8f27783-ece8-5eb3-8dc8-9495eed66fee"
|
||||
version = "1.26.0"
|
||||
|
||||
[[deps.MbedTLS_jll]]
|
||||
deps = ["Artifacts", "Libdl"]
|
||||
uuid = "c8ffd9c3-330d-5841-b78e-0817d7145fa1"
|
||||
version = "2.28.2+0"
|
||||
|
||||
[[deps.Missings]]
|
||||
deps = ["DataAPI"]
|
||||
git-tree-sha1 = "f66bdc5de519e8f8ae43bdc598782d35a25b1272"
|
||||
uuid = "e1d29d7a-bbdc-5cf2-9ac0-f12de2c33e28"
|
||||
version = "1.1.0"
|
||||
|
||||
[[deps.Mmap]]
|
||||
uuid = "a63ad114-7e13-5084-954f-fe012c677804"
|
||||
|
||||
[[deps.MozillaCACerts_jll]]
|
||||
uuid = "14a3606d-f60d-562e-9121-12d972cd8159"
|
||||
version = "2022.10.11"
|
||||
|
||||
[[deps.MutableArithmetics]]
|
||||
deps = ["LinearAlgebra", "SparseArrays", "Test"]
|
||||
git-tree-sha1 = "302fd161eb1c439e4115b51ae456da4e9984f130"
|
||||
uuid = "d8a4904e-b15c-11e9-3269-09a3773c0cb0"
|
||||
version = "1.4.1"
|
||||
|
||||
[[deps.NaNMath]]
|
||||
deps = ["OpenLibm_jll"]
|
||||
git-tree-sha1 = "0877504529a3e5c3343c6f8b4c0381e57e4387e4"
|
||||
uuid = "77ba4419-2d1f-58cd-9bb1-8ffee604a2e3"
|
||||
version = "1.0.2"
|
||||
|
||||
[[deps.NearestNeighbors]]
|
||||
deps = ["Distances", "StaticArrays"]
|
||||
git-tree-sha1 = "ded64ff6d4fdd1cb68dfcbb818c69e144a5b2e4c"
|
||||
uuid = "b8a86587-4115-5ab1-83bc-aa920d37bbce"
|
||||
version = "0.4.16"
|
||||
|
||||
[[deps.NetworkOptions]]
|
||||
uuid = "ca575930-c2e3-43a9-ace4-1e988b2c1908"
|
||||
version = "1.2.0"
|
||||
|
||||
[[deps.OpenBLAS_jll]]
|
||||
deps = ["Artifacts", "CompilerSupportLibraries_jll", "Libdl"]
|
||||
uuid = "4536629a-c528-5b80-bd46-f80d51c5b363"
|
||||
version = "0.3.21+4"
|
||||
|
||||
[[deps.OpenLibm_jll]]
|
||||
deps = ["Artifacts", "Libdl"]
|
||||
uuid = "05823500-19ac-5b8b-9628-191a04bc5112"
|
||||
version = "0.8.1+0"
|
||||
|
||||
[[deps.OpenSpecFun_jll]]
|
||||
deps = ["Artifacts", "CompilerSupportLibraries_jll", "JLLWrappers", "Libdl", "Pkg"]
|
||||
git-tree-sha1 = "13652491f6856acfd2db29360e1bbcd4565d04f1"
|
||||
uuid = "efe28fd5-8261-553b-a9e1-b2916fc3738e"
|
||||
version = "0.5.5+0"
|
||||
|
||||
[[deps.OrderedCollections]]
|
||||
git-tree-sha1 = "dfdf5519f235516220579f949664f1bf44e741c5"
|
||||
uuid = "bac558e1-5e72-5ebc-8fee-abe8a469f55d"
|
||||
version = "1.6.3"
|
||||
|
||||
[[deps.Parsers]]
|
||||
deps = ["Dates", "PrecompileTools", "UUIDs"]
|
||||
git-tree-sha1 = "8489905bcdbcfac64d1daa51ca07c0d8f0283821"
|
||||
uuid = "69de0a69-1ddd-5017-9359-2bf0b02dc9f0"
|
||||
version = "2.8.1"
|
||||
|
||||
[[deps.Pkg]]
|
||||
deps = ["Artifacts", "Dates", "Downloads", "FileWatching", "LibGit2", "Libdl", "Logging", "Markdown", "Printf", "REPL", "Random", "SHA", "Serialization", "TOML", "Tar", "UUIDs", "p7zip_jll"]
|
||||
uuid = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"
|
||||
version = "1.9.0"
|
||||
|
||||
[[deps.PooledArrays]]
|
||||
deps = ["DataAPI", "Future"]
|
||||
git-tree-sha1 = "36d8b4b899628fb92c2749eb488d884a926614d3"
|
||||
uuid = "2dfb63ee-cc39-5dd5-95bd-886bf059d720"
|
||||
version = "1.4.3"
|
||||
|
||||
[[deps.PrecompileTools]]
|
||||
deps = ["Preferences"]
|
||||
git-tree-sha1 = "03b4c25b43cb84cee5c90aa9b5ea0a78fd848d2f"
|
||||
uuid = "aea7be01-6a6a-4083-8856-8a6e6704d82a"
|
||||
version = "1.2.0"
|
||||
|
||||
[[deps.Preferences]]
|
||||
deps = ["TOML"]
|
||||
git-tree-sha1 = "00805cd429dcb4870060ff49ef443486c262e38e"
|
||||
uuid = "21216c6a-2e73-6563-6e65-726566657250"
|
||||
version = "1.4.1"
|
||||
|
||||
[[deps.PrettyTables]]
|
||||
deps = ["Crayons", "LaTeXStrings", "Markdown", "PrecompileTools", "Printf", "Reexport", "StringManipulation", "Tables"]
|
||||
git-tree-sha1 = "88b895d13d53b5577fd53379d913b9ab9ac82660"
|
||||
uuid = "08abe8d2-0d0c-5749-adfa-8a2ac140af0d"
|
||||
version = "2.3.1"
|
||||
|
||||
[[deps.Printf]]
|
||||
deps = ["Unicode"]
|
||||
uuid = "de0858da-6303-5e67-8744-51eddeeeb8d7"
|
||||
|
||||
[[deps.Profile]]
|
||||
deps = ["Printf"]
|
||||
uuid = "9abbd945-dff8-562f-b5e8-e1ebf5ef1b79"
|
||||
|
||||
[[deps.REPL]]
|
||||
deps = ["InteractiveUtils", "Markdown", "Sockets", "Unicode"]
|
||||
uuid = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb"
|
||||
|
||||
[[deps.Random]]
|
||||
deps = ["SHA", "Serialization"]
|
||||
uuid = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
|
||||
|
||||
[[deps.Reexport]]
|
||||
git-tree-sha1 = "45e428421666073eab6f2da5c9d310d99bb12f9b"
|
||||
uuid = "189a3867-3050-52da-a836-e630ba90ab69"
|
||||
version = "1.2.2"
|
||||
|
||||
[[deps.Requires]]
|
||||
deps = ["UUIDs"]
|
||||
git-tree-sha1 = "838a3a4188e2ded87a4f9f184b4b0d78a1e91cb7"
|
||||
uuid = "ae029012-a4dd-5104-9daa-d747884805df"
|
||||
version = "1.3.0"
|
||||
|
||||
[[deps.Revise]]
|
||||
deps = ["CodeTracking", "Distributed", "FileWatching", "JuliaInterpreter", "LibGit2", "LoweredCodeUtils", "OrderedCollections", "Pkg", "REPL", "Requires", "UUIDs", "Unicode"]
|
||||
git-tree-sha1 = "12aa2d7593df490c407a3bbd8b86b8b515017f3e"
|
||||
uuid = "295af30f-e4ad-537b-8983-00126c2a3abe"
|
||||
version = "3.5.14"
|
||||
|
||||
[[deps.SHA]]
|
||||
uuid = "ea8e919c-243c-51af-8825-aaa63cd721ce"
|
||||
version = "0.7.0"
|
||||
|
||||
[[deps.SentinelArrays]]
|
||||
deps = ["Dates", "Random"]
|
||||
git-tree-sha1 = "0e7508ff27ba32f26cd459474ca2ede1bc10991f"
|
||||
uuid = "91c51154-3ec4-41a3-a24f-3f23e20d615c"
|
||||
version = "1.4.1"
|
||||
|
||||
[[deps.Serialization]]
|
||||
uuid = "9e88b42a-f829-5b0c-bbe9-9e923198166b"
|
||||
|
||||
[[deps.Sockets]]
|
||||
uuid = "6462fe0b-24de-5631-8697-dd941f90decc"
|
||||
|
||||
[[deps.SortingAlgorithms]]
|
||||
deps = ["DataStructures"]
|
||||
git-tree-sha1 = "66e0a8e672a0bdfca2c3f5937efb8538b9ddc085"
|
||||
uuid = "a2af1166-a08f-5f64-846c-94a0d3cef48c"
|
||||
version = "1.2.1"
|
||||
|
||||
[[deps.SparseArrays]]
|
||||
deps = ["Libdl", "LinearAlgebra", "Random", "Serialization", "SuiteSparse_jll"]
|
||||
uuid = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"
|
||||
|
||||
[[deps.SpecialFunctions]]
|
||||
deps = ["IrrationalConstants", "LogExpFunctions", "OpenLibm_jll", "OpenSpecFun_jll"]
|
||||
git-tree-sha1 = "e2cfc4012a19088254b3950b85c3c1d8882d864d"
|
||||
uuid = "276daf66-3868-5448-9aa4-cd146d93841b"
|
||||
version = "2.3.1"
|
||||
|
||||
[deps.SpecialFunctions.extensions]
|
||||
SpecialFunctionsChainRulesCoreExt = "ChainRulesCore"
|
||||
|
||||
[deps.SpecialFunctions.weakdeps]
|
||||
ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4"
|
||||
|
||||
[[deps.StaticArrays]]
|
||||
deps = ["LinearAlgebra", "PrecompileTools", "Random", "StaticArraysCore"]
|
||||
git-tree-sha1 = "bf074c045d3d5ffd956fa0a461da38a44685d6b2"
|
||||
uuid = "90137ffa-7385-5640-81b9-e52037218182"
|
||||
version = "1.9.3"
|
||||
|
||||
[deps.StaticArrays.extensions]
|
||||
StaticArraysChainRulesCoreExt = "ChainRulesCore"
|
||||
StaticArraysStatisticsExt = "Statistics"
|
||||
|
||||
[deps.StaticArrays.weakdeps]
|
||||
ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4"
|
||||
Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"
|
||||
|
||||
[[deps.StaticArraysCore]]
|
||||
git-tree-sha1 = "36b3d696ce6366023a0ea192b4cd442268995a0d"
|
||||
uuid = "1e83bf80-4336-4d27-bf5d-d5a4f845583c"
|
||||
version = "1.4.2"
|
||||
|
||||
[[deps.Statistics]]
|
||||
deps = ["LinearAlgebra", "SparseArrays"]
|
||||
uuid = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"
|
||||
version = "1.9.0"
|
||||
|
||||
[[deps.StatsAPI]]
|
||||
deps = ["LinearAlgebra"]
|
||||
git-tree-sha1 = "1ff449ad350c9c4cbc756624d6f8a8c3ef56d3ed"
|
||||
uuid = "82ae8749-77ed-4fe6-ae5f-f523153014b0"
|
||||
version = "1.7.0"
|
||||
|
||||
[[deps.StringManipulation]]
|
||||
deps = ["PrecompileTools"]
|
||||
git-tree-sha1 = "a04cabe79c5f01f4d723cc6704070ada0b9d46d5"
|
||||
uuid = "892a3eda-7b42-436c-8928-eab12a02cf0e"
|
||||
version = "0.3.4"
|
||||
|
||||
[[deps.SuiteSparse_jll]]
|
||||
deps = ["Artifacts", "Libdl", "Pkg", "libblastrampoline_jll"]
|
||||
uuid = "bea87d4a-7f5b-5778-9afe-8cc45184846c"
|
||||
version = "5.10.1+6"
|
||||
|
||||
[[deps.TOML]]
|
||||
deps = ["Dates"]
|
||||
uuid = "fa267f1f-6049-4f14-aa54-33bafae1ed76"
|
||||
version = "1.0.3"
|
||||
|
||||
[[deps.TableTraits]]
|
||||
deps = ["IteratorInterfaceExtensions"]
|
||||
git-tree-sha1 = "c06b2f539df1c6efa794486abfb6ed2022561a39"
|
||||
uuid = "3783bdb8-4a98-5b6b-af9a-565f29a5fe9c"
|
||||
version = "1.0.1"
|
||||
|
||||
[[deps.Tables]]
|
||||
deps = ["DataAPI", "DataValueInterfaces", "IteratorInterfaceExtensions", "LinearAlgebra", "OrderedCollections", "TableTraits"]
|
||||
git-tree-sha1 = "cb76cf677714c095e535e3501ac7954732aeea2d"
|
||||
uuid = "bd369af6-aec1-5ad0-b16a-f7cc5008161c"
|
||||
version = "1.11.1"
|
||||
|
||||
[[deps.Tar]]
|
||||
deps = ["ArgTools", "SHA"]
|
||||
uuid = "a4e569a6-e804-4fa4-b0f3-eef7a1d5b13e"
|
||||
version = "1.10.0"
|
||||
|
||||
[[deps.Test]]
|
||||
deps = ["InteractiveUtils", "Logging", "Random", "Serialization"]
|
||||
uuid = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
|
||||
|
||||
[[deps.TranscodingStreams]]
|
||||
git-tree-sha1 = "54194d92959d8ebaa8e26227dbe3cdefcdcd594f"
|
||||
uuid = "3bb67fe8-82b1-5028-8e26-92a6c54297fa"
|
||||
version = "0.10.3"
|
||||
weakdeps = ["Random", "Test"]
|
||||
|
||||
[deps.TranscodingStreams.extensions]
|
||||
TestExt = ["Test", "Random"]
|
||||
|
||||
[[deps.UUIDs]]
|
||||
deps = ["Random", "SHA"]
|
||||
uuid = "cf7118a7-6976-5b1a-9a39-7adc72f591a4"
|
||||
|
||||
[[deps.Unicode]]
|
||||
uuid = "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5"
|
||||
|
||||
[[deps.WeakRefStrings]]
|
||||
deps = ["DataAPI", "InlineStrings", "Parsers"]
|
||||
git-tree-sha1 = "b1be2855ed9ed8eac54e5caff2afcdb442d52c23"
|
||||
uuid = "ea10d353-3f73-51f8-a26c-33c1cb351aa5"
|
||||
version = "1.4.2"
|
||||
|
||||
[[deps.WorkerUtilities]]
|
||||
git-tree-sha1 = "cd1659ba0d57b71a464a29e64dbc67cfe83d54e7"
|
||||
uuid = "76eceee3-57b5-4d4a-8e66-0e911cebbf60"
|
||||
version = "1.6.1"
|
||||
|
||||
[[deps.ZipFile]]
|
||||
deps = ["Libdl", "Printf", "Zlib_jll"]
|
||||
git-tree-sha1 = "f492b7fe1698e623024e873244f10d89c95c340a"
|
||||
uuid = "a5390f91-8eb1-5f08-bee0-b1d1ffed6cea"
|
||||
version = "0.10.1"
|
||||
|
||||
[[deps.Zlib_jll]]
|
||||
deps = ["Libdl"]
|
||||
uuid = "83775a58-1f1d-513f-b197-d71354ab007a"
|
||||
version = "1.2.13+0"
|
||||
|
||||
[[deps.libblastrampoline_jll]]
|
||||
deps = ["Artifacts", "Libdl"]
|
||||
uuid = "8e850b90-86db-534c-a0d3-1478176c7d93"
|
||||
version = "5.7.0+0"
|
||||
|
||||
[[deps.nghttp2_jll]]
|
||||
deps = ["Artifacts", "Libdl"]
|
||||
uuid = "8e850ede-7688-5339-a07c-302acd2aaf8d"
|
||||
version = "1.48.0+0"
|
||||
|
||||
[[deps.p7zip_jll]]
|
||||
deps = ["Artifacts", "Libdl"]
|
||||
uuid = "3f19e933-33d8-53b3-aaab-bd5110c3b7a0"
|
||||
version = "17.4.0+0"
|
@ -1,13 +1,13 @@
|
||||
name = "RELOG"
|
||||
uuid = "7cafaa7a-b311-45f0-b313-80bf15b5e5e5"
|
||||
authors = ["Alinson S. Xavier <git@axavier.org>"]
|
||||
version = "0.1.0"
|
||||
|
||||
[deps]
|
||||
CRC = "44b605c4-b955-5f2b-9b6d-d2bd01d3d205"
|
||||
CSV = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b"
|
||||
DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0"
|
||||
Geodesy = "0ef565a4-170c-5f04-8de2-149903a85f3d"
|
||||
Gurobi = "2e9cd046-0924-5485-92f1-d5272153d98b"
|
||||
JSON = "682c06a0-de6a-54ab-a142-c8b1cf79cde6"
|
||||
JuMP = "4076af6c-e467-56ae-b986-b466b2749572"
|
||||
NearestNeighbors = "b8a86587-4115-5ab1-83bc-aa920d37bbce"
|
||||
OrderedCollections = "bac558e1-5e72-5ebc-8fee-abe8a469f55d"
|
||||
Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7"
|
||||
Revise = "295af30f-e4ad-537b-8983-00126c2a3abe"
|
||||
ZipFile = "a5390f91-8eb1-5f08-bee0-b1d1ffed6cea"
|
||||
|
@ -0,0 +1,107 @@
|
||||
# RELOG: Reverse Logistics Optimization
|
||||
# Copyright (C) 2020-2024, UChicago Argonne, LLC. All rights reserved.
|
||||
# Released under the modified BSD license. See COPYING.md for more details.
|
||||
|
||||
using Geodesy
|
||||
using NearestNeighbors
|
||||
using DataFrames
|
||||
using CRC
|
||||
using ZipFile
|
||||
using Statistics
|
||||
|
||||
crc32 = crc(CRC_32)
|
||||
|
||||
abstract type DistanceMetric end
|
||||
|
||||
Base.@kwdef mutable struct KnnDrivingDistance <: DistanceMetric
|
||||
tree = nothing
|
||||
ratios = nothing
|
||||
end
|
||||
|
||||
mutable struct EuclideanDistance <: DistanceMetric end
|
||||
|
||||
function _calculate_distance(
|
||||
source_lat,
|
||||
source_lon,
|
||||
dest_lat,
|
||||
dest_lon,
|
||||
::EuclideanDistance,
|
||||
)::Float64
|
||||
x = LLA(source_lat, source_lon, 0.0)
|
||||
y = LLA(dest_lat, dest_lon, 0.0)
|
||||
return round(euclidean_distance(x, y) / 1000.0, digits=3)
|
||||
end
|
||||
|
||||
function _download_file(url, output, expected_crc32)::Nothing
|
||||
if isfile(output)
|
||||
return
|
||||
end
|
||||
mkpath(dirname(output))
|
||||
@info "Downloading: $url"
|
||||
fname = download(url)
|
||||
actual_crc32 = open(crc32, fname)
|
||||
expected_crc32 == actual_crc32 || error("CRC32 mismatch")
|
||||
cp(fname, output)
|
||||
return
|
||||
end
|
||||
|
||||
function _download_zip(url, outputdir, expected_output_file, expected_crc32)::Nothing
|
||||
if isfile(expected_output_file)
|
||||
return
|
||||
end
|
||||
mkpath(outputdir)
|
||||
@info "Downloading: $url"
|
||||
zip_filename = download(url)
|
||||
actual_crc32 = open(crc32, zip_filename)
|
||||
expected_crc32 == actual_crc32 || error("CRC32 mismatch")
|
||||
open(zip_filename) do zip_file
|
||||
zr = ZipFile.Reader(zip_file)
|
||||
for file in zr.files
|
||||
open(joinpath(outputdir, file.name), "w") do output_file
|
||||
write(output_file, read(file))
|
||||
end
|
||||
end
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
function _calculate_distance(
|
||||
source_lat,
|
||||
source_lon,
|
||||
dest_lat,
|
||||
dest_lon,
|
||||
metric::KnnDrivingDistance,
|
||||
)::Float64
|
||||
if metric.tree === nothing
|
||||
basedir = joinpath(dirname(@__FILE__), "data")
|
||||
csv_filename = joinpath(basedir, "dist_driving.csv")
|
||||
|
||||
# Download pre-computed driving data
|
||||
if !isfile(csv_filename)
|
||||
_download_zip(
|
||||
"https://axavier.org/RELOG/0.6/data/dist_driving_0b9a6ad6.zip",
|
||||
basedir,
|
||||
csv_filename,
|
||||
0x0b9a6ad6,
|
||||
)
|
||||
end
|
||||
|
||||
# Fit kNN model
|
||||
df = DataFrame(CSV.File(csv_filename, missingstring="NaN"))
|
||||
dropmissing!(df)
|
||||
coords = Matrix(df[!, [:source_lat, :source_lon, :dest_lat, :dest_lon]])'
|
||||
metric.ratios = Matrix(df[!, [:ratio]])
|
||||
metric.tree = KDTree(coords)
|
||||
end
|
||||
|
||||
# Compute Euclidean distance
|
||||
dist_euclidean =
|
||||
_calculate_distance(source_lat, source_lon, dest_lat, dest_lon, EuclideanDistance())
|
||||
|
||||
# Predict ratio
|
||||
idxs, _ = knn(metric.tree, [source_lat, source_lon, dest_lat, dest_lon], 5)
|
||||
ratio_pred = mean(metric.ratios[idxs])
|
||||
dist_pred = round(dist_euclidean * ratio_pred, digits=3)
|
||||
isfinite(dist_pred) || error("non-finite distance detected: $dist_pred")
|
||||
return dist_pred
|
||||
end
|
@ -1,306 +0,0 @@
|
||||
# RELOG: Composition Format
|
||||
|
||||
## Input Data Format (JSON)
|
||||
|
||||
## Glossary of types
|
||||
|
||||
| Type | Description | Example |
|
||||
| --------------------- | -------------------------------------------------------- | ------------------------ |
|
||||
| `int` | An integer number. | `1` |
|
||||
| `float` | A real number. | `3.1415` |
|
||||
| `str` | A string. | `"Euclidean"` |
|
||||
| `vec(int)` | A vector of integer numbers, with any length. | `[1, 2, 3]` |
|
||||
| `vec(int, 5)` | A vector of integer numbers, with 5 elements. | `[1, 2, 3, 4, 5]` |
|
||||
| `mat(float, 2, 3, 4)` | A matrix of floating point numbers with shape (2, 3, 5). | `rand(Float64, 2, 3, 4)` |
|
||||
| `dict(str, int)` | A dictionary mapping strings to integer numbers. | `Dict("A" => 1)` |
|
||||
|
||||
### Parameters
|
||||
|
||||
| Key | Type | Description |
|
||||
| :------------------------ | ---------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `time horizon (years)` | `int` | Number of years in the simulation. |
|
||||
| `building period (years)` | `vec(int)` | 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. |
|
||||
| `distance metric` | `str` | Metric used to compute distances between pairs of locations. Valid options are: `"Euclidean"`, for the straight-line distance between points; or `"driving"` for an approximated driving distance. If not specified, defaults to `"Euclidean"`. |
|
||||
|
||||
#### Example
|
||||
|
||||
```json
|
||||
{
|
||||
"parameters": {
|
||||
"time horizon (years)": 4,
|
||||
"building period (years)": [1],
|
||||
"distance metric": "driving"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Products
|
||||
|
||||
| Key | Type | Description |
|
||||
| :------------------------------------------ | :------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| `transportation cost ($/km/tonne)` | `vec(float, T)` | The cost (in dollars) to transport one tonne of the product over one kilometer at time $t$. |
|
||||
| `transportation energy (J/km/tonne)` | `vec(float, T)` | The energy (in J) required to transport this product at time $t$. |
|
||||
| `transportation emissions (tonne/km/tonne)` | `dict(str, vec(float, T))` | A dictionary mapping the name of each greenhouse gas (produced during the transportation of one tonne of this product along one kilometer at time $t$) to the amount of gas produced (in tonnes). |
|
||||
| `components` | `vec(str)` | List of components for the product. |
|
||||
|
||||
#### Example
|
||||
|
||||
```json
|
||||
{
|
||||
"products": {
|
||||
"P1": {
|
||||
"transportation cost ($/km/tonne)": [0.015, 0.015, 0.015, 0.015],
|
||||
"transportation energy (J/km/tonne)": [0.12, 0.12, 0.12, 0.12],
|
||||
"transportation emissions (tonne/km/tonne)": {
|
||||
"CO2": [0.052, 0.052, 0.052, 0.052],
|
||||
"CH4": [0.003, 0.003, 0.003, 0.003]
|
||||
},
|
||||
"components": ["P1a", "P1b", "P1c"]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Centers
|
||||
|
||||
| Key | Type | Description |
|
||||
| :------------------------------ | ------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `latitude (deg)` | `float` | The latitude of the center. |
|
||||
| `longitude (deg)` | `float` | The longitude of the center. |
|
||||
| `input` | `str` | The name of the product this center takes as input. May be `null` if the center accept no input product. |
|
||||
| `outputs` | `vec(str)` | List of output products collected by the center. May be `[]` if none. |
|
||||
| `fixed output (tonne)` | `dict(str, mat(float, T, C))` | Dictionary mapping the name of each output product $p$ to a matrix $M$, where $M_{t,c}$ is the amount (in tonne) of output product component $c$ produced by the center at time $t$, regardless of how much input material the center received. |
|
||||
| `variable output (tonne/tonne)` | `dict(str,mat(float, T, M, N))` | Dictionary mapping the name of each output product $p$ to a $(T \times m \times n)$ matrix $M$ that describes the amount (in tonnes) of output product component produced by the center, depending on how much input material the center received in prior years, where $T$ is the number of years, $m$ is the number of components of $p$ and $n$ is the number of components of the input product. |
|
||||
| `revenue ($/tonne)` | `vec(float, T)` | Revenue generated by each tonne of input material sent to the center. If the center accepts no input, this should be `null` |
|
||||
| `collection cost ($/tonne)` | `dict(str,vec(float,T))` | Dictionary mapping the name of each output product to the cost of collecting one tonne of the product. |
|
||||
| `operating cost ($)` | `vec(float,T)` | Fixed cost to operate the center for one year, regardless of amount of product received or generated. |
|
||||
| `disposal limit (tonne)` | `dict(str,vec(float,T))` | Dictionary mapping the name of each output product to the maximum disposal amount allower per year of the product at the center. Entry may be `null` if unlimited. |
|
||||
| `disposal cost ($/tonne)` | `dict(str,vec(float,T))` | Dictionary mapping the name of each output product to the cost to dispose one tonne of the product at the center. |
|
||||
|
||||
```json
|
||||
{
|
||||
"centers": {
|
||||
"C1": {
|
||||
"latitude (deg)": 41.881,
|
||||
"longitude (deg)": -87.623,
|
||||
"input": "P1",
|
||||
"outputs": ["P2", "P3"],
|
||||
"fixed output (tonne)": {
|
||||
"P2": [
|
||||
[50, 20, 10],
|
||||
[5, 2, 1],
|
||||
[0, 0, 0],
|
||||
[0, 0, 0]
|
||||
],
|
||||
"P3": [
|
||||
[20, 10],
|
||||
[10, 5],
|
||||
[0, 0],
|
||||
[0, 0]
|
||||
]
|
||||
},
|
||||
"variable output (tonne/tonne)": {
|
||||
"P2": [
|
||||
[
|
||||
[1, 0, 0],
|
||||
[0, 1, 1]
|
||||
],
|
||||
[
|
||||
[1, 0, 0],
|
||||
[0, 1, 1]
|
||||
],
|
||||
[
|
||||
[1, 0, 0],
|
||||
[0, 1, 1]
|
||||
],
|
||||
[
|
||||
[1, 0, 0],
|
||||
[0, 1, 1]
|
||||
]
|
||||
],
|
||||
"P3": [
|
||||
[
|
||||
[1, 0, 0],
|
||||
[0, 1, 1]
|
||||
],
|
||||
[
|
||||
[1, 0, 0],
|
||||
[0, 1, 1]
|
||||
],
|
||||
[
|
||||
[1, 0, 0],
|
||||
[0, 1, 1]
|
||||
],
|
||||
[
|
||||
[1, 0, 0],
|
||||
[0, 1, 1]
|
||||
]
|
||||
]
|
||||
},
|
||||
"revenue ($/tonne)": [12.0, 12.0, 12.0, 12.0],
|
||||
"collection cost ($/tonne)": {
|
||||
"P2": [0.25, 0.25, 0.25, 0.25],
|
||||
"P3": [0.37, 0.37, 0.37, 0.37]
|
||||
},
|
||||
"operating cost ($)": [150.0, 150.0, 150.0, 150.0],
|
||||
"disposal limit (tonne)": {
|
||||
"P2": [0, 0, 0, 0],
|
||||
"P3": [null, null, null, null]
|
||||
},
|
||||
"disposal cost ($/tonne)": {
|
||||
"P2": [0.23, 0.23, 0.23, 0.23],
|
||||
"P3": [1.0, 1.0, 1.0, 1.0]
|
||||
}
|
||||
},
|
||||
"C2": {
|
||||
"latitude (deg)": 41.881,
|
||||
"longitude (deg)": -87.623,
|
||||
"input": null,
|
||||
"outputs": ["P4"],
|
||||
"fixed output (tonne)": {
|
||||
"P4": [
|
||||
[50, 5],
|
||||
[60, 6],
|
||||
[70, 7],
|
||||
[80, 8]
|
||||
]
|
||||
},
|
||||
"revenue ($/tonne)": null,
|
||||
"collection cost ($/tonne)": {
|
||||
"P4": [0.25, 0.25, 0.25, 0.25]
|
||||
},
|
||||
"operating cost ($)": [150.0, 150.0, 150.0, 150.0],
|
||||
"disposal limit (tonne)": {
|
||||
"P4": [null, null, null, null]
|
||||
},
|
||||
"disposal cost ($/tonne)": {
|
||||
"P4": [0, 0, 0, 0]
|
||||
}
|
||||
},
|
||||
"C3": {
|
||||
"latitude (deg)": 41.881,
|
||||
"longitude (deg)": -87.623,
|
||||
"input": "P1",
|
||||
"outputs": [],
|
||||
"variable output (tonne/tonne)": {},
|
||||
"constant output (tonne)": {},
|
||||
"revenue ($/tonne)": [12.0, 12.0, 12.0, 12.0],
|
||||
"collection cost ($/tonne)": {},
|
||||
"operating cost ($)": [150.0, 150.0, 150.0, 150.0],
|
||||
"disposal limit (tonne)": {},
|
||||
"disposal cost ($/tonne)": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Plants
|
||||
|
||||
| Key | | Description |
|
||||
| :----------------------------- | ----------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `latitude (deg)` | `float` | The latitude of the plant, in degrees. |
|
||||
| `longitude (deg)` | `float` | The longitude of the plant, in degrees. |
|
||||
| `input mix (%)` | `dict(str,float)` | Dictionary mapping the name of each input product to the amount required (as a percentage). Must sum to 100%. |
|
||||
| `output (tonne/tonne)` | `dict(str,dict(str,mat(float, T, M, N)))` | Dictionary of matrices describing the component outputs. |
|
||||
| `processing emissions (tonne)` | `dict(str,vec(float,T))` | A dictionary mapping the name of each greenhouse gas, produced to process each tonne of input, to the amount of gas produced (in tonne). |
|
||||
| `storage cost ($/tonne)` | `dict(str,vec(float,T))` | Dictionary mapping the name of each input product to the cost of storing the product for one year at the plant for later processing. |
|
||||
| `storage limit (tonne)` | | Dictionary mapping the name of each input product to the maximum amount allowed in storage at any time. May be `null` if unlimited. |
|
||||
| `disposal cost ($/tonne)` | | Dictionary mapping the name of each output product to the cost of disposing it at the plant. |
|
||||
| `disposal limit (tonne)` | | Dictionary mapping the name of each output product to the maximum amount allowed to be disposed of at the plant. May be `null` if unlimited. |
|
||||
| `capacities` | | List describing what plant sizes are allowed, and their characteristics. |
|
||||
|
||||
The entries in the `capacities` list should be dictionaries with the following
|
||||
keys:
|
||||
|
||||
| Key | Description |
|
||||
| :---------------------------------- | :-------------------------------------------------------------------------------------------------- |
|
||||
| `size (tonne)` | The size of the plant. |
|
||||
| `opening cost ($)` | The cost to open a plant of this size. |
|
||||
| `fixed operating cost ($)` | The cost to keep the plant open, even if the plant doesn't process anything. Must be a time series. |
|
||||
| `variable operating cost ($/tonne)` | The cost that the plant incurs to process each tonne of input. Must be a time series. |
|
||||
| `initial capacity (tonne)` | Capacity already available. If the plant has not been built yet, this should be `0`. |
|
||||
|
||||
```json
|
||||
{
|
||||
"plants": {
|
||||
"L1": {
|
||||
"latitude (deg)": 41.881,
|
||||
"longitude (deg)": -87.623,
|
||||
"input mix (%)": {
|
||||
"P1": 95.3,
|
||||
"P2": 4.7
|
||||
},
|
||||
"output (tonne/tonne)": {
|
||||
"P3": {
|
||||
"P1": [
|
||||
[[1, 0, 0], [0, 1, 1]],
|
||||
[[1, 0, 0], [0, 1, 1]],
|
||||
[[1, 0, 0], [0, 1, 1]],
|
||||
[[1, 0, 0], [0, 1, 1]]
|
||||
],
|
||||
"P2": [
|
||||
[[0, 1], [1, 0]],
|
||||
[[0, 1], [1, 0]],
|
||||
[[0, 1], [1, 0]],
|
||||
[[0, 1], [1, 0]]
|
||||
]
|
||||
},
|
||||
"P4": {
|
||||
"P1": [
|
||||
[[1, 0, 0], [0, 1, 1]],
|
||||
[[1, 0, 0], [0, 1, 1]],
|
||||
[[1, 0, 0], [0, 1, 1]],
|
||||
[[1, 0, 0], [0, 1, 1]]
|
||||
],
|
||||
"P2": [
|
||||
[[0, 1], [1, 0]],
|
||||
[[0, 1], [1, 0]],
|
||||
[[0, 1], [1, 0]],
|
||||
[[0, 1], [1, 0]]
|
||||
]
|
||||
},
|
||||
"P5": {
|
||||
"P1": [[1, 0, 0], [0, 1, 1]],
|
||||
"P2": [[0, 1], [1, 0]],
|
||||
}
|
||||
},
|
||||
"processing emissions (tonne)": {
|
||||
"CO2": 0.1
|
||||
},
|
||||
"storage cost ($/tonne)": {
|
||||
"P1": 0.1,
|
||||
"P2": 0.1
|
||||
},
|
||||
"storage limit (tonne)": {
|
||||
"P1": 100,
|
||||
"P2": null
|
||||
},
|
||||
"disposal cost ($/tonne)": {
|
||||
"P3": 0,
|
||||
"P4": 0.86,
|
||||
"P5": 0.25,
|
||||
},
|
||||
"disposal limit (tonne)": {
|
||||
"P3": null,
|
||||
"P4": 1000.0,
|
||||
"P5": 1000.0
|
||||
},
|
||||
"capacities": [
|
||||
{
|
||||
"size": 100,
|
||||
"opening cost ($)": 500,
|
||||
"fixed operating cost ($)": 300,
|
||||
"variable operating cost ($/tonne)": 5.0
|
||||
},
|
||||
{
|
||||
"size": 500,
|
||||
"opening cost ($)": 1000.0,
|
||||
"fixed operating cost ($)": 400.0,
|
||||
"variable operating cost ($/tonne)": 5.0.
|
||||
}
|
||||
],
|
||||
"initial capacity (tonne)": 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
@ -0,0 +1,159 @@
|
||||
using JuMP
|
||||
using OrderedCollections
|
||||
using Gurobi
|
||||
using Random
|
||||
using Printf
|
||||
|
||||
dict = OrderedDict
|
||||
|
||||
macro pprint(var)
|
||||
quote
|
||||
println(string($(QuoteNode(var))))
|
||||
v = round.($(esc(var)), digits=2)
|
||||
display(v)
|
||||
println()
|
||||
end
|
||||
end
|
||||
|
||||
macro pprint_jump(var)
|
||||
quote
|
||||
println(string($(QuoteNode(var))))
|
||||
v = round.(value.($(esc(var))), digits=2)
|
||||
display(v)
|
||||
println()
|
||||
end
|
||||
end
|
||||
|
||||
function model1()
|
||||
Random.seed!(42)
|
||||
|
||||
model = Model(
|
||||
optimizer_with_attributes(
|
||||
Gurobi.Optimizer,
|
||||
"NonConvex" => 2,
|
||||
),
|
||||
)
|
||||
|
||||
# Data
|
||||
# -------------------------------------------------------------------------
|
||||
n_plants = 5
|
||||
n_components = 2
|
||||
plants = 1:n_plants
|
||||
components = 1:n_components
|
||||
initial_amount = [rand(1:1000) for _ in plants, _ in components]
|
||||
revenue = [rand(1:1000) for _ in plants]
|
||||
tr_cost = [
|
||||
rand(1:50)
|
||||
for _ in plants, _ in plants
|
||||
]
|
||||
|
||||
@show plants
|
||||
@show components
|
||||
@show initial_amount
|
||||
@show revenue
|
||||
|
||||
# Decision variables
|
||||
# -------------------------------------------------------------------------
|
||||
@variable(model, y_total[plants, plants], lower_bound = 0)
|
||||
@variable(model, y[plants, plants, components], lower_bound = 0)
|
||||
@variable(model, z_disp_total[plants], lower_bound = 0)
|
||||
@variable(model, z_disp[plants, components], lower_bound = 0)
|
||||
@variable(model, z_avail_total[plants])
|
||||
@variable(model, z_avail[plants, components])
|
||||
@variable(model, alpha[plants, components])
|
||||
|
||||
# Objective
|
||||
# -------------------------------------------------------------------------
|
||||
@objective(
|
||||
model,
|
||||
Max,
|
||||
sum(
|
||||
z_disp_total[p] * revenue[p]
|
||||
for p in plants
|
||||
)
|
||||
-
|
||||
sum(
|
||||
y_total[p, q] * tr_cost[p, q]
|
||||
for p in plants, q in plants
|
||||
)
|
||||
)
|
||||
|
||||
# Constraints
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
# Definition of total sent
|
||||
@constraint(
|
||||
model,
|
||||
eq_y_total_def[p in plants, q in plants],
|
||||
y_total[p, q] == sum(y[p, q, c] for c in components)
|
||||
)
|
||||
|
||||
# Definition of total disposed
|
||||
@constraint(
|
||||
model,
|
||||
eq_z_disp_total_def[p in plants], z_disp_total[p] == sum(z_disp[p, c] for c in components)
|
||||
)
|
||||
|
||||
# Definition of available amount
|
||||
@constraint(
|
||||
model,
|
||||
eq_z_avail_total[p in plants],
|
||||
z_avail_total[p] == sum(z_avail[p, c] for c in components)
|
||||
)
|
||||
|
||||
# Definition of available component
|
||||
@constraint(
|
||||
model,
|
||||
eq_z_avail[p in plants, c in components],
|
||||
z_avail[p, c] == initial_amount[p, c] + sum(y[q, p, c] for q in plants)
|
||||
)
|
||||
|
||||
# Mass balance
|
||||
@constraint(
|
||||
model,
|
||||
eq_balance[p in plants],
|
||||
z_avail_total[p] == z_disp_total[p] + sum(y_total[p, q] for q in plants)
|
||||
)
|
||||
|
||||
# Available proportion
|
||||
@constraint(
|
||||
model,
|
||||
eq_alpha_avail[p in plants, c in components],
|
||||
z_avail[p, c] == alpha[p, c] * z_avail_total[p]
|
||||
)
|
||||
|
||||
# Sending proportion
|
||||
@constraint(
|
||||
model,
|
||||
eq_alpha_send[p in plants, q in plants, c in components],
|
||||
y[p, q, c] == alpha[p, c] * y_total[p, q]
|
||||
)
|
||||
|
||||
# Disposal proportion
|
||||
@constraint(
|
||||
model,
|
||||
eq_alpha_disp[p in plants, c in components],
|
||||
z_disp[p, c] == alpha[p, c] * z_disp_total[p]
|
||||
)
|
||||
|
||||
# Run
|
||||
# -------------------------------------------------------------------------
|
||||
print(model)
|
||||
optimize!(model)
|
||||
|
||||
# Print solution
|
||||
# -------------------------------------------------------------------------
|
||||
@pprint initial_amount
|
||||
@pprint revenue
|
||||
@pprint tr_cost
|
||||
|
||||
@pprint_jump y_total
|
||||
@pprint_jump y
|
||||
@pprint_jump z_disp_total
|
||||
@pprint_jump z_disp
|
||||
@pprint_jump z_avail_total
|
||||
@pprint_jump z_avail
|
||||
@pprint_jump alpha
|
||||
end
|
||||
|
||||
model1()
|
@ -0,0 +1,282 @@
|
||||
using JuMP
|
||||
using OrderedCollections
|
||||
using Gurobi
|
||||
using Random
|
||||
using Printf
|
||||
using DataFrames
|
||||
using CSV
|
||||
|
||||
dict = OrderedDict
|
||||
|
||||
function model2()
|
||||
Random.seed!(42)
|
||||
|
||||
model = Model(
|
||||
optimizer_with_attributes(
|
||||
Gurobi.Optimizer,
|
||||
),
|
||||
)
|
||||
|
||||
# Data
|
||||
# -------------------------------------------------------------------------
|
||||
components = ["film", "paper", "cardboard"]
|
||||
centers = [
|
||||
"Chicago",
|
||||
"New York City",
|
||||
"Los Angeles",
|
||||
"Houston",
|
||||
"Phoenix",
|
||||
"Philadelphia",
|
||||
"San Antonio",
|
||||
"San Diego",
|
||||
"Dallas",
|
||||
"San Jose",
|
||||
]
|
||||
plants = [
|
||||
"Chicago",
|
||||
"Phoenix",
|
||||
"Dallas",
|
||||
]
|
||||
products = [
|
||||
"film bale",
|
||||
"cardboard bale"
|
||||
]
|
||||
initial_amount = dict(
|
||||
(q, c) => rand(1:1000)
|
||||
for q in centers, c in components
|
||||
)
|
||||
cost_tr = dict(
|
||||
(q, p) => rand(1:10)
|
||||
for q in centers, p in plants
|
||||
)
|
||||
cost_open = dict(
|
||||
p => rand(5000:10000)
|
||||
for p in plants
|
||||
)
|
||||
cost_var = dict(
|
||||
p => rand(5:10)
|
||||
for p in plants
|
||||
)
|
||||
revenue = dict(
|
||||
(p, m) => rand(10:20)
|
||||
for p in plants, m in products
|
||||
)
|
||||
alpha = dict(
|
||||
"film bale" => dict(
|
||||
"film" => dict(
|
||||
"film" => 0.98,
|
||||
"paper" => 0,
|
||||
"cardboard" => 0,
|
||||
),
|
||||
"paper" => dict(
|
||||
"film" => 0,
|
||||
"paper" => 0.02,
|
||||
"cardboard" => 0,
|
||||
),
|
||||
"cardboard" => dict(
|
||||
"film" => 0,
|
||||
"paper" => 0,
|
||||
"cardboard" => 0.02,
|
||||
),
|
||||
),
|
||||
"cardboard bale" => dict(
|
||||
"film" => dict(
|
||||
"film" => 0.0,
|
||||
"paper" => 0.0,
|
||||
"cardboard" => 0.0,
|
||||
),
|
||||
"paper" => dict(
|
||||
"film" => 0.0,
|
||||
"paper" => 0.02,
|
||||
"cardboard" => 0.0,
|
||||
),
|
||||
"cardboard" => dict(
|
||||
"film" => 0.0,
|
||||
"paper" => 0.0,
|
||||
"cardboard" => 0.75,
|
||||
),
|
||||
),
|
||||
)
|
||||
capacity = dict(
|
||||
p => rand(10000:50000)
|
||||
for p in plants
|
||||
)
|
||||
|
||||
# Variables
|
||||
# -------------------------------------------------------------------------
|
||||
@variable(model, y[centers, plants, components] >= 0)
|
||||
@variable(model, y_total[centers, plants])
|
||||
@variable(model, x[plants], Bin)
|
||||
@variable(model, z_avail[plants, components])
|
||||
@variable(model, z_prod[plants, products, components])
|
||||
|
||||
|
||||
# Objective
|
||||
# -------------------------------------------------------------------------
|
||||
@objective(
|
||||
model,
|
||||
Min,
|
||||
|
||||
# Transportation cost
|
||||
+ sum(
|
||||
cost_tr[q, p] * y[q, p, c]
|
||||
for p in plants, q in centers, c in components
|
||||
)
|
||||
|
||||
# Opening cost
|
||||
+ sum(
|
||||
cost_open[p] * x[p]
|
||||
for p in plants
|
||||
)
|
||||
|
||||
# Variable operating cost
|
||||
+ sum(
|
||||
cost_var[p] * y[q,p,c]
|
||||
for q in centers, p in plants, c in components
|
||||
)
|
||||
|
||||
# Revenue
|
||||
+ sum(
|
||||
revenue[p,m] * z_prod[p,m,c]
|
||||
for p in plants, m in products, c in components
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
# Constraints
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
# Flow balance at centers:
|
||||
@constraint(
|
||||
model,
|
||||
eq_flow_balance[q in centers, c in components],
|
||||
sum(y[q,p,c] for p in plants) == initial_amount[q, c]
|
||||
)
|
||||
|
||||
# Total flow:
|
||||
@constraint(
|
||||
model,
|
||||
eq_total_flow[q in centers, p in plants],
|
||||
y_total[q,p] == sum(y[q,p,c] for c in components)
|
||||
)
|
||||
|
||||
# Center balance mix:
|
||||
@constraint(
|
||||
model,
|
||||
eq_mix[q in centers, p in plants, c in components],
|
||||
y[q,p,c] == initial_amount[q,c] / sum(initial_amount[q,d] for d in components) * y_total[q,p]
|
||||
)
|
||||
|
||||
# Plant capacity
|
||||
@constraint(
|
||||
model,
|
||||
eq_capacity[p in plants],
|
||||
sum(y_total[q,p] for q in centers) <= capacity[p] * x[p]
|
||||
)
|
||||
|
||||
# Amount available
|
||||
@constraint(
|
||||
model,
|
||||
eq_z_avail[p in plants, c in components],
|
||||
z_avail[p,c] == sum(y[q,p,c] for q in centers)
|
||||
)
|
||||
|
||||
# Amount produced
|
||||
@constraint(
|
||||
model,
|
||||
eq_z_prod[p in plants, m in products, c in components],
|
||||
z_prod[p,m,c] ==
|
||||
sum(
|
||||
alpha[m][c][d] *
|
||||
z_avail[p,c]
|
||||
for d in components
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
# Run
|
||||
# -------------------------------------------------------------------------
|
||||
print(model)
|
||||
optimize!(model)
|
||||
|
||||
# Report: Transportation
|
||||
# -------------------------------------------------------------------------
|
||||
df = DataFrame()
|
||||
df."center" = String[]
|
||||
df."plant" = String[]
|
||||
df."component" = String[]
|
||||
df."amount sent (tonne)" = Float64[]
|
||||
df."transportation cost (\$)" = Float64[]
|
||||
df."variable operating cost (\$)" = Float64[]
|
||||
for q in centers, p in plants, c in components
|
||||
if value(y[q, p, c]) ≈ 0
|
||||
continue
|
||||
end
|
||||
push!(
|
||||
df,
|
||||
[
|
||||
q,
|
||||
p,
|
||||
c,
|
||||
value(y[q, p, c]),
|
||||
cost_tr[q, p] * value(y[q, p, c]),
|
||||
cost_var[p] * value(y[q,p,c])
|
||||
]
|
||||
)
|
||||
end
|
||||
CSV.write("output-2/tr.csv", df)
|
||||
|
||||
|
||||
# Report: Plant
|
||||
# -------------------------------------------------------------------------
|
||||
df = DataFrame()
|
||||
df."plant" = String[]
|
||||
df."is open?" = Float64[]
|
||||
df."capacity (tonne)" = Float64[]
|
||||
df."utilization (tonne)" = Float64[]
|
||||
df."opening cost (\$)" = Float64[]
|
||||
for p in plants
|
||||
if value(x[p]) ≈ 0
|
||||
continue
|
||||
end
|
||||
push!(
|
||||
df,
|
||||
[
|
||||
p,
|
||||
value(x[p]),
|
||||
capacity[p],
|
||||
sum(value(y_total[q,p]) for q in centers),
|
||||
cost_open[p] * value(x[p])
|
||||
]
|
||||
)
|
||||
end
|
||||
CSV.write("output-2/plant.csv", df)
|
||||
|
||||
# Report: Plant Outputs
|
||||
# -------------------------------------------------------------------------
|
||||
df = DataFrame()
|
||||
df."plant" = String[]
|
||||
df."product" = String[]
|
||||
df."component" = String[]
|
||||
df."amount produced (tonne)" = Float64[]
|
||||
df."revenue (\$)" = Float64[]
|
||||
for p in plants, m in products, c in components
|
||||
if value(z_prod[p, m, c]) ≈ 0
|
||||
continue
|
||||
end
|
||||
push!(
|
||||
df,
|
||||
[
|
||||
p,
|
||||
m,
|
||||
c,
|
||||
value(z_prod[p, m, c]),
|
||||
revenue[p,m] * value(z_prod[p,m,c])
|
||||
]
|
||||
)
|
||||
end
|
||||
CSV.write("output-2/plant-outputs.csv", df)
|
||||
|
||||
end
|
||||
|
||||
model2()
|
File diff suppressed because it is too large
Load Diff
Binary file not shown.
|
|
|
@ -0,0 +1,815 @@
|
||||
{
|
||||
"parameters": {
|
||||
"time horizon (years)": 2
|
||||
},
|
||||
"products": {
|
||||
"Waste": {
|
||||
"components": [
|
||||
"Film",
|
||||
"Paper",
|
||||
"Cardboard"
|
||||
],
|
||||
"disposal limit (tonne)": [
|
||||
0.0,
|
||||
0.0
|
||||
],
|
||||
"transportation cost ($/km/tonne)": [
|
||||
0.05,
|
||||
0.05
|
||||
],
|
||||
"transportation emissions (tonne/km/tonne)": {
|
||||
"CO2": [
|
||||
0.01,
|
||||
0.01
|
||||
]
|
||||
}
|
||||
},
|
||||
"Film bale": {
|
||||
"components": [
|
||||
"Film",
|
||||
"Paper",
|
||||
"Cardboard"
|
||||
],
|
||||
"disposal limit (tonne)": [
|
||||
0.0,
|
||||
0.0
|
||||
],
|
||||
"transportation cost ($/km/tonne)": [
|
||||
0.05,
|
||||
0.05
|
||||
],
|
||||
"transportation emissions (tonne/km/tonne)": {
|
||||
"CO2": [
|
||||
0.01,
|
||||
0.01
|
||||
]
|
||||
}
|
||||
},
|
||||
"Cardboard bale": {
|
||||
"components": [
|
||||
"Paper",
|
||||
"Cardboard"
|
||||
],
|
||||
"disposal limit (tonne)": [
|
||||
0.0,
|
||||
0.0
|
||||
],
|
||||
"transportation cost ($/km/tonne)": [
|
||||
0.05,
|
||||
0.05
|
||||
],
|
||||
"transportation emissions (tonne/km/tonne)": {
|
||||
"CO2": [
|
||||
0.01,
|
||||
0.01
|
||||
]
|
||||
}
|
||||
},
|
||||
"Cardboard sheets": {
|
||||
"components": [
|
||||
"Cardboard"
|
||||
],
|
||||
"disposal limit (tonne)": [
|
||||
0.0,
|
||||
0.0
|
||||
],
|
||||
"transportation cost ($/km/tonne)": [
|
||||
0.05,
|
||||
0.05
|
||||
],
|
||||
"transportation emissions (tonne/km/tonne)": {
|
||||
"CO2": [
|
||||
0.01,
|
||||
0.01
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"centers": {
|
||||
"Collection (Chicago)": {
|
||||
"latitude": 41.881832,
|
||||
"longitude": -87.623177,
|
||||
"output": {
|
||||
"Waste": {
|
||||
"initial amount (tonne)": [
|
||||
[
|
||||
716.0,
|
||||
2864.0,
|
||||
1074.0
|
||||
],
|
||||
[
|
||||
1394.0,
|
||||
5576.0,
|
||||
2091.0
|
||||
]
|
||||
],
|
||||
"disposal cost ($/tonne)": [
|
||||
0.0,
|
||||
0.0
|
||||
],
|
||||
"storage cost ($/tonne)": [
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"storage limit (tonne)": [
|
||||
1000.0,
|
||||
1000.0
|
||||
],
|
||||
"acquisition cost ($/tonne)": [
|
||||
1.0,
|
||||
1.0
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"Collection (New York City)": {
|
||||
"latitude": 40.712776,
|
||||
"longitude": -74.005974,
|
||||
"output": {
|
||||
"Waste": {
|
||||
"initial amount (tonne)": [
|
||||
[
|
||||
990.0,
|
||||
891.0,
|
||||
297.0
|
||||
],
|
||||
[
|
||||
6450.0,
|
||||
5805.0,
|
||||
1935.0
|
||||
]
|
||||
],
|
||||
"disposal cost ($/tonne)": [
|
||||
0.0,
|
||||
0.0
|
||||
],
|
||||
"storage cost ($/tonne)": [
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"storage limit (tonne)": [
|
||||
1000.0,
|
||||
1000.0
|
||||
],
|
||||
"acquisition cost ($/tonne)": [
|
||||
1.0,
|
||||
1.0
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"Collection (Los Angeles)": {
|
||||
"latitude": 34.052235,
|
||||
"longitude": -118.243683,
|
||||
"output": {
|
||||
"Waste": {
|
||||
"initial amount (tonne)": [
|
||||
[
|
||||
4160.0,
|
||||
3640.0,
|
||||
5200.0
|
||||
],
|
||||
[
|
||||
5704.0,
|
||||
4991.0,
|
||||
7130.0
|
||||
]
|
||||
],
|
||||
"disposal cost ($/tonne)": [
|
||||
0.0,
|
||||
0.0
|
||||
],
|
||||
"storage cost ($/tonne)": [
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"storage limit (tonne)": [
|
||||
1000.0,
|
||||
1000.0
|
||||
],
|
||||
"acquisition cost ($/tonne)": [
|
||||
1.0,
|
||||
1.0
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"Collection (Houston)": {
|
||||
"latitude": 29.760427,
|
||||
"longitude": -95.369804,
|
||||
"output": {
|
||||
"Waste": {
|
||||
"initial amount (tonne)": [
|
||||
[
|
||||
2668.0,
|
||||
4669.0,
|
||||
6670.0
|
||||
],
|
||||
[
|
||||
1852.0,
|
||||
3241.0,
|
||||
4630.0
|
||||
]
|
||||
],
|
||||
"disposal cost ($/tonne)": [
|
||||
0.0,
|
||||
0.0
|
||||
],
|
||||
"storage cost ($/tonne)": [
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"storage limit (tonne)": [
|
||||
1000.0,
|
||||
1000.0
|
||||
],
|
||||
"acquisition cost ($/tonne)": [
|
||||
1.0,
|
||||
1.0
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"Collection (Phoenix)": {
|
||||
"latitude": 33.448376,
|
||||
"longitude": -112.074036,
|
||||
"output": {
|
||||
"Waste": {
|
||||
"initial amount (tonne)": [
|
||||
[
|
||||
3635.0,
|
||||
6543.0,
|
||||
5089.0
|
||||
],
|
||||
[
|
||||
2275.0,
|
||||
4095.0,
|
||||
3185.0
|
||||
]
|
||||
],
|
||||
"disposal cost ($/tonne)": [
|
||||
0.0,
|
||||
0.0
|
||||
],
|
||||
"storage cost ($/tonne)": [
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"storage limit (tonne)": [
|
||||
1000.0,
|
||||
1000.0
|
||||
],
|
||||
"acquisition cost ($/tonne)": [
|
||||
1.0,
|
||||
1.0
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"Collection (Philadelphia)": {
|
||||
"latitude": 39.952583,
|
||||
"longitude": -75.165222,
|
||||
"output": {
|
||||
"Waste": {
|
||||
"initial amount (tonne)": [
|
||||
[
|
||||
220.0,
|
||||
880.0,
|
||||
880.0
|
||||
],
|
||||
[
|
||||
962.0,
|
||||
3848.0,
|
||||
3848.0
|
||||
]
|
||||
],
|
||||
"disposal cost ($/tonne)": [
|
||||
0.0,
|
||||
0.0
|
||||
],
|
||||
"storage cost ($/tonne)": [
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"storage limit (tonne)": [
|
||||
1000.0,
|
||||
1000.0
|
||||
],
|
||||
"acquisition cost ($/tonne)": [
|
||||
1.0,
|
||||
1.0
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"Collection (San Antonio)": {
|
||||
"latitude": 29.424122,
|
||||
"longitude": -98.493629,
|
||||
"output": {
|
||||
"Waste": {
|
||||
"initial amount (tonne)": [
|
||||
[
|
||||
288.0,
|
||||
252.0,
|
||||
324.0
|
||||
],
|
||||
[
|
||||
4240.0,
|
||||
3710.0,
|
||||
4770.0
|
||||
]
|
||||
],
|
||||
"disposal cost ($/tonne)": [
|
||||
0.0,
|
||||
0.0
|
||||
],
|
||||
"storage cost ($/tonne)": [
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"storage limit (tonne)": [
|
||||
1000.0,
|
||||
1000.0
|
||||
],
|
||||
"acquisition cost ($/tonne)": [
|
||||
1.0,
|
||||
1.0
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"Collection (San Diego)": {
|
||||
"latitude": 32.715736,
|
||||
"longitude": -117.161087,
|
||||
"output": {
|
||||
"Waste": {
|
||||
"initial amount (tonne)": [
|
||||
[
|
||||
6690.0,
|
||||
1338.0,
|
||||
4014.0
|
||||
],
|
||||
[
|
||||
8460.0,
|
||||
1692.0,
|
||||
5076.0
|
||||
]
|
||||
],
|
||||
"disposal cost ($/tonne)": [
|
||||
0.0,
|
||||
0.0
|
||||
],
|
||||
"storage cost ($/tonne)": [
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"storage limit (tonne)": [
|
||||
1000.0,
|
||||
1000.0
|
||||
],
|
||||
"acquisition cost ($/tonne)": [
|
||||
1.0,
|
||||
1.0
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"Collection (Dallas)": {
|
||||
"latitude": 32.776664,
|
||||
"longitude": -96.796988,
|
||||
"output": {
|
||||
"Waste": {
|
||||
"initial amount (tonne)": [
|
||||
[
|
||||
5096.0,
|
||||
728.0,
|
||||
5824.0
|
||||
],
|
||||
[
|
||||
4354.0,
|
||||
622.0,
|
||||
4976.0
|
||||
]
|
||||
],
|
||||
"disposal cost ($/tonne)": [
|
||||
0.0,
|
||||
0.0
|
||||
],
|
||||
"storage cost ($/tonne)": [
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"storage limit (tonne)": [
|
||||
1000.0,
|
||||
1000.0
|
||||
],
|
||||
"acquisition cost ($/tonne)": [
|
||||
1.0,
|
||||
1.0
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"Collection (San Jose)": {
|
||||
"latitude": 37.338208,
|
||||
"longitude": -121.886329,
|
||||
"output": {
|
||||
"Waste": {
|
||||
"initial amount (tonne)": [
|
||||
[
|
||||
1255.0,
|
||||
2510.0,
|
||||
251.0
|
||||
],
|
||||
[
|
||||
4650.0,
|
||||
9300.0,
|
||||
930.0
|
||||
]
|
||||
],
|
||||
"disposal cost ($/tonne)": [
|
||||
0.0,
|
||||
0.0
|
||||
],
|
||||
"storage cost ($/tonne)": [
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"storage limit (tonne)": [
|
||||
1000.0,
|
||||
1000.0
|
||||
],
|
||||
"acquisition cost ($/tonne)": [
|
||||
1.0,
|
||||
1.0
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"plants": {
|
||||
"MRF (Chicago)": {
|
||||
"latitude": 41.881832,
|
||||
"longitude": -87.623177,
|
||||
"input": "Waste",
|
||||
"output": {
|
||||
"Film bale": {
|
||||
"output matrix": [
|
||||
[
|
||||
0.98,
|
||||
0.0,
|
||||
0.0
|
||||
],
|
||||
[
|
||||
0.0,
|
||||
0.02,
|
||||
0.0
|
||||
],
|
||||
[
|
||||
0.0,
|
||||
0.0,
|
||||
0.02
|
||||
]
|
||||
],
|
||||
"disposal limit (tonne)": [
|
||||
1.0e6,
|
||||
1.0e6
|
||||
],
|
||||
"disposal cost ($/tonne)": [
|
||||
-10.0,
|
||||
-10.0
|
||||
]
|
||||
},
|
||||
"Cardboard bale": {
|
||||
"output matrix": [
|
||||
[
|
||||
0.0,
|
||||
0.02,
|
||||
0.0
|
||||
],
|
||||
[
|
||||
0.0,
|
||||
0.0,
|
||||
0.75
|
||||
]
|
||||
],
|
||||
"disposal limit (tonne)": [
|
||||
1.0e6,
|
||||
1.0e6
|
||||
],
|
||||
"disposal cost ($/tonne)": [
|
||||
-10.0,
|
||||
-10.0
|
||||
]
|
||||
}
|
||||
},
|
||||
"fixed operating cost ($)": [
|
||||
1000.0,
|
||||
1000.0
|
||||
],
|
||||
"variable operating cost ($/tonne)": [
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"opening cost ($)": [
|
||||
10000.0,
|
||||
10000.0
|
||||
],
|
||||
"capacity (tonne)": 50000.0,
|
||||
"emissions (tonne/tonne)": {
|
||||
"CO2": [
|
||||
0.01,
|
||||
0.01
|
||||
]
|
||||
}
|
||||
},
|
||||
"MRF (Phoenix)": {
|
||||
"latitude": 33.448376,
|
||||
"longitude": -112.074036,
|
||||
"input": "Waste",
|
||||
"output": {
|
||||
"Film bale": {
|
||||
"output matrix": [
|
||||
[
|
||||
0.98,
|
||||
0.0,
|
||||
0.0
|
||||
],
|
||||
[
|
||||
0.0,
|
||||
0.02,
|
||||
0.0
|
||||
],
|
||||
[
|
||||
0.0,
|
||||
0.0,
|
||||
0.02
|
||||
]
|
||||
],
|
||||
"disposal limit (tonne)": [
|
||||
1.0e6,
|
||||
1.0e6
|
||||
],
|
||||
"disposal cost ($/tonne)": [
|
||||
-10.0,
|
||||
-10.0
|
||||
]
|
||||
},
|
||||
"Cardboard bale": {
|
||||
"output matrix": [
|
||||
[
|
||||
0.0,
|
||||
0.02,
|
||||
0.0
|
||||
],
|
||||
[
|
||||
0.0,
|
||||
0.0,
|
||||
0.75
|
||||
]
|
||||
],
|
||||
"disposal limit (tonne)": [
|
||||
1.0e6,
|
||||
1.0e6
|
||||
],
|
||||
"disposal cost ($/tonne)": [
|
||||
-10.0,
|
||||
-10.0
|
||||
]
|
||||
}
|
||||
},
|
||||
"fixed operating cost ($)": [
|
||||
1000.0,
|
||||
1000.0
|
||||
],
|
||||
"variable operating cost ($/tonne)": [
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"opening cost ($)": [
|
||||
10000.0,
|
||||
10000.0
|
||||
],
|
||||
"capacity (tonne)": 50000.0,
|
||||
"emissions (tonne/tonne)": {
|
||||
"CO2": [
|
||||
0.01,
|
||||
0.01
|
||||
]
|
||||
}
|
||||
},
|
||||
"MRF (Dallas)": {
|
||||
"latitude": 32.776664,
|
||||
"longitude": -96.796988,
|
||||
"input": "Waste",
|
||||
"output": {
|
||||
"Film bale": {
|
||||
"output matrix": [
|
||||
[
|
||||
0.98,
|
||||
0.0,
|
||||
0.0
|
||||
],
|
||||
[
|
||||
0.0,
|
||||
0.02,
|
||||
0.0
|
||||
],
|
||||
[
|
||||
0.0,
|
||||
0.0,
|
||||
0.02
|
||||
]
|
||||
],
|
||||
"disposal limit (tonne)": [
|
||||
1.0e6,
|
||||
1.0e6
|
||||
],
|
||||
"disposal cost ($/tonne)": [
|
||||
-10.0,
|
||||
-10.0
|
||||
]
|
||||
},
|
||||
"Cardboard bale": {
|
||||
"output matrix": [
|
||||
[
|
||||
0.0,
|
||||
0.02,
|
||||
0.0
|
||||
],
|
||||
[
|
||||
0.0,
|
||||
0.0,
|
||||
0.75
|
||||
]
|
||||
],
|
||||
"disposal limit (tonne)": [
|
||||
1.0e6,
|
||||
1.0e6
|
||||
],
|
||||
"disposal cost ($/tonne)": [
|
||||
-10.0,
|
||||
-10.0
|
||||
]
|
||||
}
|
||||
},
|
||||
"fixed operating cost ($)": [
|
||||
1000.0,
|
||||
1000.0
|
||||
],
|
||||
"variable operating cost ($/tonne)": [
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"opening cost ($)": [
|
||||
10000.0,
|
||||
10000.0
|
||||
],
|
||||
"capacity (tonne)": 50000.0,
|
||||
"emissions (tonne/tonne)": {
|
||||
"CO2": [
|
||||
0.01,
|
||||
0.01
|
||||
]
|
||||
}
|
||||
},
|
||||
"Paper Mill (Chicago)": {
|
||||
"latitude": 41.881832,
|
||||
"longitude": -87.623177,
|
||||
"input": "Cardboard bale",
|
||||
"output": {
|
||||
"Cardboard sheets": {
|
||||
"output matrix": [
|
||||
[
|
||||
0.0,
|
||||
0.95
|
||||
]
|
||||
],
|
||||
"disposal limit (tonne)": [
|
||||
1.0e6,
|
||||
1.0e6
|
||||
],
|
||||
"disposal cost ($/tonne)": [
|
||||
-100.0,
|
||||
-100.0
|
||||
]
|
||||
}
|
||||
},
|
||||
"fixed operating cost ($)": [
|
||||
1000.0,
|
||||
1000.0
|
||||
],
|
||||
"variable operating cost ($/tonne)": [
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"opening cost ($)": [
|
||||
10000.0,
|
||||
10000.0
|
||||
],
|
||||
"capacity (tonne)": 50000.0,
|
||||
"emissions (tonne/tonne)": {
|
||||
"CO2": [
|
||||
0.01,
|
||||
0.01
|
||||
]
|
||||
}
|
||||
},
|
||||
"Paper Mill (Phoenix)": {
|
||||
"latitude": 33.448376,
|
||||
"longitude": -112.074036,
|
||||
"input": "Cardboard bale",
|
||||
"output": {
|
||||
"Cardboard sheets": {
|
||||
"output matrix": [
|
||||
[
|
||||
0.0,
|
||||
0.95
|
||||
]
|
||||
],
|
||||
"disposal limit (tonne)": [
|
||||
1.0e6,
|
||||
1.0e6
|
||||
],
|
||||
"disposal cost ($/tonne)": [
|
||||
-100.0,
|
||||
-100.0
|
||||
]
|
||||
}
|
||||
},
|
||||
"fixed operating cost ($)": [
|
||||
1000.0,
|
||||
1000.0
|
||||
],
|
||||
"variable operating cost ($/tonne)": [
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"opening cost ($)": [
|
||||
10000.0,
|
||||
10000.0
|
||||
],
|
||||
"capacity (tonne)": 50000.0,
|
||||
"emissions (tonne/tonne)": {
|
||||
"CO2": [
|
||||
0.01,
|
||||
0.01
|
||||
]
|
||||
}
|
||||
},
|
||||
"Paper Mill (Dallas)": {
|
||||
"latitude": 32.776664,
|
||||
"longitude": -96.796988,
|
||||
"input": "Cardboard bale",
|
||||
"output": {
|
||||
"Cardboard sheets": {
|
||||
"output matrix": [
|
||||
[
|
||||
0.0,
|
||||
0.95
|
||||
]
|
||||
],
|
||||
"disposal limit (tonne)": [
|
||||
1.0e6,
|
||||
1.0e6
|
||||
],
|
||||
"disposal cost ($/tonne)": [
|
||||
-100.0,
|
||||
-100.0
|
||||
]
|
||||
}
|
||||
},
|
||||
"fixed operating cost ($)": [
|
||||
1000.0,
|
||||
1000.0
|
||||
],
|
||||
"variable operating cost ($/tonne)": [
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"opening cost ($)": [
|
||||
10000.0,
|
||||
10000.0
|
||||
],
|
||||
"capacity (tonne)": 50000.0,
|
||||
"emissions (tonne/tonne)": {
|
||||
"CO2": [
|
||||
0.01,
|
||||
0.01
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"emissions": {
|
||||
"CO2": {
|
||||
"penalty ($/tonne)": [
|
||||
0.01,
|
||||
0.01
|
||||
],
|
||||
"limit (tonne)": [
|
||||
1.0e6,
|
||||
1.0e6
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
|
|
|
|
|
|
@ -1,14 +0,0 @@
|
||||
module RELOG
|
||||
|
||||
_round(x::Number) = round(x, digits = 5)
|
||||
|
||||
include("instance/structs.jl")
|
||||
include("instance/parse.jl")
|
||||
include("model/jumpext.jl")
|
||||
include("model/dist.jl")
|
||||
include("model/build.jl")
|
||||
include("reports/plants.jl")
|
||||
include("reports/transportation.jl")
|
||||
include("reports/centers.jl")
|
||||
|
||||
end # module RELOG
|
@ -1,145 +0,0 @@
|
||||
using JSON
|
||||
using OrderedCollections
|
||||
|
||||
function parsefile(path::String)::Instance
|
||||
return RELOG.parse(JSON.parsefile(path, dicttype = () -> OrderedDict()))
|
||||
end
|
||||
|
||||
function parse(json)::Instance
|
||||
# Read parameters
|
||||
time_horizon = json["parameters"]["time horizon (years)"]
|
||||
building_period = json["parameters"]["building period (years)"]
|
||||
distance_metric = json["parameters"]["distance metric"]
|
||||
|
||||
timeseries(x::Union{Nothing,Number}) = repeat([x], time_horizon)
|
||||
timeseries(x::Array) = x
|
||||
timeseries(d::OrderedDict) = OrderedDict(k => timeseries(v) for (k, v) in d)
|
||||
|
||||
# Read products
|
||||
products = Product[]
|
||||
products_by_name = OrderedDict{String,Product}()
|
||||
for (name, pdict) in json["products"]
|
||||
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)"])
|
||||
components = pdict["components"]
|
||||
prod = Product(; name, tr_cost, tr_energy, tr_emissions, components)
|
||||
push!(products, prod)
|
||||
products_by_name[name] = prod
|
||||
end
|
||||
|
||||
# Read centers
|
||||
centers = Center[]
|
||||
centers_by_name = OrderedDict{String,Center}()
|
||||
for (name, cdict) in json["centers"]
|
||||
latitude = cdict["latitude (deg)"]
|
||||
longitude = cdict["longitude (deg)"]
|
||||
input = nothing
|
||||
revenue = [0.0 for t = 1:time_horizon]
|
||||
if cdict["input"] !== nothing
|
||||
input = products_by_name[cdict["input"]]
|
||||
revenue = timeseries(cdict["revenue (\$/tonne)"])
|
||||
end
|
||||
outputs = [products_by_name[p] for p in cdict["outputs"]]
|
||||
operating_cost = timeseries(cdict["operating cost (\$)"])
|
||||
prod_dict(key, null_val) = OrderedDict(
|
||||
p => [v === nothing ? null_val : v for v in timeseries(cdict[key][p.name])]
|
||||
for p in outputs
|
||||
)
|
||||
to_array(x) = vcat(x'...)
|
||||
prepend_time_dimension(x) = to_array(repeat([x], time_horizon))
|
||||
|
||||
fixed_output = Dict()
|
||||
for p in outputs
|
||||
m = to_array(cdict["fixed output (tonne)"][p.name])
|
||||
if ndims(m) == 1
|
||||
m = prepend_time_dimension(m)
|
||||
end
|
||||
@assert size(m) == (time_horizon, length(p.components))
|
||||
fixed_output[p] = m
|
||||
end
|
||||
|
||||
var_output = prod_dict("variable output (tonne/tonne)", 0.0)
|
||||
collection_cost = prod_dict("collection cost (\$/tonne)", 0.0)
|
||||
disposal_limit = prod_dict("disposal limit (tonne)", Inf)
|
||||
disposal_cost = prod_dict("disposal cost (\$/tonne)", 0.0)
|
||||
|
||||
center = Center(;
|
||||
name,
|
||||
latitude,
|
||||
longitude,
|
||||
input,
|
||||
outputs,
|
||||
revenue,
|
||||
operating_cost,
|
||||
fixed_output,
|
||||
var_output,
|
||||
collection_cost,
|
||||
disposal_cost,
|
||||
disposal_limit,
|
||||
)
|
||||
push!(centers, center)
|
||||
centers_by_name[name] = center
|
||||
end
|
||||
|
||||
plants = Plant[]
|
||||
plants_by_name = OrderedDict{String,Plant}()
|
||||
for (name, pdict) in json["plants"]
|
||||
prod_dict(key; scale = 1.0, null_val = Inf) = OrderedDict{Product,Vector{Float64}}(
|
||||
products_by_name[p] => [
|
||||
v === nothing ? null_val : v * scale for v in timeseries(pdict[key][p])
|
||||
] for p in keys(pdict[key])
|
||||
)
|
||||
|
||||
latitude = pdict["latitude (deg)"]
|
||||
longitude = pdict["longitude (deg)"]
|
||||
input_mix = prod_dict("input mix (%)", scale = 0.01)
|
||||
output = prod_dict("output (tonne)")
|
||||
emissions = timeseries(pdict["processing emissions (tonne)"])
|
||||
storage_cost = prod_dict("storage cost (\$/tonne)")
|
||||
storage_limit = prod_dict("storage limit (tonne)")
|
||||
disposal_cost = prod_dict("disposal cost (\$/tonne)")
|
||||
disposal_limit = prod_dict("disposal limit (tonne)")
|
||||
initial_capacity = pdict["initial capacity (tonne)"]
|
||||
capacities = PlantCapacity[]
|
||||
for cdict in pdict["capacities"]
|
||||
size = cdict["size (tonne)"]
|
||||
opening_cost = timeseries(cdict["opening cost (\$)"])
|
||||
fix_operating_cost = timeseries(cdict["fixed operating cost (\$)"])
|
||||
var_operating_cost = timeseries(cdict["variable operating cost (\$/tonne)"])
|
||||
push!(
|
||||
capacities,
|
||||
PlantCapacity(; size, opening_cost, fix_operating_cost, var_operating_cost),
|
||||
)
|
||||
end
|
||||
|
||||
plant = Plant(;
|
||||
name,
|
||||
latitude,
|
||||
longitude,
|
||||
input_mix,
|
||||
output,
|
||||
emissions,
|
||||
storage_cost,
|
||||
storage_limit,
|
||||
disposal_cost,
|
||||
disposal_limit,
|
||||
capacities,
|
||||
initial_capacity,
|
||||
)
|
||||
push!(plants, plant)
|
||||
plants_by_name[name] = plant
|
||||
end
|
||||
|
||||
return Instance(;
|
||||
time_horizon,
|
||||
building_period,
|
||||
distance_metric,
|
||||
products,
|
||||
products_by_name,
|
||||
centers,
|
||||
centers_by_name,
|
||||
plants,
|
||||
plants_by_name,
|
||||
)
|
||||
end
|
@ -1,58 +0,0 @@
|
||||
using OrderedCollections
|
||||
|
||||
Base.@kwdef struct Product
|
||||
name::String
|
||||
tr_cost::Vector{Float64}
|
||||
tr_energy::Vector{Float64}
|
||||
tr_emissions::OrderedDict{String,Vector{Float64}}
|
||||
components::Vector{String}
|
||||
end
|
||||
|
||||
Base.@kwdef struct Center
|
||||
name::String
|
||||
latitude::Float64
|
||||
longitude::Float64
|
||||
input::Union{Product,Nothing}
|
||||
outputs::Vector{Product}
|
||||
fixed_output::OrderedDict{Product,Array{Float64,2}}
|
||||
var_output::OrderedDict{Product,Vector{Float64}}
|
||||
revenue::Vector{Float64}
|
||||
collection_cost::OrderedDict{Product,Vector{Float64}}
|
||||
operating_cost::Vector{Float64}
|
||||
disposal_limit::OrderedDict{Product,Vector{Float64}}
|
||||
disposal_cost::OrderedDict{Product,Vector{Float64}}
|
||||
end
|
||||
|
||||
Base.@kwdef struct PlantCapacity
|
||||
size::Float64
|
||||
opening_cost::Vector{Float64}
|
||||
fix_operating_cost::Vector{Float64}
|
||||
var_operating_cost::Vector{Float64}
|
||||
end
|
||||
|
||||
Base.@kwdef struct Plant
|
||||
name::String
|
||||
latitude::Float64
|
||||
longitude::Float64
|
||||
input_mix::OrderedDict{Product,Vector{Float64}}
|
||||
output::OrderedDict{Product,Vector{Float64}}
|
||||
emissions::OrderedDict{String,Vector{Float64}}
|
||||
storage_cost::OrderedDict{Product,Vector{Float64}}
|
||||
storage_limit::OrderedDict{Product,Vector{Float64}}
|
||||
disposal_cost::OrderedDict{Product,Vector{Float64}}
|
||||
disposal_limit::OrderedDict{Product,Vector{Float64}}
|
||||
capacities::Vector{PlantCapacity}
|
||||
initial_capacity::Float64
|
||||
end
|
||||
|
||||
Base.@kwdef struct Instance
|
||||
building_period::Vector{Int}
|
||||
centers_by_name::OrderedDict{String,Center}
|
||||
centers::Vector{Center}
|
||||
distance_metric::String
|
||||
products_by_name::OrderedDict{String,Product}
|
||||
products::Vector{Product}
|
||||
time_horizon::Int
|
||||
plants::Vector{Plant}
|
||||
plants_by_name::OrderedDict{String,Plant}
|
||||
end
|
@ -1,11 +0,0 @@
|
||||
# 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 Geodesy
|
||||
|
||||
function _calculate_distance(source_lat, source_lon, dest_lat, dest_lon)::Float64
|
||||
x = LLA(source_lat, source_lon, 0.0)
|
||||
y = LLA(dest_lat, dest_lon, 0.0)
|
||||
return round(euclidean_distance(x, y) / 1000.0, digits = 3)
|
||||
end
|
@ -1,91 +0,0 @@
|
||||
# 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 centers_report(model)::DataFrame
|
||||
df = DataFrame()
|
||||
df."center" = String[]
|
||||
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 = 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
|
||||
|
||||
function center_outputs_report(model)::DataFrame
|
||||
df = DataFrame()
|
||||
df."center" = String[]
|
||||
df."output product" = String[]
|
||||
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 = 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
|
||||
|
||||
write_centers_report(solution, filename) = CSV.write(filename, centers_report(solution))
|
||||
write_center_outputs_report(solution, filename) =
|
||||
CSV.write(filename, center_outputs_report(solution))
|
@ -1,72 +0,0 @@
|
||||
# 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(model)::DataFrame
|
||||
df = DataFrame()
|
||||
df."plant" = String[]
|
||||
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
|
||||
|
||||
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])
|
||||
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
|
||||
|
||||
function plant_outputs_report(model)::DataFrame
|
||||
df = DataFrame()
|
||||
df."plant" = String[]
|
||||
df."output product" = String[]
|
||||
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
|
||||
|
||||
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])
|
||||
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
|
||||
|
||||
write_plants_report(solution, filename) = CSV.write(filename, plants_report(solution))
|
||||
write_plant_outputs_report(solution, filename) =
|
||||
CSV.write(filename, plant_outputs_report(solution))
|
@ -1,56 +0,0 @@
|
||||
# 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 transportation_report(model)::DataFrame
|
||||
df = DataFrame()
|
||||
df."source" = String[]
|
||||
df."destination" = String[]
|
||||
df."product" = String[]
|
||||
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]
|
||||
T = 1:model.ext[:instance].time_horizon
|
||||
|
||||
for (p1, p2, m) in E, t in T
|
||||
amount = value(model[:y][p1.name, p2.name, m.name, t])
|
||||
amount > 1e-3 || continue
|
||||
distance = distances[p1, p2, m]
|
||||
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
|
||||
|
||||
write_transportation_report(solution, filename) =
|
||||
CSV.write(filename, transportation_report(solution))
|
@ -1,14 +0,0 @@
|
||||
name = "RELOGT"
|
||||
uuid = "d5238ab2-e29b-4856-ba0f-d2b80f40b47d"
|
||||
authors = ["Alinson S. Xavier <git@axavier.org>"]
|
||||
version = "0.1.0"
|
||||
|
||||
[deps]
|
||||
HiGHS = "87dc4568-4c63-4d18-b0c0-bb2238e4078b"
|
||||
JSON = "682c06a0-de6a-54ab-a142-c8b1cf79cde6"
|
||||
JuMP = "4076af6c-e467-56ae-b986-b466b2749572"
|
||||
JuliaFormatter = "98e50ef6-434e-11e9-1051-2b60c6c9e899"
|
||||
OrderedCollections = "bac558e1-5e72-5ebc-8fee-abe8a469f55d"
|
||||
RELOG = "7cafaa7a-b311-45f0-b313-80bf15b5e5e5"
|
||||
Revise = "295af30f-e4ad-537b-8983-00126c2a3abe"
|
||||
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
|
@ -1,181 +0,0 @@
|
||||
using OrderedCollections
|
||||
using JSON
|
||||
using RELOG
|
||||
dict = OrderedDict
|
||||
|
||||
function run_boat_example()
|
||||
cities_a = dict(
|
||||
"Chicago" => [41.881832, -87.623177],
|
||||
"New York City" => [40.712776, -74.005974],
|
||||
"Los Angeles" => [34.052235, -118.243683],
|
||||
"Houston" => [29.760427, -95.369804],
|
||||
"Phoenix" => [33.448376, -112.074036],
|
||||
"Philadelphia" => [39.952583, -75.165222],
|
||||
"San Antonio" => [29.424122, -98.493629],
|
||||
"San Diego" => [32.715736, -117.161087],
|
||||
"Dallas" => [32.776664, -96.796988],
|
||||
"San Jose" => [37.338208, -121.886329],
|
||||
)
|
||||
|
||||
cities_b = dict(
|
||||
"Chicago" => [41.881832, -87.623177],
|
||||
"Phoenix" => [33.448376, -112.074036],
|
||||
"Dallas" => [32.776664, -96.796988],
|
||||
)
|
||||
|
||||
parameters = dict(
|
||||
"time horizon (years)" => 5,
|
||||
"building period (years)" => [1],
|
||||
"distance metric" => "Euclidean",
|
||||
)
|
||||
|
||||
nail_factory = dict(
|
||||
"input" => nothing,
|
||||
"outputs" => ["Nail"],
|
||||
"fixed output (tonne)" => dict("Nail" => [1]),
|
||||
"variable output (tonne/tonne)" => dict("Nail" => 0),
|
||||
"revenue (\$/tonne)" => nothing,
|
||||
"collection cost (\$/tonne)" => dict("Nail" => 1000),
|
||||
"operating cost (\$)" => 0,
|
||||
"disposal limit (tonne)" => dict("Nail" => nothing),
|
||||
"disposal cost (\$/tonne)" => dict("Nail" => 0),
|
||||
)
|
||||
|
||||
forest = dict(
|
||||
"input" => nothing,
|
||||
"outputs" => ["Wood"],
|
||||
"fixed output (tonne)" => dict("Wood" => [[100], [100], [100], [100], [100]]),
|
||||
"variable output (tonne/tonne)" => dict("Wood" => 0),
|
||||
"revenue (\$/tonne)" => nothing,
|
||||
"collection cost (\$/tonne)" => dict("Wood" => 250),
|
||||
"operating cost (\$)" => 0,
|
||||
"disposal limit (tonne)" => dict("Wood" => nothing),
|
||||
"disposal cost (\$/tonne)" => dict("Wood" => 0),
|
||||
)
|
||||
|
||||
retail = dict(
|
||||
"input" => "NewBoat",
|
||||
"outputs" => ["UsedBoat"],
|
||||
"fixed output (tonne)" => dict("UsedBoat" => [[0], [0], [0], [0], [0]]),
|
||||
"variable output (tonne/tonne)" => dict("UsedBoat" => [0.10, 0.25, 0.10]),
|
||||
"revenue (\$/tonne)" => 12_000,
|
||||
"collection cost (\$/tonne)" => dict("UsedBoat" => 100),
|
||||
"operating cost (\$)" => 125_000,
|
||||
"disposal limit (tonne)" => dict("UsedBoat" => 0),
|
||||
"disposal cost (\$/tonne)" => dict("UsedBoat" => 0),
|
||||
)
|
||||
|
||||
prod = dict(
|
||||
"transportation cost (\$/km/tonne)" => 0.30,
|
||||
"transportation energy (J/km/tonne)" => 7_500,
|
||||
"transportation emissions (tonne/km/tonne)" => dict("CO2" => 2.68),
|
||||
"components" => ["1"],
|
||||
)
|
||||
|
||||
boat_factory = dict(
|
||||
"input mix (%)" => dict("Wood" => 95, "Nail" => 5),
|
||||
"output (tonne)" => dict("NewBoat" => 1.0),
|
||||
"processing emissions (tonne)" => dict("CO2" => 5),
|
||||
"storage cost (\$/tonne)" => dict("Wood" => 500, "Nail" => 200),
|
||||
"storage limit (tonne)" => dict("Wood" => 5, "Nail" => 1),
|
||||
"disposal cost (\$/tonne)" => dict("NewBoat" => 0),
|
||||
"disposal limit (tonne)" => dict("NewBoat" => 0),
|
||||
"capacities" => [
|
||||
dict(
|
||||
"size (tonne)" => 500,
|
||||
"opening cost (\$)" => 1_00_000,
|
||||
"fixed operating cost (\$)" => 250_000,
|
||||
"variable operating cost (\$/tonne)" => 5,
|
||||
),
|
||||
dict(
|
||||
"size (tonne)" => 1000,
|
||||
"opening cost (\$)" => 2_000_000,
|
||||
"fixed operating cost (\$)" => 500_000,
|
||||
"variable operating cost (\$/tonne)" => 5,
|
||||
),
|
||||
],
|
||||
"initial capacity (tonne)" => 0,
|
||||
)
|
||||
|
||||
recycling_plant = dict(
|
||||
"input mix (%)" => dict("UsedBoat" => 100),
|
||||
"output (tonne)" => dict("Nail" => 0.025, "Wood" => 0.475),
|
||||
"processing emissions (tonne)" => dict("CO2" => 5),
|
||||
"storage cost (\$/tonne)" => dict("UsedBoat" => 0),
|
||||
"storage limit (tonne)" => dict("UsedBoat" => 0),
|
||||
"disposal cost (\$/tonne)" => dict("Nail" => 0, "Wood" => 0),
|
||||
"disposal limit (tonne)" => dict("Nail" => 0, "Wood" => 0),
|
||||
"capacities" => [
|
||||
dict(
|
||||
"size (tonne)" => 500,
|
||||
"opening cost (\$)" => 500_000,
|
||||
"fixed operating cost (\$)" => 125_000,
|
||||
"variable operating cost (\$/tonne)" => 2.5,
|
||||
),
|
||||
dict(
|
||||
"size (tonne)" => 1000,
|
||||
"opening cost (\$)" => 1_000_000,
|
||||
"fixed operating cost (\$)" => 250_000,
|
||||
"variable operating cost (\$/tonne)" => 2.5,
|
||||
),
|
||||
],
|
||||
"initial capacity (tonne)" => 0,
|
||||
)
|
||||
|
||||
lat_lon_dict(city_location) =
|
||||
dict("latitude (deg)" => city_location[1], "longitude (deg)" => city_location[2])
|
||||
|
||||
data = dict(
|
||||
"parameters" => parameters,
|
||||
"products" =>
|
||||
dict("Nail" => prod, "Wood" => prod, "NewBoat" => prod, "UsedBoat" => prod),
|
||||
"centers" => merge(
|
||||
dict(
|
||||
"NailFactory ($city_name)" =>
|
||||
merge(nail_factory, lat_lon_dict(city_location)) for
|
||||
(city_name, city_location) in cities_b
|
||||
),
|
||||
dict(
|
||||
"Forest ($city_name)" => merge(forest, lat_lon_dict(city_location))
|
||||
for (city_name, city_location) in cities_b
|
||||
),
|
||||
dict(
|
||||
"Retail ($city_name)" => merge(retail, lat_lon_dict(city_location))
|
||||
for (city_name, city_location) in cities_a
|
||||
),
|
||||
),
|
||||
"plants" => merge(
|
||||
dict(
|
||||
"BoatFactory ($city_name)" =>
|
||||
merge(boat_factory, lat_lon_dict(city_location)) for
|
||||
(city_name, city_location) in cities_a
|
||||
),
|
||||
dict(
|
||||
"RecyclingPlant ($city_name)" =>
|
||||
merge(recycling_plant, lat_lon_dict(city_location)) for
|
||||
(city_name, city_location) in cities_a
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
# Generate instance file
|
||||
open(fixture("boat_example.json"), "w") do file
|
||||
JSON.print(file, data, 2)
|
||||
end
|
||||
|
||||
# Load and solve example
|
||||
instance = RELOG.parsefile(fixture("boat_example.json"))
|
||||
model = RELOG.build_model(instance, optimizer = HiGHS.Optimizer, variable_names = true)
|
||||
optimize!(model)
|
||||
|
||||
# Write reports
|
||||
mkpath(fixture("boat_example"))
|
||||
write_to_file(model, fixture("boat_example/model.lp"))
|
||||
RELOG.write_plants_report(model, fixture("boat_example/plants.csv"))
|
||||
RELOG.write_plant_outputs_report(model, fixture("boat_example/plant_outputs.csv"))
|
||||
RELOG.write_centers_report(model, fixture("boat_example/centers.csv"))
|
||||
RELOG.write_center_outputs_report(model, fixture("boat_example/center_outputs.csv"))
|
||||
RELOG.write_transportation_report(model, fixture("boat_example/transportation.csv"))
|
||||
|
||||
return
|
||||
end
|
File diff suppressed because it is too large
Load Diff
|
|
|
|
|
@ -1,164 +0,0 @@
|
||||
{
|
||||
"parameters": {
|
||||
"time horizon (years)": 4,
|
||||
"building period (years)": [1],
|
||||
"distance metric": "driving"
|
||||
},
|
||||
"products": {
|
||||
"P1": {
|
||||
"transportation cost ($/km/tonne)": 0.015,
|
||||
"transportation energy (J/km/tonne)": 0.12,
|
||||
"transportation emissions (tonne/km/tonne)": {
|
||||
"CO2": 0.052,
|
||||
"CH4": [0.003, 0.003, 0.003, 0.003]
|
||||
},
|
||||
"components": ["1", "2"]
|
||||
},
|
||||
"P2": {
|
||||
"transportation cost ($/km/tonne)": [0.015, 0.015, 0.015, 0.015],
|
||||
"transportation energy (J/km/tonne)": [0.12, 0.12, 0.12, 0.12],
|
||||
"transportation emissions (tonne/km/tonne)": {
|
||||
"CO2": [0.052, 0.052, 0.052, 0.052],
|
||||
"CH4": [0.003, 0.003, 0.003, 0.003]
|
||||
},
|
||||
"components": ["1"]
|
||||
},
|
||||
"P3": {
|
||||
"transportation cost ($/km/tonne)": [0.015, 0.015, 0.015, 0.015],
|
||||
"transportation energy (J/km/tonne)": [0.12, 0.12, 0.12, 0.12],
|
||||
"transportation emissions (tonne/km/tonne)": {
|
||||
"CO2": [0.052, 0.052, 0.052, 0.052],
|
||||
"CH4": [0.003, 0.003, 0.003, 0.003]
|
||||
},
|
||||
"components": ["1"]
|
||||
},
|
||||
"P4": {
|
||||
"transportation cost ($/km/tonne)": [0.015, 0.015, 0.015, 0.015],
|
||||
"transportation energy (J/km/tonne)": [0.12, 0.12, 0.12, 0.12],
|
||||
"transportation emissions (tonne/km/tonne)": {
|
||||
"CO2": [0.052, 0.052, 0.052, 0.052],
|
||||
"CH4": [0.003, 0.003, 0.003, 0.003]
|
||||
},
|
||||
"components": ["1"]
|
||||
}
|
||||
},
|
||||
"centers": {
|
||||
"C1": {
|
||||
"latitude (deg)": 41.881,
|
||||
"longitude (deg)": -87.623,
|
||||
"input": "P1",
|
||||
"outputs": ["P2", "P3"],
|
||||
"fixed output (tonne)": {
|
||||
"P2": [[100], [50], [0], [0]],
|
||||
"P3": [[20], [10], [0], [0]]
|
||||
},
|
||||
"variable output (tonne/tonne)": {
|
||||
"P2": [0.2, 0.25, 0.12],
|
||||
"P3": [0.25, 0.25, 0.25]
|
||||
},
|
||||
"revenue ($/tonne)": 12.0,
|
||||
"collection cost ($/tonne)": {
|
||||
"P2": [0.25, 0.25, 0.25, 0.25],
|
||||
"P3": [0.37, 0.37, 0.37, 0.37]
|
||||
},
|
||||
"operating cost ($)": [150.0, 150.0, 150.0, 150.0],
|
||||
"disposal limit (tonne)": {
|
||||
"P2": [0, 0, 0, 0],
|
||||
"P3": [null, null, null, null]
|
||||
},
|
||||
"disposal cost ($/tonne)": {
|
||||
"P2": [0.23, 0.23, 0.23, 0.23],
|
||||
"P3": [1.0, 1.0, 1.0, 1.0]
|
||||
}
|
||||
},
|
||||
"C2": {
|
||||
"latitude (deg)": 42.881,
|
||||
"longitude (deg)": -87.623,
|
||||
"input": null,
|
||||
"outputs": ["P1"],
|
||||
"variable output (tonne/tonne)": {
|
||||
"P1": 0
|
||||
},
|
||||
"fixed output (tonne)": {
|
||||
"P1": [
|
||||
[50, 5],
|
||||
[60, 6],
|
||||
[70, 7],
|
||||
[80, 8]
|
||||
]
|
||||
},
|
||||
"revenue ($/tonne)": null,
|
||||
"collection cost ($/tonne)": {
|
||||
"P1": 0.25
|
||||
},
|
||||
"operating cost ($)": [150.0, 150.0, 150.0, 150.0],
|
||||
"disposal limit (tonne)": {
|
||||
"P1": null
|
||||
},
|
||||
"disposal cost ($/tonne)": {
|
||||
"P1": 0
|
||||
}
|
||||
},
|
||||
"C3": {
|
||||
"latitude (deg)": 43.881,
|
||||
"longitude (deg)": -87.623,
|
||||
"input": "P4",
|
||||
"outputs": [],
|
||||
"variable output (tonne/tonne)": {},
|
||||
"constant output (tonne)": {},
|
||||
"revenue ($/tonne)": [12.0, 12.0, 12.0, 12.0],
|
||||
"collection cost ($/tonne)": {},
|
||||
"operating cost ($)": 150.0,
|
||||
"disposal limit (tonne)": {},
|
||||
"disposal cost ($/tonne)": {}
|
||||
}
|
||||
},
|
||||
"plants": {
|
||||
"L1": {
|
||||
"latitude (deg)": 44.881,
|
||||
"longitude (deg)": -87.623,
|
||||
"input mix (%)": {
|
||||
"P1": 95.3,
|
||||
"P2": 4.7
|
||||
},
|
||||
"output (tonne)": {
|
||||
"P3": 0.25,
|
||||
"P4": 0.12
|
||||
},
|
||||
"processing emissions (tonne)": {
|
||||
"CO2": 0.1
|
||||
},
|
||||
"storage cost ($/tonne)": {
|
||||
"P1": 0.1,
|
||||
"P2": 0.1
|
||||
},
|
||||
"storage limit (tonne)": {
|
||||
"P1": 100,
|
||||
"P2": null
|
||||
},
|
||||
"disposal cost ($/tonne)": {
|
||||
"P3": 0,
|
||||
"P4": 0.86
|
||||
},
|
||||
"disposal limit (tonne)": {
|
||||
"P3": null,
|
||||
"P4": 1000.0
|
||||
},
|
||||
"capacities": [
|
||||
{
|
||||
"size (tonne)": 100,
|
||||
"opening cost ($)": [300, 400, 450, 475],
|
||||
"fixed operating cost ($)": 300,
|
||||
"variable operating cost ($/tonne)": 5.0
|
||||
},
|
||||
{
|
||||
"size (tonne)": 500,
|
||||
"opening cost ($)": 1000.0,
|
||||
"fixed operating cost ($)": 400.0,
|
||||
"variable operating cost ($/tonne)": 5.0
|
||||
}
|
||||
],
|
||||
"initial capacity (tonne)": 0
|
||||
}
|
||||
}
|
||||
}
|
@ -1,650 +0,0 @@
|
||||
{
|
||||
"parameters": {
|
||||
"time horizon (years)": 5,
|
||||
"building period (years)": [1],
|
||||
"distance metric": "Euclidean"
|
||||
},
|
||||
"products": {
|
||||
"Waste": {
|
||||
"transportation cost ($/km/tonne)": 0.3,
|
||||
"transportation energy (J/km/tonne)": 7500,
|
||||
"transportation emissions (tonne/km/tonne)": {
|
||||
"CO2": 2.68
|
||||
},
|
||||
"components": ["Film", "Paper", "Cardboard"]
|
||||
},
|
||||
"Film Bale": {
|
||||
"transportation cost ($/km/tonne)": 0.3,
|
||||
"transportation energy (J/km/tonne)": 7500,
|
||||
"transportation emissions (tonne/km/tonne)": {
|
||||
"CO2": 2.68
|
||||
},
|
||||
"components": ["Film", "Paper", "Cardboard"]
|
||||
},
|
||||
"Cardboard Bale": {
|
||||
"transportation cost ($/km/tonne)": 0.3,
|
||||
"transportation energy (J/km/tonne)": 7500,
|
||||
"transportation emissions (tonne/km/tonne)": {
|
||||
"CO2": 2.68
|
||||
},
|
||||
"components": ["Film", "Paper", "Cardboard"]
|
||||
}
|
||||
},
|
||||
"centers": {
|
||||
"Collection Center (Chicago)": {
|
||||
"input": null,
|
||||
"outputs": ["Waste"],
|
||||
"fixed output (tonne)": {
|
||||
"Waste": [20, 100, 100]
|
||||
},
|
||||
"variable output (tonne/tonne)": {},
|
||||
"revenue ($/tonne)": null,
|
||||
"collection cost ($/tonne)": {
|
||||
"Waste": 10
|
||||
},
|
||||
"operating cost ($)": 0,
|
||||
"disposal limit (tonne)": {
|
||||
"Waste": null
|
||||
},
|
||||
"disposal cost ($/tonne)": {
|
||||
"Waste": 0
|
||||
},
|
||||
"latitude (deg)": 41.881832,
|
||||
"longitude (deg)": -87.623177
|
||||
},
|
||||
"Collection Center (Phoenix)": {
|
||||
"input": null,
|
||||
"outputs": ["Waste"],
|
||||
"fixed output (tonne)": {
|
||||
"Waste": [20, 100, 100]
|
||||
},
|
||||
"variable output (tonne/tonne)": {},
|
||||
"revenue ($/tonne)": null,
|
||||
"collection cost ($/tonne)": {
|
||||
"Waste": 10
|
||||
},
|
||||
"operating cost ($)": 0,
|
||||
"disposal limit (tonne)": {
|
||||
"Waste": null
|
||||
},
|
||||
"disposal cost ($/tonne)": {
|
||||
"Waste": 0
|
||||
},
|
||||
"latitude (deg)": 33.448376,
|
||||
"longitude (deg)": -112.074036
|
||||
},
|
||||
"Collection Center (Dallas)": {
|
||||
"input": null,
|
||||
"outputs": ["Waste"],
|
||||
"fixed output (tonne)": {
|
||||
"Waste": [20, 100, 100]
|
||||
},
|
||||
"variable output (tonne/tonne)": {},
|
||||
"revenue ($/tonne)": null,
|
||||
"collection cost ($/tonne)": {
|
||||
"Waste": 10
|
||||
},
|
||||
"operating cost ($)": 0,
|
||||
"disposal limit (tonne)": {
|
||||
"Waste": null
|
||||
},
|
||||
"disposal cost ($/tonne)": {
|
||||
"Waste": 0
|
||||
},
|
||||
"latitude (deg)": 32.776664,
|
||||
"longitude (deg)": -96.796988
|
||||
}
|
||||
},
|
||||
"plants": {
|
||||
"RecyclingPlant (Chicago)": {
|
||||
"input mix (%)": {
|
||||
"Waste": 100
|
||||
},
|
||||
"output (tonne)": {
|
||||
"Film Bale": {
|
||||
"Waste": [
|
||||
[0.98, 0.0, 0.0],
|
||||
[0.0, 0.02, 0.0],
|
||||
[0.0, 0.0, 0.02]
|
||||
]
|
||||
},
|
||||
"Cardboard Bale": {
|
||||
"Waste": [
|
||||
[0.0, 0.0, 0.0],
|
||||
[0.0, 0.02, 0.0],
|
||||
[0.0, 0.0, 0.75]
|
||||
]
|
||||
}
|
||||
},
|
||||
"processing emissions (tonne)": {
|
||||
"CO2": 5
|
||||
},
|
||||
"storage cost ($/tonne)": {
|
||||
"Waste": 500
|
||||
},
|
||||
"storage limit (tonne)": {
|
||||
"Waste": 5
|
||||
},
|
||||
"disposal cost ($/tonne)": {
|
||||
"Film Bale": -10,
|
||||
"Cardboard Bale": -10
|
||||
},
|
||||
"disposal limit (tonne)": {
|
||||
"Film Bale": null,
|
||||
"Cardboard Bale": null
|
||||
},
|
||||
"capacities": [
|
||||
{
|
||||
"size (tonne)": 500,
|
||||
"opening cost ($)": 100000,
|
||||
"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
|
||||
},
|
||||
"RecyclingPlant (New York City)": {
|
||||
"input mix (%)": {
|
||||
"Waste": 100
|
||||
},
|
||||
"output (tonne)": {
|
||||
"Film Bale": {
|
||||
"Waste": [
|
||||
[0.98, 0.0, 0.0],
|
||||
[0.0, 0.02, 0.0],
|
||||
[0.0, 0.0, 0.02]
|
||||
]
|
||||
},
|
||||
"Cardboard Bale": {
|
||||
"Waste": [
|
||||
[0.0, 0.0, 0.0],
|
||||
[0.0, 0.02, 0.0],
|
||||
[0.0, 0.0, 0.75]
|
||||
]
|
||||
}
|
||||
},
|
||||
"processing emissions (tonne)": {
|
||||
"CO2": 5
|
||||
},
|
||||
"storage cost ($/tonne)": {
|
||||
"Waste": 500
|
||||
},
|
||||
"storage limit (tonne)": {
|
||||
"Waste": 5
|
||||
},
|
||||
"disposal cost ($/tonne)": {
|
||||
"Film Bale": -10,
|
||||
"Cardboard Bale": -10
|
||||
},
|
||||
"disposal limit (tonne)": {
|
||||
"Film Bale": null,
|
||||
"Cardboard Bale": null
|
||||
},
|
||||
"capacities": [
|
||||
{
|
||||
"size (tonne)": 500,
|
||||
"opening cost ($)": 100000,
|
||||
"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
|
||||
},
|
||||
"RecyclingPlant (Los Angeles)": {
|
||||
"input mix (%)": {
|
||||
"Waste": 100
|
||||
},
|
||||
"output (tonne)": {
|
||||
"Film Bale": {
|
||||
"Waste": [
|
||||
[0.98, 0.0, 0.0],
|
||||
[0.0, 0.02, 0.0],
|
||||
[0.0, 0.0, 0.02]
|
||||
]
|
||||
},
|
||||
"Cardboard Bale": {
|
||||
"Waste": [
|
||||
[0.0, 0.0, 0.0],
|
||||
[0.0, 0.02, 0.0],
|
||||
[0.0, 0.0, 0.75]
|
||||
]
|
||||
}
|
||||
},
|
||||
"processing emissions (tonne)": {
|
||||
"CO2": 5
|
||||
},
|
||||
"storage cost ($/tonne)": {
|
||||
"Waste": 500
|
||||
},
|
||||
"storage limit (tonne)": {
|
||||
"Waste": 5
|
||||
},
|
||||
"disposal cost ($/tonne)": {
|
||||
"Film Bale": -10,
|
||||
"Cardboard Bale": -10
|
||||
},
|
||||
"disposal limit (tonne)": {
|
||||
"Film Bale": null,
|
||||
"Cardboard Bale": null
|
||||
},
|
||||
"capacities": [
|
||||
{
|
||||
"size (tonne)": 500,
|
||||
"opening cost ($)": 100000,
|
||||
"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
|
||||
},
|
||||
"RecyclingPlant (Houston)": {
|
||||
"input mix (%)": {
|
||||
"Waste": 100
|
||||
},
|
||||
"output (tonne)": {
|
||||
"Film Bale": {
|
||||
"Waste": [
|
||||
[0.98, 0.0, 0.0],
|
||||
[0.0, 0.02, 0.0],
|
||||
[0.0, 0.0, 0.02]
|
||||
]
|
||||
},
|
||||
"Cardboard Bale": {
|
||||
"Waste": [
|
||||
[0.0, 0.0, 0.0],
|
||||
[0.0, 0.02, 0.0],
|
||||
[0.0, 0.0, 0.75]
|
||||
]
|
||||
}
|
||||
},
|
||||
"processing emissions (tonne)": {
|
||||
"CO2": 5
|
||||
},
|
||||
"storage cost ($/tonne)": {
|
||||
"Waste": 500
|
||||
},
|
||||
"storage limit (tonne)": {
|
||||
"Waste": 5
|
||||
},
|
||||
"disposal cost ($/tonne)": {
|
||||
"Film Bale": -10,
|
||||
"Cardboard Bale": -10
|
||||
},
|
||||
"disposal limit (tonne)": {
|
||||
"Film Bale": null,
|
||||
"Cardboard Bale": null
|
||||
},
|
||||
"capacities": [
|
||||
{
|
||||
"size (tonne)": 500,
|
||||
"opening cost ($)": 100000,
|
||||
"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
|
||||
},
|
||||
"RecyclingPlant (Phoenix)": {
|
||||
"input mix (%)": {
|
||||
"Waste": 100
|
||||
},
|
||||
"output (tonne)": {
|
||||
"Film Bale": {
|
||||
"Waste": [
|
||||
[0.98, 0.0, 0.0],
|
||||
[0.0, 0.02, 0.0],
|
||||
[0.0, 0.0, 0.02]
|
||||
]
|
||||
},
|
||||
"Cardboard Bale": {
|
||||
"Waste": [
|
||||
[0.0, 0.0, 0.0],
|
||||
[0.0, 0.02, 0.0],
|
||||
[0.0, 0.0, 0.75]
|
||||
]
|
||||
}
|
||||
},
|
||||
"processing emissions (tonne)": {
|
||||
"CO2": 5
|
||||
},
|
||||
"storage cost ($/tonne)": {
|
||||
"Waste": 500
|
||||
},
|
||||
"storage limit (tonne)": {
|
||||
"Waste": 5
|
||||
},
|
||||
"disposal cost ($/tonne)": {
|
||||
"Film Bale": -10,
|
||||
"Cardboard Bale": -10
|
||||
},
|
||||
"disposal limit (tonne)": {
|
||||
"Film Bale": null,
|
||||
"Cardboard Bale": null
|
||||
},
|
||||
"capacities": [
|
||||
{
|
||||
"size (tonne)": 500,
|
||||
"opening cost ($)": 100000,
|
||||
"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
|
||||
},
|
||||
"RecyclingPlant (Philadelphia)": {
|
||||
"input mix (%)": {
|
||||
"Waste": 100
|
||||
},
|
||||
"output (tonne)": {
|
||||
"Film Bale": {
|
||||
"Waste": [
|
||||
[0.98, 0.0, 0.0],
|
||||
[0.0, 0.02, 0.0],
|
||||
[0.0, 0.0, 0.02]
|
||||
]
|
||||
},
|
||||
"Cardboard Bale": {
|
||||
"Waste": [
|
||||
[0.0, 0.0, 0.0],
|
||||
[0.0, 0.02, 0.0],
|
||||
[0.0, 0.0, 0.75]
|
||||
]
|
||||
}
|
||||
},
|
||||
"processing emissions (tonne)": {
|
||||
"CO2": 5
|
||||
},
|
||||
"storage cost ($/tonne)": {
|
||||
"Waste": 500
|
||||
},
|
||||
"storage limit (tonne)": {
|
||||
"Waste": 5
|
||||
},
|
||||
"disposal cost ($/tonne)": {
|
||||
"Film Bale": -10,
|
||||
"Cardboard Bale": -10
|
||||
},
|
||||
"disposal limit (tonne)": {
|
||||
"Film Bale": null,
|
||||
"Cardboard Bale": null
|
||||
},
|
||||
"capacities": [
|
||||
{
|
||||
"size (tonne)": 500,
|
||||
"opening cost ($)": 100000,
|
||||
"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
|
||||
},
|
||||
"RecyclingPlant (San Antonio)": {
|
||||
"input mix (%)": {
|
||||
"Waste": 100
|
||||
},
|
||||
"output (tonne)": {
|
||||
"Film Bale": {
|
||||
"Waste": [
|
||||
[0.98, 0.0, 0.0],
|
||||
[0.0, 0.02, 0.0],
|
||||
[0.0, 0.0, 0.02]
|
||||
]
|
||||
},
|
||||
"Cardboard Bale": {
|
||||
"Waste": [
|
||||
[0.0, 0.0, 0.0],
|
||||
[0.0, 0.02, 0.0],
|
||||
[0.0, 0.0, 0.75]
|
||||
]
|
||||
}
|
||||
},
|
||||
"processing emissions (tonne)": {
|
||||
"CO2": 5
|
||||
},
|
||||
"storage cost ($/tonne)": {
|
||||
"Waste": 500
|
||||
},
|
||||
"storage limit (tonne)": {
|
||||
"Waste": 5
|
||||
},
|
||||
"disposal cost ($/tonne)": {
|
||||
"Film Bale": -10,
|
||||
"Cardboard Bale": -10
|
||||
},
|
||||
"disposal limit (tonne)": {
|
||||
"Film Bale": null,
|
||||
"Cardboard Bale": null
|
||||
},
|
||||
"capacities": [
|
||||
{
|
||||
"size (tonne)": 500,
|
||||
"opening cost ($)": 100000,
|
||||
"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
|
||||
},
|
||||
"RecyclingPlant (San Diego)": {
|
||||
"input mix (%)": {
|
||||
"Waste": 100
|
||||
},
|
||||
"output (tonne)": {
|
||||
"Film Bale": {
|
||||
"Waste": [
|
||||
[0.98, 0.0, 0.0],
|
||||
[0.0, 0.02, 0.0],
|
||||
[0.0, 0.0, 0.02]
|
||||
]
|
||||
},
|
||||
"Cardboard Bale": {
|
||||
"Waste": [
|
||||
[0.0, 0.0, 0.0],
|
||||
[0.0, 0.02, 0.0],
|
||||
[0.0, 0.0, 0.75]
|
||||
]
|
||||
}
|
||||
},
|
||||
"processing emissions (tonne)": {
|
||||
"CO2": 5
|
||||
},
|
||||
"storage cost ($/tonne)": {
|
||||
"Waste": 500
|
||||
},
|
||||
"storage limit (tonne)": {
|
||||
"Waste": 5
|
||||
},
|
||||
"disposal cost ($/tonne)": {
|
||||
"Film Bale": -10,
|
||||
"Cardboard Bale": -10
|
||||
},
|
||||
"disposal limit (tonne)": {
|
||||
"Film Bale": null,
|
||||
"Cardboard Bale": null
|
||||
},
|
||||
"capacities": [
|
||||
{
|
||||
"size (tonne)": 500,
|
||||
"opening cost ($)": 100000,
|
||||
"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
|
||||
},
|
||||
"RecyclingPlant (Dallas)": {
|
||||
"input mix (%)": {
|
||||
"Waste": 100
|
||||
},
|
||||
"output (tonne)": {
|
||||
"Film Bale": {
|
||||
"Waste": [
|
||||
[0.98, 0.0, 0.0],
|
||||
[0.0, 0.02, 0.0],
|
||||
[0.0, 0.0, 0.02]
|
||||
]
|
||||
},
|
||||
"Cardboard Bale": {
|
||||
"Waste": [
|
||||
[0.0, 0.0, 0.0],
|
||||
[0.0, 0.02, 0.0],
|
||||
[0.0, 0.0, 0.75]
|
||||
]
|
||||
}
|
||||
},
|
||||
"processing emissions (tonne)": {
|
||||
"CO2": 5
|
||||
},
|
||||
"storage cost ($/tonne)": {
|
||||
"Waste": 500
|
||||
},
|
||||
"storage limit (tonne)": {
|
||||
"Waste": 5
|
||||
},
|
||||
"disposal cost ($/tonne)": {
|
||||
"Film Bale": -10,
|
||||
"Cardboard Bale": -10
|
||||
},
|
||||
"disposal limit (tonne)": {
|
||||
"Film Bale": null,
|
||||
"Cardboard Bale": null
|
||||
},
|
||||
"capacities": [
|
||||
{
|
||||
"size (tonne)": 500,
|
||||
"opening cost ($)": 100000,
|
||||
"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
|
||||
},
|
||||
"RecyclingPlant (San Jose)": {
|
||||
"input mix (%)": {
|
||||
"Waste": 100
|
||||
},
|
||||
"output (tonne)": {
|
||||
"Film Bale": {
|
||||
"Waste": [
|
||||
[0.98, 0.0, 0.0],
|
||||
[0.0, 0.02, 0.0],
|
||||
[0.0, 0.0, 0.02]
|
||||
]
|
||||
},
|
||||
"Cardboard Bale": {
|
||||
"Waste": [
|
||||
[0.0, 0.0, 0.0],
|
||||
[0.0, 0.02, 0.0],
|
||||
[0.0, 0.0, 0.75]
|
||||
]
|
||||
}
|
||||
},
|
||||
"processing emissions (tonne)": {
|
||||
"CO2": 5
|
||||
},
|
||||
"storage cost ($/tonne)": {
|
||||
"Waste": 500
|
||||
},
|
||||
"storage limit (tonne)": {
|
||||
"Waste": 5
|
||||
},
|
||||
"disposal cost ($/tonne)": {
|
||||
"Film Bale": -10,
|
||||
"Cardboard Bale": -10
|
||||
},
|
||||
"disposal limit (tonne)": {
|
||||
"Film Bale": null,
|
||||
"Cardboard Bale": null
|
||||
},
|
||||
"capacities": [
|
||||
{
|
||||
"size (tonne)": 500,
|
||||
"opening cost ($)": 100000,
|
||||
"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
|
||||
}
|
||||
}
|
||||
}
|
@ -1,38 +0,0 @@
|
||||
module RELOGT
|
||||
|
||||
using Test
|
||||
using RELOG
|
||||
using JuliaFormatter
|
||||
|
||||
include("instance/parse_test.jl")
|
||||
include("model/build_test.jl")
|
||||
include("model/dist_test.jl")
|
||||
include("reports_test.jl")
|
||||
include("../fixtures/boat_example.jl")
|
||||
|
||||
basedir = dirname(@__FILE__)
|
||||
|
||||
function fixture(path::String)::String
|
||||
return "$basedir/../fixtures/$path"
|
||||
end
|
||||
|
||||
function runtests()
|
||||
@testset "RELOG" begin
|
||||
instance_parse_test_1()
|
||||
instance_parse_test_2()
|
||||
model_build_test()
|
||||
model_dist_test()
|
||||
report_tests()
|
||||
end
|
||||
end
|
||||
|
||||
function format()
|
||||
JuliaFormatter.format(basedir, verbose = true)
|
||||
JuliaFormatter.format("$basedir/../../src", verbose = true)
|
||||
JuliaFormatter.format("$basedir/../fixtures", verbose = true)
|
||||
return
|
||||
end
|
||||
|
||||
export format, runtests
|
||||
|
||||
end # module RELOGT
|
@ -1,77 +0,0 @@
|
||||
using RELOG
|
||||
using Test
|
||||
using OrderedCollections
|
||||
|
||||
function instance_parse_test_1()
|
||||
instance = RELOG.parsefile(fixture("simple.json"))
|
||||
|
||||
# Parameters
|
||||
@test instance.time_horizon == 4
|
||||
@test instance.building_period == [1]
|
||||
@test instance.distance_metric == "driving"
|
||||
|
||||
# Products
|
||||
@test length(instance.products) == 4
|
||||
p1 = instance.products[1]
|
||||
@test p1.name == "P1"
|
||||
@test p1.tr_cost == [0.015, 0.015, 0.015, 0.015]
|
||||
@test p1.tr_energy == [0.12, 0.12, 0.12, 0.12]
|
||||
@test p1.tr_emissions ==
|
||||
Dict("CO2" => [0.052, 0.052, 0.052, 0.052], "CH4" => [0.003, 0.003, 0.003, 0.003])
|
||||
@test p1.components == ["1", "2"]
|
||||
@test instance.products_by_name["P1"] === p1
|
||||
p2 = instance.products[2]
|
||||
p3 = instance.products[3]
|
||||
p4 = instance.products[4]
|
||||
|
||||
# Centers
|
||||
@test length(instance.centers) == 3
|
||||
c1 = instance.centers[1]
|
||||
@test c1.latitude == 41.881
|
||||
@test c1.longitude == -87.623
|
||||
@test c1.input === p1
|
||||
@test c1.outputs == [p2, p3]
|
||||
@test c1.fixed_output == Dict(p2 => [100; 50; 0; 0;;], p3 => [20; 10; 0; 0;;])
|
||||
@test c1.var_output == Dict(p2 => [0.2, 0.25, 0.12], p3 => [0.25, 0.25, 0.25])
|
||||
@test c1.revenue == [12.0, 12.0, 12.0, 12.0]
|
||||
@test c1.operating_cost == [150.0, 150.0, 150.0, 150.0]
|
||||
@test c1.disposal_limit == Dict(p2 => [0, 0, 0, 0], p3 => [Inf, Inf, Inf, Inf])
|
||||
@test c1.disposal_cost ==
|
||||
Dict(p2 => [0.23, 0.23, 0.23, 0.23], p3 => [1.0, 1.0, 1.0, 1.0])
|
||||
c2 = instance.centers[2]
|
||||
@test c2.input === nothing
|
||||
@test c2.revenue == [0, 0, 0, 0]
|
||||
|
||||
# Plants
|
||||
@test length(instance.plants) == 1
|
||||
l1 = instance.plants[1]
|
||||
@test l1.latitude == 44.881
|
||||
@test l1.longitude == -87.623
|
||||
@test l1.input_mix ==
|
||||
Dict(p1 => [0.953, 0.953, 0.953, 0.953], p2 => [0.047, 0.047, 0.047, 0.047])
|
||||
@test l1.output == Dict(p3 => [0.25, 0.25, 0.25, 0.25], p4 => [0.12, 0.12, 0.12, 0.12])
|
||||
@test l1.emissions == Dict("CO2" => [0.1, 0.1, 0.1, 0.1])
|
||||
@test l1.storage_cost == Dict(p1 => [0.1, 0.1, 0.1, 0.1], p2 => [0.1, 0.1, 0.1, 0.1])
|
||||
@test l1.storage_limit == Dict(p1 => [100, 100, 100, 100], p2 => [Inf, Inf, Inf, Inf])
|
||||
@test l1.disposal_cost == Dict(p3 => [0, 0, 0, 0], p4 => [0.86, 0.86, 0.86, 0.86])
|
||||
@test l1.disposal_limit ==
|
||||
Dict(p3 => [Inf, Inf, Inf, Inf], p4 => [1000.0, 1000.0, 1000.0, 1000.0])
|
||||
@test l1.initial_capacity == 0
|
||||
@test length(l1.capacities) == 2
|
||||
c1 = l1.capacities[1]
|
||||
@test c1.size == 100
|
||||
@test c1.opening_cost == [300, 400, 450, 475]
|
||||
@test c1.fix_operating_cost == [300, 300, 300, 300]
|
||||
@test c1.var_operating_cost == [5, 5, 5, 5]
|
||||
c2 = l1.capacities[2]
|
||||
@test c2.size == 500
|
||||
@test c2.opening_cost == [1000, 1000, 1000, 1000]
|
||||
@test c2.fix_operating_cost == [400, 400, 400, 400]
|
||||
@test c2.var_operating_cost == [5, 5, 5, 5]
|
||||
end
|
||||
|
||||
|
||||
function instance_parse_test_2()
|
||||
# Should not crash
|
||||
RELOG.parsefile(fixture("boat_example.json"))
|
||||
end
|
@ -1,112 +0,0 @@
|
||||
using RELOG
|
||||
using Test
|
||||
using HiGHS
|
||||
using JuMP
|
||||
|
||||
function model_build_test()
|
||||
instance = RELOG.parsefile(fixture("simple.json"))
|
||||
model = RELOG.build_model(instance, optimizer = HiGHS.Optimizer, variable_names = true)
|
||||
y = model[:y]
|
||||
z_disp = model[:z_disp]
|
||||
z_input = model[:z_input]
|
||||
x = model[:x]
|
||||
obj = objective_function(model)
|
||||
|
||||
@test obj.terms[y["L1", "C3", "P4", 1]] == (
|
||||
111.118 * 0.015 # transportation
|
||||
- 12.0 # revenue
|
||||
)
|
||||
@test obj.terms[y["C1", "L1", "P2", 4]] == (
|
||||
333.262 * 0.015 + # transportation
|
||||
0.25 + # center collection cost
|
||||
5.0 # plant operating cost
|
||||
)
|
||||
@test obj.terms[z_disp["C1", "P2", 1]] == 0.23
|
||||
@test obj.constant == (
|
||||
150 * 4 * 3 # center operating cost
|
||||
)
|
||||
@test obj.terms[z_disp["L1", "P4", 2]] == 0.86
|
||||
@test obj.terms[x["L1", 1]] == (
|
||||
-100.0 + # opening cost
|
||||
300 # fixed operating cost
|
||||
)
|
||||
@test obj.terms[x["L1", 2]] == (
|
||||
-50.0 + # opening cost
|
||||
300 # fixed operating cost
|
||||
)
|
||||
@test obj.terms[x["L1", 3]] == (
|
||||
-25.0 + # opening cost
|
||||
300 # fixed operating cost
|
||||
)
|
||||
@test obj.terms[x["L1", 4]] == (
|
||||
475.0 + # opening cost
|
||||
300 # fixed operating cost
|
||||
)
|
||||
|
||||
# Plants: Definition of total plant input
|
||||
@test repr(model[:eq_z_input]["L1", 1]) ==
|
||||
"eq_z_input[L1,1] : -y[C2,L1,P1,1] - y[C1,L1,P2,1] + z_input[L1,1] = 0"
|
||||
|
||||
# Plants: Must meet input mix
|
||||
@test repr(model[:eq_input_mix]["L1", "P1", 1]) ==
|
||||
"eq_input_mix[L1,P1,1] : y[C2,L1,P1,1] - 0.953 z_input[L1,1] = 0"
|
||||
@test repr(model[:eq_input_mix]["L1", "P2", 1]) ==
|
||||
"eq_input_mix[L1,P2,1] : y[C1,L1,P2,1] - 0.047 z_input[L1,1] = 0"
|
||||
|
||||
# Plants: Calculate amount produced
|
||||
@test repr(model[:eq_z_prod]["L1", "P3", 1]) ==
|
||||
"eq_z_prod[L1,P3,1] : z_prod[L1,P3,1] - 0.25 z_input[L1,1] = 0"
|
||||
@test repr(model[:eq_z_prod]["L1", "P4", 1]) ==
|
||||
"eq_z_prod[L1,P4,1] : z_prod[L1,P4,1] - 0.12 z_input[L1,1] = 0"
|
||||
|
||||
# Plants: Produced material must be sent or disposed
|
||||
@test repr(model[:eq_balance]["L1", "P3", 1]) ==
|
||||
"eq_balance[L1,P3,1] : z_prod[L1,P3,1] - z_disp[L1,P3,1] = 0"
|
||||
@test repr(model[:eq_balance]["L1", "P4", 1]) ==
|
||||
"eq_balance[L1,P4,1] : -y[L1,C3,P4,1] + z_prod[L1,P4,1] - z_disp[L1,P4,1] = 0"
|
||||
|
||||
# Plants: Capacity limit
|
||||
@test repr(model[:eq_capacity]["L1", 1]) ==
|
||||
"eq_capacity[L1,1] : -100 x[L1,1] + z_input[L1,1] ≤ 0"
|
||||
|
||||
# Plants: Disposal limit
|
||||
@test repr(model[:eq_disposal_limit]["L1", "P4", 1]) ==
|
||||
"eq_disposal_limit[L1,P4,1] : z_disp[L1,P4,1] ≤ 1000"
|
||||
@test ("L1", "P3", 1) ∉ keys(model[:eq_disposal_limit])
|
||||
|
||||
# Plants: Plant remains open
|
||||
@test repr(model[:eq_keep_open]["L1", 4]) ==
|
||||
"eq_keep_open[L1,4] : -x[L1,3] + x[L1,4] ≥ 0"
|
||||
@test repr(model[:eq_keep_open]["L1", 1]) == "eq_keep_open[L1,1] : x[L1,1] ≥ 0"
|
||||
|
||||
# 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,1] + x[L1,2] ≤ 0"
|
||||
|
||||
# Centers: Definition of total center input
|
||||
@test repr(model[:eq_z_input]["C1", 1]) ==
|
||||
"eq_z_input[C1,1] : -y[C2,C1,P1,1] + z_input[C1,1] = 0"
|
||||
|
||||
# Centers: Calculate amount collected
|
||||
@test repr(model[:eq_z_collected]["C1", "P2", 1]) ==
|
||||
"eq_z_collected[C1,P2,1] : -0.2 z_input[C1,1] + z_collected[C1,P2,1] = 100"
|
||||
@test repr(model[:eq_z_collected]["C1", "P2", 2]) ==
|
||||
"eq_z_collected[C1,P2,2] : -0.25 z_input[C1,1] - 0.2 z_input[C1,2] + z_collected[C1,P2,2] = 50"
|
||||
@test repr(model[:eq_z_collected]["C1", "P2", 3]) ==
|
||||
"eq_z_collected[C1,P2,3] : -0.12 z_input[C1,1] - 0.25 z_input[C1,2] - 0.2 z_input[C1,3] + z_collected[C1,P2,3] = 0"
|
||||
@test repr(model[:eq_z_collected]["C1", "P2", 4]) ==
|
||||
"eq_z_collected[C1,P2,4] : -0.12 z_input[C1,2] - 0.25 z_input[C1,3] - 0.2 z_input[C1,4] + z_collected[C1,P2,4] = 0"
|
||||
@test repr(model[:eq_z_collected]["C2", "P1", 1]) == "eq_z_collected[C2,P1,1] : z_collected[C2,P1,1] = 55"
|
||||
|
||||
# Centers: Collected products must be disposed or sent
|
||||
@test repr(model[:eq_balance]["C1", "P2", 1]) ==
|
||||
"eq_balance[C1,P2,1] : -y[C1,L1,P2,1] - z_disp[C1,P2,1] + z_collected[C1,P2,1] = 0"
|
||||
@test repr(model[:eq_balance]["C1", "P3", 1]) ==
|
||||
"eq_balance[C1,P3,1] : -z_disp[C1,P3,1] + z_collected[C1,P3,1] = 0"
|
||||
|
||||
# Centers: Disposal limit
|
||||
@test repr(model[:eq_disposal_limit]["C1", "P2", 1]) ==
|
||||
"eq_disposal_limit[C1,P2,1] : z_disp[C1,P2,1] ≤ 0"
|
||||
@test ("C1", "P3", 1) ∉ keys(model[:eq_disposal_limit])
|
||||
end
|
@ -1,10 +0,0 @@
|
||||
# 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
|
||||
|
||||
function model_dist_test()
|
||||
# Euclidean distance between Chicago and Indianapolis
|
||||
@test RELOG._calculate_distance(41.866, -87.656, 39.764, -86.148) == 265.818
|
||||
end
|
@ -1,12 +0,0 @@
|
||||
function report_tests()
|
||||
# Load and solve the boat example
|
||||
instance = RELOG.parsefile(fixture("boat_example.json"))
|
||||
model = RELOG.build_model(instance, optimizer = HiGHS.Optimizer, variable_names = true)
|
||||
optimize!(model)
|
||||
write_to_file(model, "tmp/model.lp")
|
||||
RELOG.write_plants_report(model, "tmp/plants.csv")
|
||||
RELOG.write_plant_outputs_report(model, "tmp/plant_outputs.csv")
|
||||
RELOG.write_centers_report(model, "tmp/centers.csv")
|
||||
RELOG.write_center_outputs_report(model, "tmp/center_outputs.csv")
|
||||
RELOG.write_transportation_report(model, "tmp/transportation.csv")
|
||||
end
|
Loading…
Reference in new issue