codac 2.0.0
Loading...
Searching...
No Matches
codac2_PavingNode.h
Go to the documentation of this file.
1
9
10#pragma once
11
12#include <map>
13#include <memory>
14#include "codac2_Paving.h"
16
17namespace codac2
18{
19 template<typename P>
20 class PavingNode : public std::enable_shared_from_this<PavingNode<P>>
21 {
22 public:
23
24 explicit PavingNode(const P& paving, const IntervalVector& x, std::shared_ptr<PavingNode<P>> top = nullptr)
25 : _paving(paving), _x(P::init_tuple(x)), _top(top)
26 { }
27
28 const P& paving() const
29 {
30 return _paving;
31 }
32
33 const typename P::NodeTuple_& boxes() const
34 {
35 return _x;
36 }
37
38 typename P::NodeTuple_& boxes()
39 {
40 return const_cast<typename P::NodeTuple_&>(const_cast<const PavingNode<P>*>(this)->boxes());
41 }
42
43 void set_boxes(const typename P::NodeTuple_& x)
44 {
45 _x = x;
46 }
47
48 IntervalVector hull() const
49 {
50 IntervalVector h = std::get<0>(_x);
51 std::apply([&](auto &&... xs) { ((h |= xs), ...); }, _x);
52 return h;
53 }
54
55 IntervalVector unknown() const
56 {
57 IntervalVector h = std::get<0>(_x);
58 std::apply([&](auto &&... xs) { ((h &= xs), ...); }, _x);
59 return h;
60 }
61
62 std::shared_ptr<const PavingNode<P>> top() const
63 {
64 return _top;
65 }
66
67 std::shared_ptr<PavingNode<P>> top()
68 {
69 return std::const_pointer_cast<PavingNode<P>>(const_cast<const PavingNode<P>*>(this)->top());
70 }
71
72 std::shared_ptr<const PavingNode<P>> left() const
73 {
74 return _left;
75 }
76
77 std::shared_ptr<PavingNode<P>> left()
78 {
79 return std::const_pointer_cast<PavingNode<P>>(const_cast<const PavingNode<P>*>(this)->left());
80 }
81
82 std::shared_ptr<const PavingNode<P>> right() const
83 {
84 return _right;
85 }
86
87 std::shared_ptr<PavingNode<P>> right()
88 {
89 return std::const_pointer_cast<PavingNode<P>>(const_cast<const PavingNode<P>*>(this)->right());
90 }
91
92 // === Comment related to the following visit() methods:
93 // In some representations, the first level of the tree already holds a contraction
94 // and it is no longer possible to reconstruct the original hull box. This is the case
95 // for pavings built from contractors. Conversely, for those built from separators, the union
96 // of the separated boxes of the root allows to reconstruct the original hull box.
97 // Due to the first case, the classical tree structure is changed by duplicating the first
98 // level: the box of the root is the original one and there is only one (left) child
99 // holding the contracted box (the right child is disabled).
100 // Therefore, during the visiting process, the first level is ignored if it is redundant with
101 // the second one, as it is the case for pavings built from separators.
102
103 void visit(std::function<bool(std::shared_ptr<const PavingNode<P>>)> visitor) const
104 {
105 if(!_top && !_right && _left && left()->boxes() == _x)
106 left()->visit(visitor);
107
108 else if(visitor(this->shared_from_this()))
109 {
110 if(_left) left()->visit(visitor);
111 if(_right) right()->visit(visitor);
112 }
113 }
114
115 void visit(std::function<bool(std::shared_ptr<PavingNode<P>>)> visitor)
116 {
117 if(!_top && !_right && _left && left()->boxes() == _x)
118 _left->visit(visitor);
119
120 else if(visitor(this->shared_from_this()))
121 {
122 if(_left) left()->visit(visitor);
123 if(_right) right()->visit(visitor);
124 }
125 }
126
127 bool is_leaf() const
128 {
129 return not _left && not _right;
130 }
131
132 void bisect()
133 {
134 bisect([](const IntervalVector& x) { return x.bisect_largest(); });
135 }
136
137 void bisect(std::function<std::pair<IntervalVector,IntervalVector>(const IntervalVector&)> bisect_fnc)
138 {
139 assert_release(is_leaf() && "only leaves can be bisected");
140
141 bool bisectable_node = true;
142 std::apply([&](auto &&... xs) { ((bisectable_node &= xs.is_bisectable()), ...); }, _x);
143 assert_release(bisectable_node);
144
145 auto p = bisect_fnc(unknown());
146
147 _left = make_shared<PavingNode<P>>(_paving, p.first, this->shared_from_this());
148 _right = make_shared<PavingNode<P>>(_paving, p.second, this->shared_from_this());
149 }
150
151 std::vector<IntervalVector> complementary_value(const typename P::NodeValue_& node_value) const
152 {
153 return hull().diff(node_value(_x));
154 }
155
156 protected:
157
158 const P& _paving;
159 typename P::NodeTuple_ _x;
160 std::shared_ptr<PavingNode<P>> _top = nullptr;
161 std::shared_ptr<PavingNode<P>> _left = nullptr, _right = nullptr;
162 };
163}