Skip to content

Commit b5c5bca

Browse files
abdalla30rabdalla30r
authored andcommitted
Added Maximum Independent Set algorithm
1 parent 3d10062 commit b5c5bca

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+677
-2
lines changed

CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ set(COMMON_LIB_SOURCES
6666
algorithm/MaxClique.h
6767
algorithm/MaxFlowPushRelabel.h
6868
algorithm/MaxFlowPushRelableImpl.h
69+
algorithm/MaxIndependentSet.cpp
70+
algorithm/MaxIndependentSet.h
6971
algorithm/PrintAllPaths.cpp
7072
algorithm/PrintAllPaths.h
7173
algorithm/ShortestPath.h

GraphOffline.vcxproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@
101101
<ClCompile Include="algorithm\IsomorphismCheck.cpp" />
102102
<ClCompile Include="algorithm\MaxClique.cpp" />
103103
<ClCompile Include="algorithm\PrintAllPaths.cpp" />
104+
<ClInclude Include="algorithm/MaxIndependentSet.cpp" />
104105
<ClCompile Include="CGIProcessor.cpp" />
105106
<ClCompile Include="common\Logger.cpp" />
106107
<ClCompile Include="GraphOffline.cpp" />
@@ -150,6 +151,7 @@
150151
<ClInclude Include="graph\Graph.h" />
151152
<ClInclude Include="graph\IGraph.h" />
152153
<ClInclude Include="report\ReporterFactory.h" />
154+
<ClInclude Include="algorithm/MaxIndependentSet.h" />
153155
</ItemGroup>
154156
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
155157
<ImportGroup Label="ExtensionTargets">

GraphOffline.vcxproj.filters

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,9 @@
108108
<ClCompile Include="algorithm\MaxClique.cpp">
109109
<Filter>Source Files\algorithm</Filter>
110110
</ClCompile>
111+
<ClCompile Include="algorithm\MaxIndependentSet.cpp">
112+
<Filter>Source Files\algorithm</Filter>
113+
</ClCompile>
111114
</ItemGroup>
112115
<ItemGroup>
113116
<ClInclude Include="CGIProcessor.h">
@@ -218,5 +221,8 @@
218221
<ClInclude Include="algorithm\MaxClique.h">
219222
<Filter>Source Files\algorithm</Filter>
220223
</ClInclude>
224+
<ClInclude Include="algorithm\MaxIndependentSet.h">
225+
<Filter>Source Files\algorithm</Filter>
226+
</ClInclude>
221227
</ItemGroup>
222228
</Project>

Graphoffline.Emscripten.vcxproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
<ClCompile Include="algorithm\HamiltonianLoop.cpp" />
4848
<ClCompile Include="algorithm\IsomorphismCheck.cpp" />
4949
<ClCompile Include="algorithm\MaxClique.cpp" />
50+
<ClCompile Include="algorithm\MaxIndependentSet.cpp" />
5051
<ClCompile Include="algorithm\PrintAllPaths.cpp" />
5152
<ClCompile Include="CGIProcessor.cpp" />
5253
<ClCompile Include="common\CaseFunctions.cpp" />
@@ -74,6 +75,7 @@
7475
<ClInclude Include="algorithm\IAlgorithm.h" />
7576
<ClInclude Include="algorithm\IsomorphismCheck.h" />
7677
<ClInclude Include="algorithm\MaxClique.h" />
78+
<ClInclude Include="algorithm\MaxIndependentSet.h" />
7779
<ClInclude Include="algorithm\MaxFlowPushRelabel.h" />
7880
<ClInclude Include="algorithm\MaxFlowPushRelableImpl.h" />
7981
<ClInclude Include="algorithm\PrintAllPaths.h" />

Graphoffline.Emscripten.vcxproj.filters

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,9 @@
7777
<ClCompile Include="algorithm\MaxClique.cpp">
7878
<Filter>algorithm</Filter>
7979
</ClCompile>
80+
<ClCompile Include="algorithm\MaxIndependentSet.cpp">
81+
<Filter>algorithm</Filter>
82+
</ClCompile>
8083
</ItemGroup>
8184
<ItemGroup>
8285
<ClInclude Include="algorithm\AlgorithmFactory.h">
@@ -190,5 +193,8 @@
190193
<ClInclude Include="algorithm\MaxClique.h">
191194
<Filter>algorithm</Filter>
192195
</ClInclude>
196+
<ClInclude Include="algorithm\MaxIndependentSet.h">
197+
<Filter>algorithm</Filter>
198+
</ClInclude>
193199
</ItemGroup>
194200
</Project>

algorithm/AlgorithmFactory.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "PrintAllPaths.h"
2020
#include "BellmanFord.h"
2121
#include "MaxClique.h"
22+
#include "MaxIndependentSet.h"
2223

2324
#include <iostream>
2425

@@ -376,6 +377,12 @@ IAlgorithm* AlgorithmFactory::_CreateAlgorithm(IndexType index, bool bFloat) con
376377
break;
377378
}
378379

