Update input schema, example input file and parser

gh-actions
Alinson S. Xavier 5 years ago
parent 8b3f3206eb
commit 4a9266a1bf
No known key found for this signature in database
GPG Key ID: A796166E4E218E02

@ -1,188 +1,198 @@
{ {
"Parameters": { "parameters": {
"Time horizon (years)": 2 "time horizon (years)": 2
}, },
"Products": { "products": {
"P1": { "P1": {
"Transportation cost ($/km/tonne)": [0.015, 0.015], "transportation cost ($/km/tonne)": [0.015, 0.015],
"Initial amounts": { "transportation energy (J/km/tonne)": [0.12, 0.11],
"transportation emissions (tonne/km/tonne)": {
"CO2": [0.052, 0.050],
"CH4": [0.003, 0.002]
},
"initial amounts": {
"C1": { "C1": {
"Latitude (deg)": 7.0, "latitude (deg)": 7.0,
"Longitude (deg)": 7.0, "longitude (deg)": 7.0,
"Amount (tonne)": [934.56, 934.56] "amount (tonne)": [934.56, 934.56]
}, },
"C2": { "C2": {
"Latitude (deg)": 7.0, "latitude (deg)": 7.0,
"Longitude (deg)": 19.0, "longitude (deg)": 19.0,
"Amount (tonne)": [198.95, 198.95] "amount (tonne)": [198.95, 198.95]
}, },
"C3": { "C3": {
"Latitude (deg)": 84.0, "latitude (deg)": 84.0,
"Longitude (deg)": 76.0, "longitude (deg)": 76.0,
"Amount (tonne)": [212.97, 212.97] "amount (tonne)": [212.97, 212.97]
}, },
"C4": { "C4": {
"Latitude (deg)": 21.0, "latitude (deg)": 21.0,
"Longitude (deg)": 16.0, "longitude (deg)": 16.0,
"Amount (tonne)": [352.19, 352.19] "amount (tonne)": [352.19, 352.19]
}, },
"C5": { "C5": {
"Latitude (deg)": 32.0, "latitude (deg)": 32.0,
"Longitude (deg)": 92.0, "longitude (deg)": 92.0,
"Amount (tonne)": [510.33, 510.33] "amount (tonne)": [510.33, 510.33]
}, },
"C6": { "C6": {
"Latitude (deg)": 14.0, "latitude (deg)": 14.0,
"Longitude (deg)": 62.0, "longitude (deg)": 62.0,
"Amount (tonne)": [471.66, 471.66] "amount (tonne)": [471.66, 471.66]
}, },
"C7": { "C7": {
"Latitude (deg)": 30.0, "latitude (deg)": 30.0,
"Longitude (deg)": 83.0, "longitude (deg)": 83.0,
"Amount (tonne)": [785.21, 785.21] "amount (tonne)": [785.21, 785.21]
}, },
"C8": { "C8": {
"Latitude (deg)": 35.0, "latitude (deg)": 35.0,
"Longitude (deg)": 40.0, "longitude (deg)": 40.0,
"Amount (tonne)": [706.17, 706.17] "amount (tonne)": [706.17, 706.17]
}, },
"C9": { "C9": {
"Latitude (deg)": 74.0, "latitude (deg)": 74.0,
"Longitude (deg)": 52.0, "longitude (deg)": 52.0,
"Amount (tonne)": [30.08, 30.08] "amount (tonne)": [30.08, 30.08]
}, },
"C10": { "C10": {
"Latitude (deg)": 22.0, "latitude (deg)": 22.0,
"Longitude (deg)": 54.0, "longitude (deg)": 54.0,
"Amount (tonne)": [536.52, 536.52] "amount (tonne)": [536.52, 536.52]
} }
} }
}, },
"P2": { "P2": {
"Transportation cost ($/km/tonne)": [0.02, 0.02] "transportation cost ($/km/tonne)": [0.02, 0.02]
}, },
"P3": { "P3": {
"Transportation cost ($/km/tonne)": [0.0125, 0.0125] "transportation cost ($/km/tonne)": [0.0125, 0.0125]
}, },
"P4": { "P4": {
"Transportation cost ($/km/tonne)": [0.0175, 0.0175] "transportation cost ($/km/tonne)": [0.0175, 0.0175]
} }
}, },
"Plants": { "plants": {
"F1": { "F1": {
"Input": "P1", "input": "P1",
"Outputs (tonne)": { "outputs (tonne/tonne)": {
"P2": 0.2, "P2": 0.2,
"P3": 0.5 "P3": 0.5
}, },
"Locations": { "energy (GJ/tonne)": [0.12, 0.11],
"emissions (tonne/tonne)": {
"CO2": [0.052, 0.050],
"CH4": [0.003, 0.002]
},
"locations": {
"L1": { "L1": {
"Latitude (deg)": 0.0, "latitude (deg)": 0.0,
"Longitude (deg)": 0.0, "longitude (deg)": 0.0,
"Disposal": { "disposal": {
"P2": { "P2": {
"Cost ($/tonne)": [-10.0, -10.0], "cost ($/tonne)": [-10.0, -10.0],
"Limit (tonne)": [1.0, 1.0] "limit (tonne)": [1.0, 1.0]
}, },
"P3": { "P3": {
"Cost ($/tonne)": [-10.0, -10.0], "cost ($/tonne)": [-10.0, -10.0],
"Limit (tonne)": [1.0, 1.0] "limit (tonne)": [1.0, 1.0]
} }
}, },
"Capacities (tonne)": { "capacities (tonne)": {
"250.0": { "250.0": {
"Opening cost ($)": [500.0, 500.0], "opening cost ($)": [500.0, 500.0],
"Fixed operating cost ($)": [30.0, 30.0], "fixed operating cost ($)": [30.0, 30.0],
"Variable operating cost ($/tonne)": [30.0, 30.0] "variable operating cost ($/tonne)": [30.0, 30.0]
}, },
"1000.0": { "1000.0": {
"Opening cost ($)": [1250.0, 1250.0], "opening cost ($)": [1250.0, 1250.0],
"Fixed operating cost ($)": [30.0, 30.0], "fixed operating cost ($)": [30.0, 30.0],
"Variable operating cost ($/tonne)": [30.0, 30.0] "variable operating cost ($/tonne)": [30.0, 30.0]
} }
} }
}, },
"L2": { "L2": {
"Latitude (deg)": 0.5, "latitude (deg)": 0.5,
"Longitude (deg)": 0.5, "longitude (deg)": 0.5,
"Capacities (tonne)": { "capacities (tonne)": {
"0.0": { "0.0": {
"Opening cost ($)": [1000, 1000], "opening cost ($)": [1000, 1000],
"Fixed operating cost ($)": [50.0, 50.0], "fixed operating cost ($)": [50.0, 50.0],
"Variable operating cost ($/tonne)": [50.0, 50.0] "variable operating cost ($/tonne)": [50.0, 50.0]
}, },
"10000.0": { "10000.0": {
"Opening cost ($)": [10000, 10000], "opening cost ($)": [10000, 10000],
"Fixed operating cost ($)": [50.0, 50.0], "fixed operating cost ($)": [50.0, 50.0],
"Variable operating cost ($/tonne)": [50.0, 50.0] "variable operating cost ($/tonne)": [50.0, 50.0]
} }
} }
} }
} }
}, },
"F2": { "F2": {
"Input": "P2", "input": "P2",
"Outputs (tonne)": { "outputs (tonne/tonne)": {
"P3": 0.05, "P3": 0.05,
"P4": 0.80 "P4": 0.80
}, },
"Locations": { "locations": {
"L3": { "L3": {
"Latitude (deg)": 25.0, "latitude (deg)": 25.0,
"Longitude (deg)": 65.0, "longitude (deg)": 65.0,
"Disposal": { "disposal": {
"P3": { "P3": {
"Cost ($/tonne)": [100.0, 100.0] "cost ($/tonne)": [100.0, 100.0]
} }
}, },
"Capacities (tonne)": { "capacities (tonne)": {
"1000.0": { "1000.0": {
"Opening cost ($)": [3000, 3000], "opening cost ($)": [3000, 3000],
"Fixed operating cost ($)": [50.0, 50.0], "fixed operating cost ($)": [50.0, 50.0],
"Variable operating cost ($/tonne)": [50.0, 50.0] "variable operating cost ($/tonne)": [50.0, 50.0]
} }
} }
}, },
"L4": { "L4": {
"Latitude (deg)": 0.75, "latitude (deg)": 0.75,
"Longitude (deg)": 0.20, "longitude (deg)": 0.20,
"Capacities (tonne)": { "capacities (tonne)": {
"10000": { "10000": {
"Opening cost ($)": [3000, 3000], "opening cost ($)": [3000, 3000],
"Fixed operating cost ($)": [50.0, 50.0], "fixed operating cost ($)": [50.0, 50.0],
"Variable operating cost ($/tonne)": [50.0, 50.0] "variable operating cost ($/tonne)": [50.0, 50.0]
} }
} }
} }
} }
}, },
"F3": { "F3": {
"Input": "P4", "input": "P4",
"Locations": { "locations": {
"L5": { "L5": {
"Latitude (deg)": 100.0, "latitude (deg)": 100.0,
"Longitude (deg)": 100.0, "longitude (deg)": 100.0,
"Capacities (tonne)": { "capacities (tonne)": {
"15000": { "15000": {
"Opening cost ($)": [0.0, 0.0], "opening cost ($)": [0.0, 0.0],
"Fixed operating cost ($)": [0.0, 0.0], "fixed operating cost ($)": [0.0, 0.0],
"Variable operating cost ($/tonne)": [-15.0, -15.0] "variable operating cost ($/tonne)": [-15.0, -15.0]
} }
} }
} }
} }
}, },
"F4": { "F4": {
"Input": "P3", "input": "P3",
"Locations": { "locations": {
"L6": { "L6": {
"Latitude (deg)": 50.0, "latitude (deg)": 50.0,
"Longitude (deg)": 50.0, "longitude (deg)": 50.0,
"Capacities (tonne)": { "capacities (tonne)": {
"10000": { "10000": {
"Opening cost ($)": [0.0, 0.0], "opening cost ($)": [0.0, 0.0],
"Fixed operating cost ($)": [0.0, 0.0], "fixed operating cost ($)": [0.0, 0.0],
"Variable operating cost ($/tonne)": [-15.0, -15.0] "variable operating cost ($/tonne)": [-15.0, -15.0]
} }
} }
} }

@ -70,67 +70,67 @@ function load(path::String)::Instance
throw(msg) throw(msg)
end end
T = json["Parameters"]["Time horizon (years)"] T = json["parameters"]["time horizon (years)"]
plants = Plant[] plants = Plant[]
products = Product[] products = Product[]
collection_centers = CollectionCenter[] collection_centers = CollectionCenter[]
prod_name_to_product = Dict{String, Product}() prod_name_to_product = Dict{String, Product}()
# Create products # Create products
for (product_name, product_dict) in json["Products"] for (product_name, product_dict) in json["products"]
product = Product(product_name, product_dict["Transportation cost (\$/km/tonne)"]) product = Product(product_name, product_dict["transportation cost (\$/km/tonne)"])
push!(products, product) push!(products, product)
prod_name_to_product[product_name] = product prod_name_to_product[product_name] = product
# Create collection centers # Create collection centers
if "Initial amounts" in keys(product_dict) if "initial amounts" in keys(product_dict)
for (center_name, center_dict) in product_dict["Initial amounts"] for (center_name, center_dict) in product_dict["initial amounts"]
center = CollectionCenter(length(collection_centers) + 1, center = CollectionCenter(length(collection_centers) + 1,
center_name, center_name,
center_dict["Latitude (deg)"], center_dict["latitude (deg)"],
center_dict["Longitude (deg)"], center_dict["longitude (deg)"],
product, product,
center_dict["Amount (tonne)"]) center_dict["amount (tonne)"])
push!(collection_centers, center) push!(collection_centers, center)
end end
end end
end end
# Create plants # Create plants
for (plant_name, plant_dict) in json["Plants"] for (plant_name, plant_dict) in json["plants"]
input = prod_name_to_product[plant_dict["Input"]] input = prod_name_to_product[plant_dict["input"]]
output = Dict() output = Dict()
# Plant outputs # Plant outputs
if "Outputs (tonne)" in keys(plant_dict) if "outputs (tonne/tonne)" in keys(plant_dict)
output = Dict(prod_name_to_product[key] => value output = Dict(prod_name_to_product[key] => value
for (key, value) in plant_dict["Outputs (tonne)"] for (key, value) in plant_dict["outputs (tonne/tonne)"]
if value > 0) if value > 0)
end end
for (location_name, location_dict) in plant_dict["Locations"] for (location_name, location_dict) in plant_dict["locations"]
sizes = PlantSize[] sizes = PlantSize[]
disposal_limit = Dict(p => [0.0 for t in 1:T] for p in keys(output)) disposal_limit = Dict(p => [0.0 for t in 1:T] for p in keys(output))
disposal_cost = Dict(p => [0.0 for t in 1:T] for p in keys(output)) disposal_cost = Dict(p => [0.0 for t in 1:T] for p in keys(output))
# Disposal # Disposal
if "Disposal" in keys(location_dict) if "disposal" in keys(location_dict)
for (product_name, disposal_dict) in location_dict["Disposal"] for (product_name, disposal_dict) in location_dict["disposal"]
limit = [1e8 for t in 1:T] limit = [1e8 for t in 1:T]
if "Limit (tonne)" in keys(disposal_dict) if "limit (tonne)" in keys(disposal_dict)
limit = disposal_dict["Limit (tonne)"] limit = disposal_dict["limit (tonne)"]
end end
disposal_limit[prod_name_to_product[product_name]] = limit disposal_limit[prod_name_to_product[product_name]] = limit
disposal_cost[prod_name_to_product[product_name]] = disposal_dict["Cost (\$/tonne)"] disposal_cost[prod_name_to_product[product_name]] = disposal_dict["cost (\$/tonne)"]
end end
end end
# Capacities # Capacities
for (capacity_name, capacity_dict) in location_dict["Capacities (tonne)"] for (capacity_name, capacity_dict) in location_dict["capacities (tonne)"]
push!(sizes, PlantSize(parse(Float64, capacity_name), push!(sizes, PlantSize(parse(Float64, capacity_name),
capacity_dict["Variable operating cost (\$/tonne)"], capacity_dict["variable operating cost (\$/tonne)"],
capacity_dict["Fixed operating cost (\$)"], capacity_dict["fixed operating cost (\$)"],
capacity_dict["Opening cost (\$)"])) capacity_dict["opening cost (\$)"]))
end end
length(sizes) > 1 || push!(sizes, sizes[1]) length(sizes) > 1 || push!(sizes, sizes[1])
sort!(sizes, by = x -> x.capacity) sort!(sizes, by = x -> x.capacity)
@ -148,8 +148,8 @@ function load(path::String)::Instance
location_name, location_name,
input, input,
output, output,
location_dict["Latitude (deg)"], location_dict["latitude (deg)"],
location_dict["Longitude (deg)"], location_dict["longitude (deg)"],
disposal_limit, disposal_limit,
disposal_cost, disposal_cost,
sizes) sizes)

@ -20,7 +20,6 @@ function build_model(instance::Instance, graph::Graph, optimizer)::Manufacturing
create_objective_function!(model) create_objective_function!(model)
create_shipping_node_constraints!(model) create_shipping_node_constraints!(model)
create_process_node_constraints!(model) create_process_node_constraints!(model)
JuMP.write_to_file(model.mip, "model.lp")
return model return model
end end
@ -194,7 +193,7 @@ function create_process_node_constraints!(model::ManufacturingModel)
end end
end end
function solve(filename::String; optimizer=Cbc.Optimizer, lp_optimizer=Clp.Optimizer) function solve(filename::String; milp_optimizer=Cbc.Optimizer, lp_optimizer=Clp.Optimizer)
println("Reading $filename...") println("Reading $filename...")
instance = RELOG.load(filename) instance = RELOG.load(filename)
@ -202,7 +201,7 @@ function solve(filename::String; optimizer=Cbc.Optimizer, lp_optimizer=Clp.Optim
graph = RELOG.build_graph(instance) graph = RELOG.build_graph(instance)
println("Building optimization model...") println("Building optimization model...")
model = RELOG.build_model(instance, graph, optimizer) model = RELOG.build_model(instance, graph, milp_optimizer)
println("Optimizing MILP...") println("Optimizing MILP...")
JuMP.optimize!(model.mip) JuMP.optimize!(model.mip)

@ -12,10 +12,10 @@
"Parameters": { "Parameters": {
"type": "object", "type": "object",
"properties": { "properties": {
"Time horizon (years)": { "type": "number" } "time horizon (years)": { "type": "number" }
}, },
"required": [ "required": [
"Time horizon (years)" "time horizon (years)"
] ]
}, },
"Plant": { "Plant": {
@ -23,16 +23,21 @@
"additionalProperties": { "additionalProperties": {
"type": "object", "type": "object",
"properties": { "properties": {
"Input": { "type": "string" }, "input": { "type": "string" },
"Outputs (tonne)": { "outputs (tonne/tonne)": {
"type": "object", "type": "object",
"additionalProperties": { "type": "number" } "additionalProperties": { "type": "number" }
}, },
"Locations": { "$ref": "#/definitions/PlantLocation" } "energy (GJ/tonne)": { "$ref": "#/definitions/TimeSeries" },
"emissions (tonne/tonne)": {
"type": "object",
"additionalProperties": { "$ref": "#/definitions/TimeSeries" }
},
"locations": { "$ref": "#/definitions/PlantLocation" }
}, },
"required": [ "required": [
"Input", "input",
"Locations" "locations"
] ]
} }
}, },
@ -41,42 +46,42 @@
"additionalProperties": { "additionalProperties": {
"type": "object", "type": "object",
"properties": { "properties": {
"Latitude (deg)": { "type": "number" }, "latitude (deg)": { "type": "number" },
"Longitude (deg)": { "type": "number" }, "longitude (deg)": { "type": "number" },
"Disposal": { "disposal": {
"type": "object", "type": "object",
"additionalProperties": { "additionalProperties": {
"type": "object", "type": "object",
"properties": { "properties": {
"Cost ($/tonne)": { "$ref": "#/definitions/TimeSeries" }, "cost ($/tonne)": { "$ref": "#/definitions/TimeSeries" },
"Limit (tonne)": { "$ref": "#/definitions/TimeSeries" } "limit (tonne)": { "$ref": "#/definitions/TimeSeries" }
}, },
"required": [ "required": [
"Cost ($/tonne)" "cost ($/tonne)"
] ]
} }
}, },
"Capacities (tonne)": { "capacities (tonne)": {
"type": "object", "type": "object",
"additionalProperties": { "additionalProperties": {
"type": "object", "type": "object",
"properties": { "properties": {
"Variable operating cost ($/tonne)": { "$ref": "#/definitions/TimeSeries" }, "variable operating cost ($/tonne)": { "$ref": "#/definitions/TimeSeries" },
"Fixed operating cost ($)": { "$ref": "#/definitions/TimeSeries" }, "fixed operating cost ($)": { "$ref": "#/definitions/TimeSeries" },
"Opening cost ($)": { "$ref": "#/definitions/TimeSeries" } "opening cost ($)": { "$ref": "#/definitions/TimeSeries" }
}, },
"required": [ "required": [
"Variable operating cost ($/tonne)", "variable operating cost ($/tonne)",
"Fixed operating cost ($)", "fixed operating cost ($)",
"Opening cost ($)" "opening cost ($)"
] ]
} }
} }
}, },
"required": [ "required": [
"Latitude (deg)", "latitude (deg)",
"Longitude (deg)", "longitude (deg)",
"Capacities (tonne)" "capacities (tonne)"
] ]
} }
}, },
@ -85,14 +90,14 @@
"additionalProperties": { "additionalProperties": {
"type": "object", "type": "object",
"properties": { "properties": {
"Latitude (deg)": { "type": "number" }, "latitude (deg)": { "type": "number" },
"Longitude (deg)": { "type": "number" }, "longitude (deg)": { "type": "number" },
"Amount (tonne)": { "$ref": "#/definitions/TimeSeries" } "amount (tonne)": { "$ref": "#/definitions/TimeSeries" }
}, },
"required": [ "required": [
"Latitude (deg)", "latitude (deg)",
"Longitude (deg)", "longitude (deg)",
"Amount (tonne)" "amount (tonne)"
] ]
} }
}, },
@ -101,24 +106,29 @@
"additionalProperties": { "additionalProperties": {
"type": "object", "type": "object",
"properties": { "properties": {
"Transportation cost ($/km/tonne)": { "$ref": "#/definitions/TimeSeries" }, "transportation cost ($/km/tonne)": { "$ref": "#/definitions/TimeSeries" },
"Initial amounts": { "$ref": "#/definitions/InitialAmount" } "transportation energy (J/km/tonne)": { "$ref": "#/definitions/TimeSeries" },
"transportation emissions (tonne/km/tonne)": {
"type": "object",
"additionalProperties": { "$ref": "#/definitions/TimeSeries" }
},
"initial amounts": { "$ref": "#/definitions/InitialAmount" }
}, },
"required": [ "required": [
"Transportation cost ($/km/tonne)" "transportation cost ($/km/tonne)"
] ]
} }
} }
}, },
"type": "object", "type": "object",
"properties": { "properties": {
"Parameters": { "$ref": "#/definitions/Parameters" }, "parameters": { "$ref": "#/definitions/Parameters" },
"Plants": { "$ref": "#/definitions/Plant" }, "plants": { "$ref": "#/definitions/Plant" },
"Products": { "$ref": "#/definitions/Product" } "products": { "$ref": "#/definitions/Product" }
}, },
"required": [ "required": [
"Parameters", "parameters",
"Plants", "plants",
"Products" "products"
] ]
} }

@ -36,9 +36,9 @@ using RELOG, Cbc, JuMP, Printf, JSON, MathOptInterface.FileFormats
@test lower_bound(v) == 0.0 @test lower_bound(v) == 0.0
@test upper_bound(v) == 1.0 @test upper_bound(v) == 1.0
dest = FileFormats.Model(format = FileFormats.FORMAT_LP) #dest = FileFormats.Model(format = FileFormats.FORMAT_LP)
MOI.copy_to(dest, model.mip) #MOI.copy_to(dest, model.mip)
MOI.write_to_file(dest, "model.lp") #MOI.write_to_file(dest, "model.lp")
end end
@testset "solve" begin @testset "solve" begin

Loading…
Cancel
Save