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 protected:
36
37 Paving()
38 { }
39
40 public:
41
42 inline Index size() const
43 {
44 return std::get<0>(_tree->boxes()).size();
45 }
46
47 inline std::shared_ptr<const PavingNode<P>> tree() const
48 {
49 return _tree;
50 }
51
52 inline std::shared_ptr<PavingNode<P>> tree()
53 {
54 return std::const_pointer_cast<PavingNode<P>>(const_cast<const Paving<P,X...>*>(this)->tree());
55 }
56
57 inline std::list<IntervalVector> boxes(const NodeValue_& node_value) const
58 {
59 return boxes(node_value, IntervalVector(size()));
60 }
61
62 inline std::list<IntervalVector> boxes(const NodeValue_& node_value, const IntervalVector& intersecting_box) const
63 {
64 std::list<IntervalVector> l;
65
66 this->tree()->visit([&]
67 (Node_ n)
68 {
69 for(const auto& bi : node_value(n))
70 if(bi.intersects(intersecting_box))
71 l.push_back(bi);
72 return n->hull().intersects(intersecting_box);
73 });
74
75 if(l.empty())
76 l.push_back(IntervalVector::empty(this->size()));
77 return l;
78 }
79
80 inline std::list<ConnectedSubset_> connected_subsets(const NodeValue_& node_value) const
81 {
82 return connected_subsets(IntervalVector(size()), node_value);
83 }
84
85 inline std::list<ConnectedSubset_> connected_subsets(const IntervalVector& x0, const NodeValue_& node_value) const
86 {
87 std::list<IntervalVector> l_boxes = boxes(node_value, x0);
88 [[maybe_unused]] Index nb_boxes = l_boxes.size();
89 std::list<ConnectedSubset_> l_subsets;
90
91 while(!l_boxes.empty())
92 {
93 auto current_box = l_boxes.front();
94 l_subsets.push_back({ current_box });
95 l_boxes.pop_front();
96
97 std::list<IntervalVector> l_neighbouring_boxes_to_visit { current_box };
98
99 do
100 {
101 current_box = l_neighbouring_boxes_to_visit.front();
102 l_neighbouring_boxes_to_visit.pop_front();
103
104 for(const auto& ni : boxes(node_value, current_box))
105 {
106 if(std::find(l_boxes.begin(), l_boxes.end(), ni) != l_boxes.end())
107 {
108 l_boxes.remove(ni);
109 l_neighbouring_boxes_to_visit.push_back(ni);
110 l_subsets.back().push_back(ni);
111 }
112 }
113
114 } while(!l_neighbouring_boxes_to_visit.empty());
115 }
116
117 assert(l_boxes.empty() && "all the nodes should have been visited");
118 assert([&]() -> bool { Index s = 0; for(const auto& si : l_subsets) s += si.size(); return s == nb_boxes; } ()
119 && "the total number of boxes should match the sum of number of boxes of each subset");
120
121 return l_subsets;
122 }
123
124 protected:
125
126 friend class PavingNode<P>;
127
128 inline void init_tree(const IntervalVector& x)
129 {
130 _tree = std::make_shared<PavingNode<P>>(*static_cast<P*>(this), x);
131 }
132
133 inline static NodeTuple_ init_tuple(const IntervalVector& x)
134 {
135 return std::make_tuple(((X)x)...);
136 }
137
138 std::shared_ptr<PavingNode<P>> _tree; // must be a shared_ptr to allow enable_shared_from_this
139 };
140
141
142 class PavingOut;
143 using PavingOut_Node = PavingNode<PavingOut>;
144
145 class PavingOut : public Paving<PavingOut,IntervalVector>
146 {
147 public:
148
149 PavingOut(Index n);
150 PavingOut(const IntervalVector& x);
151
152 std::list<PavingOut::ConnectedSubset_> connected_subsets(const PavingOut::NodeValue_& node_value = PavingOut::outer) const;
153 std::list<PavingOut::ConnectedSubset_> connected_subsets(const IntervalVector& x0, const PavingOut::NodeValue_& node_value = PavingOut::outer) const;
154
155 inline IntervalVector operator&(const IntervalVector& x) const
156 {
157 assert_release(x.size() == this->size());
158
159 IntervalVector x_ = IntervalVector::empty(x.size());
160
161 if(x.is_empty())
162 return x_;
163
164 // The parts of the box that are outside of the paving can not be contracted
165 auto d = x.diff(this->tree()->hull());
166 for(const auto& di : d)
167 x_ |= di;
168
169 this->tree()->visit([&]
170 (Node_ n)
171 {
172 for(const auto& bi : PavingOut::outer(n))
173 x_ |= bi & x;
174 return n->hull().intersects(x);
175 });
176 assert(x_.is_subset(x));
177 return x_;
178 }
179
180 static const NodeValue_ outer, outer_complem;
181 };
182
183 IntervalVector operator&(const IntervalVector& x, const PavingOut& p);
184
185
186 class PavingInOut;
187 using PavingInOut_Node = PavingNode<PavingInOut>;
188
189 class PavingInOut : public Paving<PavingInOut,IntervalVector,IntervalVector>
190 {
191 public:
192
193 PavingInOut(Index n);
194 PavingInOut(const IntervalVector& x);
195
196 std::list<PavingInOut::ConnectedSubset_> connected_subsets(const PavingInOut::NodeValue_& node_value = PavingInOut::outer) const;
197 std::list<PavingInOut::ConnectedSubset_> connected_subsets(const IntervalVector& x0, const PavingInOut::NodeValue_& node_value = PavingInOut::outer) const;
198
199 static const NodeValue_ outer, outer_complem, inner, bound, all;
200 };
201}
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
CtcInterType< typenameC1::ContractedTypes >::Ctc operator&(const C1 &c1, const C2 &c2)
Builds an intersection contractor from two contractors.
Definition codac2_CtcInter.h:230