Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ set(COMMON_LIB_SOURCES
algorithm/MaxClique.h
algorithm/MaxFlowPushRelabel.h
algorithm/MaxFlowPushRelableImpl.h
algorithm/MaxIndependentSet.cpp
algorithm/MaxIndependentSet.h
algorithm/PrintAllPaths.cpp
algorithm/PrintAllPaths.h
algorithm/ShortestPath.h
Expand Down
2 changes: 2 additions & 0 deletions GraphOffline.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@
<ClCompile Include="algorithm\IsomorphismCheck.cpp" />
<ClCompile Include="algorithm\MaxClique.cpp" />
<ClCompile Include="algorithm\PrintAllPaths.cpp" />
<ClCompile Include="algorithm\MaxIndependentSet.cpp" />
<ClCompile Include="CGIProcessor.cpp" />
<ClCompile Include="common\Logger.cpp" />
<ClCompile Include="GraphOffline.cpp" />
Expand Down Expand Up @@ -150,6 +151,7 @@
<ClInclude Include="graph\Graph.h" />
<ClInclude Include="graph\IGraph.h" />
<ClInclude Include="report\ReporterFactory.h" />
<ClInclude Include="algorithm\MaxIndependentSet.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
Expand Down
6 changes: 6 additions & 0 deletions GraphOffline.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,9 @@
<ClCompile Include="algorithm\MaxClique.cpp">
<Filter>Source Files\algorithm</Filter>
</ClCompile>
<ClCompile Include="algorithm\MaxIndependentSet.cpp">
<Filter>Source Files\algorithm</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="CGIProcessor.h">
Expand Down Expand Up @@ -218,5 +221,8 @@
<ClInclude Include="algorithm\MaxClique.h">
<Filter>Source Files\algorithm</Filter>
</ClInclude>
<ClInclude Include="algorithm\MaxIndependentSet.h">
<Filter>Source Files\algorithm</Filter>
</ClInclude>
</ItemGroup>
</Project>
2 changes: 2 additions & 0 deletions Graphoffline.Emscripten.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
<ClCompile Include="algorithm\HamiltonianLoop.cpp" />
<ClCompile Include="algorithm\IsomorphismCheck.cpp" />
<ClCompile Include="algorithm\MaxClique.cpp" />
<ClCompile Include="algorithm\MaxIndependentSet.cpp" />
<ClCompile Include="algorithm\PrintAllPaths.cpp" />
<ClCompile Include="CGIProcessor.cpp" />
<ClCompile Include="common\CaseFunctions.cpp" />
Expand Down Expand Up @@ -74,6 +75,7 @@
<ClInclude Include="algorithm\IAlgorithm.h" />
<ClInclude Include="algorithm\IsomorphismCheck.h" />
<ClInclude Include="algorithm\MaxClique.h" />
<ClInclude Include="algorithm\MaxIndependentSet.h" />
<ClInclude Include="algorithm\MaxFlowPushRelabel.h" />
<ClInclude Include="algorithm\MaxFlowPushRelableImpl.h" />
<ClInclude Include="algorithm\PrintAllPaths.h" />
Expand Down
6 changes: 6 additions & 0 deletions Graphoffline.Emscripten.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,9 @@
<ClCompile Include="algorithm\MaxClique.cpp">
<Filter>algorithm</Filter>
</ClCompile>
<ClCompile Include="algorithm\MaxIndependentSet.cpp">
<Filter>algorithm</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="algorithm\AlgorithmFactory.h">
Expand Down Expand Up @@ -190,5 +193,8 @@
<ClInclude Include="algorithm\MaxClique.h">
<Filter>algorithm</Filter>
</ClInclude>
<ClInclude Include="algorithm\MaxIndependentSet.h">
<Filter>algorithm</Filter>
</ClInclude>
</ItemGroup>
</Project>
7 changes: 7 additions & 0 deletions algorithm/AlgorithmFactory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "PrintAllPaths.h"
#include "BellmanFord.h"
#include "MaxClique.h"
#include "MaxIndependentSet.h"

#include <iostream>

Expand Down Expand Up @@ -376,6 +377,12 @@ IAlgorithm* AlgorithmFactory::_CreateAlgorithm(IndexType index, bool bFloat) con
break;
}

case 12:
{
res = new MaxIndependentSet();
break;
}

}

return res;
Expand Down
75 changes: 75 additions & 0 deletions algorithm/MaxIndependentSet.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
#include "MaxIndependentSet.h"
#include "IAlgorithmFactory.h"
#include <list>
#include <string.h>
#include <algorithm>
#include "Logger.h"

