Skip to content

Commit aa35eb9

Browse files
authored
JSON search tree (#175)
* Add JSON search tree output for irregular problems * Save current state * Update JSON search tree output * Fix treesearchsolver dependency * Fix json search tree output * Update json export * Update json export * Update treesearchsolver dependency
1 parent 12a6173 commit aa35eb9

File tree

9 files changed

+268
-132
lines changed

9 files changed

+268
-132
lines changed

extern/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ FetchContent_MakeAvailable(knapsacksolver)
5050
FetchContent_Declare(
5151
treesearchsolver
5252
GIT_REPOSITORY https://github.com/fontanf/treesearchsolver.git
53-
GIT_TAG 985b0d81868cf636d3577f6e88dcad14425345ea
53+
GIT_TAG 32da334a71c5039ab031f5e7d949e4d135832352
5454
#SOURCE_DIR "${PROJECT_SOURCE_DIR}/../treesearchsolver/"
5555
EXCLUDE_FROM_ALL)
5656
FetchContent_MakeAvailable(treesearchsolver)

include/packingsolver/algorithms/common.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,9 @@ struct Parameters: optimizationtools::Parameters
300300

301301
/** New solution callback. */
302302
NewSolutionCallback<Instance, Solution> new_solution_callback = [](const Output<Instance, Solution>&) { };
303+
304+
/** JSON search tree path. */
305+
std::string json_search_tree_path;
303306
};
304307

305308
template <typename Instance>

include/packingsolver/irregular/shape.hpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,8 @@ struct ShapeElement
145145
ShapeElement axial_symmetry_y_axis() const;
146146

147147
std::string to_string() const;
148+
149+
nlohmann::json to_json() const;
148150
};
149151