380+
case 12:
381+
{
382+
res = new MaxIndependentSet();
383+
break;
384+
}
385+
379386
}
380387

381388
return res;

algorithm/MaxIndependentSet.cpp

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
#include "MaxIndependentSet.h"
2+
#include "IAlgorithmFactory.h"
3+
#include <list>
4+
#include <string.h>
5+
#include <algorithm>
6+
#include "Logger.h"
7+
8+
MaxIndependentSet::MaxIndependentSet () {
9+
10+
}
11+
12+
MaxIndependentSet::~MaxIndependentSet () {
13+
14+
}
15+
16+
bool MaxIndependentSet::Calculate() {
17+
18+
// this->m_pGraph is not saved in ProcessConsoleParams stack -> no need for delete
19+
20+
// make a copy of the graph's complement graph
21+
GraphPtr pGraph = GraphPtr(m_pGraph->MakeBaseCopy(GTC_COMPLEMENT));
22+
if (!pGraph)
23+
{
24+
return false;
25+
}
26+
27+
LOG_INFO(pGraph->PrintGraph());
28+
29+
// run MaxClique algorithm on the complement graph
30+
AlgorithmPtr maxCliqueAlgo = AlgorithmPtr(m_pAlgorithmFactory->CreateAlgorithm("mc", pGraph.get()));
31+
32+
/**
33+
* By default, MaxClique algorithm will have the following values:
34+
* m_num_threads = 1
35+
* m_param_lower_bound = 0
36+
* m_param_upper_bound = UINT_MAX
37+
* m_param_algorithm_type = Exact (Algorithm { Heuristic, Hybrid, Exact })
38+
*/
39+
40+
maxCliqueAlgo->Calculate();
41+
maxCliqueAlgo->UnitTest();
42+
43+
IntWeightType resultCount = maxCliqueAlgo->GetResultCount();
44+
45+
for (int idx = 1; idx < resultCount; idx++) {
46+
this->m_maxIndependentSet.emplace_back(maxCliqueAlgo->GetResult(idx).nodeId);
47+
}
48+
49+
return true;
50+
}
51+
52+
53+
/**
54+
* Used to loop over the result using GetResult
55+
*/
56+
IndexType MaxIndependentSet::GetResultCount() const {
57+
return this->m_maxIndependentSet.size() + 1;
58+
}
59+
60+
// Get result of index. Algorithms can have complex result.
61+
/**
62+
* Index 0 will return number of nodes in the MIS found by the algorithm
63+
* Index 1 - <number of nodes> will get the corresponding node id.
64+
*/
65+
AlgorithmResult MaxIndependentSet::GetResult(IndexType index) const {
66+
AlgorithmResult res;
67+
if (index == 0) {
68+
res.type = ART_INT;
69+
res.nValue = m_maxIndependentSet.size();
70+
} else if (index < m_maxIndependentSet.size() + 1 && index > 0) {
71+
res.type = ART_NODE_ID;
72+
res.nodeId = m_maxIndependentSet[index - 1];
73+
}
74+
return res;
75+
}

algorithm/MaxIndependentSet.h

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
//
2+
// MaxIndependentSet.h
3+
// Graphoffline
4+
//
5+
// Created by Abdalla Egbareia on 16/04/2025
6+
//
7+
//
8+
9+
#ifndef Max_Independent_Set_HPP
10+
#define Max_Independent_Set_HPP
11+
12+
#include <stdio.h>
13+
#include "BaseAlgorithm.h"
14+
#include "IGraph.h"
15+
#include <vector>
16+
17+
class MaxIndependentSet : public BaseAlgorithm
18+
{
19+
public:
20+
MaxIndependentSet ();
21+
virtual ~MaxIndependentSet ();
22+
23+
// Long name of algoright: MaxIndependentSet.
24+
virtual const char* GetFullName() const override {return "Max Independent Set";};
25+
// Short name of algorithm: mis
26+
virtual const char* GetShortName() const override {return "mis"; };
27+
// Calculate algorithm.
28+
virtual bool Calculate() override ;
29+
30+
// Get result count.
31+
virtual IndexType GetResultCount() const override;
32+
// Get result of index. Algorithms can have complex result.
33+
virtual AlgorithmResult GetResult(IndexType index) const override;
34+
35+
virtual void UnitTest() const override {}
36+
37+
private:
38+
39+
std::vector<ObjectId> m_maxIndependentSet;
40+
41+
};
42+
43+
#endif /* Max_Independent_Set_HPP */

