bux API Reference 1.9.0
Static library of whatever are seen required in general purpose but not directly supported from Modern C++. Or whatever reusable originated from my side projects.
Loading...
Searching...
No Matches
PartialOrdering.h
Go to the documentation of this file.
1#pragma once
2
3#include <concepts> // std::constructible_from<>, std::equality_comparable<>, std::invocable<>
4#include <list> // std::list<>
5
6namespace bux {
7
8//
9// Types
10//
16
17template<std::equality_comparable T>
24{
25public:
26
27 // Types
28 typedef std::list<T> C_ValList;
29
30 // Nonvirtuals
31 template<class T1, class T2>
32 [[nodiscard]]bool addOrder(T1 a, T2 b);
33 // Return true if given order (a,b) is successfully added
34 template<class T2>
35 bool anyLeft(const T2 &R) const;
36 template<class T2>
37 bool anyRight(const T2 &L) const;
38 void clear() { m_Relation.clear(); }
39 std::size_t depthToLeft(T t) const;
40 // Return 0 for the leftmosts.
41 bool empty() const { return m_Relation.empty(); }
42 template<class T2, class F>
43 void getRelated(T2 L, F R, std::size_t maxDepth = 0) const requires std::constructible_from<T,T2> && std::invocable<F,T>;
44 template<class F>
45 void getRelated(C_ValList L, F R, std::size_t maxDepth = 0) const requires std::invocable<F,T>;
46 template<class F, class T2>
47 void getRelated(F L, T2 R, std::size_t maxDepth = 0) const requires std::constructible_from<T,T2> && std::invocable<F,T>;
48 template<class F>
49 void getRelated(F L, C_ValList R, std::size_t maxDepth = 0) const requires std::invocable<F,T>;
50 template<class F>
51 void makeLinear(F apply, E_MakeLinearPolicy policy = MLP_BREADTH_FIRST) const requires std::invocable<F,T>;
52 bool related(const T &a, const T &b) const;
53
54private:
55
56 // Data
57 std::list<std::pair<T,T>> m_Relation;
58
59 // Nonvirtuals
60 bool find(const C_ValList &src, T t) const;
61 void pruneLeftmost(C_ValList &l, const C_ValList &r) const;
62};
63
64//
65// Function Templates
66//
67template<class C, class T>
68void addUnique(C &c, T &&value)
69{
70 for (auto &i: c)
71 if (i == value)
72 return;
73
74 c.emplace_back(std::forward<T>(value));
75}
76
77//
78// Implement Class Templates
79//
80template<std::equality_comparable T>
81template<class T1, class T2>
83{
84 if (a == b)
85 return false;
86
87 if (related(b, a))
88 // Looping
89 return false;
90
91 for (auto &i: m_Relation)
92 if (a == i.first && b == i.second)
93 // Already added
94 return true;
95
96 m_Relation.emplace_back(a, b);
97 return true;
98}
99
100template<std::equality_comparable T>
102{
103 std::size_t ret =0;
104 for (auto &i: m_Relation)
105 if (t == i.second)
106 {
107 const std::size_t cur = depthToLeft(i.first) +1;
108 if (cur > ret)
109 ret = cur;
110 }
111 return ret;
112}
113
114template<std::equality_comparable T>
115bool C_PartialOrdering<T>::find(const C_ValList &src, T t) const
116{
117 for (auto &i: src)
118 if (t == i)
119 return true;
120
121 return false;
122}
123
124template<std::equality_comparable T>
125template<class T2>
126bool C_PartialOrdering<T>::anyLeft(const T2 &R) const
127{
128 for (auto &i: m_Relation)
129 if (i.second == R)
130 return true;
131
132 return false;
133}
134
135template<std::equality_comparable T>
136template<class T2>
137bool C_PartialOrdering<T>::anyRight(const T2 &L) const
138{
139 for (auto &i: m_Relation)
140 if (L == i.first)
141 return true;
142
143 return false;
144}
145
146template<std::equality_comparable T>
147template<class T2, class F>
148void C_PartialOrdering<T>::getRelated(T2 L, F R, std::size_t maxDepth) const requires std::constructible_from<T,T2> && std::invocable<F,T>
149{
150 getRelated({1, std::forward<T2>(L)}, R, maxDepth);
151}
152
153template<std::equality_comparable T>
154template<class F, class T2>
155void C_PartialOrdering<T>::getRelated(F L, T2 R, std::size_t maxDepth) const requires std::constructible_from<T,T2> && std::invocable<F,T>
156{
157 getRelated(L, {1, std::forward<T2>(R)}, maxDepth);
158}
159
160template<std::equality_comparable T>
161template<class F>
162void C_PartialOrdering<T>::getRelated(C_ValList L, F R, std::size_t maxDepth) const requires std::invocable<F,T>
163{
164 std::size_t oldSize = 0;
165 C_ValList dst;
166 for (std::size_t depth = 0; !maxDepth || depth < maxDepth; ++depth)
167 {
168 for (auto &i: m_Relation)
169 for (auto &j: L)
170 if (j == i.first)
171 addUnique(dst, i.second);
172
173 if (oldSize == dst.size())
174 break;
175
176 auto iDst = dst.begin();
177 std::advance(iDst, oldSize);
178 L.assign(iDst, dst.end());
179 oldSize = dst.size();
180 }
181 for (auto &i: dst)
182 R(i);
183}
184
185template<std::equality_comparable T>
186template<class F>
187void C_PartialOrdering<T>::getRelated(F L, C_ValList R, std::size_t maxDepth) const requires std::invocable<F,T>
188{
189 std::size_t oldSize = 0;
190 C_ValList dst;
191 for (std::size_t depth = 0; !maxDepth || depth < maxDepth; ++depth)
192 {
193 for (auto &i: m_Relation)
194 for (auto &j: R)
195 if (j == i.second)
196 addUnique(dst, i.first);
197
198 if (oldSize == dst.size())
199 break;
200
201 auto iDst = dst.begin();
202 std::advance(iDst, oldSize);
203 R.assign(iDst, dst.end());
204 oldSize = dst.size();
205 }
206 for (auto &i: dst)
207 L(i);
208}
209
210template<std::equality_comparable T>
211template<class F>
212void C_PartialOrdering<T>::makeLinear(F apply, E_MakeLinearPolicy policy) const requires std::invocable<F,T>
213{
237 C_ValList q, r;
238 auto mapping = m_Relation;
239 for (auto &i: mapping)
240 {
241 addUnique(q, i.first);
242 addUnique(r, i.second);
243 }
244 pruneLeftmost(q, r);
245
246 while (!q.empty())
247 {
248 const T t =q.front();
249 q.pop_front();
250 apply(t);
251
252 C_ValList l;
253 r.clear();
254 for (auto i = mapping.begin(), end = mapping.end(); i != end;)
255 {
256 if (t == i->first)
257 {
258 addUnique(l, i->second);
259 i = mapping.erase(i);
260 }
261 else
262 {
263 addUnique(r, i->second);
264 ++i;
265 }
266 }
267
268 pruneLeftmost(l, r);
269 switch (policy)
270 {
272 q.splice(q.end(), l);
273 break;
274 case MLP_DEPTH_FIRST:
275 q.splice(q.begin(), l);
276 break;
277 }
278 }
279}
280
281template<std::equality_comparable T>
283{
284 for (auto i = l.begin(), end = l.end(); i != end;)
285 {
286 if (find(r, *i))
287 i = l.erase(i);
288 else
289 ++i;
290 }
291}
292
293template<std::equality_comparable T>
294bool C_PartialOrdering<T>::related(const T &a, const T &b) const
295{
296 for (auto &i: m_Relation)
297 if (a == i.first)
298 {
299 if (i.second == b)
300 // aRb
301 return true;
302
303 if (related(i.second, b))
304 // aRt && tRb
305 return true;
306 }
307 return false;
308}
309
310} // namespace bux
void makeLinear(F apply, E_MakeLinearPolicy policy=MLP_BREADTH_FIRST) const
bool anyLeft(const T2 &R) const
void getRelated(T2 L, F R, std::size_t maxDepth=0) const
std::size_t depthToLeft(T t) const
bool related(const T &a, const T &b) const
bool anyRight(const T2 &L) const
bool addOrder(T1 a, T2 b)
THE common namespace of bux library.
Definition AtomiX.cpp:3
E_MakeLinearPolicy
@ MLP_DEPTH_FIRST
@ MLP_BREADTH_FIRST
void addUnique(C &c, T &&value)