150152
/**
@@ -232,6 +234,8 @@ struct Shape
232234

233235
std::string to_string(Counter indentation) const;
234236

237+
nlohmann::json to_json() const;
238+
235239
std::string to_svg(double factor) const;
236240

237241
void write_svg(

src/irregular/branching_scheme.cpp

Lines changed: 186 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -95,27 +95,7 @@ BranchingScheme::BranchingScheme(
9595
//std::cout << "bin_type_id " << bin_type_id << std::endl;
9696
const BinType& bin_type = instance().bin_type(bin_type_id);
9797
BranchingSchemeBinType& bb_bin_type = bin_types_[(int)direction][bin_type_id];
98-
Shape bin_shape = bin_type.shape;
99-
if (direction == Direction::LeftToRightThenTopToBottom) {
100-
bin_shape = bin_shape.axial_symmetry_x_axis();
101-
} else if (direction == Direction::RightToLeftThenBottomToTop) {
102-
bin_shape = bin_shape.axial_symmetry_y_axis();
103-
} else if (direction == Direction::RightToLeftThenTopToBottom) {
104-
bin_shape = bin_shape.axial_symmetry_x_axis();
105-
bin_shape = bin_shape.axial_symmetry_y_axis();
106-
} else if (direction == Direction::BottomToTopThenLeftToRight) {
107-
bin_shape = bin_shape.axial_symmetry_identity_line();
108-
} else if (direction == Direction::BottomToTopThenRightToLeft) {
109-
bin_shape = bin_shape.axial_symmetry_identity_line();
110-
bin_shape = bin_shape.axial_symmetry_x_axis();
111-
} else if (direction == Direction::TopToBottomThenLeftToRight) {
112-
bin_shape = bin_shape.axial_symmetry_identity_line();
113-
bin_shape = bin_shape.axial_symmetry_y_axis();
114-
} else if (direction == Direction::TopToBottomThenRightToLeft) {
115-
bin_shape = bin_shape.axial_symmetry_identity_line();
116-
bin_shape = bin_shape.axial_symmetry_y_axis();
117-
bin_shape = bin_shape.axial_symmetry_x_axis();
118-
}
98+
Shape bin_shape = convert_shape(bin_type.shape, direction);
11999

120100
auto mm = bin_shape.compute_min_max();
121101
bb_bin_type.x_min = mm.first.x;
@@ -755,6 +735,58 @@ BranchingScheme::BranchingScheme(
755735
}
756736
}
757737

738+
Shape BranchingScheme::convert_shape(
739+
Shape shape,
740+
Direction direction) const
741+
{
742+
if (direction == Direction::LeftToRightThenTopToBottom) {
743+
shape = shape.axial_symmetry_x_axis();
744+
} else if (direction == Direction::RightToLeftThenBottomToTop) {
745+
shape = shape.axial_symmetry_y_axis();
746+
} else if (direction == Direction::RightToLeftThenTopToBottom) {
747+
shape = shape.axial_symmetry_x_axis();
748+
shape = shape.axial_symmetry_y_axis();
749+
} else if (direction == Direction::BottomToTopThenLeftToRight) {
750+
shape = shape.axial_symmetry_identity_line();
751+
} else if (direction == Direction::BottomToTopThenRightToLeft) {
752+
shape = shape.axial_symmetry_identity_line();
753+
shape = shape.axial_symmetry_x_axis();
754+
} else if (direction == Direction::TopToBottomThenLeftToRight) {
755+
shape = shape.axial_symmetry_identity_line();
756+
shape = shape.axial_symmetry_y_axis();
757+
} else if (direction == Direction::TopToBottomThenRightToLeft) {
758+
shape = shape.axial_symmetry_identity_line();
759+
shape = shape.axial_symmetry_y_axis();
760+
shape = shape.axial_symmetry_x_axis();
761+
}
762+
return shape;
763+
}
764+
765+
Point BranchingScheme::convert_point_back(
766+
const Point& point,
767+
Direction direction) const
768+
{
769+
if (direction == Direction::LeftToRightThenBottomToTop) {
770+
return Point{point.x, point.y};
771+
} else if (direction == Direction::LeftToRightThenTopToBottom) {
772+
return Point{point.x, -point.y};
773+
} else if (direction == Direction::RightToLeftThenBottomToTop) {
774+
return Point{-point.x, point.y};
775+
} else if (direction == Direction::RightToLeftThenTopToBottom) {
776+
return Point{-point.x, -point.y};
777+
} else if (direction == Direction::BottomToTopThenLeftToRight) {
778+
return Point{point.y, point.x};
779+
} else if (direction == Direction::BottomToTopThenRightToLeft) {
780+
return Point{-point.y, point.x};
781+
} else if (direction == Direction::TopToBottomThenLeftToRight) {
782+
return Point{point.y, -point.x};
783+
} else if (direction == Direction::TopToBottomThenRightToLeft) {
784+
return Point{-point.y, -point.x};
785+
}
786+
throw std::runtime_error("");
787+
return Point();
788+
}
789+
758790
void BranchingScheme::compute_inflated_trapezoid_sets()
759791
{
760792
for (Direction direction: {
@@ -2333,24 +2365,7 @@ Solution BranchingScheme::to_solution(
23332365
bin_pos = solution.add_bin(instance().bin_type_id(current_node->number_of_bins - 1), 1);
23342366

23352367
const TrapezoidSet& trapezoid_set = trapezoid_sets_[(int)current_node->last_bin_direction][current_node->trapezoid_set_id];
2336-
Point bl_corner = {0, 0};
2337-
if (current_node->last_bin_direction == Direction::LeftToRightThenBottomToTop) {
2338-
bl_corner = Point{current_node->x, current_node->y};
2339-
} else if (current_node->last_bin_direction == Direction::LeftToRightThenTopToBottom) {
2340-
bl_corner = Point{current_node->x, -current_node->y};
2341-
} else if (current_node->last_bin_direction == Direction::RightToLeftThenBottomToTop) {
2342-
bl_corner = Point{-current_node->x, current_node->y};
2343-
} else if (current_node->last_bin_direction == Direction::RightToLeftThenTopToBottom) {
2344-
bl_corner = Point{-current_node->x, -current_node->y};
2345-
} else if (current_node->last_bin_direction == Direction::BottomToTopThenLeftToRight) {
2346-
bl_corner = Point{current_node->y, current_node->x};
2347-
} else if (current_node->last_bin_direction == Direction::BottomToTopThenRightToLeft) {
2348-
bl_corner = Point{-current_node->y, current_node->x};
2349-
} else if (current_node->last_bin_direction == Direction::TopToBottomThenLeftToRight) {
2350-
bl_corner = Point{current_node->y, -current_node->x};
2351-
} else if (current_node->last_bin_direction == Direction::TopToBottomThenRightToLeft) {
2352-
bl_corner = Point{-current_node->y, -current_node->x};
2353-
}
2368+
Point bl_corner = convert_point_back({current_node->x, current_node->y}, current_node->last_bin_direction);
23542369
//std::cout << "bin_pos " << bin_pos
23552370
// << " item_type_id " << trapezoid_set.item_type_id
23562371
// << " bl_corner " << bl_corner.to_string()
@@ -2389,6 +2404,138 @@ Solution BranchingScheme::to_solution(
23892404
////////////////////////////////////////////////////////////////////////////////
23902405
////////////////////////////////////////////////////////////////////////////////
23912406

2407+
nlohmann::json BranchingScheme::json_export_init() const
2408+
{
2409+
const auto& trapezoid_sets = trapezoid_sets_[(int)Direction::LeftToRightThenBottomToTop];
2410+
nlohmann::json json_init;
2411+
Counter i = 0;
2412+
2413+
// Bins.
2414+
json_bins_init_ids_ = std::vector<Counter>(instance().number_of_bin_types(), -1);
2415+
for (BinTypeId bin_type_id = 0;
2416+
bin_type_id < instance().number_of_bin_types();
2417+
++bin_type_id) {
2418+
const BinType& bin_type = instance().bin_type(bin_type_id);
2419+
2420+
json_bins_init_ids_[bin_type_id] = i;
2421+
json_init[i][0] = {
2422+
{"Shape", bin_type.shape.to_json()},
2423+
{"FillColor", ""},
2424+
};
2425+
for (DefectId defect_id = 0;
2426+
defect_id < (DefectId)bin_type.defects.size();
2427+
++defect_id) {
2428+
const Defect& defect = bin_type.defects[defect_id];
2429+
json_init[i][defect_id + 1] = {
2430+
{"Shape", bin_type.shape.to_json()},
2431+
{"FillColor", "red"},
2432+
};
2433+
for (Counter hole_pos = 0;
2434+
hole_pos < (Counter)defect.holes.size();
2435+
++hole_pos) {
2436+
const Shape& hole = defect.holes[hole_pos];
2437+
json_init[i][hole_pos]["Holes"][hole_pos] = hole.to_json();
2438+
}
2439+
}
2440+
i++;
2441+
}
2442+
2443+
// Items.
2444+
json_items_init_ids_ = std::vector<std::vector<std::unordered_map<double, Counter>>>(instance().number_of_item_types());
2445+
for (ItemTypeId item_type_id = 0;
2446+
item_type_id < instance().number_of_item_types();
2447+
++item_type_id) {
2448+
const ItemType& item_type = instance().item_type(item_type_id);
2449+
2450+
json_items_init_ids_[item_type_id] = std::vector<std::unordered_map<double, Counter>>(2);
2451+
for (bool mirror: {false, true}) {
2452+
2453+
for (const auto& angle_range: item_type.allowed_rotations) {
2454+
2455+
json_items_init_ids_[item_type_id][mirror][angle_range.first] = i;
2456+
2457+
for (ItemShapePos item_shape_pos = 0;
2458+
item_shape_pos < (ItemShapePos)item_type.shapes.size();
2459+
++item_shape_pos) {
2460+
const ItemShape& item_shape = item_type.shapes[item_shape_pos];
2461+
Shape shape = (!mirror)?
2462+
item_shape.shape:
2463+
item_shape.shape.axial_symmetry_y_axis();
2464+
shape = shape.rotate(angle_range.first);
2465+
json_init[i][item_shape_pos] = {
2466+
{"Shape", shape.to_json()},
2467+
{"FillColor", "blue"},
2468+
};
2469+
for (Counter hole_pos = 0;
2470+
hole_pos < (Counter)item_shape.holes.size();
2471+
++hole_pos) {
2472+
const Shape& hole = item_shape.holes[hole_pos];
2473+
json_init[i][item_shape_pos]["Holes"][hole_pos] = hole.to_json();
2474+
}
2475+
}
2476+
i++;
2477+
}
2478+
}
2479+
}
2480+
2481+
return json_init;
2482+
}
2483+
2484+
nlohmann::json BranchingScheme::json_export(
2485+
const std::shared_ptr<Node>& node) const
2486+
{
2487+
const TrapezoidSet& trapezoid_set = trapezoid_sets_[(int)node->last_bin_direction][node->trapezoid_set_id];
2488+
Point bl_orig = convert_point_back({node->x, node->y}, node->last_bin_direction);
2489+
nlohmann::json json = {
2490+
{"Id", node->id},
2491+
{"ParentId", (node->parent == nullptr)? -1: node->parent->id},
2492+
{"TrapezoidSetId", node->trapezoid_set_id},
2493+
{"ItemTypeId", trapezoid_set.item_type_id},
2494+
{"Angle", trapezoid_set.angle},
2495+
{"Mirror", trapezoid_set.mirror},
2496+
{"X", node->x},
2497+
{"Y", node->y},
2498+
{"XOrig", bl_orig.x},
2499+
{"YOrig", bl_orig.y},
2500+
{"NumberOfItems", node->number_of_items},
2501+
{"NumberOfBins", node->number_of_bins},
2502+
{"Profit", node->profit},
2503+
{"ItemArea", node->item_area},
2504+
{"ItemConvexHullArea", node->item_convex_hull_area},
2505+
{"GuideArea", node->guide_area},
2506+
};
2507+
if (node->number_of_items == 0)
2508+
return json;
2509+
2510+
nlohmann::json plot;
2511+
Counter i = 0;
2512+
// Plot bin.
2513+
BinTypeId bin_type_id = instance().bin_type_id(node->number_of_bins - 1);
2514+
plot[i] = {
2515+
{"Id",json_bins_init_ids_[bin_type_id]},
2516+
{"X", 0},
2517+
{"Y", 0},
2518+
};
2519+
i++;
2520+
// Plot items.
2521+
for (std::shared_ptr<const Node> node_tmp = node;
2522+
node_tmp->number_of_bins == node->number_of_bins;
2523+
node_tmp = node_tmp->parent) {
2524+
const TrapezoidSet& trapezoid_set = trapezoid_sets_[(int)node_tmp->last_bin_direction][node_tmp->trapezoid_set_id];
2525+
Point bl_corner = convert_point_back({node_tmp->x, node_tmp->y}, node_tmp->last_bin_direction);
2526+
plot[i] = {
2527+
{"Id", json_items_init_ids_[trapezoid_set.item_type_id][trapezoid_set.mirror].at(trapezoid_set.angle)},
2528+
{"X", bl_corner.x},
2529+
{"Y", bl_corner.y},
2530+
};
2531+
if (node_tmp == node)
2532+
plot[i]["FillColor"] = "green";
2533+
i++;
2534+
}
2535+
json["Plot"] = plot;
2536+
return json;
2537+
}
2538+
23922539
void BranchingScheme::write_svg(
23932540
const std::shared_ptr<Node>& node,
23942541
const std::string& file_path) const

src/irregular/branching_scheme.hpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -413,10 +413,18 @@ class BranchingScheme
413413
Solution to_solution(
414414
const std::shared_ptr<Node>& node) const;
415415

416+
std::string to_svg(
417+
const std::shared_ptr<Node>& node) const;
418+
416419
void write_svg(
417420
const std::shared_ptr<Node>& node,
418421
const std::string& file_path) const;
419422

423+
nlohmann::json json_export_init() const;
424+
425+
nlohmann::json json_export(
426+
const std::shared_ptr<Node>& node) const;
427+
420428
private:
421429

422430
/** Instance. */
@@ -438,6 +446,10 @@ class BranchingScheme
438446

439447
std::vector<AreaDbl> item_types_convex_hull_area_;
440448

449+
mutable std::vector<std::vector<std::unordered_map<Angle, Counter>>> json_items_init_ids_;
450+
451+
mutable std::vector<Counter> json_bins_init_ids_;
452+
441453
mutable Counter node_id_ = 0;
442454

443455
mutable std::vector<GeneralizedTrapezoid> uncovered_trapezoids_cur_;
@@ -446,6 +458,14 @@ class BranchingScheme
446458
* Private methods
447459
*/
448460

461+
Shape convert_shape(
462+
Shape shape,
463+
Direction direction) const;
464+
465+
Point convert_point_back(
466+
const Point& point,
467+
Direction direction) const;
468+
449469
/** Get the percentage of item inserted into a node. */
450470
inline double item_percentage(const Node& node) const { return (double)node.number_of_items / instance().number_of_items(); }
451471

0 commit comments

Comments
 (0)