MaxIndependentSet::MaxIndependentSet () {

}

MaxIndependentSet::~MaxIndependentSet () {

}

bool MaxIndependentSet::Calculate() {

// this->m_pGraph is not saved in ProcessConsoleParams stack -> no need for delete

// make a copy of the graph's complement graph
GraphPtr pGraph = GraphPtr(m_pGraph->MakeBaseCopy(GTC_COMPLEMENT));
if (!pGraph)
{
return false;
}

LOG_INFO(pGraph->PrintGraph());

// run MaxClique algorithm on the complement graph
AlgorithmPtr maxCliqueAlgo = AlgorithmPtr(m_pAlgorithmFactory->CreateAlgorithm("mc", pGraph.get()));

/**
* By default, MaxClique algorithm will have the following values:
* m_num_threads = 1
* m_param_lower_bound = 0
* m_param_upper_bound = UINT_MAX
* m_param_algorithm_type = Exact (Algorithm { Heuristic, Hybrid, Exact })
*/

maxCliqueAlgo->Calculate();
maxCliqueAlgo->UnitTest();

IntWeightType resultCount = maxCliqueAlgo->GetResultCount();

for (int idx = 1; idx < resultCount; idx++) {
this->m_maxIndependentSet.emplace_back(maxCliqueAlgo->GetResult(idx).nodeId);
}

return true;
}


/**
* Used to loop over the result using GetResult
*/
IndexType MaxIndependentSet::GetResultCount() const {
return this->m_maxIndependentSet.size() + 1;
}

// Get result of index. Algorithms can have complex result.
/**
* Index 0 will return number of nodes in the MIS found by the algorithm
* Index 1 - <number of nodes> will get the corresponding node id.
*/
AlgorithmResult MaxIndependentSet::GetResult(IndexType index) const {
AlgorithmResult res;
if (index == 0) {
res.type = ART_INT;
res.nValue = m_maxIndependentSet.size();
} else if (index < m_maxIndependentSet.size() + 1 && index > 0) {
res.type = ART_NODE_ID;
res.nodeId = m_maxIndependentSet[index - 1];
}
return res;
}
43 changes: 43 additions & 0 deletions algorithm/MaxIndependentSet.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
//
// MaxIndependentSet.h
// Graphoffline
//
// Created by Abdalla Egbareia on 16/04/2025
//
//

#ifndef Max_Independent_Set_HPP
#define Max_Independent_Set_HPP

#include <stdio.h>
#include "BaseAlgorithm.h"
#include "IGraph.h"
#include <vector>

class MaxIndependentSet : public BaseAlgorithm
{
public:
MaxIndependentSet ();
virtual ~MaxIndependentSet ();

// Long name of algoright: MaxIndependentSet.
virtual const char* GetFullName() const override {return "Max Independent Set";};
// Short name of algorithm: mis
virtual const char* GetShortName() const override {return "mis"; };
// Calculate algorithm.
virtual bool Calculate() override ;

// Get result count.
virtual IndexType GetResultCount() const override;
// Get result of index. Algorithms can have complex result.
virtual AlgorithmResult GetResult(IndexType index) const override;

virtual void UnitTest() const override {}

private:

std::vector<ObjectId> m_maxIndependentSet;

};

#endif /* Max_Independent_Set_HPP */
52 changes: 51 additions & 1 deletion graph/Graph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -483,6 +483,7 @@ Graph* Graph::MakeGraphCopy(GraphCopyType type, const std::function<Graph*()> &
case GTC_INVERSE: res = MakeGraphInverse(createFunction); break;
case GTC_REMOVE_SELF_LOOP: res = MakeGraphRemoveSelfLoop(createFunction); break;
case GTC_REMOVE_NEGATIVE: res = MakeGraphRemoveNegative(createFunction); break;
case GTC_COMPLEMENT: res = MakeGraphComplement(createFunction); break;
}

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


