diff --git a/data/boxstacks/tests/semi_trailer_truck_middle_axle_bin_packing/bins.csv b/data/boxstacks/tests/semi_trailer_truck_middle_axle_bin_packing/bins.csv new file mode 100644 index 000000000..6173b1e5e --- /dev/null +++ b/data/boxstacks/tests/semi_trailer_truck_middle_axle_bin_packing/bins.csv @@ -0,0 +1,2 @@ +ID,X,Y,Z,COST,COPIES,MAXIMUM_WEIGHT,MAXIMUM_STACK_DENSITY,IS_SEMI_TRAILER_TRUCK,TRACTOR_WEIGHT,FRONT_AXLE_MIDDLE_AXLE_DISTANCE,FRONT_AXLE_TRACTOR_GRAVITY_CENTER_DISTANCE,FRONT_AXLE_HARNESS_DISTANCE,EMPTY_TRAILER_WEIGHT,HARNESS_REAR_AXLE_DISTANCE,TRAILER_GRAVITY_CENTER_REAR_AXLE_DISTANCE,TRAILER_START_HARNESS_DISTANCE,REAR_AXLE_MAXIMUM_WEIGHT,MIDDLE_AXLE_MAXIMUM_WEIGHT +0,1360,240,260,1,1,24000,1000,1,8000,380,100,320,6000,800,400,100,20000,9300 diff --git a/data/boxstacks/tests/semi_trailer_truck_middle_axle_bin_packing/items.csv b/data/boxstacks/tests/semi_trailer_truck_middle_axle_bin_packing/items.csv new file mode 100644 index 000000000..12b02013a --- /dev/null +++ b/data/boxstacks/tests/semi_trailer_truck_middle_axle_bin_packing/items.csv @@ -0,0 +1,2 @@ +ID,X,Y,Z,ROTATION_XYZ,ROTATION_YXZ,ROTATION_ZYX,ROTATION_YZX,ROTATION_XZY,ROTATION_ZXY,WEIGHT,COPIES,GROUP_ID,STACKABILITY_ID,NESTING_HEIGHT,MAXIMUM_STACKABILITY,MAXIMUM_WEIGHT_ABOVE +0,100,200,200,1,0,0,0,0,0,2000,3,0,0,0,1,10000 diff --git a/data/boxstacks/tests/semi_trailer_truck_middle_axle_bin_packing/parameters.csv b/data/boxstacks/tests/semi_trailer_truck_middle_axle_bin_packing/parameters.csv new file mode 100644 index 000000000..e72e86bc5 --- /dev/null +++ b/data/boxstacks/tests/semi_trailer_truck_middle_axle_bin_packing/parameters.csv @@ -0,0 +1,2 @@ +NAME,VALUE +objective,bin-packing diff --git a/data/boxstacks/tests/semi_trailer_truck_middle_axle_bin_packing/solution.csv b/data/boxstacks/tests/semi_trailer_truck_middle_axle_bin_packing/solution.csv new file mode 100644 index 000000000..0a20cca79 --- /dev/null +++ b/data/boxstacks/tests/semi_trailer_truck_middle_axle_bin_packing/solution.csv @@ -0,0 +1 @@ +TYPE,ID,COPIES,BIN,STACK,X,Y,Z,LX,LY,LZ,GROUP_ID,ROTATION diff --git a/data/boxstacks/tests/semi_trailer_truck_middle_axle_knapsack/bins.csv b/data/boxstacks/tests/semi_trailer_truck_middle_axle_knapsack/bins.csv new file mode 100644 index 000000000..6173b1e5e --- /dev/null +++ b/data/boxstacks/tests/semi_trailer_truck_middle_axle_knapsack/bins.csv @@ -0,0 +1,2 @@ +ID,X,Y,Z,COST,COPIES,MAXIMUM_WEIGHT,MAXIMUM_STACK_DENSITY,IS_SEMI_TRAILER_TRUCK,TRACTOR_WEIGHT,FRONT_AXLE_MIDDLE_AXLE_DISTANCE,FRONT_AXLE_TRACTOR_GRAVITY_CENTER_DISTANCE,FRONT_AXLE_HARNESS_DISTANCE,EMPTY_TRAILER_WEIGHT,HARNESS_REAR_AXLE_DISTANCE,TRAILER_GRAVITY_CENTER_REAR_AXLE_DISTANCE,TRAILER_START_HARNESS_DISTANCE,REAR_AXLE_MAXIMUM_WEIGHT,MIDDLE_AXLE_MAXIMUM_WEIGHT +0,1360,240,260,1,1,24000,1000,1,8000,380,100,320,6000,800,400,100,20000,9300 diff --git a/data/boxstacks/tests/semi_trailer_truck_middle_axle_knapsack/items.csv b/data/boxstacks/tests/semi_trailer_truck_middle_axle_knapsack/items.csv new file mode 100644 index 000000000..12b02013a --- /dev/null +++ b/data/boxstacks/tests/semi_trailer_truck_middle_axle_knapsack/items.csv @@ -0,0 +1,2 @@ +ID,X,Y,Z,ROTATION_XYZ,ROTATION_YXZ,ROTATION_ZYX,ROTATION_YZX,ROTATION_XZY,ROTATION_ZXY,WEIGHT,COPIES,GROUP_ID,STACKABILITY_ID,NESTING_HEIGHT,MAXIMUM_STACKABILITY,MAXIMUM_WEIGHT_ABOVE +0,100,200,200,1,0,0,0,0,0,2000,3,0,0,0,1,10000 diff --git a/data/boxstacks/tests/semi_trailer_truck_middle_axle_knapsack/parameters.csv b/data/boxstacks/tests/semi_trailer_truck_middle_axle_knapsack/parameters.csv new file mode 100644 index 000000000..5e7f5aca4 --- /dev/null +++ b/data/boxstacks/tests/semi_trailer_truck_middle_axle_knapsack/parameters.csv @@ -0,0 +1,2 @@ +NAME,VALUE +objective,knapsack diff --git a/data/boxstacks/tests/semi_trailer_truck_middle_axle_knapsack/solution.csv b/data/boxstacks/tests/semi_trailer_truck_middle_axle_knapsack/solution.csv new file mode 100644 index 000000000..0a20cca79 --- /dev/null +++ b/data/boxstacks/tests/semi_trailer_truck_middle_axle_knapsack/solution.csv @@ -0,0 +1 @@ +TYPE,ID,COPIES,BIN,STACK,X,Y,Z,LX,LY,LZ,GROUP_ID,ROTATION diff --git a/src/boxstacks/sequential_onedimensional_rectangle.cpp b/src/boxstacks/sequential_onedimensional_rectangle.cpp index 5383e42a4..d5a7cc3f6 100644 --- a/src/boxstacks/sequential_onedimensional_rectangle.cpp +++ b/src/boxstacks/sequential_onedimensional_rectangle.cpp @@ -214,9 +214,10 @@ SequentialOneDimensionalRectangleSubproblemOutput sequential_onedimensional_rect const std::vector>& rectangle2boxstacks, const rectangle::BranchingScheme::Parameters rectangle_parameters) { + auto logger = parameters.get_logger(); SequentialOneDimensionalRectangleSubproblemOutput output(instance); FFOT_LOG_FOLD_START( - parameters.logger, + logger, "it " << sor_output.number_of_iterations << " guide " << rectangle_parameters.guide_id << std::endl); @@ -241,7 +242,7 @@ SequentialOneDimensionalRectangleSubproblemOutput sequential_onedimensional_rect sor_output.number_of_rectangle_calls++; auto rectangle_solution = rectangle_branching_scheme.to_solution(rectangle_output.solution_pool.best()); FFOT_LOG( - parameters.logger, + logger, "rectangle_solution.number_of_items " << rectangle_solution.number_of_items() << " / " << rectangle_instance.number_of_items() << std::endl); @@ -404,7 +405,7 @@ SequentialOneDimensionalRectangleSubproblemOutput sequential_onedimensional_rect number_of_items_before_repair); output.profit_before_repair = solution.profit(); FFOT_LOG( - parameters.logger, + logger, "number of items " << solution.number_of_items() << std::endl << "profit " << solution.profit() << std::endl << "middle axle weight constraints violation " << solution.compute_middle_axle_weight_constraints_violation() << std::endl @@ -422,7 +423,7 @@ SequentialOneDimensionalRectangleSubproblemOutput sequential_onedimensional_rect parameters.new_solution_callback(sor_output); } output.solution = solution; - FFOT_LOG_FOLD_END(parameters.logger, ""); + FFOT_LOG_FOLD_END(logger, ""); return output; } @@ -430,8 +431,9 @@ const SequentialOneDimensionalRectangleOutput boxstacks::sequential_onedimension const Instance& instance, const SequentialOneDimensionalRectangleParameters& parameters) { + auto logger = parameters.get_logger(); FFOT_LOG_FOLD_START( - parameters.logger, + logger, "sequential_onedimensional_rectangle" << std::endl); SequentialOneDimensionalRectangleOutput output(instance); @@ -548,7 +550,7 @@ const SequentialOneDimensionalRectangleOutput boxstacks::sequential_onedimension } } FFOT_LOG( - parameters.logger, + logger, "fixed_items_solutions.size() " << fixed_items_solutions.size() << std::endl); @@ -561,7 +563,7 @@ const SequentialOneDimensionalRectangleOutput boxstacks::sequential_onedimension // Part of solution which is fixed. Solution fixed_items = fixed_items_solutions[fixed_items_solutions_pos]; FFOT_LOG_FOLD_START( - parameters.logger, + logger, "iteration " << output.number_of_iterations << std::endl << "fixed_items.number_of_items() " << fixed_items.number_of_items() << std::endl << "fixed_items.x_max() " << fixed_items.x_max() << std::endl); @@ -750,7 +752,7 @@ const SequentialOneDimensionalRectangleOutput boxstacks::sequential_onedimension auto onedim_solution = onedim_output.solution_pool.best(); if (parameters.timer.needs_to_end()) { - FFOT_LOG_FOLD_END(parameters.logger, ""); + FFOT_LOG_FOLD_END(logger, ""); algorithm_formatter.end(); return output; } @@ -789,7 +791,7 @@ const SequentialOneDimensionalRectangleOutput boxstacks::sequential_onedimension for (output.number_of_stack_splits = 0; output.number_of_stack_splits < 7; ++output.number_of_stack_splits) { - FFOT_LOG(parameters.logger, "number of splitted stacks " << output.number_of_stack_splits << std::endl); + FFOT_LOG(logger, "number of splitted stacks " << output.number_of_stack_splits << std::endl); Area stack_area = 0; for (BinPos bin_pos = 0; bin_pos < fixed_items.number_of_different_bins(); ++bin_pos) { @@ -982,8 +984,8 @@ const SequentialOneDimensionalRectangleOutput boxstacks::sequential_onedimension failed_middle_axle_weight_constraint_cur |= (subproblem_output.solution.compute_middle_axle_weight_constraints_violation() > 0); failed_rear_axle_weight_constraint_cur |= (subproblem_output.solution.compute_rear_axle_weight_constraints_violation() > 0); if (output.solution_pool.best().full()) { - FFOT_LOG_FOLD_END(parameters.logger, ""); - FFOT_LOG_FOLD_END(parameters.logger, ""); + FFOT_LOG_FOLD_END(logger, ""); + FFOT_LOG_FOLD_END(logger, ""); algorithm_formatter.end(); return output; } @@ -1011,8 +1013,8 @@ const SequentialOneDimensionalRectangleOutput boxstacks::sequential_onedimension failed_middle_axle_weight_constraint_cur |= (subproblem_output.solution.compute_middle_axle_weight_constraints_violation() > 0); failed_rear_axle_weight_constraint_cur |= (subproblem_output.solution.compute_rear_axle_weight_constraints_violation() > 0); if (output.solution_pool.best().full()) { - FFOT_LOG_FOLD_END(parameters.logger, ""); - FFOT_LOG_FOLD_END(parameters.logger, ""); + FFOT_LOG_FOLD_END(logger, ""); + FFOT_LOG_FOLD_END(logger, ""); algorithm_formatter.end(); return output; } @@ -1037,8 +1039,8 @@ const SequentialOneDimensionalRectangleOutput boxstacks::sequential_onedimension rectangle2boxstacks, rectangle_parameters); if (output.solution_pool.best().full()) { - FFOT_LOG_FOLD_END(parameters.logger, ""); - FFOT_LOG_FOLD_END(parameters.logger, ""); + FFOT_LOG_FOLD_END(logger, ""); + FFOT_LOG_FOLD_END(logger, ""); algorithm_formatter.end(); return output; } @@ -1062,8 +1064,8 @@ const SequentialOneDimensionalRectangleOutput boxstacks::sequential_onedimension rectangle2boxstacks, rectangle_parameters); if (output.solution_pool.best().full()) { - FFOT_LOG_FOLD_END(parameters.logger, ""); - FFOT_LOG_FOLD_END(parameters.logger, ""); + FFOT_LOG_FOLD_END(logger, ""); + FFOT_LOG_FOLD_END(logger, ""); algorithm_formatter.end(); return output; } @@ -1101,8 +1103,8 @@ const SequentialOneDimensionalRectangleOutput boxstacks::sequential_onedimension failed_middle_axle_weight_constraint_cur |= (subproblem_output.solution.compute_middle_axle_weight_constraints_violation() > 0); failed_rear_axle_weight_constraint_cur |= (subproblem_output.solution.compute_rear_axle_weight_constraints_violation() > 0); if (output.solution_pool.best().full()) { - FFOT_LOG_FOLD_END(parameters.logger, ""); - FFOT_LOG_FOLD_END(parameters.logger, ""); + FFOT_LOG_FOLD_END(logger, ""); + FFOT_LOG_FOLD_END(logger, ""); algorithm_formatter.end(); return output; } @@ -1126,8 +1128,8 @@ const SequentialOneDimensionalRectangleOutput boxstacks::sequential_onedimension rectangle2boxstacks, rectangle_parameters); if (output.solution_pool.best().full()) { - FFOT_LOG_FOLD_END(parameters.logger, ""); - FFOT_LOG_FOLD_END(parameters.logger, ""); + FFOT_LOG_FOLD_END(logger, ""); + FFOT_LOG_FOLD_END(logger, ""); algorithm_formatter.end(); return output; } @@ -1139,8 +1141,8 @@ const SequentialOneDimensionalRectangleOutput boxstacks::sequential_onedimension && !failed_rear_axle_weight_constraint_cur && fixed_items_solutions_pos == 0 && output.number_of_stack_splits == 0) { - FFOT_LOG_FOLD_END(parameters.logger, ""); - FFOT_LOG_FOLD_END(parameters.logger, ""); + FFOT_LOG_FOLD_END(logger, ""); + FFOT_LOG_FOLD_END(logger, ""); algorithm_formatter.end(); return output; } @@ -1164,8 +1166,8 @@ const SequentialOneDimensionalRectangleOutput boxstacks::sequential_onedimension rectangle2boxstacks, rectangle_parameters); if (output.solution_pool.best().full()) { - FFOT_LOG_FOLD_END(parameters.logger, ""); - FFOT_LOG_FOLD_END(parameters.logger, ""); + FFOT_LOG_FOLD_END(logger, ""); + FFOT_LOG_FOLD_END(logger, ""); algorithm_formatter.end(); return output; } @@ -1189,7 +1191,7 @@ const SequentialOneDimensionalRectangleOutput boxstacks::sequential_onedimension rectangle2boxstacks, rectangle_parameters); if (output.solution_pool.best().full()) { - FFOT_LOG_FOLD_END(parameters.logger, ""); + FFOT_LOG_FOLD_END(logger, ""); algorithm_formatter.end(); return output; } @@ -1268,7 +1270,7 @@ const SequentialOneDimensionalRectangleOutput boxstacks::sequential_onedimension fixed_items = fixed_items_builder.build(); } FFOT_LOG( - parameters.logger, + logger, "failed_middle_axle_weight_constraint " << failed_middle_axle_weight_constraint << std::endl << "failed_rear_axle_weight_constraint " << failed_rear_axle_weight_constraint << std::endl << "x_max " << x_max << " / " << xi << std::endl); @@ -1277,8 +1279,8 @@ const SequentialOneDimensionalRectangleOutput boxstacks::sequential_onedimension fixed_items_solutions_pos_lower_bound = fixed_items_solutions_pos + 1; fixed_items_solutions_pos = 0; for (ItemPos pos = 0; pos < (ItemPos)fixed_items_solutions.size(); ++pos) { - if (pos + 1 < (ItemPos)fixed_items_solutions.size() - && fixed_items_solutions[pos + 1].x_max() > xi - x_max) + if (pos + 1 >= (ItemPos)fixed_items_solutions.size() + || fixed_items_solutions[pos + 1].x_max() > xi - x_max) break; //std::cout << "pos " << pos << " x " << fixed_items_x[pos] << " " << fixed_items_x[pos + 1] << std::endl; fixed_items_solutions_pos++; @@ -1296,17 +1298,17 @@ const SequentialOneDimensionalRectangleOutput boxstacks::sequential_onedimension //fixed_items.write("fixed_items.csv"); FFOT_LOG( - parameters.logger, + logger, "fixed_items_solutions_pos " << fixed_items_solutions_pos << std::endl << "fixed_items_solutions_pos_lower_bound " << fixed_items_solutions_pos_lower_bound << std::endl << "fixed_items_solutions_pos_upper_bound " << fixed_items_solutions_pos_upper_bound << std::endl); - FFOT_LOG_FOLD_END(parameters.logger, ""); + FFOT_LOG_FOLD_END(logger, ""); if (fixed_items_solutions_pos_lower_bound > fixed_items_solutions_pos_upper_bound) break; } - FFOT_LOG_FOLD_END(parameters.logger, ""); + FFOT_LOG_FOLD_END(logger, ""); algorithm_formatter.end(); return output; } diff --git a/src/boxstacks/solution.cpp b/src/boxstacks/solution.cpp index 97c6b874e..57c4155be 100644 --- a/src/boxstacks/solution.cpp +++ b/src/boxstacks/solution.cpp @@ -374,7 +374,7 @@ void Solution::write( "unable to open file \"" + certificate_path + "\"."); } - file << "TYPE,ID,COPIES,BIN,STACK,X,Y,Z,LX,LY,LZ,GROUP_ID" << std::endl; + file << "TYPE,ID,COPIES,BIN,STACK,X,Y,Z,LX,LY,LZ,GROUP_ID,ROTATION" << std::endl; for (BinPos bin_pos = 0; bin_pos < number_of_different_bins(); ++bin_pos) { @@ -393,6 +393,7 @@ void Solution::write( << instance().bin_type(bin_type_id).box.x << "," << instance().bin_type(bin_type_id).box.y << "," << instance().bin_type(bin_type_id).box.z << "," + << "," << std::endl; for (DefectId defect_id = 0; @@ -412,6 +413,7 @@ void Solution::write( << defect.rect.y << "," << "0," << defect.rect.x << "," + << "," << std::endl; } @@ -429,6 +431,7 @@ void Solution::write( << stack.x_end - stack.x_start << "," << stack.y_end - stack.y_start << "," << stack.z_end << "," + << "," << std::endl; for (const SolutionItem& item: stack.items) { @@ -445,7 +448,8 @@ void Solution::write( << item_type.x(item.rotation) << "," << item_type.y(item.rotation) << "," << item_type.z(item.rotation) << "," - << item_type.group_id << std::endl; + << item_type.group_id << "," + << to_string(item.rotation) << std::endl; } } diff --git a/src/boxstacks/solution_builder.cpp b/src/boxstacks/solution_builder.cpp index 40e2d16bf..42761338f 100644 --- a/src/boxstacks/solution_builder.cpp +++ b/src/boxstacks/solution_builder.cpp @@ -1,8 +1,76 @@ #include "boxstacks/solution_builder.hpp" +#include "optimizationtools/utils/utils.hpp" + +#include + using namespace packingsolver; using namespace packingsolver::boxstacks; +void SolutionBuilder::read( + const std::string& certificate_path) +{ + std::ifstream file(certificate_path); + if (!file.good()) { + throw std::runtime_error( + FUNC_SIGNATURE + ": " + "unable to open file \"" + certificate_path + "\"."); + } + + std::string tmp; + std::vector line; + std::vector labels; + + getline(file, tmp); + labels = optimizationtools::split(tmp, ','); + while (getline(file, tmp)) { + line = optimizationtools::split(tmp, ','); + + std::string type = ""; + ItemTypeId id = -1; + BinPos copies = -1; + BinPos bin_pos = -1; + StackId stack_id = -1; + Length x = -1; + Length y = -1; + Length lx = -1; + Length ly = -1; + Rotation rotation = Rotation::XYZ; + + for (Counter i = 0; i < (Counter)line.size(); ++i) { + if (labels[i] == "TYPE") { + type = line[i]; + } else if (labels[i] == "ID") { + id = (ItemTypeId)std::stol(line[i]); + } else if (labels[i] == "COPIES") { + copies = (BinPos)std::stol(line[i]); + } else if (labels[i] == "BIN") { + bin_pos = (BinPos)std::stol(line[i]); + } else if (labels[i] == "STACK") { + stack_id = (StackId)std::stol(line[i]); + } else if (labels[i] == "X") { + x = (Length)std::stol(line[i]); + } else if (labels[i] == "Y") { + y = (Length)std::stol(line[i]); + } else if (labels[i] == "LX") { + lx = (Length)std::stol(line[i]); + } else if (labels[i] == "LY") { + ly = (Length)std::stol(line[i]); + } else if (labels[i] == "ROTATION" && !line[i].empty()) { + rotation = rotation_from_string(line[i]); + } + } + + if (type == "BIN") { + add_bin(id, copies); + } else if (type == "STACK") { + add_stack(bin_pos, x, x + lx, y, y + ly); + } else if (type == "ITEM") { + add_item(bin_pos, stack_id, id, rotation); + } + } +} + BinPos SolutionBuilder::add_bin( BinTypeId bin_type_id, BinPos copies) diff --git a/src/boxstacks/solution_builder.hpp b/src/boxstacks/solution_builder.hpp index 0bee0c42c..7af8c2988 100644 --- a/src/boxstacks/solution_builder.hpp +++ b/src/boxstacks/solution_builder.hpp @@ -15,6 +15,9 @@ class SolutionBuilder /** Constructor. */ SolutionBuilder(const Instance& instance): solution_(instance) { } + /** Read a solution from a file. */ + void read(const std::string& certificate_path); + /** Add a bin at the end of the solution. */ BinPos add_bin( BinTypeId bin_type_id, diff --git a/test/boxstacks/CMakeLists.txt b/test/boxstacks/CMakeLists.txt index 680dda002..7c916e699 100644 --- a/test/boxstacks/CMakeLists.txt +++ b/test/boxstacks/CMakeLists.txt @@ -1,6 +1,7 @@ add_executable(PackingSolver_boxstacks_test) target_sources(PackingSolver_boxstacks_test PRIVATE - boxstacks_test.cpp) + boxstacks_test.cpp + sequential_onedimensional_rectangle_test.cpp) target_include_directories(PackingSolver_boxstacks_test PRIVATE ${PROJECT_SOURCE_DIR}/src) target_link_libraries(PackingSolver_boxstacks_test diff --git a/test/boxstacks/sequential_onedimensional_rectangle_test.cpp b/test/boxstacks/sequential_onedimensional_rectangle_test.cpp new file mode 100644 index 000000000..674848f0b --- /dev/null +++ b/test/boxstacks/sequential_onedimensional_rectangle_test.cpp @@ -0,0 +1,73 @@ +#include "packingsolver/boxstacks/instance_builder.hpp" +#include "boxstacks/sequential_onedimensional_rectangle.hpp" +#include "boxstacks/solution_builder.hpp" + +#include +#include + +using namespace packingsolver::boxstacks; +namespace fs = boost::filesystem; + +struct BoxStacksSequentialOneDimensionalRectangleTestParams +{ + fs::path items_path; + fs::path bins_path; + fs::path parameters_path; + fs::path certificate_path; +}; + +inline std::ostream& operator<<(std::ostream& os, const BoxStacksSequentialOneDimensionalRectangleTestParams& test_params) +{ + os << test_params.items_path; + return os; +} + +class BoxStacksSequentialOneDimensionalRectangleTest: public testing::TestWithParam { }; + +TEST_P(BoxStacksSequentialOneDimensionalRectangleTest, BoxStacksSequentialOneDimensionalRectangle) +{ + BoxStacksSequentialOneDimensionalRectangleTestParams test_params = GetParam(); + InstanceBuilder instance_builder; + instance_builder.read_item_types(test_params.items_path.string()); + instance_builder.read_bin_types(test_params.bins_path.string()); + instance_builder.read_parameters(test_params.parameters_path.string()); + Instance instance = instance_builder.build(); + + // These instances enter the axle weight repair loop, which used to read + // 'fixed_items_solutions' one element past the end and throw + // 'std::bad_array_new_length'/'std::bad_alloc'. + SequentialOneDimensionalRectangleParameters sodr_parameters; + SequentialOneDimensionalRectangleOutput output = sequential_onedimensional_rectangle(instance, sodr_parameters); + + SolutionBuilder solution_builder(instance); + solution_builder.read(test_params.certificate_path.string()); + Solution solution = solution_builder.build(); + std::cout << std::endl + << "Reference solution" << std::endl + << "------------------" << std::endl; + solution.format(std::cout); + + EXPECT_EQ(!(output.solution_pool.best() < solution), true); + EXPECT_EQ(!(solution < output.solution_pool.best()), true); +} + +INSTANTIATE_TEST_SUITE_P( + BoxStacksSequentialOneDimensionalRectangle, + BoxStacksSequentialOneDimensionalRectangleTest, + testing::ValuesIn(std::vector{ + { + // The repair returns an empty solution for both instances: + // called directly (unlike through 'optimize()'), the + // algorithm has no later tree search pass to refine the + // result, so this only pins down that it returns at all + // instead of throwing. + fs::path("data") / "boxstacks" / "tests" / "semi_trailer_truck_middle_axle_bin_packing" / "items.csv", + fs::path("data") / "boxstacks" / "tests" / "semi_trailer_truck_middle_axle_bin_packing" / "bins.csv", + fs::path("data") / "boxstacks" / "tests" / "semi_trailer_truck_middle_axle_bin_packing" / "parameters.csv", + fs::path("data") / "boxstacks" / "tests" / "semi_trailer_truck_middle_axle_bin_packing" / "solution.csv", + }, { + fs::path("data") / "boxstacks" / "tests" / "semi_trailer_truck_middle_axle_knapsack" / "items.csv", + fs::path("data") / "boxstacks" / "tests" / "semi_trailer_truck_middle_axle_knapsack" / "bins.csv", + fs::path("data") / "boxstacks" / "tests" / "semi_trailer_truck_middle_axle_knapsack" / "parameters.csv", + fs::path("data") / "boxstacks" / "tests" / "semi_trailer_truck_middle_axle_knapsack" / "solution.csv", + }}));