Skip to content

Commit d03387b

Browse files
committed
Fix box branching scheme
1 parent 662aee2 commit d03387b

File tree

9 files changed

+248
-110
lines changed

9 files changed

+248
-110
lines changed

include/packingsolver/box/algorithm_formatter.hpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,10 @@ class AlgorithmFormatter
4848
const Solution& solution,
4949
const std::string& s);
5050

51+
/** Update the knapsack bound. */
52+
void update_knapsack_bound(
53+
Profit profit);
54+
5155
/** Update the bin packing bound. */
5256
void update_bin_packing_bound(
5357
BinPos number_of_bins);

src/box/algorithm_formatter.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,23 @@ void AlgorithmFormatter::update_solution(
231231
mutex_.unlock();
232232
}
233233

234+
void AlgorithmFormatter::update_knapsack_bound(
235+
Profit profit)
236+
{
237+
mutex_.lock();
238+
if (profit < output_.knapsack_bound) {
239+
output_.knapsack_bound = profit;
240+
output_.json["IntermediaryOutputs"].push_back(output_.to_json());
241+
parameters_.new_solution_callback(output_);
242+
243+
// Check optimality.
244+
if (equal(output_.knapsack_bound, output_.solution_pool.best().profit())) {
245+
end_ = true;
246+
}
247+
}
248+
mutex_.unlock();
249+
}
250+
234251
void AlgorithmFormatter::update_bin_packing_bound(
235252
BinPos number_of_bins)
236253
{

src/box/branching_scheme.cpp

Lines changed: 143 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -80,10 +80,10 @@ void BranchingScheme::update_uncovered_item(
8080
// << " ye " << ye
8181
// << " zs " << zs
8282
// << " ze " << ze << std::endl;
83-
if (ys > uncovered_item.ye
84-
|| ye < uncovered_item.ys
85-
|| zs > uncovered_item.ze
86-
|| ze < uncovered_item.zs) {
83+
if (ys >= uncovered_item.ye
84+
|| ye <= uncovered_item.ys
85+
|| zs >= uncovered_item.ze
86+
|| ze <= uncovered_item.zs) {
8787
uncovered_items.push_back(uncovered_item);
8888
return;
8989
}
@@ -168,57 +168,109 @@ void BranchingScheme::update_uncovered_item(
168168
void BranchingScheme::update_y_uncovered_item(
169169
std::vector<YUncoveredItem>& y_uncovered_items,
170170
const YUncoveredItem& y_uncovered_item,
171-
Length ys,
172-
Length ye,
173-
Length zs,
174-
Length ze) const
171+
const UncoveredItem& ref) const
175172
{
176-
if (ys >= y_uncovered_item.y
177-
|| ye < y_uncovered_item.y
178-
|| zs > y_uncovered_item.ze
179-
|| ze < y_uncovered_item.zs) {
173+
if (ref.ys > y_uncovered_item.y
174+
|| ref.ye < y_uncovered_item.y
175+
|| ref.zs >= y_uncovered_item.ze
176+
|| ref.ze <= y_uncovered_item.zs) {
180177
y_uncovered_items.push_back(y_uncovered_item);
181178
return;
182179
}
183-
bool has_z_low = (zs > y_uncovered_item.zs);
184-
bool has_z_high = (ze < y_uncovered_item.ze);
180+
bool has_z_low = (ref.zs > y_uncovered_item.zs);
181+
bool has_z_middle = (ref.x < y_uncovered_item.xe);
182+
bool has_z_high = (ref.ze < y_uncovered_item.ze);
185183
if (has_z_low) {
186184
YUncoveredItem y_uncovered_item_new = y_uncovered_item;
187-
y_uncovered_item_new.ze = zs;
185+
y_uncovered_item_new.ze = ref.zs;
186+
y_uncovered_items.push_back(y_uncovered_item_new);
187+
}
188+
if (has_z_middle) {
189+
YUncoveredItem y_uncovered_item_new = y_uncovered_item;
190+
y_uncovered_item_new.zs = (std::max)(y_uncovered_item.zs, ref.zs);
191+
y_uncovered_item_new.ze = (std::min)(y_uncovered_item.ze, ref.ze);
192+
y_uncovered_item_new.xs = (std::max)(y_uncovered_item.xs, ref.x);
188193
y_uncovered_items.push_back(y_uncovered_item_new);
189194
}
190195
if (has_z_high) {
191196
YUncoveredItem y_uncovered_item_new = y_uncovered_item;
192-
y_uncovered_item_new.zs = ze;
197+
y_uncovered_item_new.zs = ref.ze;
193198
y_uncovered_items.push_back(y_uncovered_item_new);
194199
}
195200
}
196201

197202
void BranchingScheme::update_z_uncovered_item(
198203
std::vector<ZUncoveredItem>& z_uncovered_items,
199204
const ZUncoveredItem& z_uncovered_item,
200-
Length ys,
201-
Length ye,
202-
Length zs,
203-
Length ze) const
205+
const UncoveredItem& ref) const
204206
{
205-
if (zs >= z_uncovered_item.z
206-
|| ze < z_uncovered_item.z
207-
|| ys > z_uncovered_item.ye
208-
|| ye < z_uncovered_item.ys) {
207+
if (ref.zs > z_uncovered_item.z
208+
|| ref.ze < z_uncovered_item.z
209+
|| ref.ys >= z_uncovered_item.ye
210+
|| ref.ye <= z_uncovered_item.ys) {
209211
z_uncovered_items.push_back(z_uncovered_item);
210212
return;
211213
}
212-
bool has_y_low = (ys > z_uncovered_item.ys);
213-
bool has_y_high = (ye < z_uncovered_item.ye);
214+
bool has_y_low = (ref.ys > z_uncovered_item.ys);
215+
bool has_y_middle = (ref.x < z_uncovered_item.xe);
216+
bool has_y_high = (ref.ye < z_uncovered_item.ye);
214217
if (has_y_low) {
215218
ZUncoveredItem z_uncovered_item_new = z_uncovered_item;
216-
z_uncovered_item_new.ye = ys;
219+
z_uncovered_item_new.ye = ref.ys;
220+
if (z_uncovered_item_new.ys == z_uncovered_item_new.ye) {
221+
throw std::logic_error(
222+
FUNC_SIGNATURE + ": "
223+
"'z_uncovered_item_new.ys' must be different from 'z_uncovered_item_new.ye' (y_low); "
224+
"z_uncovered_item_new.ys: " + std::to_string(z_uncovered_item_new.ys) + "; "
225+
"z_uncovered_item_new.ye: " + std::to_string(z_uncovered_item_new.ye) + "; "
226+
"z_uncovered_item.ys: " + std::to_string(z_uncovered_item.ys) + "; "
227+
"z_uncovered_item.ye: " + std::to_string(z_uncovered_item.ye) + "; "
228+
"xe: " + std::to_string(ref.x) + "; "
229+
"ys: " + std::to_string(ref.ys) + "; "
230+
"ye: " + std::to_string(ref.ye) + "; "
231+
"zs: " + std::to_string(ref.zs) + "; "
232+
"ze: " + std::to_string(ref.ze) + ".");
233+
}
234+
z_uncovered_items.push_back(z_uncovered_item_new);
235+
}
236+
if (has_y_middle) {
237+
ZUncoveredItem z_uncovered_item_new = z_uncovered_item;
238+
z_uncovered_item_new.ys = (std::max)(z_uncovered_item.ys, ref.ys);
239+
z_uncovered_item_new.ye = (std::min)(z_uncovered_item.ye, ref.ye);
240+
z_uncovered_item_new.xs = (std::max)(z_uncovered_item.xs, ref.x);
241+
if (z_uncovered_item_new.ys == z_uncovered_item_new.ye) {
242+
throw std::logic_error(
243+
FUNC_SIGNATURE + ": "
244+
"'z_uncovered_item_new.ys' must be different from 'z_uncovered_item_new.ye' (y_middle); "
245+
"z_uncovered_item_new.ys: " + std::to_string(z_uncovered_item_new.ys) + "; "
246+
"z_uncovered_item_new.ye: " + std::to_string(z_uncovered_item_new.ye) + "; "
247+
"z_uncovered_item.ys: " + std::to_string(z_uncovered_item.ys) + "; "
248+
"z_uncovered_item.ye: " + std::to_string(z_uncovered_item.ye) + "; "
249+
"xe: " + std::to_string(ref.x) + "; "
250+
"ys: " + std::to_string(ref.ys) + "; "
251+
"ye: " + std::to_string(ref.ye) + "; "
252+
"zs: " + std::to_string(ref.zs) + "; "
253+
"ze: " + std::to_string(ref.ze) + ".");
254+
}
217255
z_uncovered_items.push_back(z_uncovered_item_new);
218256
}
219257
if (has_y_high) {
220258
ZUncoveredItem z_uncovered_item_new = z_uncovered_item;
221-
z_uncovered_item_new.ys = ye;
259+
z_uncovered_item_new.ys = ref.ye;
260+
if (z_uncovered_item_new.ys == z_uncovered_item_new.ye) {
261+
throw std::logic_error(
262+
FUNC_SIGNATURE + ": "
263+
"'z_uncovered_item_new.ys' must be different from 'z_uncovered_item_new.ye' (y_high); "
264+
"z_uncovered_item_new.ys: " + std::to_string(z_uncovered_item_new.ys) + "; "
265+
"z_uncovered_item_new.ye: " + std::to_string(z_uncovered_item_new.ye) + "; "
266+
"z_uncovered_item.ys: " + std::to_string(z_uncovered_item.ys) + "; "
267+
"z_uncovered_item.ye: " + std::to_string(z_uncovered_item.ye) + "; "
268+
"xe: " + std::to_string(ref.x) + "; "
269+
"ys: " + std::to_string(ref.ys) + "; "
270+
"ye: " + std::to_string(ref.ye) + "; "
271+
"zs: " + std::to_string(ref.zs) + "; "
272+
"ze: " + std::to_string(ref.ze) + ".");
273+
}
222274
z_uncovered_items.push_back(z_uncovered_item_new);
223275
}
224276
}
@@ -276,6 +328,27 @@ BranchingScheme::Node BranchingScheme::child_tmp(
276328
+ ".");
277329
}
278330

331+
UncoveredItem new_uncovered_item;
332+
new_uncovered_item.x = xe;
333+
new_uncovered_item.ys = ys;
334+
new_uncovered_item.ye = ye;
335+
new_uncovered_item.zs = zs;
336+
new_uncovered_item.ze = ze;
337+
338+
YUncoveredItem new_y_uncovered_item;
339+
new_y_uncovered_item.xs = xs;
340+
new_y_uncovered_item.xe = xe;
341+
new_y_uncovered_item.y = ye;
342+
new_y_uncovered_item.zs = zs;
343+
new_y_uncovered_item.ze = ze;
344+
345+
ZUncoveredItem new_z_uncovered_item;
346+
new_z_uncovered_item.xs = xs;
347+
new_z_uncovered_item.xe = xe;
348+
new_z_uncovered_item.ys = ys;
349+
new_z_uncovered_item.ye = ye;
350+
new_z_uncovered_item.z = ze;
351+
279352
// Update uncovered_items.
280353
if (insertion.new_bin > 0) { // New bin.
281354
{
@@ -287,65 +360,61 @@ BranchingScheme::Node BranchingScheme::child_tmp(
287360
uncovered_item.ze = bin_type.box.z;
288361
update_uncovered_item(node.uncovered_items, uncovered_item, ys, ye, zs, ze);
289362
}
363+
node.uncovered_items.push_back(new_uncovered_item);
290364
{
291365
YUncoveredItem y_uncovered_item;
292366
y_uncovered_item.xs = 0;
293367
y_uncovered_item.xe = bin_type.box.x;
294368
y_uncovered_item.y = 0;
295369
y_uncovered_item.zs = 0;
296370
y_uncovered_item.ze = bin_type.box.z;
297-
update_y_uncovered_item(node.y_uncovered_items, y_uncovered_item, ys, ye, zs, ze);
371+
update_y_uncovered_item(node.y_uncovered_items, y_uncovered_item, new_uncovered_item);
298372
}
373+
node.y_uncovered_items.push_back(new_y_uncovered_item);
299374
{
300375
ZUncoveredItem z_uncovered_item;
301376
z_uncovered_item.xs = 0;
302377
z_uncovered_item.xe = bin_type.box.x;
303378
z_uncovered_item.ys = 0;
304379
z_uncovered_item.ye = bin_type.box.y;
305380
z_uncovered_item.z = 0;
306-
update_z_uncovered_item(node.z_uncovered_items, z_uncovered_item, ys, ye, zs, ze);
381+
update_z_uncovered_item(node.z_uncovered_items, z_uncovered_item, new_uncovered_item);
307382
}
308-
}
383+
node.z_uncovered_items.push_back(new_z_uncovered_item);
309384

310-
// Compute node.uncovered_item.
311-
for (const UncoveredItem& uncovered_item: parent.uncovered_items)
312-
update_uncovered_item(node.uncovered_items, uncovered_item, ys, ye, zs, ze);
313-
{
314-
UncoveredItem uncovered_item;
315-
uncovered_item.x = xe;
316-
uncovered_item.ys = ys;
317-
uncovered_item.ye = ye;
318-
uncovered_item.zs = zs;
319-
uncovered_item.ze = ze;
320-
node.uncovered_items.push_back(uncovered_item);
321-
}
322-
323-
// Compute node.y_uncovered_item.
324-
for (const YUncoveredItem& y_uncovered_item: parent.y_uncovered_items) {
325-
update_y_uncovered_item(node.y_uncovered_items, y_uncovered_item, ys, ye, zs, ze);
326-
}
327-
{
328-
YUncoveredItem y_uncovered_item;
329-
y_uncovered_item.xs = xs;
330-
y_uncovered_item.xe = xe;
331-
y_uncovered_item.y = ye;
332-
y_uncovered_item.zs = zs;
333-
y_uncovered_item.ze = ze;
334-
node.y_uncovered_items.push_back(y_uncovered_item);
335-
}
336-
337-
// Compute node.z_uncovered_item.
338-
for (ZUncoveredItem z_uncovered_item: parent.z_uncovered_items) {
339-
update_z_uncovered_item(node.z_uncovered_items, z_uncovered_item, ys, ye, zs, ze);
340-
}
341-
{
342-
ZUncoveredItem z_uncovered_item;
343-
z_uncovered_item.xs = xs;
344-
z_uncovered_item.xe = xe;
345-
z_uncovered_item.ys = ys;
346-
z_uncovered_item.ye = ye;
347-
z_uncovered_item.z = ze;
348-
node.z_uncovered_items.push_back(z_uncovered_item);
385+
} else {
386+
// Compute node.uncovered_item.
387+
for (const UncoveredItem& uncovered_item: parent.uncovered_items)
388+
update_uncovered_item(node.uncovered_items, uncovered_item, ys, ye, zs, ze);
389+
node.uncovered_items.push_back(new_uncovered_item);
390+
391+
// Compute node.y_uncovered_item.
392+
for (const YUncoveredItem& y_uncovered_item: parent.y_uncovered_items)
393+
update_y_uncovered_item(node.y_uncovered_items, y_uncovered_item, new_uncovered_item);
394+
std::vector<YUncoveredItem> y_uncovered_items = {new_y_uncovered_item};
395+
std::vector<YUncoveredItem> y_uncovered_items_tmp;
396+
for (const UncoveredItem& uncovered_item: parent.uncovered_items) {
397+
for (const YUncoveredItem& y_uncovered_item: y_uncovered_items)
398+
update_y_uncovered_item(y_uncovered_items_tmp, y_uncovered_item, uncovered_item);
399+
y_uncovered_items.swap(y_uncovered_items_tmp);
400+
y_uncovered_items_tmp.clear();
401+
}
402+
for (const YUncoveredItem& y_uncovered_item: y_uncovered_items)
403+
node.y_uncovered_items.push_back(y_uncovered_item);
404+
405+
// Compute node.z_uncovered_item.
406+
for (ZUncoveredItem z_uncovered_item: parent.z_uncovered_items)
407+
update_z_uncovered_item(node.z_uncovered_items, z_uncovered_item, new_uncovered_item);
408+
std::vector<ZUncoveredItem> z_uncovered_items = {new_z_uncovered_item};
409+
std::vector<ZUncoveredItem> z_uncovered_items_tmp;
410+
for (const UncoveredItem& uncovered_item: parent.uncovered_items) {
411+
for (const ZUncoveredItem& z_uncovered_item: z_uncovered_items)
412+
update_z_uncovered_item(z_uncovered_items_tmp, z_uncovered_item, uncovered_item);
413+
z_uncovered_items.swap(z_uncovered_items_tmp);
414+
z_uncovered_items_tmp.clear();
415+
}
416+
for (const ZUncoveredItem& z_uncovered_item: z_uncovered_items)
417+
node.z_uncovered_items.push_back(z_uncovered_item);
349418
}
350419

351420
// Compute item_number_of_copies, number_of_items, items_area,
@@ -780,7 +849,6 @@ Solution BranchingScheme::to_solution(
780849

781850
Solution solution(instance());
782851
BinPos bin_pos = -1;
783-
std::map<std::tuple<BinPos, Length, Length>, StackId> coord2stack;
784852
for (auto current_node: descendents) {
785853
const Instance& instance = this->instance(current_node->last_bin_direction);
786854
if (current_node->number_of_bins > solution.number_of_bins())
@@ -791,6 +859,9 @@ Solution BranchingScheme::to_solution(
791859
Point bl_corner = convert_point_back(
792860
{current_node->x, current_node->y, current_node->z},
793861
current_node->last_bin_direction);
862+
int original_rotation = get_flipped_rotation(
863+
current_node->rotation,
864+
current_node->last_bin_direction);
794865
//std::cout
795866
// << " item_type_id " << current_node->item_type_id
796867
// << " x " << current_node->x
@@ -805,7 +876,7 @@ Solution BranchingScheme::to_solution(
805876
bin_pos,
806877
current_node->item_type_id,
807878
bl_corner,
808-
current_node->rotation);
879+
original_rotation);
809880
}
810881
return solution;
811882
}

src/box/branching_scheme.hpp

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -473,18 +473,12 @@ class BranchingScheme
473473
void update_y_uncovered_item(
474474
std::vector<YUncoveredItem>& y_uncovered_items,
475475
const YUncoveredItem& y_uncovered_item,
476-
Length ys,
477-
Length ye,
478-
Length zs,
479-
Length ze) const;
476+
const UncoveredItem& ref) const;
480477

481478
void update_z_uncovered_item(
482479
std::vector<ZUncoveredItem>& z_uncovered_items,
483480
const ZUncoveredItem& z_uncovered_item,
484-
Length ys,
485-
Length ye,
486-
Length zs,
487-
Length ze) const;
481+
const UncoveredItem& ref) const;
488482

489483
/** Insertion of one item in a new stack. */
490484
void insertion_item(

src/box/instance.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
#include <iostream>
44
#include <fstream>
5+
#include <bitset>
56

67
using namespace packingsolver;
78
using namespace packingsolver::box;
@@ -156,7 +157,7 @@ std::ostream& Instance::format(
156157
<< std::setw(10) << "Z"
157158
<< std::setw(12) << "Profit"
158159
<< std::setw(10) << "Copies"
159-
<< std::setw(10) << "Rot."
160+
<< std::setw(10) << "Rotations"
160161
<< std::setw(10) << "Weight"
161162
<< std::endl
162163
<< std::setw(10) << "---------"
@@ -179,7 +180,7 @@ std::ostream& Instance::format(
179180
<< std::setw(10) << item_type.box.z
180181
<< std::setw(12) << item_type.profit
181182
<< std::setw(10) << item_type.copies
182-
<< std::setw(10) << item_type.rotations
183+
<< std::setw(10) << std::bitset<6>(item_type.rotations)
183184
<< std::setw(10) << item_type.weight
184185
<< std::endl;
185186
}

0 commit comments

Comments
 (0)