From 08d9b26a19384ca0558226fdf03a79f40f65b673 Mon Sep 17 00:00:00 2001 From: Alinson S Xavier Date: Fri, 6 Mar 2020 11:44:08 -0600 Subject: [PATCH] Update output format --- instances/samples/s2_solution.json | 434 +++++++++++++++++++++-------- src/model.jl | 94 +++++-- test/model_test.jl | 34 +-- 3 files changed, 390 insertions(+), 172 deletions(-) diff --git a/instances/samples/s2_solution.json b/instances/samples/s2_solution.json index 34c4279..033f351 100644 --- a/instances/samples/s2_solution.json +++ b/instances/samples/s2_solution.json @@ -1,137 +1,337 @@ { "plants": { - "Disassembly Plant (Darien)": { - "total output": { - "lead": 138000.0, - "plastic casings": 11500.0 - }, - "fixed cost": 11000.0, - "output": { - "lead": { - "Lead Recycling Plant (Milwaukee)": 138000.0 + "Lead Recycling Plant": { + "Milwaukee": { + "total output": { + "lead ingots": 189000.0 + }, + "latitude": 43.05, + "fixed cost": 11000.0, + "output": { + "lead ingots": { + "Lead Sales Point": { + "Milwaukee": 189000.0 + } + } + }, + "longitude": -87.95, + "total input": 210000.0, + "transportation costs": { + "Disassembly Plant": { + "Greendale": { + "latitude": 42.9375, + "cost": 1411.56, + "distance": 13.07, + "longitude": -87.996944 + }, + "Darien": { + "latitude": 41.745556, + "cost": 29998.44, + "distance": 144.92, + "longitude": -87.981111 + } + } }, - "plastic casings": { - "Plastic Recycling Plant (Milwaukee)": 11500.0 + "variable costs": { + "Disassembly Plant": { + "Greendale": { + "latitude": 42.9375, + "cost": 14400.0, + "longitude": -87.996944 + }, + "Darien": { + "latitude": 41.745556, + "cost": 27600.0, + "longitude": -87.981111 + } + } + }, + "input": { + "Disassembly Plant": { + "Greendale": { + "amount": 72000.0, + "latitude": 42.9375, + "longitude": -87.996944 + }, + "Darien": { + "amount": 138000.0, + "latitude": 41.745556, + "longitude": -87.981111 + } + } } - }, - "total input": 230000.0, - "transportation costs": { - "Origin (Westmont)": 204.0, - "Origin (Darien)": 0.0, - "Origin (Chicago)": 8673.0 - }, - "variable costs": { - "Origin (Westmont)": 3000.0, - "Origin (Darien)": 3600.0, - "Origin (Chicago)": 21000.0 - }, - "input": { - "Origin (Westmont)": 25000.0, - "Origin (Darien)": 30000.0, - "Origin (Chicago)": 175000.0 - } - }, - "Plastic Sales Point (Milwaukee)": { - "total output": {}, - "fixed cost": 0.0, - "output": {}, - "total input": 15750.0, - "transportation costs": { - "Plastic Recycling Plant (Milwaukee)": 0.0 - }, - "variable costs": { - "Plastic Recycling Plant (Milwaukee)": -9765.0 - }, - "input": { - "Plastic Recycling Plant (Milwaukee)": 15750.0 } }, - "Lead Recycling Plant (Milwaukee)": { - "total output": { - "lead ingots": 189000.0 - }, - "fixed cost": 11000.0, - "output": { - "lead ingots": { - "Lead Sales Point (Milwaukee)": 189000.0 + "Disassembly Plant": { + "Greendale": { + "total output": { + "lead": 72000.0, + "plastic casings": 6000.0 + }, + "latitude": 42.9375, + "fixed cost": 11000.0, + "output": { + "lead": { + "Lead Recycling Plant": { + "Milwaukee": 72000.0 + } + }, + "plastic casings": { + "Plastic Recycling Plant": { + "Milwaukee": 6000.0 + } + } + }, + "longitude": -87.996944, + "total input": 120000.0, + "transportation costs": { + "Origin": { + "Milwaukee": { + "latitude": 43.05, + "cost": 2352.6, + "distance": 13.07, + "longitude": -87.95 + } + } + }, + "variable costs": { + "Origin": { + "Milwaukee": { + "latitude": 43.05, + "cost": 21600.0, + "longitude": -87.95 + } + } + }, + "input": { + "Origin": { + "Milwaukee": { + "amount": 120000.0, + "latitude": 43.05, + "longitude": -87.95 + } + } } }, - "total input": 210000.0, - "transportation costs": { - "Disassembly Plant (Darien)": 29998.44, - "Disassembly Plant (Greendale)": 1411.56 - }, - "variable costs": { - "Disassembly Plant (Darien)": 27600.0, - "Disassembly Plant (Greendale)": 14400.0 - }, - "input": { - "Disassembly Plant (Darien)": 138000.0, - "Disassembly Plant (Greendale)": 72000.0 + "Darien": { + "total output": { + "lead": 138000.0, + "plastic casings": 11500.0 + }, + "latitude": 41.745556, + "fixed cost": 11000.0, + "output": { + "lead": { + "Lead Recycling Plant": { + "Milwaukee": 138000.0 + } + }, + "plastic casings": { + "Plastic Recycling Plant": { + "Milwaukee": 11500.0 + } + } + }, + "longitude": -87.981111, + "total input": 230000.0, + "transportation costs": { + "Origin": { + "Chicago": { + "latitude": 41.881944, + "cost": 8673.0, + "distance": 33.04, + "longitude": -87.627778 + }, + "Westmont": { + "latitude": 41.794444, + "cost": 204.0, + "distance": 5.44, + "longitude": -87.976389 + }, + "Darien": { + "latitude": 41.745556, + "cost": 0.0, + "distance": 0.0, + "longitude": -87.981111 + } + } + }, + "variable costs": { + "Origin": { + "Chicago": { + "latitude": 41.881944, + "cost": 21000.0, + "longitude": -87.627778 + }, + "Westmont": { + "latitude": 41.794444, + "cost": 3000.0, + "longitude": -87.976389 + }, + "Darien": { + "latitude": 41.745556, + "cost": 3600.0, + "longitude": -87.981111 + } + } + }, + "input": { + "Origin": { + "Chicago": { + "amount": 175000.0, + "latitude": 41.881944, + "longitude": -87.627778 + }, + "Westmont": { + "amount": 25000.0, + "latitude": 41.794444, + "longitude": -87.976389 + }, + "Darien": { + "amount": 30000.0, + "latitude": 41.745556, + "longitude": -87.981111 + } + } + } } }, - "Plastic Recycling Plant (Milwaukee)": { - "total output": { - "plastic pellets": 15750.0 - }, - "fixed cost": 11000.0, - "output": { - "plastic pellets": { - "Plastic Sales Point (Milwaukee)": 15750.0 + "Plastic Recycling Plant": { + "Milwaukee": { + "total output": { + "plastic pellets": 15750.0 + }, + "latitude": 43.05, + "fixed cost": 11000.0, + "output": { + "plastic pellets": { + "Plastic Sales Point": { + "Milwaukee": 15750.0 + } + } + }, + "longitude": -87.95, + "total input": 17500.0, + "transportation costs": { + "Disassembly Plant": { + "Greendale": { + "latitude": 42.9375, + "cost": 180.366, + "distance": 13.07, + "longitude": -87.996944 + }, + "Darien": { + "latitude": 41.745556, + "cost": 3833.134, + "distance": 144.92, + "longitude": -87.981111 + } + } + }, + "variable costs": { + "Disassembly Plant": { + "Greendale": { + "latitude": 42.9375, + "cost": 480.0, + "longitude": -87.996944 + }, + "Darien": { + "latitude": 41.745556, + "cost": 920.0, + "longitude": -87.981111 + } + } + }, + "input": { + "Disassembly Plant": { + "Greendale": { + "amount": 6000.0, + "latitude": 42.9375, + "longitude": -87.996944 + }, + "Darien": { + "amount": 11500.0, + "latitude": 41.745556, + "longitude": -87.981111 + } + } } - }, - "total input": 17500.0, - "transportation costs": { - "Disassembly Plant (Darien)": 3833.134, - "Disassembly Plant (Greendale)": 180.366 - }, - "variable costs": { - "Disassembly Plant (Darien)": 920.0, - "Disassembly Plant (Greendale)": 480.0 - }, - "input": { - "Disassembly Plant (Darien)": 11500.0, - "Disassembly Plant (Greendale)": 6000.0 } }, - "Lead Sales Point (Milwaukee)": { - "total output": {}, - "fixed cost": 0.0, - "output": {}, - "total input": 189000.0, - "transportation costs": { - "Lead Recycling Plant (Milwaukee)": 0.0 - }, - "variable costs": { - "Lead Recycling Plant (Milwaukee)": -519750.0 - }, - "input": { - "Lead Recycling Plant (Milwaukee)": 189000.0 + "Lead Sales Point": { + "Milwaukee": { + "total output": {}, + "latitude": 43.05, + "fixed cost": 0.0, + "output": {}, + "longitude": -87.95, + "total input": 189000.0, + "transportation costs": { + "Lead Recycling Plant": { + "Milwaukee": { + "latitude": 43.05, + "cost": 0.0, + "distance": 0.0, + "longitude": -87.95 + } + } + }, + "variable costs": { + "Lead Recycling Plant": { + "Milwaukee": { + "latitude": 43.05, + "cost": -519750.0, + "longitude": -87.95 + } + } + }, + "input": { + "Lead Recycling Plant": { + "Milwaukee": { + "amount": 189000.0, + "latitude": 43.05, + "longitude": -87.95 + } + } + } } }, - "Disassembly Plant (Greendale)": { - "total output": { - "lead": 72000.0, - "plastic casings": 6000.0 - }, - "fixed cost": 11000.0, - "output": { - "lead": { - "Lead Recycling Plant (Milwaukee)": 72000.0 + "Plastic Sales Point": { + "Milwaukee": { + "total output": {}, + "latitude": 43.05, + "fixed cost": 0.0, + "output": {}, + "longitude": -87.95, + "total input": 15750.0, + "transportation costs": { + "Plastic Recycling Plant": { + "Milwaukee": { + "latitude": 43.05, + "cost": 0.0, + "distance": 0.0, + "longitude": -87.95 + } + } + }, + "variable costs": { + "Plastic Recycling Plant": { + "Milwaukee": { + "latitude": 43.05, + "cost": -9765.0, + "longitude": -87.95 + } + } }, - "plastic casings": { - "Plastic Recycling Plant (Milwaukee)": 6000.0 + "input": { + "Plastic Recycling Plant": { + "Milwaukee": { + "amount": 15750.0, + "latitude": 43.05, + "longitude": -87.95 + } + } } - }, - "total input": 120000.0, - "transportation costs": { - "Origin (Milwaukee)": 2352.6 - }, - "variable costs": { - "Origin (Milwaukee)": 21600.0 - }, - "input": { - "Origin (Milwaukee)": 120000.0 } } }, diff --git a/src/model.jl b/src/model.jl index cb89edb..69748c2 100644 --- a/src/model.jl +++ b/src/model.jl @@ -262,62 +262,98 @@ function get_solution(instance::ReverseManufacturingInstance, ) for (plant_name, plant) in instance.plants + skip_plant = true + plant_dict = Dict{Any, Any}() input_product_name = plant["input"] + for (location_name, location) in plant["locations"] - skip_plant = true + skip_location = true process_node = model.process_nodes[input_product_name, plant_name, location_name] - dict = Dict{Any, Any}( + plant_loc_dict = Dict{Any, Any}( "input" => Dict(), "output" => Dict(), "total input" => 0.0, "total output" => Dict(), "transportation costs" => Dict(), "variable costs" => Dict(), + "latitude" => location["latitude"], + "longitude" => location["longitude"], ) - dict["fixed cost"] = round(vals[process_node] * process_node.cost, digits=5) - output["costs"]["fixed"] += dict["fixed cost"] + plant_loc_dict["fixed cost"] = round(vals[process_node] * process_node.cost, digits=5) + output["costs"]["fixed"] += plant_loc_dict["fixed cost"] # Inputs for a in process_node.incoming_arcs - if vals[a] > 0 - val = round(vals[a], digits=5) - skip_plant = false - source_key = "$(a.source.plant_name) ($(a.source.location_name))" - dict["input"][source_key] = val - dict["total input"] += val - - cost_transportation = round(a.costs["transportation"] * val, digits=5) - cost_variable = round(a.costs["variable"] * val, digits=5) - dict["transportation costs"][source_key] = cost_transportation - dict["variable costs"][source_key] = cost_variable - output["costs"]["transportation"] += cost_transportation - output["costs"]["variable"] += cost_variable + if vals[a] <= 0 + continue end + skip_plant = skip_location = false + val = round(vals[a], digits=5) + if !(a.source.plant_name in keys(plant_loc_dict["input"])) + plant_loc_dict["input"][a.source.plant_name] = Dict() + plant_loc_dict["transportation costs"][a.source.plant_name] = Dict() + plant_loc_dict["variable costs"][a.source.plant_name] = Dict() + end + if a.source.plant_name == "Origin" + product = instance.products[a.source.product_name] + source_location = product["initial amounts"][a.source.location_name] + else + source_plant = instance.plants[a.source.plant_name] + source_location = source_plant["locations"][a.source.location_name] + end + + # Input + plant_loc_dict["input"][a.source.plant_name][a.source.location_name] = dict = Dict() + dict["amount"] = val + dict["latitude"] = source_location["latitude"] + dict["longitude"] = source_location["longitude"] + plant_loc_dict["total input"] += val + + # Transportation costs + cost_transportation = round(a.costs["transportation"] * val, digits=5) + plant_loc_dict["transportation costs"][a.source.plant_name][a.source.location_name] = dict = Dict() + dict["cost"] = cost_transportation + dict["latitude"] = source_location["latitude"] + dict["longitude"] = source_location["longitude"] + dict["distance"] = a.values["distance"] + output["costs"]["transportation"] += cost_transportation + + cost_variable = round(a.costs["variable"] * val, digits=5) + plant_loc_dict["variable costs"][a.source.plant_name][a.source.location_name] = dict = Dict() + dict["cost"] = cost_variable + dict["latitude"] = source_location["latitude"] + dict["longitude"] = source_location["longitude"] + output["costs"]["variable"] += cost_variable end # Outputs for output_product_name in keys(plant["outputs"]) - dict["output"][output_product_name] = output_dict = Dict() - dict["total output"][output_product_name] = 0.0 + plant_loc_dict["total output"][output_product_name] = 0.0 + plant_loc_dict["output"][output_product_name] = product_dict = Dict() decision_node = model.decision_nodes[output_product_name, plant_name, location_name] for a in decision_node.outgoing_arcs - if vals[a] > 0 - val = round(vals[a], digits=5) - skip_plant = false - dict["total output"][output_product_name] += val - dest_key = "$(a.dest.plant_name) ($(a.dest.location_name))" - output_dict[dest_key] = val + if vals[a] <= 0 + continue + end + skip_plant = skip_location = false + if !(a.dest.plant_name in keys(product_dict)) + product_dict[a.dest.plant_name] = Dict{Any,Any}() end + val = round(vals[a], digits=5) + plant_loc_dict["total output"][output_product_name] += val + product_dict[a.dest.plant_name][a.dest.location_name] = val end end - - if !skip_plant - key = "$(plant_name) ($(location_name))" - output["plants"][key] = dict + + if !skip_location + plant_dict[location_name] = plant_loc_dict end end + if !skip_plant + output["plants"][plant_name] = plant_dict + end end output["costs"]["total"] = sum(values(output["costs"])) diff --git a/test/model_test.jl b/test/model_test.jl index 5693626..b0daae1 100644 --- a/test/model_test.jl +++ b/test/model_test.jl @@ -46,33 +46,15 @@ using ReverseManufacturing, Cbc, JuMP, Printf arc = p2_f1_l1.incoming_arcs[1] @test arc.values["weight"] == 0.2 @test isempty(arc.costs) - -# @show model.mip -# JuMP.optimize!(model.mip) - -# values = Dict(a => JuMP.value(model.vars.flow[a]) for a in model.arcs) -# @printf("source,dest,amount\n") -# for (arc, value) in values -# if value > 1e-6 -# @printf("%s-%s-%s,%s-%s-%s,%.2f\n", -# arc.source.plant_name, -# arc.source.location_name, -# arc.source.product_name, -# arc.dest.plant_name, -# arc.dest.location_name, -# arc.dest.product_name, -# value) -# end -# end - -# for a in model.arcs -# @printf("%20s\t%20s\t%8.2f\n", -# "$(a.source.product_name) $(a.source.plant_name) $(a.source.location_name)", -# "$(a.dest.product_name) $(a.dest.plant_name) $(a.dest.location_name)", -# a.weight) -# end end @testset "Solve" begin - ReverseManufacturing.solve("$(pwd())/../instances/samples/s2.json") + solution = ReverseManufacturing.solve("$(pwd())/../instances/samples/s1.json") + @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 "L2" in keys(solution["plants"]["F1"]) + @test "total output" in keys(solution["plants"]["F1"]["L2"]) end \ No newline at end of file