/**
* It adds all edges (<source, target> pairs) that did not occur in the original graph
* Sets all weights to zero
* All edges of the new graph are directed
*/
Graph* Graph::MakeGraphComplement(const std::function<Graph*()> & createFunction) const
{
Graph* res = createFunction ? createFunction() : CreateGraph();

CopyPropertiesTo(res);

res->m_weightType = m_weightType;

// Create all nodes.
for (NodePtr node : m_nodes)
{
res->m_nodes.push_back(NodePtr(new Node(node->id, node->privateId, node->fake, node->index)));
res->m_idToNode[node->privateId] = res->m_nodes.back();
}

// Add all edges that do not exist in the original graph

for (NodePtr source : res->m_nodes) {
for (NodePtr target : res->m_nodes) {

// no self loop is permitted
if (source->privateId == target->privateId) continue;

// if the original graph does not contain the edge - add it to the copy graph
// pass false to IsEgdeExists to handle undirected edges correctly
if (!this->IsEgdeExists(source->privateId, target->privateId, false)) {
auto indexId = res->GetNextId();

res->AddEdge(String().FromInt(indexId),
source->privateId,
target->privateId,
true,
0,
indexId);
}

}
}

return res;
}



void Graph::RemoveEdge(ObjectId source, ObjectId target)
{
EdgePtr edge = FindEdge(source, target);
Expand Down Expand Up @@ -905,7 +955,7 @@ const char* Graph::PrintGraph() const
report += "Edges:\n";
for (auto edge : m_edges)
{
report += std::string("Public id: ") + edge->id.Locale().Data() + " " + "private id: " + std::to_string(edge->privateId) + "\n";
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";
}

return report.c_str();
Expand Down
2 changes: 2 additions & 0 deletions graph/Graph.h
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,8 @@ class Graph: public virtual IGraph
Graph* MakeGraphRemoveSelfLoop(const std::function<Graph*()> & createFunction) const;
// Remove negative edges
virtual Graph* MakeGraphRemoveNegative(const std::function<Graph*()> & createFunction) const;
// Convert current graph to its complement
Graph* MakeGraphComplement(const std::function<Graph*()> & createFunction) const;

bool IsDouble(double value);

Expand Down
3 changes: 2 additions & 1 deletion graph/IGraph.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ enum GraphCopyType {GCT_COPY = 0,
GTC_REMOVE_SELF_LOOP,
GTC_MULTI_TO_COMMON_GRAPH_MINIMAL_EDGES,
GTC_MULTI_TO_COMMON_GRAPH_SUM_EDGES,
GTC_REMOVE_NEGATIVE};
GTC_REMOVE_NEGATIVE,
GTC_COMPLEMENT};

/**
* Call back for enum nodes methods (DFS, BSF).
Expand Down
28 changes: 28 additions & 0 deletions test/MaxIndependentSet/_runTests.bat
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
@echo off

if "%~1"=="" (
set exePath="../../bin/Windows/Release/GraphOffline.exe"
) else (
set exePath="%1"
)

cd /D "%~dp0"
set COUNTER=0

FOR /F "tokens=1-10" %%A IN (testList_full.txt) DO (
%exePath% -%%A %%B %%C %%D %%E %%F %%G %%H %%I %%J > %%B.test
fc %%B.test %%B.res > nul
if errorlevel 1 @echo %%I\%%B && goto faild
del %%B.test
set /A COUNTER=COUNTER+1
)

cd ..

@echo OK - %COUNTER% tests
exit /B

:faild
cd ..
@echo "Faild"
exit 1
29 changes: 29 additions & 0 deletions test/MaxIndependentSet/_runTests.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# @echo off

isFaild=0;

rm *.test &>/dev/null

while IFS=$' ' read -r command xmlFile; do
if [ "$2" == "-debug" ]; then
echo "$exePath ${command} ./${xmlFile} > ${xmlFile}.test"
fi

$exePath ${command} ./${xmlFile} > ${xmlFile}.test

if diff --ignore-all-space ${xmlFile}.res ${xmlFile}.test >/dev/null ; then
continue;
else
isFaild=1;
echo "${xmlFile} failed."
break;
fi
done < "testList.txt"

if [ $isFaild -eq 1 ]; then
echo "Failed";
exit 1;
else
echo "OK"
rm *.test &>/dev/null
fi
15 changes: 15 additions & 0 deletions test/MaxIndependentSet/graph1.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<graphml xmlns="http://graphml.graphdrawing.org/xmlns"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns
http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
<graph id="G" edgedefault="undirected">
<node id="n0"/>
<node id="n1"/>
<node id="n2"/>
<node id="n3"/>
<edge source="n0" target="n1" id="e1"/>
<edge source="n1" target="n2" id="e2"/>
<!-- <edge source="n0" target="n2" id="e3"/> -->
</graph>
</graphml>
1 change: 1 addition & 0 deletions test/MaxIndependentSet/graph1.xml.res
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Result is 3 (n0 n2 n3)
Loading
Loading