Skip to content

Commit c95efdc

Browse files
committed
Debugged SCC algorithm
1 parent dccd18f commit c95efdc

2 files changed

Lines changed: 38 additions & 47 deletions

File tree

algorithms/scc/decreasing_edges_mrv.cpp

Lines changed: 37 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -49,58 +49,55 @@ Set LtEdgesMRV::decreasingRepresentative(const PWMap& rmap) const
4949
return result;
5050
}
5151

52-
Set LtEdgesMRV::edgesInPaths(const PWMap& smap) const
53-
{
54-
PWMap mapB = _dsbg.mapB();
55-
PWMap mapD = _dsbg.mapD();
56-
57-
// Vertices that are successors of other vertices in a path
58-
Set not_fixed = smap.domain().difference(smap.fixedPoints());
59-
Set succs = smap.restrict(not_fixed).image();
60-
// Edges whose endings are successors
61-
Set ending_edges = mapD.preImage(succs);
62-
// Map from a 'successor' edge to its start
63-
PWMap auxB = mapB.restrict(ending_edges);
64-
// Map from edge to the successor of its start
65-
PWMap map_succs = smap.composition(auxB);
66-
67-
return map_succs.equalImage(mapD);
68-
}
69-
70-
PWMap LtEdgesMRV::recursivePaths(const Set& ith_paths_edges, const Set& outgoing)
52+
PWMap LtEdgesMRV::recursivePaths(const PWMap& rmap
53+
, const PWMap& decreasing_smap)
7154
{
7255
PWMap result = PWMAP_FACT.createPWMap();
7356

57+
// Calculate edges in paths described by _smap
58+
const PWMap& mapB = _dsbg.mapB();
59+
const PWMap& mapD = _dsbg.mapD();
60+
Set ithP = decreasing_smap.composition(mapB).equalImage(mapD);
61+
62+
// Check if there is a recursion
7463
PWMap Emap = _dsbg.Emap();
75-
Set ithSE = Emap.image(ith_paths_edges);
76-
_visitedSE = std::move(_visitedSE).cup(ithSE);
64+
Set ithSE = Emap.image(ithP);
7765
Set repeatedSE = _visitedSE.intersection(ithSE);
7866
if (!repeatedSE.isEmpty()) {
79-
PWMap mapB = _dsbg.mapB();
80-
PWMap mapD = _dsbg.mapD();
81-
67+
Set P = _smap.composition(mapB).equalImage(mapD);
8268
Set ith_start = _smap.domain().difference(_smap.image());
83-
Set E = SET_FACT.createSet();
84-
Set ithE = mapB.preImage(ith_start).intersection(ith_paths_edges);
69+
Set ithE = mapB.preImage(ith_start).intersection(P);
8570
if (!ithE.isEmpty()) {
71+
Set E = SET_FACT.createSet();
8672
bool exit_condition = true;
8773
do {
88-
ithE = mapB.preImage(ith_start).intersection(ith_paths_edges);
89-
E = std::move(E).disjointCup(std::move(ithE));
90-
ith_start = mapD.image(ithE);
9174
exit_condition = !repeatedSE.intersection(Emap.image(E)).isEmpty();
75+
ithE = mapB.preImage(ith_start).intersection(P);
76+
ith_start = mapD.image(ithE);
77+
E = std::move(E).disjointCup(std::move(ithE));
9278
} while (!exit_condition);
79+
// Take out edges that reach a MRV different from that of the recursion
80+
PWMap ithP_rmap = rmap.composition(mapD.restrict(ithP));
81+
Set ithP_mrvs = ithP_rmap.image();
82+
E = E.intersection(ithP_rmap.preImage(ithP_mrvs));
83+
84+
Set E_plus = Emap.preImage(Emap.image(E));
85+
// In the presence of a cycle, if the minimum vertex belongs to the
86+
// recursion, it will be assigned a successor. This results in a cycling
87+
// smap, which is an error. For example, if there's a cycle
88+
// 1 -> 2 -> ... -> 10 -> 1, this function calculates smap(1) = 2,
89+
// when it should be smap(1) = 1. To avoid this, we erase outgoing edges
90+
// from vertices that already reach the desired MRV.
91+
Set outgoing = mapB.preImage(rmap.preImage(ithP_mrvs));
92+
E_plus = E_plus.difference(outgoing);
93+
94+
PWMap mapB_plus = _dsbg.mapB().restrict(E_plus);
95+
PWMap mapD_plus = _dsbg.mapD().restrict(E_plus);
96+
result = mapB_plus.minAdj(mapD_plus);
9397
}
94-
95-
Set smap_edges = edgesInPaths(_smap);
96-
Set adj = mapB.preImage(mapB.image(smap_edges));
97-
98-
Set E_plus = Emap.preImage(Emap.image(E));
99-
E_plus = E_plus.difference(mapB.preImage(outgoing));
100-
E_plus = E_plus.difference(adj);
101-
PWMap mapB_plus = _dsbg.mapB().restrict(E_plus);
102-
PWMap mapD_plus = _dsbg.mapD().restrict(E_plus);
103-
result = mapB_plus.minAdj(mapD_plus);
98+
_visitedSE = _visitedSE.difference(Emap.image(P));
99+
} else {
100+
_visitedSE = std::move(_visitedSE).disjointCup(std::move(ithSE));
104101
}
105102

106103
return result;
@@ -122,7 +119,6 @@ PWMap LtEdgesMRV::calculate(const DirectedSBG& dsbg)
122119
if (!_dsbg.V().isEmpty() && !_dsbg.E().isEmpty()) {
123120
PWMap old_rmap = PWMAP_FACT.createPWMap();
124121
Set E = SET_FACT.createSet();
125-
Set paths_edges = SET_FACT.createSet();
126122
do {
127123
old_rmap = rmap;
128124

@@ -134,10 +130,7 @@ PWMap LtEdgesMRV::calculate(const DirectedSBG& dsbg)
134130
_smap = decreasing_smap.combine(std::move(_smap));
135131

136132
// Recursive paths
137-
Set ith_paths_edges = edgesInPaths(decreasing_smap);
138-
Set outgoing = rmap.image(mapD.image(ith_paths_edges));
139-
PWMap smap_plus = recursivePaths(ith_paths_edges, outgoing);
140-
_smap = std::move(smap_plus).combine(std::move(_smap));
133+
_smap = recursivePaths(rmap, decreasing_smap).combine(std::move(_smap));
141134

142135
// Calculate representatives map
143136
rmap = _smap.mapInf();

algorithms/scc/decreasing_edges_mrv.hpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,12 +64,10 @@ class LtEdgesMRV : public MRVContext<LtEdgesMRV> {
6464
*/
6565
Set decreasingRepresentative(const PWMap& rmap) const;
6666

67-
Set edgesInPaths(const PWMap& smap) const;
68-
6967
/*
7068
* @brief Calculates the MRV for recursive paths.
7169
*/
72-
PWMap recursivePaths(const Set& paths_edges, const Set& outgoing);
70+
PWMap recursivePaths(const PWMap& rmap, const PWMap& decreasing_smap);
7371

7472
DirectedSBG _dsbg;
7573
PWMap _smap;

0 commit comments

Comments
 (0)