mirror of https://github.com/ANL-CEEESA/RELOG.git
parent
a8e4491ea3
commit
22d73c9ded
@ -1,5 +0,0 @@
|
||||
[deps]
|
||||
JuliaFormatter = "98e50ef6-434e-11e9-1051-2b60c6c9e899"
|
||||
|
||||
[compat]
|
||||
JuliaFormatter = "0.14.4"
|
@ -1,8 +0,0 @@
|
||||
using JuliaFormatter
|
||||
format(
|
||||
[
|
||||
"../../src",
|
||||
"../../test",
|
||||
],
|
||||
verbose=true,
|
||||
)
|
@ -1,75 +0,0 @@
|
||||
#!/bin/bash
|
||||
# UnitCommitment.jl: Optimization Package for Security-Constrained Unit Commitment
|
||||
# Copyright (C) 2020-2021, UChicago Argonne, LLC. All rights reserved.
|
||||
# Released under the modified BSD license. See COPYING.md for more details.
|
||||
|
||||
if [ ! -e Project.toml ]; then
|
||||
echo "juliaw: Project.toml not found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -e Manifest.toml ]; then
|
||||
julia --project=. -e 'using Pkg; Pkg.instantiate()' || exit 1
|
||||
fi
|
||||
|
||||
if [ ! -e build/sysimage.so -o Project.toml -nt build/sysimage.so ]; then
|
||||
echo "juliaw: rebuilding system image..."
|
||||
|
||||
# Generate temporary project folder
|
||||
rm -rf $HOME/.juliaw
|
||||
mkdir -p $HOME/.juliaw/src
|
||||
cp Project.toml Manifest.toml $HOME/.juliaw
|
||||
NAME=$(julia -e 'using TOML; toml = TOML.parsefile("Project.toml"); "name" in keys(toml) && print(toml["name"])')
|
||||
if [ ! -z $NAME ]; then
|
||||
cat > $HOME/.juliaw/src/$NAME.jl << EOF
|
||||
module $NAME
|
||||
end
|
||||
EOF
|
||||
fi
|
||||
|
||||
# Add PackageCompiler dependencies to temporary project
|
||||
julia --project=$HOME/.juliaw -e 'using Pkg; Pkg.add(["PackageCompiler", "TOML", "Logging"])'
|
||||
|
||||
# Generate system image scripts
|
||||
cat > $HOME/.juliaw/sysimage.jl << EOF
|
||||
using PackageCompiler
|
||||
using TOML
|
||||
using Logging
|
||||
|
||||
Logging.disable_logging(Logging.Info)
|
||||
mkpath("$PWD/build")
|
||||
|
||||
println("juliaw: generating precompilation statements...")
|
||||
run(\`julia --project="$PWD" --trace-compile="$PWD"/build/precompile.jl \$(ARGS)\`)
|
||||
|
||||
println("juliaw: finding dependencies...")
|
||||
project = TOML.parsefile("Project.toml")
|
||||
manifest = TOML.parsefile("Manifest.toml")
|
||||
deps = Symbol[]
|
||||
for dep in keys(project["deps"])
|
||||
if dep in keys(manifest)
|
||||
# Up to Julia 1.6
|
||||
dep_entry = manifest[dep][1]
|
||||
else
|
||||
# Julia 1.7+
|
||||
dep_entry = manifest["deps"][dep][1]
|
||||
end
|
||||
if "path" in keys(dep_entry)
|
||||
println(" - \$(dep) [skip]")
|
||||
else
|
||||
println(" - \$(dep)")
|
||||
push!(deps, Symbol(dep))
|
||||
end
|
||||
end
|
||||
|
||||
println("juliaw: building system image...")
|
||||
create_sysimage(
|
||||
deps,
|
||||
precompile_statements_file = "$PWD/build/precompile.jl",
|
||||
sysimage_path = "$PWD/build/sysimage.so",
|
||||
)
|
||||
EOF
|
||||
julia --project=$HOME/.juliaw $HOME/.juliaw/sysimage.jl $*
|
||||
else
|
||||
julia --project=. --sysimage build/sysimage.so $*
|
||||
fi
|
@ -1,23 +0,0 @@
|
||||
site_name: RELOG
|
||||
theme: cinder
|
||||
copyright: "Copyright © 2020, UChicago Argonne, LLC. All Rights Reserved."
|
||||
repo_url: https://github.com/ANL-CEEESA/RELOG
|
||||
edit_uri: edit/master/src/docs/
|
||||
nav:
|
||||
- Home: index.md
|
||||
- Usage: usage.md
|
||||
- Data Format: format.md
|
||||
- Reports: reports.md
|
||||
- Optimization Model: model.md
|
||||
plugins:
|
||||
- search
|
||||
markdown_extensions:
|
||||
- admonition
|
||||
- mdx_math
|
||||
extra_javascript:
|
||||
- https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js?config=TeX-AMS-MML_HTMLorMML
|
||||
- js/mathjax.js
|
||||
docs_dir: src/docs
|
||||
site_dir: docs
|
||||
extra_css:
|
||||
- "css/custom.css"
|
@ -0,0 +1,19 @@
|
||||
name = "RELOGT"
|
||||
uuid = "a6dae211-05d8-42ed-9081-b88c982fc90a"
|
||||
authors = ["Alinson S. Xavier <git@axavier.org>"]
|
||||
version = "0.1.0"
|
||||
|
||||
[deps]
|
||||
Cbc = "9961bab8-2fa3-5c5a-9d89-47fab24efd76"
|
||||
GZip = "92fee26a-97fe-5a0c-ad85-20a5f3185b63"
|
||||
JSON = "682c06a0-de6a-54ab-a142-c8b1cf79cde6"
|
||||
JuMP = "4076af6c-e467-56ae-b986-b466b2749572"
|
||||
JuliaFormatter = "98e50ef6-434e-11e9-1051-2b60c6c9e899"
|
||||
MathOptInterface = "b8f27783-ece8-5eb3-8dc8-9495eed66fee"
|
||||
Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7"
|
||||
RELOG = "a2afcdf7-cf04-4913-85f9-c0d81ddf2008"
|
||||
Revise = "295af30f-e4ad-537b-8983-00126c2a3abe"
|
||||
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
|
||||
|
||||
[compat]
|
||||
JuliaFormatter = "1"
|
Binary file not shown.
@ -1,39 +0,0 @@
|
||||
# Copyright (C) 2020 Argonne National Laboratory
|
||||
# Written by Alinson Santos Xavier <axavier@anl.gov>
|
||||
|
||||
using RELOG
|
||||
|
||||
@testset "build_graph" begin
|
||||
basedir = dirname(@__FILE__)
|
||||
instance = RELOG.parsefile("$basedir/../../instances/s1.json")
|
||||
graph = RELOG.build_graph(instance)
|
||||
process_node_by_location_name =
|
||||
Dict(n.location.location_name => n for n in graph.process_nodes)
|
||||
|
||||
@test length(graph.plant_shipping_nodes) == 8
|
||||
@test length(graph.collection_shipping_nodes) == 10
|
||||
@test length(graph.process_nodes) == 6
|
||||
|
||||
node = graph.collection_shipping_nodes[1]
|
||||
@test node.location.name == "C1"
|
||||
@test length(node.incoming_arcs) == 0
|
||||
@test length(node.outgoing_arcs) == 2
|
||||
@test node.outgoing_arcs[1].source.location.name == "C1"
|
||||
@test node.outgoing_arcs[1].dest.location.plant_name == "F1"
|
||||
@test node.outgoing_arcs[1].dest.location.location_name == "L1"
|
||||
@test node.outgoing_arcs[1].values["distance"] == 1695.364
|
||||
|
||||
node = process_node_by_location_name["L1"]
|
||||
@test node.location.plant_name == "F1"
|
||||
@test node.location.location_name == "L1"
|
||||
@test length(node.incoming_arcs) == 10
|
||||
@test length(node.outgoing_arcs) == 2
|
||||
|
||||
node = process_node_by_location_name["L3"]
|
||||
@test node.location.plant_name == "F2"
|
||||
@test node.location.location_name == "L3"
|
||||
@test length(node.incoming_arcs) == 2
|
||||
@test length(node.outgoing_arcs) == 2
|
||||
|
||||
@test length(graph.arcs) == 38
|
||||
end
|
@ -1,25 +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
|
||||
|
||||
@testset "KnnDrivingDistance" begin
|
||||
# Euclidean distance between Chicago and Indianapolis
|
||||
@test RELOG._calculate_distance(
|
||||
41.866,
|
||||
-87.656,
|
||||
39.764,
|
||||
-86.148,
|
||||
RELOG.EuclideanDistance(),
|
||||
) == 265.818
|
||||
|
||||
# Approximate driving distance between Chicago and Indianapolis
|
||||
@test RELOG._calculate_distance(
|
||||
41.866,
|
||||
-87.656,
|
||||
39.764,
|
||||
-86.148,
|
||||
RELOG.KnnDrivingDistance(),
|
||||
) == 316.43
|
||||
end
|
@ -1,53 +0,0 @@
|
||||
# Copyright (C) 2020 Argonne National Laboratory
|
||||
# Written by Alinson Santos Xavier <axavier@anl.gov>
|
||||
|
||||
using RELOG
|
||||
|
||||
@testset "compress" begin
|
||||
basedir = dirname(@__FILE__)
|
||||
instance = RELOG.parsefile("$basedir/../../instances/s1.json")
|
||||
compressed = RELOG._compress(instance)
|
||||
|
||||
product_name_to_product = Dict(p.name => p for p in compressed.products)
|
||||
location_name_to_facility = Dict()
|
||||
for p in compressed.plants
|
||||
location_name_to_facility[p.location_name] = p
|
||||
end
|
||||
for c in compressed.collection_centers
|
||||
location_name_to_facility[c.name] = c
|
||||
end
|
||||
|
||||
p1 = product_name_to_product["P1"]
|
||||
p2 = product_name_to_product["P2"]
|
||||
p3 = product_name_to_product["P3"]
|
||||
c1 = location_name_to_facility["C1"]
|
||||
l1 = location_name_to_facility["L1"]
|
||||
|
||||
@test compressed.time == 1
|
||||
@test compressed.building_period == [1]
|
||||
|
||||
@test p1.name == "P1"
|
||||
@test p1.transportation_cost ≈ [0.015]
|
||||
@test p1.transportation_energy ≈ [0.115]
|
||||
@test p1.transportation_emissions["CO2"] ≈ [0.051]
|
||||
@test p1.transportation_emissions["CH4"] ≈ [0.0025]
|
||||
|
||||
@test c1.name == "C1"
|
||||
@test c1.amount ≈ [1869.12]
|
||||
|
||||
@test l1.plant_name == "F1"
|
||||
@test l1.location_name == "L1"
|
||||
@test l1.energy ≈ [0.115]
|
||||
@test l1.emissions["CO2"] ≈ [0.051]
|
||||
@test l1.emissions["CH4"] ≈ [0.0025]
|
||||
@test l1.sizes[1].opening_cost ≈ [500]
|
||||
@test l1.sizes[2].opening_cost ≈ [1250]
|
||||
@test l1.sizes[1].fixed_operating_cost ≈ [60]
|
||||
@test l1.sizes[2].fixed_operating_cost ≈ [60]
|
||||
@test l1.sizes[1].variable_operating_cost ≈ [30]
|
||||
@test l1.sizes[2].variable_operating_cost ≈ [30]
|
||||
@test l1.disposal_limit[p2] ≈ [2.0]
|
||||
@test l1.disposal_limit[p3] ≈ [2.0]
|
||||
@test l1.disposal_cost[p2] ≈ [-10.0]
|
||||
@test l1.disposal_cost[p3] ≈ [-10.0]
|
||||
end
|
@ -1,25 +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
|
||||
|
||||
@testset "geodb_query (2018-us-county)" begin
|
||||
region = RELOG.geodb_query("2018-us-county:17043")
|
||||
@test region.centroid.lat == 41.83956
|
||||
@test region.centroid.lon == -88.08857
|
||||
@test region.population == 922_921
|
||||
end
|
||||
|
||||
# @testset "geodb_query (2018-us-zcta)" begin
|
||||
# region = RELOG.geodb_query("2018-us-zcta:60439")
|
||||
# @test region.centroid.lat == 41.68241
|
||||
# @test region.centroid.lon == -87.98954
|
||||
# end
|
||||
|
||||
@testset "geodb_query (us-state)" begin
|
||||
region = RELOG.geodb_query("us-state:IL")
|
||||
@test region.centroid.lat == 39.73939
|
||||
@test region.centroid.lon == -89.50414
|
||||
@test region.population == 12_671_821
|
||||
end
|
@ -1,93 +0,0 @@
|
||||
# Copyright (C) 2020 Argonne National Laboratory
|
||||
# Written by Alinson Santos Xavier <axavier@anl.gov>
|
||||
|
||||
using RELOG
|
||||
|
||||
@testset "parse" begin
|
||||
basedir = dirname(@__FILE__)
|
||||
instance = RELOG.parsefile("$basedir/../../instances/s1.json")
|
||||
|
||||
centers = instance.collection_centers
|
||||
plants = instance.plants
|
||||
products = instance.products
|
||||
location_name_to_plant = Dict(p.location_name => p for p in plants)
|
||||
product_name_to_product = Dict(p.name => p for p in products)
|
||||
|
||||
@test length(centers) == 10
|
||||
@test centers[1].name == "C1"
|
||||
@test centers[1].latitude == 7
|
||||
@test centers[1].latitude == 7
|
||||
@test centers[1].longitude == 7
|
||||
@test centers[1].amount == [934.56, 934.56]
|
||||
@test centers[1].product.name == "P1"
|
||||
|
||||
@test length(plants) == 6
|
||||
|
||||
plant = location_name_to_plant["L1"]
|
||||
@test plant.plant_name == "F1"
|
||||
@test plant.location_name == "L1"
|
||||
@test plant.input.name == "P1"
|
||||
@test plant.latitude == 0
|
||||
@test plant.longitude == 0
|
||||
|
||||
@test length(plant.sizes) == 2
|
||||
@test plant.sizes[1].capacity == 250
|
||||
@test plant.sizes[1].opening_cost == [500, 500]
|
||||
@test plant.sizes[1].fixed_operating_cost == [30, 30]
|
||||
@test plant.sizes[1].variable_operating_cost == [30, 30]
|
||||
@test plant.sizes[2].capacity == 1000
|
||||
@test plant.sizes[2].opening_cost == [1250, 1250]
|
||||
@test plant.sizes[2].fixed_operating_cost == [30, 30]
|
||||
@test plant.sizes[2].variable_operating_cost == [30, 30]
|
||||
|
||||
p1 = product_name_to_product["P1"]
|
||||
@test p1.disposal_limit == [1.0, 1.0]
|
||||
@test p1.disposal_cost == [-1000.0, -1000.0]
|
||||
|
||||
p2 = product_name_to_product["P2"]
|
||||
@test p2.disposal_limit == [0.0, 0.0]
|
||||
@test p2.disposal_cost == [0.0, 0.0]
|
||||
|
||||
p3 = product_name_to_product["P3"]
|
||||
@test length(plant.output) == 2
|
||||
@test plant.output[p2] == 0.2
|
||||
@test plant.output[p3] == 0.5
|
||||
@test plant.disposal_limit[p2] == [1, 1]
|
||||
@test plant.disposal_limit[p3] == [1, 1]
|
||||
@test plant.disposal_cost[p2] == [-10, -10]
|
||||
@test plant.disposal_cost[p3] == [-10, -10]
|
||||
|
||||
plant = location_name_to_plant["L3"]
|
||||
@test plant.location_name == "L3"
|
||||
@test plant.input.name == "P2"
|
||||
@test plant.latitude == 25
|
||||
@test plant.longitude == 65
|
||||
|
||||
@test length(plant.sizes) == 2
|
||||
@test plant.sizes[1].capacity == 1000.0
|
||||
@test plant.sizes[1].opening_cost == [3000, 3000]
|
||||
@test plant.sizes[1].fixed_operating_cost == [50, 50]
|
||||
@test plant.sizes[1].variable_operating_cost == [50, 50]
|
||||
@test plant.sizes[1] == plant.sizes[2]
|
||||
|
||||
p4 = product_name_to_product["P4"]
|
||||
@test plant.output[p3] == 0.05
|
||||
@test plant.output[p4] == 0.8
|
||||
@test plant.disposal_limit[p3] == [1e8, 1e8]
|
||||
@test plant.disposal_limit[p4] == [0, 0]
|
||||
end
|
||||
|
||||
@testset "parse (geodb)" begin
|
||||
basedir = dirname(@__FILE__)
|
||||
instance = RELOG.parsefile("$basedir/../../instances/s2.json")
|
||||
|
||||
centers = instance.collection_centers
|
||||
@test centers[1].name == "C1"
|
||||
@test centers[1].latitude == 41.83956
|
||||
@test centers[1].longitude == -88.08857
|
||||
end
|
||||
|
||||
# @testset "parse (invalid)" begin
|
||||
# basedir = dirname(@__FILE__)
|
||||
# @test_throws ErrorException RELOG.parsefile("$basedir/../fixtures/s1-wrong-length.json")
|
||||
# end
|
@ -1,38 +0,0 @@
|
||||
# Copyright (C) 2020 Argonne National Laboratory
|
||||
# Written by Alinson Santos Xavier <axavier@anl.gov>
|
||||
|
||||
using RELOG, Cbc, JuMP, Printf, JSON, MathOptInterface.FileFormats
|
||||
|
||||
@testset "build" begin
|
||||
basedir = dirname(@__FILE__)
|
||||
instance = RELOG.parsefile("$basedir/../../instances/s1.json")
|
||||
graph = RELOG.build_graph(instance)
|
||||
model = RELOG.build_model(instance, graph, Cbc.Optimizer)
|
||||
set_optimizer_attribute(model, "logLevel", 0)
|
||||
|
||||
process_node_by_location_name =
|
||||
Dict(n.location.location_name => n for n in graph.process_nodes)
|
||||
|
||||
shipping_node_by_loc_and_prod_names = Dict(
|
||||
(n.location.location_name, n.product.name) => n for n in graph.plant_shipping_nodes
|
||||
)
|
||||
|
||||
@test length(model[:flow]) == 76
|
||||
@test length(model[:plant_dispose]) == 16
|
||||
@test length(model[:open_plant]) == 12
|
||||
@test length(model[:capacity]) == 12
|
||||
@test length(model[:expansion]) == 12
|
||||
|
||||
l1 = process_node_by_location_name["L1"]
|
||||
v = model[:capacity][l1, 1]
|
||||
@test lower_bound(v) == 0.0
|
||||
@test upper_bound(v) == 1000.0
|
||||
|
||||
v = model[:expansion][l1, 1]
|
||||
@test lower_bound(v) == 0.0
|
||||
@test upper_bound(v) == 750.0
|
||||
|
||||
v = model[:plant_dispose][shipping_node_by_loc_and_prod_names["L1", "P2"], 1]
|
||||
@test lower_bound(v) == 0.0
|
||||
@test upper_bound(v) == 1.0
|
||||
end
|
@ -1,13 +0,0 @@
|
||||
# Copyright (C) 2020 Argonne National Laboratory
|
||||
# Written by Alinson Santos Xavier <axavier@anl.gov>
|
||||
|
||||
using RELOG
|
||||
|
||||
basedir = @__DIR__
|
||||
|
||||
@testset "Resolve" begin
|
||||
# Shoud not crash
|
||||
filename = "$basedir/../../instances/s1.json"
|
||||
solution_old, model_old = RELOG.solve(filename, return_model = true)
|
||||
solution_new = RELOG.resolve(model_old, filename)
|
||||
end
|
@ -1,70 +0,0 @@
|
||||
# Copyright (C) 2020 Argonne National Laboratory
|
||||
# Written by Alinson Santos Xavier <axavier@anl.gov>
|
||||
|
||||
using RELOG, Cbc, JuMP, Printf, JSON, MathOptInterface.FileFormats
|
||||
|
||||
basedir = dirname(@__FILE__)
|
||||
|
||||
@testset "solve (exact)" begin
|
||||
solution_filename_a = tempname()
|
||||
solution_filename_b = tempname()
|
||||
solution = RELOG.solve("$basedir/../../instances/s1.json", output = solution_filename_a)
|
||||
|
||||
@test isfile(solution_filename_a)
|
||||
|
||||
RELOG.write(solution, solution_filename_b)
|
||||
@test isfile(solution_filename_b)
|
||||
|
||||
@test "Costs" in keys(solution)
|
||||
@test "Fixed operating (\$)" in keys(solution["Costs"])
|
||||
@test "Transportation (\$)" in keys(solution["Costs"])
|
||||
@test "Variable operating (\$)" in keys(solution["Costs"])
|
||||
@test "Total (\$)" in keys(solution["Costs"])
|
||||
|
||||
@test "Plants" in keys(solution)
|
||||
@test "F1" in keys(solution["Plants"])
|
||||
@test "F2" in keys(solution["Plants"])
|
||||
@test "F3" in keys(solution["Plants"])
|
||||
@test "F4" in keys(solution["Plants"])
|
||||
|
||||
@test "Products" in keys(solution)
|
||||
@test "P1" in keys(solution["Products"])
|
||||
@test "C1" in keys(solution["Products"]["P1"])
|
||||
@test "Dispose (tonne)" in keys(solution["Products"]["P1"]["C1"])
|
||||
|
||||
total_disposal =
|
||||
sum([loc["Dispose (tonne)"] for loc in values(solution["Products"]["P1"])])
|
||||
@test total_disposal == [1.0, 1.0]
|
||||
end
|
||||
|
||||
@testset "solve (heuristic)" begin
|
||||
# Should not crash
|
||||
solution = RELOG.solve("$basedir/../../instances/s1.json", heuristic = true)
|
||||
end
|
||||
|
||||
@testset "solve (infeasible)" begin
|
||||
json = JSON.parsefile("$basedir/../../instances/s1.json")
|
||||
for (location_name, location_dict) in json["products"]["P1"]["initial amounts"]
|
||||
location_dict["amount (tonne)"] *= 1000
|
||||
end
|
||||
@test_throws ErrorException("No solution available") RELOG.solve(RELOG.parse(json))
|
||||
end
|
||||
|
||||
@testset "solve (with storage)" begin
|
||||
basedir = dirname(@__FILE__)
|
||||
filename = "$basedir/../fixtures/storage.json"
|
||||
instance = RELOG.parsefile(filename)
|
||||
@test instance.plants[1].storage_limit == 50.0
|
||||
@test instance.plants[1].storage_cost == [2.0, 1.5, 1.0]
|
||||
|
||||
solution = RELOG.solve(filename)
|
||||
plant_dict = solution["Plants"]["mega plant"]["Chicago"]
|
||||
@test plant_dict["Variable operating cost (\$)"] == [500.0, 0.0, 100.0]
|
||||
@test plant_dict["Process (tonne)"] == [50.0, 0.0, 50.0]
|
||||
@test plant_dict["Storage (tonne)"] == [50.0, 50.0, 0.0]
|
||||
@test plant_dict["Storage cost (\$)"] == [100.0, 75.0, 0.0]
|
||||
|
||||
@test solution["Costs"]["Variable operating (\$)"] == [500.0, 0.0, 100.0]
|
||||
@test solution["Costs"]["Storage (\$)"] == [100.0, 75.0, 0.0]
|
||||
@test solution["Costs"]["Total (\$)"] == [600.0, 75.0, 100.0]
|
||||
end
|
@ -1,21 +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, JSON, GZip
|
||||
|
||||
basedir = @__DIR__
|
||||
|
||||
@testset "Reports" begin
|
||||
@testset "from solve" begin
|
||||
solution = RELOG.solve("$basedir/../instances/s1.json")
|
||||
tmp_filename = tempname()
|
||||
# The following should not crash
|
||||
RELOG.write_plant_emissions_report(solution, tmp_filename)
|
||||
RELOG.write_plant_outputs_report(solution, tmp_filename)
|
||||
RELOG.write_plants_report(solution, tmp_filename)
|
||||
RELOG.write_products_report(solution, tmp_filename)
|
||||
RELOG.write_transportation_emissions_report(solution, tmp_filename)
|
||||
RELOG.write_transportation_report(solution, tmp_filename)
|
||||
end
|
||||
end
|
@ -1,22 +0,0 @@
|
||||
# Copyright (C) 2020 Argonne National Laboratory
|
||||
# Written by Alinson Santos Xavier <axavier@anl.gov>
|
||||
|
||||
using Test
|
||||
|
||||
@testset "RELOG" begin
|
||||
@testset "Instance" begin
|
||||
include("instance/compress_test.jl")
|
||||
include("instance/geodb_test.jl")
|
||||
include("instance/parse_test.jl")
|
||||
end
|
||||
@testset "Graph" begin
|
||||
include("graph/build_test.jl")
|
||||
include("graph/dist_test.jl")
|
||||
end
|
||||
@testset "Model" begin
|
||||
include("model/build_test.jl")
|
||||
include("model/solve_test.jl")
|
||||
include("model/resolve_test.jl")
|
||||
end
|
||||
include("reports_test.jl")
|
||||
end
|
@ -0,0 +1,51 @@
|
||||
module RELOGT
|
||||
|
||||
using Test
|
||||
using JuliaFormatter
|
||||
|
||||
include("instance/compress_test.jl")
|
||||
include("instance/geodb_test.jl")
|
||||
include("instance/parse_test.jl")
|
||||
include("graph/build_test.jl")
|
||||
include("graph/dist_test.jl")
|
||||
include("model/build_test.jl")
|
||||
include("model/solve_test.jl")
|
||||
include("model/resolve_test.jl")
|
||||
include("reports_test.jl")
|
||||
|
||||
basedir = dirname(@__FILE__)
|
||||
|
||||
function fixture(path::String)::String
|
||||
return "$basedir/../fixtures/$path"
|
||||
end
|
||||
|
||||
function runtests()
|
||||
@testset "RELOG" begin
|
||||
@testset "instance" begin
|
||||
instance_compress_test()
|
||||
instance_geodb_test()
|
||||
instance_parse_test()
|
||||
end
|
||||
@testset "graph" begin
|
||||
graph_build_test()
|
||||
graph_dist_test()
|
||||
end
|
||||
@testset "model" begin
|
||||
model_build_test()
|
||||
model_solve_test()
|
||||
model_resolve_test()
|
||||
end
|
||||
reports_test()
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
function format()
|
||||
JuliaFormatter.format(basedir, verbose = true)
|
||||
JuliaFormatter.format("$basedir/../../src", verbose = true)
|
||||
return
|
||||
end
|
||||
|
||||
export runtests, format
|
||||
|
||||
end # module RELOGT
|
@ -0,0 +1,40 @@
|
||||
# Copyright (C) 2020 Argonne National Laboratory
|
||||
# Written by Alinson Santos Xavier <axavier@anl.gov>
|
||||
|
||||
using RELOG
|
||||
|
||||
function graph_build_test()
|
||||
@testset "build_graph" begin
|
||||
instance = RELOG.parsefile(fixture("s1.json"))
|
||||
graph = RELOG.build_graph(instance)
|
||||
process_node_by_location_name =
|
||||
Dict(n.location.location_name => n for n in graph.process_nodes)
|
||||
|
||||
@test length(graph.plant_shipping_nodes) == 8
|
||||
@test length(graph.collection_shipping_nodes) == 10
|
||||
@test length(graph.process_nodes) == 6
|
||||
|
||||
node = graph.collection_shipping_nodes[1]
|
||||
@test node.location.name == "C1"
|
||||
@test length(node.incoming_arcs) == 0
|
||||
@test length(node.outgoing_arcs) == 2
|
||||
@test node.outgoing_arcs[1].source.location.name == "C1"
|
||||
@test node.outgoing_arcs[1].dest.location.plant_name == "F1"
|
||||
@test node.outgoing_arcs[1].dest.location.location_name == "L1"
|
||||
@test node.outgoing_arcs[1].values["distance"] == 1695.364
|
||||
|
||||
node = process_node_by_location_name["L1"]
|
||||
@test node.location.plant_name == "F1"
|
||||
@test node.location.location_name == "L1"
|
||||
@test length(node.incoming_arcs) == 10
|
||||
@test length(node.outgoing_arcs) == 2
|
||||
|
||||
node = process_node_by_location_name["L3"]
|
||||
@test node.location.plant_name == "F2"
|
||||
@test node.location.location_name == "L3"
|
||||
@test length(node.incoming_arcs) == 2
|
||||
@test length(node.outgoing_arcs) == 2
|
||||
|
||||
@test length(graph.arcs) == 38
|
||||
end
|
||||
end
|
@ -0,0 +1,27 @@
|
||||
# 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 graph_dist_test()
|
||||
@testset "KnnDrivingDistance" begin
|
||||
# Euclidean distance between Chicago and Indianapolis
|
||||
@test RELOG._calculate_distance(
|
||||
41.866,
|
||||
-87.656,
|
||||
39.764,
|
||||
-86.148,
|
||||
RELOG.EuclideanDistance(),
|
||||
) == 265.818
|
||||
|
||||
# Approximate driving distance between Chicago and Indianapolis
|
||||
@test RELOG._calculate_distance(
|
||||
41.866,
|
||||
-87.656,
|
||||
39.764,
|
||||
-86.148,
|
||||
RELOG.KnnDrivingDistance(),
|
||||
) == 316.43
|
||||
end
|
||||
end
|
@ -0,0 +1,54 @@
|
||||
# Copyright (C) 2020 Argonne National Laboratory
|
||||
# Written by Alinson Santos Xavier <axavier@anl.gov>
|
||||
|
||||
using RELOG
|
||||
|
||||
function instance_compress_test()
|
||||
@testset "compress" begin
|
||||
instance = RELOG.parsefile(fixture("s1.json"))
|
||||
compressed = RELOG._compress(instance)
|
||||
|
||||
product_name_to_product = Dict(p.name => p for p in compressed.products)
|
||||
location_name_to_facility = Dict()
|
||||
for p in compressed.plants
|
||||
location_name_to_facility[p.location_name] = p
|
||||
end
|
||||
for c in compressed.collection_centers
|
||||
location_name_to_facility[c.name] = c
|
||||
end
|
||||
|
||||
p1 = product_name_to_product["P1"]
|
||||
p2 = product_name_to_product["P2"]
|
||||
p3 = product_name_to_product["P3"]
|
||||
c1 = location_name_to_facility["C1"]
|
||||
l1 = location_name_to_facility["L1"]
|
||||
|
||||
@test compressed.time == 1
|
||||
@test compressed.building_period == [1]
|
||||
|
||||
@test p1.name == "P1"
|
||||
@test p1.transportation_cost ≈ [0.015]
|
||||
@test p1.transportation_energy ≈ [0.115]
|
||||
@test p1.transportation_emissions["CO2"] ≈ [0.051]
|
||||
@test p1.transportation_emissions["CH4"] ≈ [0.0025]
|
||||
|
||||
@test c1.name == "C1"
|
||||
@test c1.amount ≈ [1869.12]
|
||||
|
||||
@test l1.plant_name == "F1"
|
||||
@test l1.location_name == "L1"
|
||||
@test l1.energy ≈ [0.115]
|
||||
@test l1.emissions["CO2"] ≈ [0.051]
|
||||
@test l1.emissions["CH4"] ≈ [0.0025]
|
||||
@test l1.sizes[1].opening_cost ≈ [500]
|
||||
@test l1.sizes[2].opening_cost ≈ [1250]
|
||||
@test l1.sizes[1].fixed_operating_cost ≈ [60]
|
||||
@test l1.sizes[2].fixed_operating_cost ≈ [60]
|
||||
@test l1.sizes[1].variable_operating_cost ≈ [30]
|
||||
@test l1.sizes[2].variable_operating_cost ≈ [30]
|
||||
@test l1.disposal_limit[p2] ≈ [2.0]
|
||||
@test l1.disposal_limit[p3] ≈ [2.0]
|
||||
@test l1.disposal_cost[p2] ≈ [-10.0]
|
||||
@test l1.disposal_cost[p3] ≈ [-10.0]
|
||||
end
|
||||
end
|
@ -0,0 +1,27 @@
|
||||
# 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 instance_geodb_test()
|
||||
@testset "geodb_query (2018-us-county)" begin
|
||||
region = RELOG.geodb_query("2018-us-county:17043")
|
||||
@test region.centroid.lat == 41.83956
|
||||
@test region.centroid.lon == -88.08857
|
||||
@test region.population == 922_921
|
||||
end
|
||||
|
||||
# @testset "geodb_query (2018-us-zcta)" begin
|
||||
# region = RELOG.geodb_query("2018-us-zcta:60439")
|
||||
# @test region.centroid.lat == 41.68241
|
||||
# @test region.centroid.lon == -87.98954
|
||||
# end
|
||||
|
||||
@testset "geodb_query (us-state)" begin
|
||||
region = RELOG.geodb_query("us-state:IL")
|
||||
@test region.centroid.lat == 39.73939
|
||||
@test region.centroid.lon == -89.50414
|
||||
@test region.population == 12_671_821
|
||||
end
|
||||
end
|
@ -0,0 +1,87 @@
|
||||
# Copyright (C) 2020 Argonne National Laboratory
|
||||
# Written by Alinson Santos Xavier <axavier@anl.gov>
|
||||
|
||||
using RELOG
|
||||
|
||||
function instance_parse_test()
|
||||
@testset "parse" begin
|
||||
instance = RELOG.parsefile(fixture("s1.json"))
|
||||
|
||||
centers = instance.collection_centers
|
||||
plants = instance.plants
|
||||
products = instance.products
|
||||
location_name_to_plant = Dict(p.location_name => p for p in plants)
|
||||
product_name_to_product = Dict(p.name => p for p in products)
|
||||
|
||||
@test length(centers) == 10
|
||||
@test centers[1].name == "C1"
|
||||
@test centers[1].latitude == 7
|
||||
@test centers[1].latitude == 7
|
||||
@test centers[1].longitude == 7
|
||||
@test centers[1].amount == [934.56, 934.56]
|
||||
@test centers[1].product.name == "P1"
|
||||
|
||||
@test length(plants) == 6
|
||||
|
||||
plant = location_name_to_plant["L1"]
|
||||
@test plant.plant_name == "F1"
|
||||
@test plant.location_name == "L1"
|
||||
@test plant.input.name == "P1"
|
||||
@test plant.latitude == 0
|
||||
@test plant.longitude == 0
|
||||
|
||||
@test length(plant.sizes) == 2
|
||||
@test plant.sizes[1].capacity == 250
|
||||
@test plant.sizes[1].opening_cost == [500, 500]
|
||||
@test plant.sizes[1].fixed_operating_cost == [30, 30]
|
||||
@test plant.sizes[1].variable_operating_cost == [30, 30]
|
||||
@test plant.sizes[2].capacity == 1000
|
||||
@test plant.sizes[2].opening_cost == [1250, 1250]
|
||||
@test plant.sizes[2].fixed_operating_cost == [30, 30]
|
||||
@test plant.sizes[2].variable_operating_cost == [30, 30]
|
||||
|
||||
p1 = product_name_to_product["P1"]
|
||||
@test p1.disposal_limit == [1.0, 1.0]
|
||||
@test p1.disposal_cost == [-1000.0, -1000.0]
|
||||
|
||||
p2 = product_name_to_product["P2"]
|
||||
@test p2.disposal_limit == [0.0, 0.0]
|
||||
@test p2.disposal_cost == [0.0, 0.0]
|
||||
|
||||
p3 = product_name_to_product["P3"]
|
||||
@test length(plant.output) == 2
|
||||
@test plant.output[p2] == 0.2
|
||||
@test plant.output[p3] == 0.5
|
||||
@test plant.disposal_limit[p2] == [1, 1]
|
||||
@test plant.disposal_limit[p3] == [1, 1]
|
||||
@test plant.disposal_cost[p2] == [-10, -10]
|
||||
@test plant.disposal_cost[p3] == [-10, -10]
|
||||
|
||||
plant = location_name_to_plant["L3"]
|
||||
@test plant.location_name == "L3"
|
||||
@test plant.input.name == "P2"
|
||||
@test plant.latitude == 25
|
||||
@test plant.longitude == 65
|
||||
|
||||
@test length(plant.sizes) == 2
|
||||
@test plant.sizes[1].capacity == 1000.0
|
||||
@test plant.sizes[1].opening_cost == [3000, 3000]
|
||||
@test plant.sizes[1].fixed_operating_cost == [50, 50]
|
||||
@test plant.sizes[1].variable_operating_cost == [50, 50]
|
||||
@test plant.sizes[1] == plant.sizes[2]
|
||||
|
||||
p4 = product_name_to_product["P4"]
|
||||
@test plant.output[p3] == 0.05
|
||||
@test plant.output[p4] == 0.8
|
||||
@test plant.disposal_limit[p3] == [1e8, 1e8]
|
||||
@test plant.disposal_limit[p4] == [0, 0]
|
||||
end
|
||||
|
||||
@testset "parse (geodb)" begin
|
||||
instance = RELOG.parsefile(fixture("s2.json"))
|
||||
centers = instance.collection_centers
|
||||
@test centers[1].name == "C1"
|
||||
@test centers[1].latitude == 41.83956
|
||||
@test centers[1].longitude == -88.08857
|
||||
end
|
||||
end
|
@ -0,0 +1,40 @@
|
||||
# Copyright (C) 2020 Argonne National Laboratory
|
||||
# Written by Alinson Santos Xavier <axavier@anl.gov>
|
||||
|
||||
using RELOG, Cbc, JuMP, Printf, JSON, MathOptInterface.FileFormats
|
||||
|
||||
function model_build_test()
|
||||
@testset "build" begin
|
||||
instance = RELOG.parsefile(fixture("s1.json"))
|
||||
graph = RELOG.build_graph(instance)
|
||||
model = RELOG.build_model(instance, graph, Cbc.Optimizer)
|
||||
set_optimizer_attribute(model, "logLevel", 0)
|
||||
|
||||
process_node_by_location_name =
|
||||
Dict(n.location.location_name => n for n in graph.process_nodes)
|
||||
|
||||
shipping_node_by_loc_and_prod_names = Dict(
|
||||
(n.location.location_name, n.product.name) => n for
|
||||
n in graph.plant_shipping_nodes
|
||||
)
|
||||
|
||||
@test length(model[:flow]) == 76
|
||||
@test length(model[:plant_dispose]) == 16
|
||||
@test length(model[:open_plant]) == 12
|
||||
@test length(model[:capacity]) == 12
|
||||
@test length(model[:expansion]) == 12
|
||||
|
||||
l1 = process_node_by_location_name["L1"]
|
||||
v = model[:capacity][l1, 1]
|
||||
@test lower_bound(v) == 0.0
|
||||
@test upper_bound(v) == 1000.0
|
||||
|
||||
v = model[:expansion][l1, 1]
|
||||
@test lower_bound(v) == 0.0
|
||||
@test upper_bound(v) == 750.0
|
||||
|
||||
v = model[:plant_dispose][shipping_node_by_loc_and_prod_names["L1", "P2"], 1]
|
||||
@test lower_bound(v) == 0.0
|
||||
@test upper_bound(v) == 1.0
|
||||
end
|
||||
end
|
@ -0,0 +1,13 @@
|
||||
# Copyright (C) 2020 Argonne National Laboratory
|
||||
# Written by Alinson Santos Xavier <axavier@anl.gov>
|
||||
|
||||
using RELOG
|
||||
|
||||
function model_resolve_test()
|
||||
@testset "Resolve" begin
|
||||
# Shoud not crash
|
||||
filename = fixture("s1.json")
|
||||
solution_old, model_old = RELOG.solve(filename, return_model = true)
|
||||
solution_new = RELOG.resolve(model_old, filename)
|
||||
end
|
||||
end
|
@ -0,0 +1,70 @@
|
||||
# Copyright (C) 2020 Argonne National Laboratory
|
||||
# Written by Alinson Santos Xavier <axavier@anl.gov>
|
||||
|
||||
using RELOG, Cbc, JuMP, Printf, JSON, MathOptInterface.FileFormats
|
||||
|
||||
|
||||
function model_solve_test()
|
||||
@testset "solve (exact)" begin
|
||||
solution_filename_a = tempname()
|
||||
solution_filename_b = tempname()
|
||||
solution = RELOG.solve(fixture("s1.json"), output = solution_filename_a)
|
||||
|
||||
@test isfile(solution_filename_a)
|
||||
|
||||
RELOG.write(solution, solution_filename_b)
|
||||
@test isfile(solution_filename_b)
|
||||
|
||||
@test "Costs" in keys(solution)
|
||||
@test "Fixed operating (\$)" in keys(solution["Costs"])
|
||||
@test "Transportation (\$)" in keys(solution["Costs"])
|
||||
@test "Variable operating (\$)" in keys(solution["Costs"])
|
||||
@test "Total (\$)" in keys(solution["Costs"])
|
||||
|
||||
@test "Plants" in keys(solution)
|
||||
@test "F1" in keys(solution["Plants"])
|
||||
@test "F2" in keys(solution["Plants"])
|
||||
@test "F3" in keys(solution["Plants"])
|
||||
@test "F4" in keys(solution["Plants"])
|
||||
|
||||
@test "Products" in keys(solution)
|
||||
@test "P1" in keys(solution["Products"])
|
||||
@test "C1" in keys(solution["Products"]["P1"])
|
||||
@test "Dispose (tonne)" in keys(solution["Products"]["P1"]["C1"])
|
||||
|
||||
total_disposal =
|
||||
sum([loc["Dispose (tonne)"] for loc in values(solution["Products"]["P1"])])
|
||||
@test total_disposal == [1.0, 1.0]
|
||||
end
|
||||
|
||||
@testset "solve (heuristic)" begin
|
||||
# Should not crash
|
||||
solution = RELOG.solve(fixture("s1.json"), heuristic = true)
|
||||
end
|
||||
|
||||
@testset "solve (infeasible)" begin
|
||||
json = JSON.parsefile(fixture("s1.json"))
|
||||
for (location_name, location_dict) in json["products"]["P1"]["initial amounts"]
|
||||
location_dict["amount (tonne)"] *= 1000
|
||||
end
|
||||
@test_throws ErrorException("No solution available") RELOG.solve(RELOG.parse(json))
|
||||
end
|
||||
|
||||
@testset "solve (with storage)" begin
|
||||
filename = fixture("storage.json")
|
||||
instance = RELOG.parsefile(filename)
|
||||
@test instance.plants[1].storage_limit == 50.0
|
||||
@test instance.plants[1].storage_cost == [2.0, 1.5, 1.0]
|
||||
|
||||
solution = RELOG.solve(filename)
|
||||
plant_dict = solution["Plants"]["mega plant"]["Chicago"]
|
||||
@test plant_dict["Variable operating cost (\$)"] == [500.0, 0.0, 100.0]
|
||||
@test plant_dict["Process (tonne)"] == [50.0, 0.0, 50.0]
|
||||
@test plant_dict["Storage (tonne)"] == [50.0, 50.0, 0.0]
|
||||
@test plant_dict["Storage cost (\$)"] == [100.0, 75.0, 0.0]
|
||||
|
||||
@test solution["Costs"]["Variable operating (\$)"] == [500.0, 0.0, 100.0]
|
||||
@test solution["Costs"]["Storage (\$)"] == [100.0, 75.0, 0.0]
|
||||
@test solution["Costs"]["Total (\$)"] == [600.0, 75.0, 100.0]
|
||||
end
|
||||
end
|
@ -0,0 +1,21 @@
|
||||
# RELOG: Reverse Logistics Optimization
|
||||
# Copyright (C) 2020, UChicago Argonne, LLC. All rights reserved.
|
||||
# Released under the modified BSD license. See COPYING.md for more details.
|
||||
|
||||
using RELOG, JSON, GZip
|
||||
|
||||
function reports_test()
|
||||
@testset "reports" begin
|
||||
@testset "from solve" begin
|
||||
solution = RELOG.solve(fixture("s1.json"))
|
||||
tmp_filename = tempname()
|
||||
# The following should not crash
|
||||
RELOG.write_plant_emissions_report(solution, tmp_filename)
|
||||
RELOG.write_plant_outputs_report(solution, tmp_filename)
|
||||
RELOG.write_plants_report(solution, tmp_filename)
|
||||
RELOG.write_products_report(solution, tmp_filename)
|
||||
RELOG.write_transportation_emissions_report(solution, tmp_filename)
|
||||
RELOG.write_transportation_report(solution, tmp_filename)
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in new issue