|
25 | 25 | namespace SBG { |
26 | 26 |
|
27 | 27 | namespace LIB { |
28 | | - |
| 28 | + |
29 | 29 | //////////////////////////////////////////////////////////////////////////////// |
30 | | -// Tearing --------------------------------------------------------------------- |
| 30 | +// Auxiliary structures -------------------------------------------------------- |
31 | 31 | //////////////////////////////////////////////////////////////////////////////// |
32 | 32 |
|
33 | | -bool sccNotEqId(const Map &sbgmap) { return !(sbgmap.isId()); } |
34 | | - |
35 | | -Tearing::Tearing(const DSBG &dsbg, bool debug) |
36 | | - : fact_(dsbg.fact()), |
37 | | - dsbg_(dsbg), |
38 | | - V_(fact_.createSet()), |
39 | | - Vmap_(fact_.createPWMap()), |
40 | | - Emap_(fact_.createPWMap()), |
41 | | - subEmap_(fact_.createPWMap()), |
42 | | - E_(fact_.createSet()), |
43 | | - Ediff_(fact_.createSet()), |
44 | | - mapB_(fact_.createPWMap()), |
45 | | - mapD_(fact_.createPWMap()), |
46 | | - rmap_(fact_.createPWMap()), |
47 | | - debug_(debug) |
48 | | -{ |
49 | | - DSBG dg = dsbg; |
50 | | - dsbg_ = dg; |
51 | | - |
52 | | - V_ = dg.V(); |
53 | | - Vmap_ = dg.Vmap(); |
54 | | - |
55 | | - E_ = dg.E(); |
56 | | - Emap_ = dg.Emap(); |
57 | | - subEmap_ = dg.subEmap(); |
58 | | - |
59 | | - mapB_ = dg.mapB(); |
60 | | - mapD_ = dg.mapD(); |
61 | | - |
62 | | - rmap_ = fact_.createPWMap(V_); |
63 | | -} |
64 | | - |
65 | | -member_imp(Tearing, DSBG, dsbg); |
66 | | -member_imp(Tearing, Set, V); |
67 | | -member_imp(Tearing, PWMap, Vmap); |
68 | | -member_imp(Tearing, Set, E); |
69 | | -member_imp(Tearing, PWMap, Emap); |
70 | | -member_imp(Tearing, PWMap, subEmap); |
71 | | - |
72 | | -member_imp(Tearing, PWMap, mapB); |
73 | | -member_imp(Tearing, PWMap, mapD); |
74 | | - |
75 | | -member_imp(Tearing, Set, Ediff); |
76 | | - |
77 | | -member_imp(Tearing, PWMap, rmap); |
78 | | - |
79 | | -member_imp(Tearing, bool, debug); |
80 | | - |
81 | | -PWMap Tearing::sccMinReach(const DSBG &dg) const |
82 | | -{ |
83 | | - if (debug()) |
84 | | - Util::SBG_LOG << "Min reach graph:\n" << dg << "\n\n"; |
85 | | - |
86 | | - Set V = dg.V(), E = dg.E(); |
87 | | - PWMap mapB = dg.mapB(), mapD = dg.mapD(), subEmap = dg.subEmap(); |
88 | | - if (!V.isEmpty()) { |
89 | | - unsigned int copies = V.arity(); |
90 | | - PWMap rmap = fact_.createPWMap(V), old_rmap = fact_.createPWMap(); |
91 | | - |
92 | | - if (E.isEmpty()) |
93 | | - return rmap; |
94 | | - |
95 | | - Set Vc = fact_.createSet(); |
96 | | - do { |
97 | | - old_rmap = rmap; |
98 | | - |
99 | | - PWMap ermapD = rmap.composition(mapD); |
100 | | - |
101 | | - PWMap new_rmap = mapB.minAdjMap(ermapD); |
102 | | - rmap = rmap.minMap(new_rmap).combine(rmap); |
103 | | - if (debug()) |
104 | | - Util::SBG_LOG << "rmap before rec: " << rmap << "\n\n"; |
105 | | - |
106 | | - Set positive = fact_.createSet(SetPiece(copies, Interval(1, 1, Inf))); |
107 | | - PWMap rec_rmap = fact_.createPWMap(); |
108 | | - Vc = V.difference(old_rmap.equalImage(rmap)); |
109 | | - if (!Vc.isEmpty()) { |
110 | | - for (const Map &subv : dg.Vmap()) { |
111 | | - Set vs = subv.dom(); |
112 | | - if (!vs.intersection(Vc).isEmpty()) { |
113 | | - // If the mrv is in the same SV, the algorithm would detect a false |
114 | | - // recursion, i.e. if we have a cycle 1 -> 2 -> ... -> 10 -> 1, |
115 | | - // where SV = [1:10], then it detects a recursion when mrv(10) |
116 | | - // becomes "1" (false recursion). So we take self mrvs out. |
117 | | - auto other_rep = rmap.filterMap([](const Map &sbgmap) { |
118 | | - return sccNotEqId(sbgmap); |
119 | | - }).dom(); |
120 | | - // Vertices in the set-vertex that share its rep with other vertex |
121 | | - // in the set-vertex |
122 | | - Set VR = rmap.restrict(vs.intersection(other_rep)).sharedImage(); |
123 | | - // There is a recursive vertex that changed its rep in the last step |
124 | | - // (to avoid computing again an already found recursion) |
125 | | - if (!VR.intersection(Vc).isEmpty()) { |
126 | | - // Vertices that reach the shared representative |
127 | | - Set repV = rmap.preImage(rmap.image(VR)); |
128 | | - Set end = VR.difference(Vc); |
129 | | - |
130 | | - // Edges with both endings in VR (path to a minimum rep) |
131 | | - Set ERB = mapB.preImage(repV), ERD = mapD.preImage(repV); |
132 | | - Set ER = ERB.intersection(ERD); |
133 | | - if (!end.isEmpty() && !ER.isEmpty()) { |
134 | | - // Distance map |
135 | | - PWMap dmap = fact_.createPWMap(); |
136 | | - Set ith = end; |
137 | | - NAT dist = 0; |
138 | | - // Calculate distance for vertices in same_rep that reach reps |
139 | | - for (; dmap.dom().intersection(Vc.intersection(VR)).isEmpty();) { |
140 | | - Set dom = ith.difference(dmap.dom()); |
141 | | - Exp exp(MD_NAT(copies, dist)); |
142 | | - dmap.emplaceBack(fact_.createMap(dom, exp)); |
143 | | - // Update ith to vertices that have outgoing edges entering ith |
144 | | - ith = mapB.image(mapD.preImage(ith)); |
145 | | - ++dist; |
146 | | - } |
147 | | - PWMap dmapB = dmap.composition(mapB), dmapD = dmap.composition(mapD); |
148 | | - // Get edges where the end is closer to the rep than the beginning |
149 | | - Set not_cycle_edges = (dmapB - dmapD).preImage(positive); |
150 | | - ER = ER.intersection(not_cycle_edges); |
151 | | - |
152 | | - // Extend to subset-edge |
153 | | - Set ER_plus = subEmap.preImage(subEmap.image(ER)); |
154 | | - // Calculate a succesor |
155 | | - PWMap auxB = mapB.restrict(ER_plus), auxD = mapD.restrict(ER_plus); |
156 | | - PWMap smap_plus = rmap.restrict(VR); |
157 | | - smap_plus = smap_plus.combine(auxB.minAdjMap(auxD)); |
158 | | - |
159 | | - // Update rmap for recursion, and leave the rest unchanged |
160 | | - rec_rmap = smap_plus.combine(rec_rmap).compact(); |
| 33 | +TearingData::TearingData(DSBG dsbg, PWMap rmap, PWMap tearIOMap) |
| 34 | + : dsbg_(dsbg), rmap_(rmap), tearIOMap_(tearIOMap) {} |
161 | 35 |
|
162 | | - if (debug()) { |
163 | | - Util::SBG_LOG << "VR: " << VR << "\n"; |
164 | | - Util::SBG_LOG << "repV: " << repV << "\n"; |
165 | | - Util::SBG_LOG << "ER: " << ER << "\n"; |
166 | | - Util::SBG_LOG << "dmap: " << dmap << "\n"; |
167 | | - Util::SBG_LOG << "not_cycle_edges: " << not_cycle_edges << "\n"; |
168 | | - Util::SBG_LOG << "ER_plus: " << ER_plus << "\n"; |
169 | | - Util::SBG_LOG << "smap_plus: " << smap_plus << "\n"; |
170 | | - Util::SBG_LOG << "rec_rmap: " << rec_rmap << "\n\n"; |
171 | | - } |
172 | | - } |
173 | | - } |
174 | | - } |
175 | | - } |
176 | | - PWMap rmap_plus = rec_rmap.combine(rmap); |
177 | | - rmap_plus = rmap_plus.mapInf(); |
178 | | - rmap = rmap.minMap(rmap_plus).compact(); |
| 36 | +const DSBG& TearingData::dsbg() const { return dsbg_; } |
| 37 | +const PWMap& TearingData::rmap() const { return rmap_; } |
| 38 | +const PWMap& TearingData::tearIOMap() const { return tearIOMap_; } |
179 | 39 |
|
180 | | - if (debug()) |
181 | | - Util::SBG_LOG << "rmap after rec: " << rmap << "\n\n"; |
182 | | - } |
183 | | - } while (!Vc.isEmpty()); |
184 | | - |
185 | | - return rmap; |
186 | | - } |
187 | | - |
188 | | - return fact_.createPWMap(); |
189 | | -} |
190 | | - |
191 | | -PWMap Tearing::sccStep() |
192 | | -{ |
193 | | - PWMap id_V = fact_.createPWMap(V()); |
194 | | - |
195 | | - DSBG aux_dsbg( |
196 | | - fact_, V(), Vmap() |
197 | | - , mapB().restrict(E()), mapD().restrict(E()), Emap().restrict(E()).compact() |
198 | | - , subEmap().restrict(E()) |
199 | | - ); |
200 | | - PWMap new_rmap = sccMinReach(aux_dsbg); |
201 | | - if (debug()) |
202 | | - Util::SBG_LOG << "SCC new_rmap: " << new_rmap << "\n"; |
203 | | - |
204 | | - PWMap rmap_B = new_rmap.composition(mapB()); |
205 | | - PWMap rmap_D = new_rmap.composition(mapD()); |
206 | | - Set Esame = rmap_B.equalImage(rmap_D); // Edges in the same SCC |
207 | | - |
208 | | - // Leave edges in the same SCC |
209 | | - Ediff_ = E().difference(Esame); |
210 | | - E_ = Esame; |
211 | | - if (debug()) |
212 | | - Util::SBG_LOG << "SCC erased edges: " << Ediff() << "\n\n"; |
213 | | - |
214 | | - // Swap directions |
215 | | - PWMap aux_B = mapB(); |
216 | | - mapB_ = mapD(); |
217 | | - mapD_ = aux_B; |
| 40 | +//////////////////////////////////////////////////////////////////////////////// |
| 41 | +// Tearing Algorithm Abstract Strategy Constructors -------------------------------- |
| 42 | +//////////////////////////////////////////////////////////////////////////////// |
218 | 43 |
|
219 | | - return new_rmap; |
220 | | -} |
| 44 | +TearingStrategy::TearingStrategy() {} |
221 | 45 |
|
222 | | -void Tearing::restoreSBG() |
223 | | -{ |
224 | | - V_ = dsbg_.V(); |
225 | | - Vmap_ = dsbg_.Vmap(); |
| 46 | +//////////////////////////////////////////////////////////////////////////////// |
| 47 | +// Tearing Algorithm Interface ----------------------------------------------------- |
| 48 | +//////////////////////////////////////////////////////////////////////////////// |
226 | 49 |
|
227 | | - E_ = dsbg_.E(); |
228 | | - Emap_ = dsbg_.Emap(); |
229 | | - subEmap_ = dsbg_.subEmap(); |
| 50 | +Tearing::Tearing(TearingStratPtr strat) : strategy_(std::move(strat)) {} |
230 | 51 |
|
231 | | - mapB_ = dsbg_.mapB(); |
232 | | - mapD_ = dsbg_.mapD(); |
233 | | -} |
234 | | -PWMap Tearing::calculateSCC() |
| 52 | +TearingData Tearing::calculate(const DSBG& dsbg) |
235 | 53 | { |
236 | | - PWMap rmap = sccStep(); |
237 | | - do { |
238 | | - rmap = sccStep(); |
239 | | - } while (Ediff() != fact_.createSet()); |
240 | | - return rmap.compact(); |
| 54 | + return strategy_->calculate(dsbg); |
241 | 55 | } |
242 | | -PWMap Tearing::calculate() |
243 | | -{ |
244 | | - if (debug()) Util::SBG_LOG << "Tearing dsbg: \n" << dsbg() << "\n\n"; |
245 | | - |
246 | | - auto begin = std::chrono::high_resolution_clock::now(); |
247 | | - Set vrem = fact_.createSet(); |
248 | | - Set e_notscc = dsbg().E(); |
249 | | - MD_NAT maxOffset = V().maxElem(); |
250 | | - PWMap rmap = calculateSCC(); |
251 | | - PWMap tearIOMap_ = fact_.createPWMap(); |
252 | | - rmap_ = rmap; |
253 | | - |
254 | | - while (!E().isEmpty()) { |
255 | | - Set e_scc = E(); |
256 | | - Set e_noscc = e_notscc.difference(e_scc); |
257 | | - Set v_tear = rmap.image(); |
258 | | - PWMap tearIOMap = fact_.createPWMap(v_tear).offsetImage(maxOffset); |
259 | | - tearIOMap_ = tearIOMap.combine(tearIOMap_); |
260 | | - PWMap mapB_scc = mapB().restrict(e_scc).composition(rmap); |
261 | | - PWMap mapB_noscc = mapB().restrict(e_noscc).composition(rmap).composition(tearIOMap); |
262 | | - PWMap mapD_scc = mapD().restrict(e_scc).composition(rmap).composition(tearIOMap); |
263 | | - PWMap mapD_noscc = mapD().restrict(e_noscc).composition(rmap); |
264 | | - // combine wit mapB and mapD |
265 | | - rmap = calculateSCC(); |
266 | | - } |
267 | | - auto end = std::chrono::high_resolution_clock::now(); |
268 | | - |
269 | | - auto total = std::chrono::duration_cast<std::chrono::microseconds>(end - begin); |
270 | | - Util::SBG_LOG << "Total Tearing exec time: " << total.count() << " [μs]\n\n"; |
271 | | - std::cout << vrem << std::endl; |
272 | | - std::cout << dsbg().E() << std::endl; |
273 | | - |
274 | | - if (debug()) { |
275 | | - Util::SBG_LOG << "Tearing result: " << rmap.compact() << "\n\n"; |
276 | | - E().print(std::cout); |
277 | | - } |
278 | | - |
279 | | - return rmap_; |
280 | | -} |
281 | | - |
282 | | -const PWMapAF &Tearing::fact() const { return fact_; } |
283 | 56 |
|
284 | 57 | } // namespace LIB |
285 | 58 |
|
|
0 commit comments