codac 2.0.0
Loading...
Searching...
No Matches
codac2_Paving.h
Go to the documentation of this file.
1
9
10#pragma once
11
12#include <map>
13#include <memory>
14#include "codac2_PavingNode.h"
15
16namespace codac2
17{
18 template<typename P>
19 class PavingNode;
20
21 template<typename P>
22 class Subpaving;
23
24 template<typename P,typename... X>
25 requires (std::is_same_v<X,IntervalVector> && ...)
26 class Paving : public Domain
27 {
28 public:
29
30 using Node_ = std::shared_ptr<const PavingNode<P>>;
31 using NodeTuple_ = std::tuple<X...>;
32 using NodeValue_ = std::function<std::list<IntervalVector>(Node_)>;
33 using ConnectedSubset_ = Subpaving<P>;
34
35 Paving(Index n)
36 : Paving(IntervalVector(n))
37 {
38 assert_release(n > 0);
39 }
40
41 Paving(const IntervalVector& x)
42 : _tree(std::make_shared<PavingNode<P>>(*static_cast<P*>(this), x))
43 { }
44
45 inline Index size() const
46 {
47 return std::get<0>(_tree->boxes()).size();
48 }
49
50 inline std::shared_ptr<const PavingNode<P>> tree() const
51 {
52 return _tree;
53 }
54
55 inline std::shared_ptr<PavingNode<P>> tree()
56 {
57 return std::const_pointer_cast<PavingNode<P>>(const_cast<const Paving<P,X...>*>(this)->tree());
58 }
59
60 inline std::list<IntervalVector> boxes(const NodeValue_& node_value) const
61 {
62 return boxes(node_value, IntervalVector(size()));
63 }
64
65 inline std::list<IntervalVector> boxes(const NodeValue_& node_value, const IntervalVector& intersecting_box) const
66 {
67 std::list<IntervalVector> l;
68
69 this->tree()->visit([&]
70 (Node_ n)
71 {
72 for(const auto& bi : node_value(n))
73 if(bi.intersects(intersecting_box))
74 l.push_back(bi);
75 return n->hull().intersects(intersecting_box);
76 });
77
78 if(l.empty())
79 l.push_back(IntervalVector::empty(this->size()));
80 return l;
81 }
82
83 inline std::list<ConnectedSubset_> connected_subsets(const NodeValue_& node_value) const
84 {
85 return connected_subsets(IntervalVector(size()), node_value);
86 }
87
88 inline std::list<ConnectedSubset_> connected_subsets(const IntervalVector& x0, const NodeValue_& node_value) const
89 {
90 std::list<IntervalVector> l_boxes = boxes(node_value, x0);
91 [[maybe_unused]] Index nb_boxes = l_boxes.size();
92 std::list<ConnectedSubset_> l_subsets;
93
94 while(!l_boxes.empty())
95 {
96 auto current_box = l_boxes.front();
97 l_subsets.push_back({ current_box });
98 l_boxes.pop_front();
99
100 std::list<IntervalVector> l_neighbouring_boxes_to_visit { current_box };
101
102 do
103 {
104 current_box = l_neighbouring_boxes_to_visit.front();
105 l_neighbouring_boxes_to_visit.pop_front();
106
107 for(const auto& ni : boxes(node_value, current_box))
108 {
109 if(std::find(l_boxes.begin(), l_boxes.end(), ni) != l_boxes.end())
110 {
111 l_boxes.remove(ni);
112 l_neighbouring_boxes_to_visit.push_back(ni);
113 l_subsets.back().push_back(ni);
114 }
115 }
116
117 } while(!l_neighbouring_boxes_to_visit.empty());
118 }
119
120 assert(l_boxes.empty() && "all the nodes should have been visited");
121 assert([&]() -> bool { Index s = 0; for(const auto& si : l_subsets) s += si.size(); return s == nb_boxes; } ()
122 && "the total number of boxes should match the sum of number of boxes of each subset");
123
124 return l_subsets;
125 }
126
127 protected:
128
129 friend class PavingNode<P>;
130
131 inline static NodeTuple_ init_tuple(const IntervalVector& x)
132 {
133 return std::make_tuple(((X)x)...);
134 }
135
136 std::shared_ptr<PavingNode<P>> _tree; // must be a shared_ptr to allow enable_shared_from_this
137 };
138
139
140 class PavingOut;
141 using PavingOut_Node = PavingNode<PavingOut>;
142
143 class PavingOut : public Paving<PavingOut,IntervalVector>
144 {
145 public:
146
147 PavingOut(Index n);
148 PavingOut(const IntervalVector& x);
149
150 std::list<PavingOut::ConnectedSubset_> connected_subsets(const PavingOut::NodeValue_& node_value = PavingOut::outer) const;
151 std::list<PavingOut::ConnectedSubset_> connected_subsets(const IntervalVector& x0, const PavingOut::NodeValue_& node_value = PavingOut::outer) const;
152
153 inline IntervalVector operator&(const IntervalVector& x) const
154 {
155 assert_release(x.size() == this->size());
156
157 IntervalVector x_ = IntervalVector::empty(x.size());
158
159 if(x.is_empty())
160 return x_;
161
162 this->tree()->visit([&]
163 (Node_ n)
164 {
165 for(const auto& bi : PavingOut::outer(n))
166 x_ |= bi & x;
167 return n->hull().intersects(x);
168 });
169 assert(x_.is_subset(x));
170 return x_;
171 }
172
173 static const NodeValue_ outer, outer_complem;
174 };
175
176
177 class PavingInOut;
178 using PavingInOut_Node = PavingNode<PavingInOut>;
179
180 class PavingInOut : public Paving<PavingInOut,IntervalVector,IntervalVector>
181 {
182 public:
183
184 PavingInOut(Index n);
185 PavingInOut(const IntervalVector& x);
186
187 std::list<PavingInOut::ConnectedSubset_> connected_subsets(const PavingInOut::NodeValue_& node_value = PavingInOut::outer) const;
188 std::list<PavingInOut::ConnectedSubset_> connected_subsets(const IntervalVector& x0, const PavingInOut::NodeValue_& node_value = PavingInOut::outer) const;
189
190 static const NodeValue_ outer, outer_complem, inner, bound, all;
191 };
192}
Definition codac2_OctaSym.h:21
Eigen::Matrix< Interval,-1, 1 > IntervalVector
Alias for a dynamic-size column vector of intervals.
Definition codac2_IntervalVector.h:25