Skip to content

Commit 1ce2d6e

Browse files
committed
Added smallest set-vertex MFVS implementation
1 parent 4aae6b4 commit 1ce2d6e

16 files changed

Lines changed: 284 additions & 51 deletions

algorithms/matching/matching.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ Matching::Matching(MatchKind kind) : _kind(kind), _impl()
6060

6161
default: {
6262
Util::ERROR("Unsupported matching algorithm implementation");
63+
break;
6364
}
6465
}
6566
}

algorithms/mfvs/CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
target_sources(
22
sbgraph
33
PRIVATE
4+
greedy_mfvs.cpp
45
min_feedback_vertex_set.cpp
56
mfvs_fact.cpp
6-
greedy_mfvs.cpp
7+
smallest_sv_mfvs.cpp
78
)

algorithms/mfvs/mfvs_fact.cpp

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,20 +25,29 @@ namespace SBG {
2525
namespace LIB {
2626

2727
////////////////////////////////////////////////////////////////////////////////
28-
// Maximum Degree Cut Vertex Factory -------------------------------------------
28+
// Maximum Degree MFVS Factory -------------------------------------------------
2929
////////////////////////////////////////////////////////////////////////////////
3030

3131
MinFeedbackVertexSet GreedyMFVSFact::createMFVSAlgorithm() const
3232
{
3333
return MinFeedbackVertexSet{MFVSKind::kGreedy};
3434
}
3535

36+
////////////////////////////////////////////////////////////////////////////////
37+
// Smallest set-vertex MFVS Factory --------------------------------------------
38+
////////////////////////////////////////////////////////////////////////////////
39+
40+
MinFeedbackVertexSet SmallSVMFVSFact::createMFVSAlgorithm() const
41+
{
42+
return MinFeedbackVertexSet{MFVSKind::kSmallSV};
43+
}
44+
3645
////////////////////////////////////////////////////////////////////////////////
3746
// Factory for clients ---------------------------------------------------------
3847
////////////////////////////////////////////////////////////////////////////////
3948

4049
MFVSFactory::MFVSFactory()
41-
: _kind(MFVSKind::kGreedy), _impl(GreedyMFVSFact{}) {}
50+
: _kind(MFVSKind::kSmallSV), _impl(SmallSVMFVSFact{}) {}
4251

4352
MFVSFactory& MFVSFactory::instance()
4453
{
@@ -54,6 +63,12 @@ void MFVSFactory::set_mfvs_fact(MFVSKind kind)
5463
switch (kind) {
5564
case MFVSKind::kGreedy: {
5665
_impl = GreedyMFVSFact{};
66+
break;
67+
}
68+
69+
case MFVSKind::kSmallSV: {
70+
_impl = SmallSVMFVSFact{};
71+
break;
5772
}
5873

5974
default: {

algorithms/mfvs/mfvs_fact.hpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,13 @@ class GreedyMFVSFact {
3939
MinFeedbackVertexSet createMFVSAlgorithm() const;
4040
};
4141

42+
class SmallSVMFVSFact {
43+
public:
44+
SmallSVMFVSFact() = default;
45+
46+
MinFeedbackVertexSet createMFVSAlgorithm() const;
47+
};
48+
4249
/**
4350
* @brief Single instance of cv factory to be used by clients in need of
4451
* creating an instance of a cv algorithm. A client includes this file and
@@ -56,7 +63,7 @@ class MFVSFactory {
5663
MinFeedbackVertexSet createMFVSAlgorithm() const;
5764

5865
private:
59-
using MFVSFactImpl = std::variant<GreedyMFVSFact>;
66+
using MFVSFactImpl = std::variant<GreedyMFVSFact, SmallSVMFVSFact>;
6067

6168
MFVSFactory();
6269

algorithms/mfvs/min_feedback_vertex_set.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,11 @@ std::ostream& operator<<(std::ostream& out, const MFVSKind kind)
3737
break;
3838
}
3939

40+
case MFVSKind::kSmallSV: {
41+
out << "smallest set-vertex";
42+
break;
43+
}
44+
4045
default: {
4146
Util::ERROR("MFVSKind::operator<<: unsupported MFVS implementation");
4247
break;
@@ -58,6 +63,11 @@ MinFeedbackVertexSet::MinFeedbackVertexSet(MFVSKind kind) : _kind(kind), _impl()
5863
break;
5964
}
6065

66+
case MFVSKind::kSmallSV: {
67+
_impl = detail::SmallestSVMFVS{};
68+
break;
69+
}
70+
6171
default: {
6272
Util::ERROR("MinFeedbackVertexSet: unsupported MFVS implementation");
6373
break;

algorithms/mfvs/min_feedback_vertex_set.hpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#define SBGRAPH_ALGORITHMS_MFVS_MIN_FEEDBACK_VERTEX_SET_HPP_
2626

2727
#include "algorithms/mfvs/greedy_mfvs.hpp"
28+
#include "algorithms/mfvs/smallest_sv_mfvs.hpp"
2829
#include "sbg/directed_sbg.hpp"
2930

3031
#include <iosfwd>
@@ -40,11 +41,11 @@ namespace detail {
4041
// Minimum Feedback Vertex Set Implementations --------------------------------
4142
///////////////////////////////////////////////////////////////////////////////
4243

43-
using MFVSImpl = std::variant<GreedyMFVS>;
44+
using MFVSImpl = std::variant<GreedyMFVS, SmallestSVMFVS>;
4445

4546
}
4647

47-
enum class MFVSKind { kGreedy };
48+
enum class MFVSKind { kGreedy, kSmallSV };
4849

4950
std::ostream& operator<<(std::ostream& out, const MFVSKind kind);
5051

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
/*******************************************************************************
2+
3+
This file is part of Set--Based Graph Library.
4+
5+
SBG Library is free software: you can redistribute it and/or modify
6+
it under the terms of the GNU General Public License as published by
7+
the Free Software Foundation, either version 3 of the License, or
8+
(at your option) any later version.
9+
10+
SBG Library is distributed in the hope that it will be useful,
11+
but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
GNU General Public License for more details.
14+
15+
You should have received a copy of the GNU General Public License
16+
along with SBG Library. If not, see <http://www.gnu.org/licenses/>.
17+
18+
******************************************************************************/
19+
20+
#include "algorithms/mfvs/smallest_sv_mfvs.hpp"
21+
#include "algorithms/scc/scc.hpp"
22+
#include "algorithms/scc/scc_fact.hpp"
23+
#include "sbg/natural.hpp"
24+
#include "sbg/pw_map.hpp"
25+
#include "sbg/set_fact.hpp"
26+
#include "util/logger.hpp"
27+
28+
#include <numeric>
29+
30+
namespace SBG {
31+
32+
namespace LIB {
33+
34+
namespace detail {
35+
36+
////////////////////////////////////////////////////////////////////////////////
37+
// Greedy MFVS Algorithm -------------------------------------------------------
38+
////////////////////////////////////////////////////////////////////////////////
39+
40+
SmallestSVMFVS::SmallestSVMFVS() {}
41+
42+
/**
43+
* @brief It calculates the minimum vertex from the smallest SV.
44+
*/
45+
MD_NAT getVertexFromSmallestSV(const DirectedSBG& dsbg)
46+
{
47+
PWMap Vmap = dsbg.Vmap();
48+
PWMap mmap = Vmap.imageMultiplicity();
49+
50+
MD_NAT min_mult{dsbg.V().arity(), Inf};
51+
Set remaining = mmap.image();
52+
while (!remaining.isEmpty()) {
53+
MD_NAT jth_mult = remaining.minElem();
54+
NAT current_degree = std::accumulate(min_mult.begin(), min_mult.end()
55+
, 0);
56+
NAT jth_degree = std::accumulate(jth_mult.begin(), jth_mult.end(), 0);
57+
if (jth_degree < current_degree) {
58+
min_mult = jth_mult;
59+
}
60+
61+
remaining = remaining.difference(SET_FACT.createSet(jth_mult));
62+
}
63+
64+
Set small_sv = mmap.preImage(SET_FACT.createSet(min_mult));
65+
Set vertex = Vmap.preImage(small_sv);
66+
67+
return vertex.minElem();
68+
}
69+
70+
Set SmallestSVMFVS::calculate(const DirectedSBG& input_dsbg) const
71+
{
72+
DirectedSBG dsbg = input_dsbg;
73+
74+
Util::DEBUG_LOG << "initial smallest set-vertex mfvs dsbg:\n" << dsbg << "\n";
75+
76+
PWMap rmap = SCC_FACT.createSCCAlgorithm().calculate(dsbg).rmap();
77+
Set fvs_result = SET_FACT.createSet();
78+
Set visitedSV = SET_FACT.createSet();
79+
while (rmap.fixedPoints() != rmap.domain()) {
80+
// Get vertex from smallest set-vertex
81+
MD_NAT smallest_sv_vertex = getVertexFromSmallestSV(dsbg);
82+
Set Vj = SET_FACT.createSet(smallest_sv_vertex);
83+
fvs_result = std::move(fvs_result).disjointCup(Vj);
84+
85+
// Handle repetition
86+
PWMap Vmap = dsbg.Vmap();
87+
Set repeatedSV = visitedSV.intersection(Vmap.image(Vj));
88+
if (!repeatedSV.isEmpty()) {
89+
Set V_plus = Vmap.preImage(Vmap.image(Vj));
90+
fvs_result = std::move(fvs_result).cup(std::move(V_plus));
91+
92+
visitedSV = repeatedSV.difference(Vmap.image(Vj));
93+
} else {
94+
visitedSV = std::move(repeatedSV).disjointCup(Vmap.image(Vj));
95+
}
96+
97+
// Erase selected vertices
98+
dsbg.eraseVertices(fvs_result);
99+
100+
// Resulting SCC from induced graph
101+
rmap = SCC_FACT.createSCCAlgorithm().calculate(dsbg).rmap();
102+
103+
Util::DEBUG_LOG << "Vj: " << Vj << "\n";
104+
Util::DEBUG_LOG << "new rmap: " << rmap << "\n\n";
105+
}
106+
107+
fvs_result.compact();
108+
return fvs_result;
109+
}
110+
111+
} // namespace detail
112+
113+
} // namespace LIB
114+
115+
} // namespace SBG
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/** @file smallest_sv_mfvs.hpp
2+
3+
@brief <b>Concrete SBG Smallest SV MFVS Algorithm implementation</b>
4+
5+
<hr>
6+
7+
This file is part of Set--Based Graph Library.
8+
9+
SBG Library is free software: you can redistribute it and/or modify
10+
it under the terms of the GNU General Public License as published by
11+
the Free Software Foundation, either version 3 of the License, or
12+
(at your option) any later version.
13+
14+
SBG Library is distributed in the hope that it will be useful,
15+
but WITHOUT ANY WARRANTY; without even the implied warranty of
16+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17+
GNU General Public License for more details.
18+
19+
You should have received a copy of the GNU General Public License
20+
along with SBG Library. If not, see <http://www.gnu.org/licenses/>.
21+
22+
******************************************************************************/
23+
24+
#ifndef SBGRAPH_ALGORITHMS_MFVS_SMALLEST_SV_MFVS_HPP_
25+
#define SBGRAPH_ALGORITHMS_MFVS_SMALLEST_SV_MFVS_HPP_
26+
27+
#include "sbg/directed_sbg.hpp"
28+
#include "sbg/set.hpp"
29+
30+
namespace SBG {
31+
32+
namespace LIB {
33+
34+
namespace detail {
35+
36+
///////////////////////////////////////////////////////////////////////////////
37+
// Smallest set-vertex MFVS Algorithm Implementation --------------------------
38+
///////////////////////////////////////////////////////////////////////////////
39+
40+
/**
41+
* @brief In each step takes out vertices of the smallest set-vertex available.
42+
* This way, it is first checked if it is possible to disconnect the SBG
43+
* with a constant number of elements.
44+
*/
45+
class SmallestSVMFVS {
46+
public:
47+
SmallestSVMFVS();
48+
49+
Set calculate(const DirectedSBG& input_dsbg) const;
50+
};
51+
52+
} // namespace detail
53+
54+
} // namespace LIB
55+
56+
} // namespace SBG
57+
58+
#endif // SBGRAPH_ALGORITHMS_MFVS_GREEDY_MFVS_HPP_

algorithms/misc/causalization_builders.cpp

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -89,14 +89,15 @@ std::tuple<SBG::LIB::PWMap, SBG::LIB::PWMap, SBG::LIB::PWMap> buildSCCEdges(
8989
return {mapB, mapD, Emap};
9090
}
9191

92-
SBG::LIB::PWMap partitionEmap(const SBG::LIB::DirectedSBG& dsbg)
92+
void partitionEmap(SBG::LIB::DirectedSBG& dsbg)
9393
{
94+
SBG::LIB::Set V = dsbg.V();
9495
SBG::LIB::PWMap Vmap = dsbg.Vmap();
9596
SBG::LIB::PWMap mapB = dsbg.mapB();
9697
SBG::LIB::PWMap mapD = dsbg.mapD();
9798
SBG::LIB::PWMap Emap = dsbg.Emap();
9899

99-
std::size_t arity = dsbg.V().arity();
100+
std::size_t arity = V.arity();
100101
SBG::LIB::NAT j = 1;
101102
SBG::LIB::PWMap partitioned_Emap = SBG::LIB::PWMAP_FACT.createPWMap();
102103
dsbg.foreachSetEdge([&](const SBG::LIB::MD_NAT& SE)
@@ -132,7 +133,7 @@ SBG::LIB::PWMap partitionEmap(const SBG::LIB::DirectedSBG& dsbg)
132133
}
133134
});
134135

135-
return partitioned_Emap;
136+
dsbg = SBG::LIB::DirectedSBG{V, Vmap, mapB, mapD, partitioned_Emap};
136137
}
137138

138139
SBG::LIB::DirectedSBG buildLoopDetectionSBG(const SBG::LIB::MatchData& data)
@@ -148,10 +149,10 @@ SBG::LIB::DirectedSBG buildLoopDetectionSBG(const SBG::LIB::MatchData& data)
148149
SBG::LIB::PWMap Emap = SBG::LIB::PWMAP_FACT.createPWMap();
149150
std::tie(mapB, mapD, Emap) = buildSCCEdges(data, Vmap);
150151

151-
//SBG::LIB::DirectedSBG dsbg{V, Vmap, mapB, mapD, Emap};
152-
//Emap = partitionEmap(dsbg);
152+
SBG::LIB::DirectedSBG dsbg{V, Vmap, mapB, mapD, Emap};
153+
partitionEmap(dsbg);
153154

154-
return SBG::LIB::DirectedSBG{V, Vmap, mapB, mapD, Emap};
155+
return dsbg;
155156
}
156157

157158
////////////////////////////////////////////////////////////////////////////////

0 commit comments

Comments
 (0)