Skip to content

Commit 4848874

Browse files
committed
Adapted tearing algorithm for Strategy pattern
1 parent 2081a0f commit 4848874

7 files changed

Lines changed: 370 additions & 272 deletions

File tree

algorithms/tearing/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
target_sources(
22
sbgraph
33
PRIVATE
4+
tearing_impl.cpp
45
tearing.cpp
6+
tearing_fact.cpp
57
)

algorithms/tearing/tearing.cpp

Lines changed: 17 additions & 244 deletions
Original file line numberDiff line numberDiff line change
@@ -25,261 +25,34 @@
2525
namespace SBG {
2626

2727
namespace LIB {
28-
28+
2929
////////////////////////////////////////////////////////////////////////////////
30-
// Tearing ---------------------------------------------------------------------
30+
// Auxiliary structures --------------------------------------------------------
3131
////////////////////////////////////////////////////////////////////////////////
3232

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) {}
16135

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_; }
17939

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+
////////////////////////////////////////////////////////////////////////////////
21843

219-
return new_rmap;
220-
}
44+
TearingStrategy::TearingStrategy() {}
22145

222-
void Tearing::restoreSBG()
223-
{
224-
V_ = dsbg_.V();
225-
Vmap_ = dsbg_.Vmap();
46+
////////////////////////////////////////////////////////////////////////////////
47+
// Tearing Algorithm Interface -----------------------------------------------------
48+
////////////////////////////////////////////////////////////////////////////////
22649

227-
E_ = dsbg_.E();
228-
Emap_ = dsbg_.Emap();
229-
subEmap_ = dsbg_.subEmap();
50+
Tearing::Tearing(TearingStratPtr strat) : strategy_(std::move(strat)) {}
23051

231-
mapB_ = dsbg_.mapB();
232-
mapD_ = dsbg_.mapD();
233-
}
234-
PWMap Tearing::calculateSCC()
52+
TearingData Tearing::calculate(const DSBG& dsbg)
23553
{
236-
PWMap rmap = sccStep();
237-
do {
238-
rmap = sccStep();
239-
} while (Ediff() != fact_.createSet());
240-
return rmap.compact();
54+
return strategy_->calculate(dsbg);
24155
}
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_; }
28356

28457
} // namespace LIB
28558

algorithms/tearing/tearing.hpp

Lines changed: 38 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/** @file scc.hpp
22
3-
@brief <b>SCC SBG implementation</b>
3+
@brief <b>SBG Tearing Algorithm Abstract Interface</b>
44
55
<hr>
66
@@ -21,8 +21,8 @@
2121
2222
******************************************************************************/
2323

24-
#ifndef SBG_SCC_HPP
25-
#define SBG_SCC_HPP
24+
#ifndef SBG_TEARING_HPP
25+
#define SBG_TEARING_HPP
2626

2727
#include "sbg/sbg.hpp"
2828

@@ -31,45 +31,55 @@ namespace SBG {
3131
namespace LIB {
3232

3333
////////////////////////////////////////////////////////////////////////////////
34-
// SCC -------------------------------------------------------------------------
34+
// Auxiliary classures --------------------------------------------------------
3535
////////////////////////////////////////////////////////////////////////////////
3636

37-
struct Tearing {
37+
/**
38+
* @brief Saves input and output data from a Tearing algorithm run.
39+
*/
40+
struct TearingData {
41+
public:
42+
TearingData(DSBG dsbg, PWMap rmap, PWMap tearIOMap);
43+
44+
const DSBG& dsbg() const;
45+
const PWMap& rmap() const;
46+
const PWMap& tearIOMap() const;
47+
3848
private:
39-
const PWMapAF &fact_;
49+
DSBG dsbg_; ///< Original input directed SBG
50+
PWMap rmap_; ///< Resulting SCCs
51+
PWMap tearIOMap_; ///< Paired tearing vertices
52+
};
53+
54+
////////////////////////////////////////////////////////////////////////////////
55+
// Tearing Algorithm Abstract Strategy ---------------------------------------------
56+
////////////////////////////////////////////////////////////////////////////////
4057

41-
//*** SBG info, constant
42-
member_class(DSBG, dsbg);
58+
class TearingStrategy;
4359

44-
member_class(Set, V);
45-
member_class(PWMap, Vmap);
60+
typedef std::unique_ptr<TearingStrategy> TearingStratPtr;
4661

47-
member_class(PWMap, Emap);
48-
member_class(PWMap, subEmap);
62+
class TearingStrategy {
63+
public:
64+
virtual ~TearingStrategy() = default;
4965

50-
//-----------------------------
51-
member_class(Set, E); // Edges in the same SCC in each step
52-
member_class(Set, Ediff); // Edges between different SCC in each step
66+
TearingStrategy();
5367

54-
member_class(PWMap, mapB);
55-
member_class(PWMap, mapD);
56-
57-
member_class(PWMap, rmap);
68+
virtual TearingData calculate(const DSBG& dsbg) = 0;
69+
};
5870

59-
member_class(bool, debug);
71+
////////////////////////////////////////////////////////////////////////////////
72+
// Tearing Algorithm Interface (context) -------------------------------------------
73+
////////////////////////////////////////////////////////////////////////////////
6074

75+
class Tearing {
6176
public:
62-
Tearing(const DSBG &dsbg, bool debug);
63-
64-
PWMap calculate();
77+
Tearing(TearingStratPtr strat);
6578

66-
const PWMapAF &fact() const;
79+
TearingData calculate(const DSBG& dsbg);
6780

6881
private:
69-
PWMap sccMinReach(const DSBG &dg) const;
70-
PWMap sccStep();
71-
PWMap calculateSCC();
72-
void restoreSBG();
82+
TearingStratPtr strategy_;
7383
};
7484

7585
} // namespace LIB

0 commit comments

Comments
 (0)