From 58883685048f4c3e373e775112becb5255ba8959 Mon Sep 17 00:00:00 2001 From: "Alinson S. Xavier" Date: Wed, 24 Apr 2024 12:57:57 -0500 Subject: [PATCH] Heuristic: Use max/min instead of sum for demand, storage, disposal --- model-3.jl | 147 ++++++++++++++++++++++++++++++----------------------- 1 file changed, 83 insertions(+), 64 deletions(-) diff --git a/model-3.jl b/model-3.jl index e64c22c..f05a42b 100644 --- a/model-3.jl +++ b/model-3.jl @@ -113,39 +113,39 @@ function generate_data() cardboard = Component("Cardboard") # Products - waste = Product(name = "Waste", comp = [film, paper, cardboard]) - film_bale = Product(name = "Film bale", comp = [film, paper, cardboard]) - cardboard_bale = Product(name = "Cardboard bale", comp = [paper, cardboard]) - cardboard_sheets = Product(name = "Cardboard sheets", comp = [cardboard]) + waste = Product(name="Waste", comp=[film, paper, cardboard]) + film_bale = Product(name="Film bale", comp=[film, paper, cardboard]) + cardboard_bale = Product(name="Cardboard bale", comp=[paper, cardboard]) + cardboard_sheets = Product(name="Cardboard sheets", comp=[cardboard]) products = [waste, film_bale, cardboard_bale, cardboard_sheets] # Centers centers = [ Center( - name = "Collection ($city_name)", - latitude = city_lat, - longitude = city_lon, - prod_out = [waste], + name="Collection ($city_name)", + latitude=city_lat, + longitude=city_lon, + prod_out=[waste], ) for (city_name, (city_lat, city_lon)) in cities_a ] # Plants plants_a = [ Plant( - name = "MRF ($city_name)", - latitude = city_lat, - longitude = city_lon, - prod_in = waste, - prod_out = [film_bale, cardboard_bale], + name="MRF ($city_name)", + latitude=city_lat, + longitude=city_lon, + prod_in=waste, + prod_out=[film_bale, cardboard_bale], ) for (city_name, (city_lat, city_lon)) in cities_b ] plants_b = [ Plant( - name = "Paper Mill ($city_name)", - latitude = city_lat, - longitude = city_lon, - prod_in = cardboard_bale, - prod_out = [cardboard_sheets], + name="Paper Mill ($city_name)", + latitude=city_lat, + longitude=city_lon, + prod_in=cardboard_bale, + prod_out=[cardboard_sheets], ) for (city_name, (city_lat, city_lon)) in cities_b ] plants = [plants_a; plants_b] @@ -311,7 +311,7 @@ end # Read # ============================================================================== -function read_json(filename; max_centers = Inf, max_plants = Inf)::Instance +function read_json(filename; max_centers=Inf, max_plants=Inf)::Instance json = JSON.parsefile(filename) T = 1:json["parameters"]["time horizon (years)"] centers = [] @@ -530,24 +530,24 @@ function compress(original::Instance)::Instance (s, 1) => sum([original.m_emission[s, t] for t in T]) for s in original.emissions ) m_init = Dict( - (q, r, c, 1) => sum([original.m_init[q, r, c, t] for t in T]) for + (q, r, c, 1) => length(T) * maximum([original.m_init[q, r, c, t] for t in T]) for q in original.centers for r in q.prod_out for c in r.comp ) m_plant_disp = Dict( - (p, r, 1) => sum([original.m_plant_disp[p, r, t] for t in T]) for + (p, r, 1) => length(T) * minimum([original.m_plant_disp[p, r, t] for t in T]) for p in original.plants for r in p.prod_out ) m_store = Dict( - (q, r, 1) => sum([original.m_store[q, r, t] for t in T]) for + (q, r, 1) => length(T) * minimum([original.m_store[q, r, t] for t in T]) for q in original.centers for r in q.prod_out ) return Instance(; - T = 1:1, - centers = original.centers, - plants = original.plants, - products = original.products, - emissions = original.emissions, - alpha_mix = original.alpha_mix, + T=1:1, + centers=original.centers, + plants=original.plants, + products=original.products, + emissions=original.emissions, + alpha_mix=original.alpha_mix, alpha_plant_emission, alpha_tr_emission, c_acq, @@ -561,7 +561,7 @@ function compress(original::Instance)::Instance c_var, m_cap, m_center_disp, - m_dist = original.m_dist, + m_dist=original.m_dist, m_emission, m_init, m_plant_disp, @@ -569,13 +569,13 @@ function compress(original::Instance)::Instance ) end -function benchmark_compress(filename, optimizer; max_centers = [Inf], max_plants = [Inf]) +function benchmark_compress(filename, optimizer; max_centers=[Inf], max_plants=[Inf]) stats = [] for mc in max_centers, mp in max_plants # Solve original - orig = read_json(filename; max_centers = mc, max_plants = mp) + orig = read_json(filename; max_centers=mc, max_plants=mp) reset_timer!() - model_orig, stats_orig = solve(orig; optimizer) + _, stats_orig = solve(orig; optimizer) stats_orig["Filename"] = filename stats_orig["Method"] = "Original" push!(stats, stats_orig) @@ -605,20 +605,21 @@ function generate_json() write_json(data, "output-3/case.json") end -function solve(filename, optimizer; max_centers = Inf, max_plants = Inf, heuristic = false) +function solve(filename, optimizer; max_centers=Inf, max_plants=Inf, heuristic=false) reset_timer!() @timeit "Read JSON" begin data = read_json(filename; max_centers, max_plants) end - return solve(data; optimizer = optimizer, output_dir = dirname(filename), heuristic) + return solve(data; optimizer=optimizer, output_dir=dirname(filename), heuristic) print_timer() end -function solve(data::Instance; optimizer, output_dir = nothing, heuristic = false) +function solve(data::Instance; optimizer, output_dir=nothing, heuristic=false) if heuristic + @info "Solving compressed instance..." comp_data = compress(data) - comp_model, comp_stats = solve(comp_data; optimizer, heuristic = false) + comp_model, comp_stats = solve(comp_data; optimizer, heuristic=false) # Filter plants selected_plants = Plant[] @@ -641,7 +642,7 @@ function solve(data::Instance; optimizer, output_dir = nothing, heuristic = fals data = Instance(; data.T, data.centers, - plants = selected_plants, + plants=selected_plants, data.products, data.emissions, data.alpha_mix, @@ -686,7 +687,6 @@ function solve(data::Instance; optimizer, output_dir = nothing, heuristic = fals function push_edge!(src, dst, r) e = (src, dst, r) if data.selected_edges !== nothing && e ∉ data.selected_edges - @info "Skipping: $(src.name) $(dst.name) $(r.name)" return end push!(E, e) @@ -724,6 +724,25 @@ function solve(data::Instance; optimizer, output_dir = nothing, heuristic = fals @printf(" %8d time periods\n", length(T)) @printf(" %8d transportation edges\n", length(E)) + available = Dict((r, t) => 0.0 for r in data.products, t in T) + for q in centers, t in T + for r in q.prod_out, s in r.comp + available[r, t] += data.m_init[q, r, s, t] + end + end + + capacity = Dict(r => 0.0 for r in data.products) + for p in plants + capacity[p.prod_in] += data.m_cap[p] + end + + for r in products, t in T + if available[r, t] > capacity[r] + @warn "Not enough capacity to process $(r.name) at time $t: $(available[r,t]) > $(capacity[r])" + end + end + + # Decision variables # ------------------------------------------------------------------------- @timeit "Model: Add variables" begin @@ -1108,7 +1127,7 @@ function solve(data::Instance; optimizer, output_dir = nothing, heuristic = fals "Model build time (s)" => model_build_time, "Variables" => num_variables(model), "Constraints" => - num_constraints(model, count_variable_in_set_constraints = false), + num_constraints(model, count_variable_in_set_constraints=false), "Objective Value" => objective_value(model), "Solve time (s)" => solve_time(model), ) @@ -1141,13 +1160,13 @@ function solve(data::Instance; optimizer, output_dir = nothing, heuristic = fals r.name, c.name, t, - round(data.m_dist[q, p], digits = 2), - round(value(y[q, p, r][c, t]), digits = 2), + round(data.m_dist[q, p], digits=2), + round(value(y[q, p, r][c, t]), digits=2), round( data.m_dist[q, p] * data.c_tr[r, t] * value(y[q, p, r][c, t]), - digits = 2, + digits=2, ), - round(data.c_var[p, t] * value(y[q, p, r][c, t]), digits = 2), + round(data.c_var[p, t] * value(y[q, p, r][c, t]), digits=2), ], ) end @@ -1175,18 +1194,18 @@ function solve(data::Instance; optimizer, output_dir = nothing, heuristic = fals r.name, c.name, t, - round(data.m_init[q, r, c, t], digits = 2), + round(data.m_init[q, r, c, t], digits=2), round( sum(value(y[q, p, r][c, t]) for (p, r2) in E_out[q] if r == r2), - digits = 2, + digits=2, ), - round(value(z_store[q, r, c, t]), digits = 2), - round(value(z_center_disp[q, r, c, t]), digits = 2), - round(data.m_init[q, r, c, t] * data.c_acq[q, r, t], digits = 2), - round(data.c_store[q, r, t] * value(z_store[q, r, c, t]), digits = 2), + round(value(z_store[q, r, c, t]), digits=2), + round(value(z_center_disp[q, r, c, t]), digits=2), + round(data.m_init[q, r, c, t] * data.c_acq[q, r, t], digits=2), + round(data.c_store[q, r, t] * value(z_store[q, r, c, t]), digits=2), round( data.c_center_disp[q, r, t] * value(z_center_disp[q, r, c, t]), - digits = 2, + digits=2, ), ], ) @@ -1207,12 +1226,12 @@ function solve(data::Instance; optimizer, output_dir = nothing, heuristic = fals [ p.name, t, - round(value(x_open[p, t]), digits = 2), + round(value(x_open[p, t]), digits=2), round( data.c_open[p, t] * (value(x_open[p, t]) - value(x_open[p, t-1])), - digits = 2, + digits=2, ), - round(data.c_fix[p, t] * value(x_open[p, t]), digits = 2), + round(data.c_fix[p, t] * value(x_open[p, t]), digits=2), ], ) end @@ -1240,18 +1259,18 @@ function solve(data::Instance; optimizer, output_dir = nothing, heuristic = fals r.name, c.name, t, - round(value(z_prod[p, r, c, t]), digits = 2), - round(value(z_plant_disp[p, r, c, t]), digits = 2), + round(value(z_prod[p, r, c, t]), digits=2), + round(value(z_plant_disp[p, r, c, t]), digits=2), round( sum( value(y[p, q, r][c, t]) for (q, r2) in E_out[p] if r == r2; - init = 0.0, + init=0.0, ), - digits = 2, + digits=2, ), round( data.c_plant_disp[p, r, t] * value(z_plant_disp[p, r, c, t]), - digits = 2, + digits=2, ), ], ) @@ -1273,10 +1292,10 @@ function solve(data::Instance; optimizer, output_dir = nothing, heuristic = fals p.name, s.name, t, - round(value(z_plant_emissions[p, s, t]), digits = 2), + round(value(z_plant_emissions[p, s, t]), digits=2), round( data.c_emission[s, t] * value(z_plant_emissions[p, s, t]), - digits = 2, + digits=2, ), ], ) @@ -1307,12 +1326,12 @@ function solve(data::Instance; optimizer, output_dir = nothing, heuristic = fals r.name, s.name, t, - round(data.m_dist[q, p], digits = 2), - round(value(y_total[q, p, r][t]), digits = 2), - round(value(z_tr_emissions[q, p, r, s, t]), digits = 2), + round(data.m_dist[q, p], digits=2), + round(value(y_total[q, p, r][t]), digits=2), + round(value(z_tr_emissions[q, p, r, s, t]), digits=2), round( data.c_emission[s, t] * value(z_tr_emissions[q, p, r, s, t]), - digits = 2, + digits=2, ), ], )