From 2cddb90686fb4a0e92f4ee1b4335ceaa2048d2f4 Mon Sep 17 00:00:00 2001 From: Florian Fontan Date: Tue, 3 Dec 2024 20:44:49 +0100 Subject: [PATCH] Improve SVC algorithm for VSBPP objective --- .../tests/variable_sized_bin_packing_bins.csv | 3 + .../variable_sized_bin_packing_items.csv | 2 + .../variable_sized_bin_packing_parameters.csv | 2 + .../variable_sized_bin_packing_solution.csv | 4 ++ .../sequential_value_correction.hpp | 64 +++++++++++++++++-- test/rectangle/rectangle_test.cpp | 6 ++ 6 files changed, 75 insertions(+), 6 deletions(-) create mode 100644 data/rectangle/tests/variable_sized_bin_packing_bins.csv create mode 100644 data/rectangle/tests/variable_sized_bin_packing_items.csv create mode 100644 data/rectangle/tests/variable_sized_bin_packing_parameters.csv create mode 100644 data/rectangle/tests/variable_sized_bin_packing_solution.csv diff --git a/data/rectangle/tests/variable_sized_bin_packing_bins.csv b/data/rectangle/tests/variable_sized_bin_packing_bins.csv new file mode 100644 index 000000000..bc175da6e --- /dev/null +++ b/data/rectangle/tests/variable_sized_bin_packing_bins.csv @@ -0,0 +1,3 @@ +WIDTH,HEIGHT,COST +15,15,1 +20,30,3 diff --git a/data/rectangle/tests/variable_sized_bin_packing_items.csv b/data/rectangle/tests/variable_sized_bin_packing_items.csv new file mode 100644 index 000000000..b71a66342 --- /dev/null +++ b/data/rectangle/tests/variable_sized_bin_packing_items.csv @@ -0,0 +1,2 @@ +WIDTH,HEIGHT,COPIES +10,10,2 diff --git a/data/rectangle/tests/variable_sized_bin_packing_parameters.csv b/data/rectangle/tests/variable_sized_bin_packing_parameters.csv new file mode 100644 index 000000000..fbdd3fc31 --- /dev/null +++ b/data/rectangle/tests/variable_sized_bin_packing_parameters.csv @@ -0,0 +1,2 @@ +NAME,VALUE +objective,variable-sized-bin-packing diff --git a/data/rectangle/tests/variable_sized_bin_packing_solution.csv b/data/rectangle/tests/variable_sized_bin_packing_solution.csv new file mode 100644 index 000000000..ecf839c98 --- /dev/null +++ b/data/rectangle/tests/variable_sized_bin_packing_solution.csv @@ -0,0 +1,4 @@ +TYPE,ID,COPIES,BIN,X,Y,LX,LY +BIN,1,1,0,0,0,20,30 +ITEM,0,1,0,0,0,10,10 +ITEM,0,1,0,10,0,10,10 diff --git a/src/algorithms/sequential_value_correction.hpp b/src/algorithms/sequential_value_correction.hpp index 43d8f23cf..2694d08b3 100644 --- a/src/algorithms/sequential_value_correction.hpp +++ b/src/algorithms/sequential_value_correction.hpp @@ -232,11 +232,43 @@ SequentialValueCorrectionOutput sequential_value_correction( auto kp_solution = kp_solution_pool.best(); + if (kp_solution.number_of_different_bins() == 0) { + solutions_cur[bin_type_id].first = Solution(instance); + solutions_cur[bin_type_id].second = 0; + continue; + } + + // Compute the number of copies of the selected Knapsack solution + // to add. + BinPos number_of_copies + = instance.bin_type(bin_type_id).copies + - solution.bin_copies(bin_type_id); + for (ItemTypeId kp_item_type_id = 0; + kp_item_type_id < kp_instance.number_of_item_types(); + ++kp_item_type_id) { + ItemTypeId item_type_id = kp2orig[kp_item_type_id]; + ItemPos item_remaining_copies + = instance.item_type(item_type_id).copies + - solution.item_copies(item_type_id); + ItemPos item_packed_copies = kp_solution.item_copies(kp_item_type_id); + if (item_packed_copies > 0) { + number_of_copies = std::min( + number_of_copies, + (BinPos)(item_remaining_copies / item_packed_copies)); + } + } + if (number_of_copies < 1) { + throw std::logic_error( + "number_of_copies: " + std::to_string(number_of_copies) + "."); + } + // If the objective is BinPackingWithLeftovers and this is the // last bin, then we re-optimize it to maximize the leftover // value. if (instance.objective() == Objective::BinPackingWithLeftovers - && kp_solution.number_of_items() == kp_instance.number_of_items()) { + && solution.number_of_items() + + number_of_copies * kp_solution.number_of_items() + == instance.number_of_items()) { InstanceBuilder bppl_instance_builder; bppl_instance_builder.set_objective(Objective::BinPackingWithLeftovers); @@ -264,12 +296,32 @@ SequentialValueCorrectionOutput sequential_value_correction( } } - Solution solution(instance); - if (kp_solution.number_of_different_bins() > 0) - solution.append(kp_solution, 0, 1, {bin_type_id}, kp2orig); - solutions_cur[bin_type_id].first = solution; + Solution kp_solution_orig(instance); + kp_solution_orig.append(kp_solution, 0, 1, {bin_type_id}, kp2orig); + solutions_cur[bin_type_id].first = kp_solution_orig; solutions_cur[bin_type_id].second = kp_solution.profit(); - output.all_patterns.push_back(solution); + output.all_patterns.push_back(kp_solution_orig); + + // If the objective is VariableSizedBinPacking and the + // current solution is full, check if it is the new best + // solution. + if (instance.objective() == Objective::VariableSizedBinPacking + && solution.number_of_items() + + number_of_copies * kp_solution.number_of_items() + == instance.number_of_items()) { + + // Update current solution. + Solution solution_tmp = solution; + solution_tmp.append( + kp_solution_orig, + 0, + number_of_copies); + + // Update best solution. + std::stringstream ss; + ss << "iteration " << output.number_of_iterations; + algorithm_formatter.update_solution(solution_tmp, ss.str()); + } } // Find best solution. diff --git a/test/rectangle/rectangle_test.cpp b/test/rectangle/rectangle_test.cpp index 351f56922..3564365e1 100644 --- a/test/rectangle/rectangle_test.cpp +++ b/test/rectangle/rectangle_test.cpp @@ -71,4 +71,10 @@ INSTANTIATE_TEST_SUITE_P( fs::path(""), fs::path("data") / "rectangle" / "tests" / "bin_packing_with_leftovers_parameters.csv", fs::path("data") / "rectangle" / "tests" / "bin_packing_with_leftovers_solution.csv", + }, { + fs::path("data") / "rectangle" / "tests" / "variable_sized_bin_packing_items.csv", + fs::path("data") / "rectangle" / "tests" / "variable_sized_bin_packing_bins.csv", + fs::path(""), + fs::path("data") / "rectangle" / "tests" / "variable_sized_bin_packing_parameters.csv", + fs::path("data") / "rectangle" / "tests" / "variable_sized_bin_packing_solution.csv", }}));