graph/Graph.cpp

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -483,6 +483,7 @@ Graph* Graph::MakeGraphCopy(GraphCopyType type, const std::function<Graph*()> &
483483
case GTC_INVERSE: res = MakeGraphInverse(createFunction); break;
484484
case GTC_REMOVE_SELF_LOOP: res = MakeGraphRemoveSelfLoop(createFunction); break;
485485
case GTC_REMOVE_NEGATIVE: res = MakeGraphRemoveNegative(createFunction); break;
486+
case GTC_COMPLEMENT: res = MakeGraphComplement(createFunction); break;
486487
}
487488

488489
if (res)
@@ -737,6 +738,55 @@ Graph* Graph::MakeGraphRemoveNegative(const std::function<Graph*()> & createFunc
737738
}
738739

739740

741+
/**
742+
* It adds all edges (<source, target> pairs) that did not occur in the original graph
743+
* Sets all weights to zero
744+
* All edges of the new graph are directed
745+
*/
746+
Graph* Graph::MakeGraphComplement(const std::function<Graph*()> & createFunction) const
747+
{
748+
Graph* res = createFunction ? createFunction() : CreateGraph();
749+
750+
CopyPropertiesTo(res);
751+
752+
res->m_weightType = m_weightType;
753+
754+
// Create all nodes.
755+
for (NodePtr node : m_nodes)
756+
{
757+
res->m_nodes.push_back(NodePtr(new Node(node->id, node->privateId, node->fake, node->index)));
758+
res->m_idToNode[node->privateId] = res->m_nodes.back();
759+
}
760+
761+
// Add all edges that do not exist in the original graph
762+
763+
for (NodePtr source : res->m_nodes) {
764+
for (NodePtr target : res->m_nodes) {
765+
766+
// no self loop is permitted
767+
if (source->privateId == target->privateId) continue;
768+
769+
// if the original graph does not contain the edge - add it to the copy graph
770+
// pass false to IsEgdeExists to handle undirected edges correctly
771+
if (!this->IsEgdeExists(source->privateId, target->privateId, false)) {
772+
auto indexId = res->GetNextId();
773+
774+
res->AddEdge(String().FromInt(indexId),
775+
source->privateId,
776+
target->privateId,
777+
true,
778+
0,
779+
indexId);
780+
}
781+
782+
}
783+
}
784+
785+
return res;
786+
}
787+
788+
789+
740790
void Graph::RemoveEdge(ObjectId source, ObjectId target)
741791
{
742792
EdgePtr edge = FindEdge(source, target);
@@ -905,7 +955,7 @@ const char* Graph::PrintGraph() const
905955
report += "Edges:\n";
906956
for (auto edge : m_edges)
907957
{
908-
report += std::string("Public id: ") + edge->id.Locale().Data() + " " + "private id: " + std::to_string(edge->privateId) + "\n";
958+
report += std::string("Public id: ") + edge->id.Locale().Data() + " " + "private id: " + std::to_string(edge->privateId) + " source: " + edge->source->id.Locale().Data() + " target: " + edge->target->id.Locale().Data() + " directed: " + std::to_string(edge->direct) +"\n";
909959
}
910960

911961
return report.c_str();

graph/Graph.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,8 @@ class Graph: public virtual IGraph
264264
Graph* MakeGraphRemoveSelfLoop(const std::function<Graph*()> & createFunction) const;
265265
// Remove negative edges
266266
virtual Graph* MakeGraphRemoveNegative(const std::function<Graph*()> & createFunction) const;
267+
// Convert current graph to its complement
268+
Graph* MakeGraphComplement(const std::function<Graph*()> & createFunction) const;
267269

268270
bool IsDouble(double value);
269271

0 commit comments

Comments
 (0)