Model: Objective function and plant constraints

This commit is contained in:
2023-12-06 11:50:03 -06:00
parent 0da66b571a
commit d41ff30326
10 changed files with 273 additions and 32 deletions

View File

@@ -68,32 +68,32 @@
}
},
"C2": {
"latitude (deg)": 41.881,
"latitude (deg)": 42.881,
"longitude (deg)": -87.623,
"input": null,
"outputs": ["P4"],
"outputs": ["P1"],
"variable output (tonne/tonne)": {
"P4": 0
"P1": 0
},
"fixed output (tonne)": {
"P4": [50, 60, 70, 80]
"P1": [50, 60, 70, 80]
},
"revenue ($/tonne)": null,
"collection cost ($/tonne)": {
"P4": 0.25
"P1": 0.25
},
"operating cost ($)": [150.0, 150.0, 150.0, 150.0],
"disposal limit (tonne)": {
"P4": null
"P1": null
},
"disposal cost ($/tonne)": {
"P4": 0
"P1": 0
}
},
"C3": {
"latitude (deg)": 41.881,
"latitude (deg)": 43.881,
"longitude (deg)": -87.623,
"input": "P1",
"input": "P4",
"outputs": [],
"variable output (tonne/tonne)": {},
"constant output (tonne)": {},
@@ -106,7 +106,7 @@
},
"plants": {
"L1": {
"latitude (deg)": 41.881,
"latitude (deg)": 44.881,
"longitude (deg)": -87.623,
"input mix (%)": {
"P1": 95.3,
@@ -138,7 +138,7 @@
"capacities": [
{
"size (tonne)": 100,
"opening cost ($)": 500,
"opening cost ($)": [300, 400, 450, 475],
"fixed operating cost ($)": 300,
"variable operating cost ($/tonne)": 5.0
},
@@ -149,7 +149,7 @@
"variable operating cost ($/tonne)": 5.0
}
],
"initial capacity (tonne)": 150
"initial capacity (tonne)": 0
}
}
}

View File

@@ -6,6 +6,7 @@ using JuliaFormatter
include("instance/parse_test.jl")
include("model/build_test.jl")
include("model/dist_test.jl")
basedir = dirname(@__FILE__)
@@ -18,6 +19,7 @@ function runtests()
instance_parse_test_1()
instance_parse_test_2()
model_build_test()
model_dist_test()
end
end

View File

@@ -45,7 +45,7 @@ function instance_parse_test_1()
# Plants
@test length(instance.plants) == 1
l1 = instance.plants[1]
@test l1.latitude == 41.881
@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])
@@ -56,11 +56,11 @@ function instance_parse_test_1()
@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 == 150
@test l1.initial_capacity == 0
@test length(l1.capacities) == 2
c1 = l1.capacities[1]
@test c1.size == 100
@test c1.opening_cost == [500, 500, 500, 500]
@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]
@@ -74,4 +74,4 @@ end
function instance_parse_test_2()
# Should not crash
RELOG.parsefile(fixture("boat_example.json"))
end
end

View File

@@ -5,6 +5,79 @@ using JuMP
function model_build_test()
instance = RELOG.parsefile(fixture("simple.json"))
model = RELOG.build_model(instance, optimizer=HiGHS.Optimizer, variable_names=true)
print(model)
end
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)
# print(model)
@test obj.terms[y["L1", "C3", "P4", 1]] == (
111.118 + # transportation
12.0 # revenue
)
@test obj.terms[y["C1", "L1", "P2", 4]] == (
333.262 + # 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"
end

View File

@@ -0,0 +1,10 @@
# 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