1414#include " ortools/sat/2d_packing_brute_force.h"
1515
1616#include < algorithm>
17- #include < array>
1817#include < limits>
1918#include < tuple>
2019#include < utility>
2120#include < vector>
2221
23- #include " absl/container/inlined_vector.h"
2422#include " absl/log/check.h"
2523#include " absl/strings/str_cat.h"
2624#include " absl/types/span.h"
2725#include " ortools/base/logging.h"
2826#include " ortools/sat/diffn_util.h"
2927#include " ortools/sat/integer_base.h"
28+ #include " ortools/sat/util.h"
3029#include " ortools/util/bitset.h"
3130
3231namespace operations_research {
@@ -143,25 +142,28 @@ bool BruteForceOrthogonalPackingImpl(
143142 std::pair<IntegerValue, IntegerValue> bounding_box_size,
144143 IntegerValue smallest_x, IntegerValue smallest_y,
145144 absl::Span<Rectangle> item_positions, Bitset64<int >& placed_item_indexes,
146- absl::Span< const absl::InlinedVector<PotentialPositionForItem, 16 >>
145+ const CompactVectorVector< int , PotentialPositionForItem>&
147146 potential_item_positions,
148147 IntegerValue slack) {
149148 const auto add_position_if_valid =
150149 [&item_positions, bounding_box_size, &sizes_x, &sizes_y,
151150 &placed_item_indexes](
152- absl::InlinedVector<PotentialPositionForItem, 16 >& positions, int i,
151+ CompactVectorVector< int , PotentialPositionForItem >& positions, int i,
153152 IntegerValue x, IntegerValue y) {
154153 const Rectangle rect = {.x_min = x,
155154 .x_max = x + sizes_x[i],
156155 .y_min = y,
157156 .y_max = y + sizes_y[i]};
158157 if (ShouldPlaceItemAtPosition (i, rect, bounding_box_size,
159158 item_positions, placed_item_indexes)) {
160- positions.push_back ({x, y, false });
159+ positions.AppendToLastVector ({x, y, false });
161160 }
162161 };
163162
164163 const int num_items = sizes_x.size ();
164+ CompactVectorVector<int , PotentialPositionForItem> new_potential_positions;
165+ new_potential_positions.reserve (num_items,
166+ 3 * potential_item_positions.num_entries ());
165167 bool has_unplaced_item = false ;
166168 for (int i = 0 ; i < num_items; ++i) {
167169 if (placed_item_indexes[i]) {
@@ -261,48 +263,31 @@ bool BruteForceOrthogonalPackingImpl(
261263 // (like the point in the left boundary in the example above) but we will
262264 // detect that by testing each item one by one. Importantly, we only pass
263265 // valid positions down to the next search level.
264- std::array<absl::InlinedVector<PotentialPositionForItem, 16 >,
265- kMaxProblemSize >
266- new_potential_positions_storage;
267- absl::Span<absl::InlinedVector<PotentialPositionForItem, 16 >>
268- new_potential_positions (new_potential_positions_storage. data (),
269- num_items);
270- for ( const int k : placed_item_indexes) {
271- if (k == i ) {
266+ new_potential_positions. clear ();
267+ bool is_unfeasible = false ;
268+ for ( int j = 0 ; j < num_items; ++j) {
269+ // We will find all potential positions for the j-th item.
270+ new_potential_positions. Add ({});
271+ // No need to attribute potential positions to already placed items
272+ // (including the one we just placed).
273+ if (placed_item_indexes[j] ) {
272274 continue ;
273275 }
274-
275- const bool add_below =
276- // We only add points below this one...
277- item_positions[k].y_max <= item_position.y_max &&
278- // ...and where we can fit at least the smallest element.
279- item_position.x_max + smallest_x <= bounding_box_size.first &&
280- item_positions[k].y_max + smallest_y <= bounding_box_size.second ;
281- const bool add_left =
282- item_positions[k].x_max <= item_position.x_max &&
283- item_positions[k].x_max + smallest_x <= bounding_box_size.first &&
284- item_position.y_max + smallest_y <= bounding_box_size.second ;
285- for (int j = 0 ; j < num_items; ++j) {
286- if (k == j || placed_item_indexes[j]) {
276+ DCHECK_NE (i, j);
277+ // Add the new "potential positions" derived from the new item.
278+ for (const int k : placed_item_indexes) {
279+ DCHECK_NE (j, k);
280+ if (k == i) {
287281 continue ;
288282 }
289- if (add_below) {
290- add_position_if_valid (new_potential_positions[j], j,
291- item_position.x_max , item_positions[k].y_max );
292- }
293- if (add_left) {
294- add_position_if_valid (new_potential_positions[j], j,
295- item_positions[k].x_max , item_position.y_max );
296- }
297- }
298- }
299- bool is_unfeasible = false ;
300- for (int j = 0 ; j < num_items; ++j) {
301- // No positions to attribute to the item we just placed.
302- if (i == j || placed_item_indexes[j]) {
303- continue ;
283+
284+ add_position_if_valid (new_potential_positions, j, item_position.x_max ,
285+ item_positions[k].y_max );
286+ add_position_if_valid (new_potential_positions, j,
287+ item_positions[k].x_max , item_position.y_max );
304288 }
305- // First copy previously valid positions that remain valid.
289+
290+ // Then copy previously valid positions that remain valid.
306291 for (const PotentialPositionForItem& original_position :
307292 potential_item_positions[j]) {
308293 if (!original_position.GetRectangle (sizes_x[j], sizes_y[j])
@@ -319,14 +304,14 @@ bool BruteForceOrthogonalPackingImpl(
319304 // have to retest those positions down in the search tree.
320305 PotentialPositionForItem position = original_position;
321306 position.already_explored = true ;
322- new_potential_positions[j]. push_back (position);
307+ new_potential_positions. AppendToLastVector (position);
323308 } else {
324- new_potential_positions[j]. push_back (original_position);
309+ new_potential_positions. AppendToLastVector (original_position);
325310 }
326311 }
327- add_position_if_valid (new_potential_positions[j] , j,
312+ add_position_if_valid (new_potential_positions, j,
328313 item_positions[i].x_max , 0 );
329- add_position_if_valid (new_potential_positions[j] , j, 0 ,
314+ add_position_if_valid (new_potential_positions, j, 0 ,
330315 item_positions[i].y_max );
331316 if (new_potential_positions[j].empty ()) {
332317 // After placing the item i, there is no valid place to choose for the
@@ -380,27 +365,21 @@ bool BruteForceOrthogonalPackingNoPreprocessing(
380365 std::make_tuple (b.size_x * b.size_y , b.index );
381366 });
382367
383- std::array<IntegerValue, kMaxProblemSize > new_sizes_x_storage,
384- new_sizes_y_storage;
385- absl::Span<IntegerValue> new_sizes_x (new_sizes_x_storage.data (), num_items);
386- absl::Span<IntegerValue> new_sizes_y (new_sizes_y_storage.data (), num_items);
387- std::array<absl::InlinedVector<PotentialPositionForItem, 16 >, kMaxProblemSize >
388- potential_item_positions_storage;
389- absl::Span<absl::InlinedVector<PotentialPositionForItem, 16 >>
390- potential_item_positions (potential_item_positions_storage.data (),
391- num_items);
368+ std::vector<IntegerValue> new_sizes_x (num_items);
369+ std::vector<IntegerValue> new_sizes_y (num_items);
370+ CompactVectorVector<int , PotentialPositionForItem> potential_item_positions;
371+ potential_item_positions.reserve (num_items, num_items);
392372 for (int i = 0 ; i < num_items; ++i) {
393373 new_sizes_x[i] = items[i].size_x ;
394374 new_sizes_y[i] = items[i].size_y ;
395- potential_item_positions[i]. push_back ({ 0 , 0 , false });
375+ potential_item_positions. Add ({PotentialPositionForItem{ 0 , 0 , false } });
396376 }
397- std::array<Rectangle, kMaxProblemSize > item_positions_storage;
398- absl::Span<Rectangle> item_positions (item_positions_storage.data (),
399- num_items);
377+ std::vector<Rectangle> item_positions (num_items);
400378 Bitset64<int > placed_item_indexes (num_items);
401379 const bool found_solution = BruteForceOrthogonalPackingImpl (
402380 new_sizes_x, new_sizes_y, bounding_box_size, smallest_x, smallest_y,
403- item_positions, placed_item_indexes, potential_item_positions, slack);
381+ absl::MakeSpan (item_positions), placed_item_indexes,
382+ potential_item_positions, slack);
404383 if (!found_solution) {
405384 return false ;
406385 }
@@ -651,13 +630,12 @@ BruteForceResult BruteForceOrthogonalPacking(
651630 }
652631 CHECK_LE (num_items, kMaxProblemSize );
653632
654- std::array<PermutableItem, kMaxProblemSize > items_storage;
655- absl::Span<PermutableItem> items (items_storage.data (), num_items);
633+ std::vector<PermutableItem> items (num_items);
656634 for (int i = 0 ; i < num_items; ++i) {
657635 items[i] = {
658636 .size_x = sizes_x[i], .size_y = sizes_y[i], .index = i, .position = {}};
659637 }
660- absl::Span<PermutableItem> post_processed_items = items;
638+ absl::Span<PermutableItem> post_processed_items = absl::MakeSpan ( items) ;
661639 std::pair<IntegerValue, IntegerValue> post_processed_bounding_box_size =
662640 bounding_box_size;
663641 const bool post_processed =
0 commit comments