20 #ifndef __CXXGRAPH_GRAPH_H__
21 #define __CXXGRAPH_GRAPH_H__
27 #include <unordered_set>
48 #include "Edge/Weighted.hpp"
49 #include "Node/Node.hpp"
50 #include "Edge/Edge.hpp"
51 #include "Edge/DirectedEdge.hpp"
52 #include "Edge/UndirectedEdge.hpp"
53 #include "Edge/DirectedWeightedEdge.hpp"
54 #include "Edge/UndirectedWeightedEdge.hpp"
55 #include "Utility/ThreadSafe.hpp"
56 #include "Utility/Writer.hpp"
57 #include "Utility/Reader.hpp"
58 #include "Utility/ConstString.hpp"
59 #include "Utility/ConstValue.hpp"
60 #include "Utility/Typedef.hpp"
61 #include "Partitioning/Partition.hpp"
62 #include "Partitioning/PartitionAlgorithm.hpp"
63 #include "Partitioning/Partitioner.hpp"
64 #include "Partitioning/Utility/Globals.hpp"
75 using T_EdgeSet = std::unordered_set<const Edge<T> *>;
77 namespace PARTITIONING
84 std::ostream &operator<<(std::ostream &o,
const Graph<T> &graph);
86 std::ostream &operator<<(std::ostream &o,
const AdjacencyMatrix<T> &adj);
93 T_EdgeSet<T> edgeSet = {};
94 std::optional<std::pair<std::string, char>> getExtenstionAndSeparator(InputOutputFormat format)
const;
95 int writeToStandardFile(
const std::string &workingDir,
const std::string &OFileName,
bool compress,
bool writeNodeFeat,
bool writeEdgeWeight, InputOutputFormat format)
const;
96 int readFromStandardFile(
const std::string &workingDir,
const std::string &OFileName,
bool compress,
bool readNodeFeat,
bool readEdgeWeight, InputOutputFormat format);
97 void recreateGraphFromReadFiles(std::unordered_map<
unsigned long long, std::pair<std::string, std::string>> &edgeMap, std::unordered_map<unsigned long long, bool> &edgeDirectedMap, std::unordered_map<std::string, T> &nodeFeatMap, std::unordered_map<unsigned long long, double> &edgeWeightMap);
98 int compressFile(
const std::string &inputFile,
const std::string &outputFile)
const;
99 int decompressFile(
const std::string &inputFile,
const std::string &outputFile)
const;
103 Graph(
const T_EdgeSet<T> &edgeSet);
104 virtual ~
Graph() =
default;
113 virtual const T_EdgeSet<T> &
getEdgeSet()
const;
122 virtual void setEdgeSet(T_EdgeSet<T> &edgeSet);
140 virtual void removeEdge(
unsigned long long edgeId);
149 virtual const std::set<const Node<T> *>
getNodeSet()
const;
159 virtual const std::optional<const Edge<T> *>
getEdge(
unsigned long long edgeId)
const;
175 virtual unsigned long long setFind(std::unordered_map<unsigned long long, Subset> *,
const unsigned long long elem)
const;
185 virtual void setUnion(std::unordered_map<unsigned long long, Subset> *,
const unsigned long long set1,
const unsigned long long elem2)
const;
315 virtual bool containsCycle(
const T_EdgeSet<T> *edgeSet, std::unordered_map<unsigned long long, Subset> *)
const;
363 virtual std::vector<std::vector<Node<T>>>
kosaraju()
const;
434 virtual int writeToFile(InputOutputFormat format = InputOutputFormat::STANDARD_CSV,
const std::string &workingDir =
".",
const std::string &OFileName =
"graph",
bool compress =
false,
bool writeNodeFeat =
false,
bool writeEdgeWeight =
false)
const;
449 virtual int readFromFile(InputOutputFormat format = InputOutputFormat::STANDARD_CSV,
const std::string &workingDir =
".",
const std::string &OFileName =
"graph",
bool compress =
false,
bool readNodeFeat =
false,
bool readEdgeWeight =
false);
460 virtual PartitionMap<T>
partitionGraph(PARTITIONING::PartitionAlgorithm algorithm,
unsigned int numberOfPartitions,
double param1 = 0.0,
double param2 = 0.0,
double param3 = 0.0,
unsigned int numberOfthreads = std::thread::hardware_concurrency())
const;
462 friend std::ostream &operator<<<>(std::ostream &os,
const Graph<T> &graph);
463 friend std::ostream &operator<<<>(std::ostream &os,
const AdjacencyMatrix<T> &adj);
466 template <
typename T>
469 for (
const auto &edgeSetIt : edgeSet)
478 this->edgeSet.insert(edgeSetIt);
482 template <
typename T>
488 template <
typename T>
491 this->edgeSet.clear();
492 for (
const auto &edgeSetIt : edgeSet)
501 this->edgeSet.insert(edgeSetIt);
505 template <
typename T>
515 edgeSet.insert(edge);
518 template <
typename T>
522 if (edgeOpt.has_value())
528 edgeSet.erase(edgeSet.find(edgeOpt.value()));
532 template <
typename T>
535 std::set <const Node<T> *> nodeSet;
536 for (
const auto &edgeSetIt : edgeSet)
538 nodeSet.insert(edgeSetIt->getNodePair().first);
539 nodeSet.insert(edgeSetIt->getNodePair().second);
560 template <
typename T>
563 for (
const auto &it : edgeSet)
565 if (it->getId() == edgeId)
574 template <
typename T>
577 if (format == InputOutputFormat::STANDARD_CSV)
579 return std::pair<std::string, char>(
".csv",
',');
581 else if (format == InputOutputFormat::STANDARD_TSV)
583 return std::pair<std::string, char>(
".tsv",
'\t');
591 template <
typename T>
592 int Graph<T>::writeToStandardFile(
const std::string &workingDir,
const std::string &OFileName,
bool compress,
bool writeNodeFeat,
bool writeEdgeWeight, InputOutputFormat format)
const
594 auto result = getExtenstionAndSeparator(format);
597 std::cerr <<
"Unknown format\n";
600 auto &[extension, separator] = *result;
602 std::ofstream ofileGraph;
603 std::string completePathToFileGraph = workingDir +
"/" + OFileName + extension;
604 ofileGraph.open(completePathToFileGraph);
605 if (!ofileGraph.is_open())
611 for (
const auto &edge : edgeSet)
613 ofileGraph << edge->getId() << separator
614 << edge->getNodePair().first->getUserId() << separator
615 << edge->getNodePair().second->getUserId() << separator
616 << ((edge->isDirected().has_value() && edge->isDirected().value()) ? 1 : 0)
623 std::ofstream ofileNodeFeat;
624 std::string completePathToFileNodeFeat = workingDir +
"/" + OFileName +
"_NodeFeat" + extension;
625 ofileNodeFeat.open(completePathToFileNodeFeat);
626 if (!ofileNodeFeat.is_open())
631 auto nodeSet = getNodeSet();
632 for (
const auto &node : nodeSet)
634 ofileNodeFeat << node->getUserId() << separator << node->getData() << std::endl;
636 ofileNodeFeat.close();
641 std::ofstream ofileEdgeWeight;
642 std::string completePathToFileEdgeWeight = workingDir +
"/" + OFileName +
"_EdgeWeight" + extension;
643 ofileEdgeWeight.open(completePathToFileEdgeWeight);
644 if (!ofileEdgeWeight.is_open())
647 std::cout <<
"ERROR File Not Open" << std::endl;
651 for (
const auto &edge : edgeSet)
653 ofileEdgeWeight << edge->getId() << separator
654 << (edge->isWeighted().has_value() && edge->isWeighted().value() ? (
dynamic_cast<const Weighted *
>(edge))->getWeight() : 0.0) << separator
655 << (edge->isWeighted().has_value() && edge->isWeighted().value() ? 1 : 0)
658 ofileEdgeWeight.close();
666 static const mask *make_table()
669 static std::vector<mask> v(classic_table(), classic_table() + table_size);
675 csv_whitespace(std::size_t refs = 0) : ctype(make_table(),
false, refs) {}
678 template <
typename T>
679 int Graph<T>::readFromStandardFile(
const std::string &workingDir,
const std::string &OFileName,
bool compress,
bool readNodeFeat,
bool readEdgeWeight, InputOutputFormat format)
681 auto result = getExtenstionAndSeparator(format);
684 std::cerr <<
"Unknown format\n";
687 auto &[extension, separator] = *result;
689 std::ifstream ifileGraph;
690 std::ifstream ifileNodeFeat;
691 std::ifstream ifileEdgeWeight;
693 std::unordered_map<unsigned long long, std::pair<std::string, std::string>> edgeMap;
694 std::unordered_map<unsigned long long, bool> edgeDirectedMap;
695 std::unordered_map<std::string, T> nodeFeatMap;
696 std::unordered_map<unsigned long long, double> edgeWeightMap;
697 std::string completePathToFileGraph = workingDir +
"/" + OFileName + extension;
699 ifileGraph.open(completePathToFileGraph);
700 if (!ifileGraph.is_open())
707 ifileGraph.imbue(std::locale(ifileGraph.getloc(),
new csv_whitespace));
708 unsigned long long edgeId;
712 while (ifileGraph >> edgeId >> nodeId1 >> nodeId2 >> directed)
714 edgeMap[edgeId] = std::pair<std::string, std::string>(nodeId1, nodeId2);
715 edgeDirectedMap[edgeId] = directed;
719 remove(completePathToFileGraph.c_str());
723 std::string completePathToFileNodeFeat = workingDir +
"/" + OFileName +
"_NodeFeat" + extension;
724 ifileNodeFeat.open(completePathToFileNodeFeat);
725 if (!ifileNodeFeat.is_open())
731 ifileNodeFeat.imbue(std::locale(ifileGraph.getloc(),
new csv_whitespace));
734 while (ifileNodeFeat >> nodeId >> nodeFeat)
736 nodeFeatMap[nodeId] = nodeFeat;
738 ifileNodeFeat.close();
740 remove(completePathToFileNodeFeat.c_str());
745 std::string completePathToFileEdgeWeight = workingDir +
"/" + OFileName +
"_EdgeWeight" + extension;
746 ifileEdgeWeight.open(completePathToFileEdgeWeight);
747 if (!ifileEdgeWeight.is_open())
753 ifileEdgeWeight.imbue(std::locale(ifileGraph.getloc(),
new csv_whitespace));
754 unsigned long long edgeId;
757 while (ifileEdgeWeight >> edgeId >> weight >> weighted)
761 edgeWeightMap[edgeId] = weight;
764 ifileEdgeWeight.close();
766 remove(completePathToFileEdgeWeight.c_str());
768 recreateGraphFromReadFiles(edgeMap, edgeDirectedMap, nodeFeatMap, edgeWeightMap);
772 template <
typename T>
773 void Graph<T>::recreateGraphFromReadFiles(std::unordered_map<
unsigned long long, std::pair<std::string, std::string>> &edgeMap, std::unordered_map<unsigned long long, bool> &edgeDirectedMap, std::unordered_map<std::string, T> &nodeFeatMap, std::unordered_map<unsigned long long, double> &edgeWeightMap)
775 std::unordered_map<std::string, Node<T> *> nodeMap;
776 for (
const auto &edgeIt : edgeMap)
778 Node<T> *node1 =
nullptr;
779 Node<T> *node2 =
nullptr;
780 if (nodeMap.find(edgeIt.second.first) == nodeMap.end())
784 if (nodeFeatMap.find(edgeIt.second.first) != nodeFeatMap.end())
786 feat = nodeFeatMap.at(edgeIt.second.first);
788 node1 =
new Node<T>(edgeIt.second.first, feat);
789 nodeMap[edgeIt.second.first] = node1;
793 node1 = nodeMap.at(edgeIt.second.first);
795 if (nodeMap.find(edgeIt.second.second) == nodeMap.end())
799 if (nodeFeatMap.find(edgeIt.second.second) != nodeFeatMap.end())
801 feat = nodeFeatMap.at(edgeIt.second.second);
803 node2 =
new Node<T>(edgeIt.second.second, feat);
804 nodeMap[edgeIt.second.second] = node2;
808 node2 = nodeMap.at(edgeIt.second.second);
811 if (edgeWeightMap.find(edgeIt.first) != edgeWeightMap.end())
813 if (edgeDirectedMap.find(edgeIt.first) != edgeDirectedMap.end() && edgeDirectedMap.at(edgeIt.first))
815 auto edge =
new DirectedWeightedEdge<T>(edgeIt.first, *node1, *node2, edgeWeightMap.at(edgeIt.first));
820 auto edge =
new UndirectedWeightedEdge<T>(edgeIt.first, *node1, *node2, edgeWeightMap.at(edgeIt.first));
826 if (edgeDirectedMap.find(edgeIt.first) != edgeDirectedMap.end() && edgeDirectedMap.at(edgeIt.first))
828 auto edge =
new DirectedEdge<T>(edgeIt.first, *node1, *node2);
833 auto edge =
new UndirectedEdge<T>(edgeIt.first, *node1, *node2);
840 template <
typename T>
841 int Graph<T>::compressFile(
const std::string &inputFile,
const std::string &outputFile)
const
850 std::string content((std::istreambuf_iterator<char>(ifs)),
851 (std::istreambuf_iterator<char>()));
853 const char *content_ptr = content.c_str();
854 gzFile outFileZ = gzopen(outputFile.c_str(),
"wb");
855 if (outFileZ == NULL)
861 unsigned int zippedBytes;
862 zippedBytes = gzwrite(outFileZ, content_ptr, strlen(content_ptr));
869 template <
typename T>
870 int Graph<T>::decompressFile(
const std::string &inputFile,
const std::string &outputFile)
const
872 gzFile inFileZ = gzopen(inputFile.c_str(),
"rb");
878 unsigned char unzipBuffer[8192];
879 unsigned int unzippedBytes;
880 std::vector<unsigned char> unzippedData;
882 ofs.open(outputFile);
890 unzippedBytes = gzread(inFileZ, unzipBuffer, 8192);
891 if (unzippedBytes > 0)
893 unzippedData.insert(unzippedData.end(), unzipBuffer, unzipBuffer + unzippedBytes);
900 for (
const auto &c : unzippedData)
910 template <
typename T>
911 unsigned long long Graph<T>::setFind(std::unordered_map<unsigned long long, Subset> *subsets,
const unsigned long long nodeId)
const
915 if ((*subsets)[nodeId].parent != nodeId)
917 (*subsets)[nodeId].parent =
Graph<T>::setFind(subsets, (*subsets)[nodeId].parent);
920 return (*subsets)[nodeId].parent;
923 template <
typename T>
924 void Graph<T>::setUnion(std::unordered_map<unsigned long long, Subset> *subsets,
const unsigned long long elem1,
const unsigned long long elem2)
const
928 if ((*subsets)[elem1].parent == (*subsets)[elem2].parent)
932 if ((*subsets)[elem1Parent].rank < (*subsets)[elem2Parent].rank)
933 (*subsets)[elem1].parent = elem2Parent;
934 else if ((*subsets)[elem1Parent].rank > (*subsets)[elem2Parent].rank)
935 (*subsets)[elem2].parent = elem1Parent;
938 (*subsets)[elem2].parent = elem1Parent;
939 (*subsets)[elem1Parent].rank++;
943 template <
typename T>
948 std::vector<Node<T>> eulerPath;
949 std::vector<const Node<T> *> currentPath;
950 auto currentNode = *(nodeSet.begin());
951 currentPath.push_back(currentNode);
952 while (currentPath.size() > 0)
954 auto &edges = adj.at(currentNode);
959 auto firstEdge = edges.back().second;
960 auto nextNodeId = firstEdge->getNodePair().second;
961 currentPath.push_back(nextNodeId);
962 currentNode = nextNodeId;
967 eulerPath.push_back(*currentNode);
968 currentNode = currentPath.back();
969 currentPath.pop_back();
975 template <
typename T>
979 AdjacencyMatrix<T> adj;
980 auto addElementToAdjMatrix = [&adj](
const Node<T> *nodeFrom,
const Node<T> *nodeTo,
const Edge<T> *edge){
981 std::pair<const Node<T> *,
const Edge<T> *> elem = {nodeTo, edge};
982 adj[nodeFrom].push_back(std::move(elem));
984 for (
const auto &edgeSetIt : edgeSet)
986 if (edgeSetIt->isDirected().has_value() && edgeSetIt->isDirected().value())
989 addElementToAdjMatrix(&(d_edge->getFrom()), &(d_edge->getTo()), d_edge);
991 else if (edgeSetIt->isDirected().has_value() && !edgeSetIt->isDirected().value())
995 addElementToAdjMatrix(&(ud_edge->getNode1()), &(ud_edge->getNode2()), ud_edge);
996 addElementToAdjMatrix(&(ud_edge->getNode2()), &(ud_edge->getNode1()), ud_edge);
1006 template <
typename T>
1011 if (std::find(nodeSet.begin(), nodeSet.end(), &source) == nodeSet.end())
1014 result.errorMessage = ERR_SOURCE_NODE_NOT_IN_GRAPH;
1017 if (std::find(nodeSet.begin(), nodeSet.end(), &target) == nodeSet.end())
1020 result.errorMessage = ERR_TARGET_NODE_NOT_IN_GRAPH;
1028 std::unordered_map<const Node<T> *,
double> dist;
1030 for (
const auto &node : nodeSet )
1032 dist[node] = INF_DOUBLE;
1038 std::priority_queue<std::pair<double, const Node<T> *>, std::vector<std::pair<double, const Node<T> *>>,
1039 std::greater<std::pair<double, const Node<T> *>>>
1043 pq.push(std::make_pair(0.0, &source));
1051 const Node<T> *currentNode = pq.top().second;
1054 double currentDist = pq.top().first;
1060 if (adj.find(currentNode) != adj.end())
1062 for (
const auto &elem : adj.at(currentNode))
1065 if (elem.second->isWeighted().has_value() && elem.second->isWeighted().value())
1067 if (elem.second->isDirected().has_value() && elem.second->isDirected().value())
1070 if (dw_edge->getWeight() < 0)
1072 result.errorMessage = ERR_NEGATIVE_WEIGHTED_EDGE;
1075 else if (currentDist + dw_edge->getWeight() < dist[elem.first])
1077 dist[elem.first] = currentDist + dw_edge->getWeight();
1078 pq.push(std::make_pair(dist[elem.first], elem.first));
1081 else if (elem.second->isDirected().has_value() && !elem.second->isDirected().value())
1084 if (udw_edge->getWeight() < 0)
1086 result.errorMessage = ERR_NEGATIVE_WEIGHTED_EDGE;
1089 else if (currentDist + udw_edge->getWeight() < dist[elem.first])
1091 dist[elem.first] = currentDist + udw_edge->getWeight();
1092 pq.push(std::make_pair(dist[elem.first], elem.first));
1098 result.errorMessage = ERR_NO_DIR_OR_UNDIR_EDGE;
1105 result.errorMessage = ERR_NO_WEIGHTED_EDGE;
1111 if (dist[&target] != INF_DOUBLE)
1113 result.success =
true;
1114 result.errorMessage =
"";
1115 result.result = dist[&target];
1118 result.errorMessage = ERR_TARGET_NODE_NOT_REACHABLE;
1122 template <
typename T>
1126 result.success =
false;
1127 result.errorMessage =
"";
1128 result.result = INF_DOUBLE;
1130 if (std::find(nodeSet.begin(), nodeSet.end(), &source) == nodeSet.end())
1133 result.errorMessage = ERR_SOURCE_NODE_NOT_IN_GRAPH;
1136 if (std::find(nodeSet.begin(), nodeSet.end(), &target) == nodeSet.end())
1139 result.errorMessage = ERR_TARGET_NODE_NOT_IN_GRAPH;
1143 std::unordered_map<const Node<T> *,
double> dist, currentDist;
1145 auto n = nodeSet.size();
1146 for (
const auto &elem : nodeSet)
1148 dist[elem] = INF_DOUBLE;
1149 currentDist[elem] = INF_DOUBLE;
1156 auto earlyStopping =
false;
1158 for (
int i = 0; i < n - 1; ++i)
1163 for (
const auto &edge : edgeSet)
1165 auto elem = edge->getNodePair();
1166 if (edge->isWeighted().has_value() && edge->isWeighted().value())
1168 auto edge_weight = (
dynamic_cast<const Weighted *
>(edge))->getWeight();
1169 if (dist[elem.first] + edge_weight < dist[elem.second])
1170 dist[elem.second] = dist[elem.first] + edge_weight;
1175 result.errorMessage = ERR_NO_WEIGHTED_EDGE;
1180 for (
const auto &[key, value] : dist)
1182 if (currentDist[key] != value)
1188 for (
const auto &[key, value] : dist)
1190 currentDist[key] = value;
1194 earlyStopping =
true;
1203 for (
const auto &edge : edgeSet)
1205 auto elem = edge->getNodePair();
1206 auto edge_weight = (
dynamic_cast<const Weighted *
>(edge))->getWeight();
1207 if (dist[elem.first] + edge_weight < dist[elem.second])
1209 result.success =
true;
1210 result.negativeCycle =
true;
1211 result.errorMessage =
"";
1217 if (dist[&target] != INF_DOUBLE)
1219 result.success =
true;
1220 result.errorMessage =
"";
1221 result.negativeCycle =
false;
1222 result.result = dist[&target];
1225 result.errorMessage = ERR_TARGET_NODE_NOT_REACHABLE;
1230 template <
typename T>
1234 result.success =
false;
1235 result.errorMessage =
"";
1236 std::unordered_map<std::pair<std::string, std::string>, double,
CXXGRAPH::pair_hash> pairwise_dist;
1240 for (
const auto &elem1 : nodeSet)
1242 for (
const auto &elem2 : nodeSet)
1244 auto key = std::make_pair(elem1->getUserId(), elem2->getUserId());
1246 pairwise_dist[key] = INF_DOUBLE;
1248 pairwise_dist[key] = 0.0;
1255 for (
const auto &edge : edgeSet)
1257 const auto &elem = edge->getNodePair();
1258 if (edge->isWeighted().has_value() && edge->isWeighted().value())
1260 auto edgeWeight = (
dynamic_cast<const Weighted *
>(edge))->getWeight();
1261 auto key = std::make_pair(elem.first->getUserId(), elem.second->getUserId());
1262 pairwise_dist[key] = edgeWeight;
1268 result.errorMessage = ERR_NO_WEIGHTED_EDGE;
1273 for (
const auto &k : nodeSet)
1276 for (
const auto &src : nodeSet)
1280 auto src_k = std::make_pair(src->getUserId(), k->getUserId());
1281 for (
const auto &dst : nodeSet)
1286 auto src_dst = std::make_pair(src->getUserId(), dst->getUserId());
1287 auto k_dst = std::make_pair(k->getUserId(), dst->getUserId());
1288 if (pairwise_dist[src_dst] > (pairwise_dist[src_k] + pairwise_dist[k_dst]) && (pairwise_dist[k_dst] != INF_DOUBLE && pairwise_dist[src_k] != INF_DOUBLE))
1289 pairwise_dist[src_dst] = pairwise_dist[src_k] + pairwise_dist[k_dst];
1294 result.success =
true;
1297 for (
const auto &node : nodeSet)
1299 auto diag = std::make_pair(node->getUserId(), node->getUserId());
1300 if (pairwise_dist[diag] < 0.)
1302 result.negativeCycle =
true;
1306 result.result = std::move(pairwise_dist);
1310 template <
typename T>
1314 result.success =
false;
1315 result.errorMessage =
"";
1316 result.mstCost = INF_DOUBLE;
1317 if (!isUndirectedGraph())
1319 result.errorMessage = ERR_DIR_GRAPH;
1322 if (!isConnectedGraph())
1324 result.errorMessage = ERR_NOT_STRONG_CONNECTED;
1328 auto n = nodeSet.size();
1332 std::unordered_map<const Node<T> *,
double> dist;
1333 for (
const auto &elem : adj)
1335 dist[elem.first] = INF_DOUBLE;
1341 std::priority_queue<std::pair<double, const Node<T> *>, std::vector<std::pair<double, const Node<T> *>>,
1342 std::greater<std::pair<double, const Node<T> *>>>
1346 auto source = *(nodeSet.begin());
1347 pq.push(std::make_pair(0.0, source));
1349 std::vector<unsigned long long> doneNode;
1352 doneNode.push_back(source->getId());
1355 std::unordered_map<unsigned long long, std::string> parentNode;
1359 const Node<T> *currentNode = pq.top().second;
1360 auto nodeId = currentNode->getId();
1361 if (std::find(doneNode.begin(), doneNode.end(), nodeId) == doneNode.end())
1363 auto pair = std::make_pair(parentNode[nodeId], currentNode->getUserId());
1364 result.mst.push_back(pair);
1365 result.mstCost += pq.top().first;
1366 doneNode.push_back(nodeId);
1372 if (adj.find(currentNode) != adj.end())
1374 for (
const auto &elem : adj.at(currentNode))
1377 if (elem.second->isWeighted().has_value() && elem.second->isWeighted().value())
1381 (udw_edge->getWeight() < dist[elem.first]) &&
1382 (std::find(doneNode.begin(), doneNode.end(), elem.first->getId()) == doneNode.end()))
1384 dist[elem.first] = udw_edge->getWeight();
1385 parentNode[elem.first->getId()] = currentNode->getUserId();
1386 pq.push(std::make_pair(dist[elem.first], elem.first));
1392 result.errorMessage = ERR_NO_WEIGHTED_EDGE;
1398 result.success =
true;
1402 template <
typename T>
1406 result.success =
false;
1407 result.errorMessage =
"";
1408 result.mstCost = INF_DOUBLE;
1409 if (!isUndirectedGraph())
1411 result.errorMessage = ERR_DIR_GRAPH;
1415 const auto n = nodeSet.size();
1418 std::unordered_map<unsigned long long, Subset> subsets;
1427 std::unordered_map<unsigned long long, double> edgeWeight;
1428 for (
const auto &edge : edgeSet)
1430 if (edge->isWeighted().has_value() && edge->isWeighted().value())
1431 edgeWeight[edge->getId()] = (
dynamic_cast<const Weighted *
>(edge))->getWeight();
1435 result.errorMessage = ERR_NO_WEIGHTED_EDGE;
1440 for (
const auto &node : nodeSet)
1442 Subset set{node->getId(), 0};
1443 subsets[node->getId()] = set;
1448 while (numTrees > 1)
1452 std::unordered_map<unsigned long long, unsigned long long> cheapest;
1453 for (
const auto &node : nodeSet)
1454 cheapest[node->getId()] = INT_MAX;
1458 for (
const auto &edge : edgeSet)
1460 auto elem = edge->getNodePair();
1461 auto edgeId = edge->getId();
1473 if (cheapest[set1] == INT_MAX ||
1474 edgeWeight[cheapest[set1]] > edgeWeight[edgeId])
1475 cheapest[set1] = edgeId;
1477 if (cheapest[set2] == INT_MAX ||
1478 edgeWeight[cheapest[set2]] > edgeWeight[edgeId])
1479 cheapest[set2] = edgeId;
1484 for (
const auto &[nodeId, edgeId] : cheapest)
1487 if (edgeId != INT_MAX)
1494 result.mstCost += edgeWeight[edgeId];
1495 auto newEdgeMST = std::make_pair(cheapestNode.first->getUserId(), cheapestNode.second->getUserId());
1496 result.mst.push_back(newEdgeMST);
1503 result.success =
true;
1507 template <
typename T>
1511 result.success =
false;
1512 result.errorMessage =
"";
1513 result.mstCost = INF_DOUBLE;
1514 if (!isUndirectedGraph())
1516 result.errorMessage = ERR_DIR_GRAPH;
1520 auto n = nodeSet.size();
1525 std::priority_queue<std::pair<double, const Edge<T> *>, std::vector<std::pair<double, const Edge<T> *>>,
1526 std::greater<std::pair<double, const Edge<T> *>>>
1528 for (
const auto &edge : edgeSet)
1530 if (edge->isWeighted().has_value() && edge->isWeighted().value())
1532 auto weight = (
dynamic_cast<const Weighted *
>(edge))->getWeight();
1533 sortedEdges.push(std::make_pair(weight, edge));
1538 result.errorMessage = ERR_NO_WEIGHTED_EDGE;
1543 std::unordered_map<unsigned long long, Subset> subset;
1545 for (
const auto &node : nodeSet)
1547 Subset set{node->getId(), 0};
1548 subset[node->getId()] = set;
1551 while ((!sortedEdges.empty()) && (result.mst.size() < n))
1553 auto [edgeWeight, cheapestEdge] = sortedEdges.top();
1555 auto &[first, second] = cheapestEdge->getNodePair();
1560 result.mst.push_back(std::make_pair(first->getUserId(), second->getUserId()));
1561 result.mstCost += edgeWeight;
1565 result.success =
true;
1569 template <
typename T>
1573 std::vector<Node<T>> visited;
1576 if (std::find(nodeSet.begin(), nodeSet.end(), &start) == nodeSet.end())
1582 std::queue<const Node<T> *> tracker;
1585 visited.push_back(start);
1586 tracker.push(&start);
1587 while (!tracker.empty())
1589 const Node<T> *node = tracker.front();
1591 if (adj.find(node) != adj.end())
1593 for (
const auto &elem : adj.at(node))
1597 if (std::find(visited.begin(), visited.end(), *(elem.first)) == visited.end())
1599 visited.push_back(*(elem.first));
1600 tracker.push(elem.first);
1609 template <
typename T>
1613 std::vector<Node<T>> visited;
1616 if (std::find(nodeSet.begin(), nodeSet.end(), &start) == nodeSet.end())
1621 std::function<void(
const AdjacencyMatrix<T> &,
const Node<T> &, std::vector<
Node<T>> &)> explore;
1622 explore = [&explore](
const AdjacencyMatrix<T> &adj,
const Node<T> &node, std::vector<Node<T>> &visited) ->
void
1624 visited.push_back(node);
1625 if (adj.find(&node) != adj.end())
1627 for (
const auto &x : adj.at(&node))
1629 if (std::find(visited.begin(), visited.end(), *(x.first)) == visited.end())
1631 explore(adj, *(x.first), visited);
1636 explore(adj, start, visited);
1641 template <
typename T>
1644 if (!isDirectedGraph())
1648 enum nodeStates : uint8_t
1664 std::unordered_map<unsigned long long, nodeStates> state;
1665 for (
const auto &node : nodeSet)
1667 state[node->getId()] = not_visited;
1669 int stateCounter = 0;
1672 for (
const auto &node : nodeSet)
1677 if (state[node->getId()] == not_visited)
1680 std::function<bool(AdjacencyMatrix<T> &, std::unordered_map<unsigned long long, nodeStates> &,
const Node<T> *)> isCyclicDFSHelper;
1681 isCyclicDFSHelper = [
this, &isCyclicDFSHelper](AdjacencyMatrix<T> &adjMatrix, std::unordered_map<unsigned long long, nodeStates> &states,
const Node<T> *node)
1684 states[node->getId()] = in_stack;
1688 auto const it = adjMatrix.find(node);
1689 if (it != adjMatrix.end())
1691 for (
const auto &child : it->second)
1695 auto state_of_child = states.at((std::get<0>(child))->getId());
1696 if (state_of_child == not_visited)
1698 if (isCyclicDFSHelper(adjMatrix, states, std::get<0>(child)))
1703 else if (state_of_child == in_stack)
1715 states[node->getId()] = visited;
1719 if (isCyclicDFSHelper(adjMatrix, state, node))
1731 template <
typename T>
1734 std::unordered_map<unsigned long long, Subset> subset;
1736 for (
const auto &edge : *edgeSet)
1738 auto &[first, second] = edge->getNodePair();
1739 std::vector<unsigned long long> nodeId(2);
1740 nodeId.push_back(first->getId());
1741 nodeId.push_back(second->getId());
1742 for (
const auto &
id : nodeId)
1744 auto nodeExists = [id](
const auto &it)
1745 {
return (
id == (it.second).parent); };
1747 if (std::find_if(subset.begin(), subset.end(), nodeExists) == subset.end())
1759 template <
typename T>
1762 for (
const auto &edge : *edgeSet)
1764 auto &[first, second] = edge->getNodePair();
1774 template <
typename T>
1777 if (!isDirectedGraph())
1784 std::unordered_map<unsigned long, unsigned int> indegree;
1785 for (
const auto &node : nodeSet)
1787 indegree[node->getId()] = 0;
1790 for (
auto const &list : adjMatrix)
1792 auto children = list.second;
1793 for (
auto const &child : children)
1795 indegree[std::get<0>(child)->getId()]++;
1799 std::queue<const Node<T> *> can_be_solved;
1800 for (
const auto &node : nodeSet)
1804 if (!indegree[node->getId()])
1806 can_be_solved.emplace(&(*node));
1813 while (!can_be_solved.empty())
1815 auto solved = can_be_solved.front();
1817 can_be_solved.pop();
1822 auto it = adjMatrix.find(solved);
1823 if (it != adjMatrix.end())
1825 for (
const auto &child : it->second)
1828 if (--indegree[std::get<0>(child)->getId()] == 0)
1832 can_be_solved.emplace(std::get<0>(child));
1840 return !(remain == 0);
1843 template <
typename T>
1847 for (
const auto &edge : edgeSet)
1849 if (!(edge->isDirected().has_value() && edge->isDirected().value()))
1859 template <
typename T>
1863 for (
const auto &edge : edgeSet)
1865 if ((edge->isDirected().has_value() && edge->isDirected().value()))
1875 template <
typename T>
1878 if (!isUndirectedGraph())
1884 auto nodeSet = getNodeSet();
1885 auto adjMatrix = getAdjMatrix();
1887 std::unordered_map<unsigned long, bool> visited;
1888 for (
const auto &node : nodeSet)
1890 visited[node->getId()] =
false;
1892 std::function<void(
const Node<T> *)> dfs_helper = [
this, &adjMatrix, &visited, &dfs_helper](
const Node<T> *source)
1895 visited[source->getId()] =
true;
1898 for (
int i = 0; i < adjMatrix[source].size(); i++)
1900 const Node<T> *neighbor = adjMatrix[source].at(i).first;
1901 if (visited[neighbor->getId()] ==
false)
1904 dfs_helper(neighbor);
1909 dfs_helper(*(nodeSet.begin()));
1912 for (
const auto &node : nodeSet)
1914 if (visited[node->getId()] ==
false)
1923 template <
typename T>
1926 if (!isDirectedGraph())
1932 auto nodeSet = getNodeSet();
1933 auto adjMatrix = getAdjMatrix();
1934 for (
const auto &start_node : nodeSet)
1937 std::unordered_map<unsigned long, bool> visited;
1938 for (
const auto &node : nodeSet)
1940 visited[node->getId()] =
false;
1942 std::function<void(
const Node<T> *)> dfs_helper = [
this, &adjMatrix, &visited, &dfs_helper](
const Node<T> *source)
1945 visited[source->getId()] =
true;
1948 for (
int i = 0; i < adjMatrix[source].size(); i++)
1950 const Node<T> *neighbor = adjMatrix[source].at(i).first;
1951 if (visited[neighbor->getId()] ==
false)
1954 dfs_helper(neighbor);
1959 dfs_helper(start_node);
1962 for (
const auto &node : nodeSet)
1964 if (visited[node->getId()] ==
false)
1974 template <
typename T>
1977 std::vector<std::vector<Node<T>>> connectedComps;
1979 if (!isDirectedGraph())
1981 return connectedComps;
1985 auto nodeSet = getNodeSet();
1986 auto adjMatrix = getAdjMatrix();
1988 std::unordered_map<unsigned long, bool> visited;
1989 for (
const auto &node : nodeSet)
1991 visited[node->getId()] =
false;
1994 std::stack<const Node<T> *> st;
1995 std::function<void(
const Node<T> *)> dfs_helper = [
this, &adjMatrix, &visited, &dfs_helper, &st](
const Node<T> *source)
1998 visited[source->getId()] =
true;
2001 for (
int i = 0; i < adjMatrix[source].size(); i++)
2003 const Node<T> *neighbor = adjMatrix[source].at(i).first;
2004 if (visited[neighbor->getId()] ==
false)
2007 dfs_helper(neighbor);
2014 for (
const auto &node : nodeSet)
2016 if (visited[node->getId()] ==
false)
2023 AdjacencyMatrix<T> rev;
2024 auto addElementToAdjMatrix = [&rev](
const Node<T> *nodeFrom,
const Node<T> *nodeTo,
const Edge<T> *edge){
2025 std::pair<const Node<T> *,
const Edge<T> *> elem = {nodeTo, edge};
2026 rev[nodeFrom].push_back(std::move(elem));
2028 for (
const auto &edgeSetIt : edgeSet)
2032 addElementToAdjMatrix(&(d_edge->getTo()), &(d_edge->getFrom()), d_edge);
2037 std::function<void(
const Node<T> *, std::vector<
Node<T>> &)> dfs_helper1 = [
this, &rev, &visited, &dfs_helper1](
const Node<T> *source, std::vector<Node<T>> &comp)
2040 visited[source->getId()] =
true;
2042 comp.push_back(*source);
2045 for (
int i = 0; i < rev[source].size(); i++)
2047 const Node<T> *neighbor = rev[source].at(i).first;
2048 if (visited[neighbor->getId()] ==
false)
2051 dfs_helper1(neighbor, comp);
2056 while(st.size()!=0){
2057 auto rem = st.top();
2059 if(visited[rem->getId()] ==
false){
2060 std::vector<Node<T>> comp;
2061 dfs_helper1(rem, comp);
2062 connectedComps.push_back(comp);
2066 return connectedComps;
2070 template <
typename T>
2074 result.success =
false;
2079 if (std::find(nodeSet.begin(), nodeSet.end(), &source) == nodeSet.end())
2082 result.errorMessage = ERR_SOURCE_NODE_NOT_IN_GRAPH;
2090 unsigned int V = nodeSet.size();
2091 std::unordered_map<const Node<T> *, std::pair<long, const Node<T> *>> dist;
2094 for (
const auto &node : nodeSet)
2096 dist[&(*node)].first = std::numeric_limits<long>::max();
2101 std::deque<const Node<T> *> B[maxWeight * V + 1];
2103 B[0].push_back(&source);
2104 dist[&source].first = 0;
2111 while (B[idx].size() == 0 && idx < maxWeight * V)
2117 if (idx == maxWeight * V)
2123 auto u = B[idx].front();
2128 for (
const auto &i : adj[u])
2132 if (i.second->isWeighted().has_value() && i.second->isWeighted().value())
2134 if (i.second->isDirected().has_value() && i.second->isDirected().value())
2137 weight = dw_edge->getWeight();
2139 else if (i.second->isDirected().has_value() && !i.second->isDirected().value())
2142 weight = udw_edge->getWeight();
2147 result.errorMessage = ERR_NO_DIR_OR_UNDIR_EDGE;
2154 result.errorMessage = ERR_NO_WEIGHTED_EDGE;
2157 auto u_i = std::find_if(dist.begin(), dist.end(), [u](std::pair<
const Node<T> *, std::pair<
long,
const Node<T> *>>
const &it)
2158 { return (*u == *(it.first)); });
2160 auto v_i = std::find_if(dist.begin(), dist.end(), [v](std::pair<
const Node<T> *, std::pair<
long,
const Node<T> *>>
const &it)
2161 { return (*v == *(it.first)); });
2162 long du = u_i->second.first;
2163 long dv = v_i->second.first;
2166 if (dv > du + weight)
2171 if (dv != std::numeric_limits<long>::max())
2173 auto findIter = std::find(B[dv].begin(), B[dv].end(), dist[v].second);
2174 B[dv].erase(findIter);
2178 dist[v].first = du + weight;
2182 B[dv].push_front(v);
2185 dist[v].second = *(B[dv].begin());
2189 for (
const auto &dist_i : dist)
2191 result.minDistanceMap[dist_i.first->getId()] = dist_i.second.first;
2193 result.success =
true;
2198 template <
typename T>
2201 if (!isDirectedGraph())
2206 std::unordered_map<const Node<T> *,
const Node<T> *> parent;
2207 std::map<const Node<T> *, std::map<const Node<T> *,
double>> weightMap;
2209 auto edgeSet = this->getEdgeSet();
2210 for (
const auto &edge : edgeSet)
2213 if (edge->isWeighted().value_or(
false))
2216 weightMap[edge->getNodePair().first][edge->getNodePair().second] = dw_edge->getWeight();
2220 weightMap[edge->getNodePair().first][edge->getNodePair().second] = 0;
2224 auto bfs_helper = [
this, &source, &target, &parent, &weightMap]() ->
bool
2226 std::unordered_map<const Node<T> *,
bool> visited;
2227 std::queue<const Node<T> *> queue;
2228 queue.push(&source);
2229 visited[&source] =
true;
2230 parent[&source] =
nullptr;
2231 while (!queue.empty())
2233 auto u = queue.front();
2235 for (
auto &v : weightMap[u])
2237 if (!visited[v.first] && v.second > 0)
2239 queue.push(v.first);
2240 visited[v.first] =
true;
2241 parent[v.first] = u;
2246 return (visited[&target]);
2249 while (bfs_helper())
2251 double pathFlow = std::numeric_limits<double>::max();
2252 for (
auto v = ⌖ v != &source; v = parent[v])
2255 pathFlow = std::min(pathFlow, weightMap[u][v]);
2257 for (
auto v = ⌖ v != &source; v = parent[v])
2260 weightMap[u][v] -= pathFlow;
2261 weightMap[v][u] += pathFlow;
2264 maxFlow += pathFlow;
2270 template <
typename T>
2273 std::vector<Node<T>> result;
2277 if (std::find(nodeSet.begin(), nodeSet.end(), &start) == nodeSet.end())
2282 std::deque<const Node<T> *> C1;
2283 for (
auto const &node : nodeSet)
2286 if (std::find_if(C.begin(), C.end(), [node](
const Node<T> nodeC)
2287 { return (*node == nodeC); }) == C.end())
2293 std::vector<Node<T>> M;
2294 for (
auto const &node : C1)
2297 M.insert(M.end(), reachableNodes.begin(), reachableNodes.end());
2300 for (
const auto &nodeC : C)
2302 if (std::find_if(M.begin(), M.end(), [nodeC](
const Node<T> nodeM)
2303 { return (nodeM == nodeC); }) == M.end())
2304 result.push_back(nodeC);
2309 template <
typename T>
2310 int Graph<T>::writeToFile(InputOutputFormat format,
const std::string &workingDir,
const std::string &OFileName,
bool compress,
bool writeNodeFeat,
bool writeEdgeWeight)
const
2313 result = writeToStandardFile(workingDir, OFileName, compress, writeNodeFeat, writeEdgeWeight, format);
2314 if (result == 0 && compress)
2316 auto _compress = [
this, &workingDir, &OFileName, &writeNodeFeat, &writeEdgeWeight](
const std::string &extension)
2318 std::string completePathToFileGraph = workingDir +
"/" + OFileName + extension;
2319 std::string completePathToFileGraphCompressed = workingDir +
"/" + OFileName + extension +
".gz";
2320 int _result = compressFile(completePathToFileGraph, completePathToFileGraphCompressed);
2323 _result = remove(completePathToFileGraph.c_str());
2329 std::string completePathToFileNodeFeat = workingDir +
"/" + OFileName +
"_NodeFeat" + extension;
2330 std::string completePathToFileNodeFeatCompressed = workingDir +
"/" + OFileName +
"_NodeFeat" + extension +
".gz";
2331 _result = compressFile(completePathToFileNodeFeat, completePathToFileNodeFeatCompressed);
2334 _result = remove(completePathToFileNodeFeat.c_str());
2340 if (writeEdgeWeight)
2342 std::string completePathToFileEdgeWeight = workingDir +
"/" + OFileName +
"_EdgeWeight" + extension;
2343 std::string completePathToFileEdgeWeightCompressed = workingDir +
"/" + OFileName +
"_EdgeWeight" + extension +
".gz";
2344 _result = compressFile(completePathToFileEdgeWeight, completePathToFileEdgeWeightCompressed);
2347 _result = remove(completePathToFileEdgeWeight.c_str());
2353 if (format == InputOutputFormat::STANDARD_CSV)
2355 auto result = _compress(
".csv");
2357 else if (format == InputOutputFormat::STANDARD_TSV)
2359 auto result = _compress(
".tsv");
2370 template <
typename T>
2371 int Graph<T>::readFromFile(InputOutputFormat format,
const std::string &workingDir,
const std::string &OFileName,
bool compress,
bool readNodeFeat,
bool readEdgeWeight)
2376 auto decompress = [
this, &workingDir, &OFileName, &readNodeFeat, &readEdgeWeight](
const std::string &extension)
2378 std::string completePathToFileGraph = workingDir +
"/" + OFileName + extension;
2379 std::string completePathToFileGraphCompressed = workingDir +
"/" + OFileName + extension +
".gz";
2380 int _result = decompressFile(completePathToFileGraphCompressed, completePathToFileGraph);
2385 std::string completePathToFileNodeFeat = workingDir +
"/" + OFileName +
"_NodeFeat" + extension;
2386 std::string completePathToFileNodeFeatCompressed = workingDir +
"/" + OFileName +
"_NodeFeat" + extension +
".gz";
2387 _result = decompressFile(completePathToFileNodeFeatCompressed, completePathToFileNodeFeat);
2394 std::string completePathToFileEdgeWeight = workingDir +
"/" + OFileName +
"_EdgeWeight" + extension;
2395 std::string completePathToFileEdgeWeightCompressed = workingDir +
"/" + OFileName +
"_EdgeWeight" + extension +
".gz";
2396 _result = decompressFile(completePathToFileEdgeWeightCompressed, completePathToFileEdgeWeight);
2401 if (format == InputOutputFormat::STANDARD_CSV)
2403 result = decompress(
".csv");
2405 else if (format == InputOutputFormat::STANDARD_TSV)
2407 result = decompress(
".tsv");
2417 result = readFromStandardFile(workingDir, OFileName, compress, readNodeFeat, readEdgeWeight, format);
2422 template <
typename T>
2423 PartitionMap<T>
Graph<T>::partitionGraph(PARTITIONING::PartitionAlgorithm algorithm,
unsigned int numberOfPartitions,
double param1,
double param2,
double param3,
unsigned int numberOfthreads)
const
2425 PartitionMap<T> partitionMap;
2426 PARTITIONING::Globals globals(numberOfPartitions, algorithm, param1, param2, param3, numberOfthreads);
2427 const T_EdgeSet<T> & edgeSet = getEdgeSet();
2428 globals.edgeCardinality = edgeSet.size();
2429 globals.vertexCardinality = this->getNodeSet().size();
2432 partitionMap = partitionState.getPartitionMap();
2433 return partitionMap;
2436 template <
typename T>
2437 std::ostream &operator<<(std::ostream &os,
const Graph<T> &graph)
2441 auto it = edgeList.begin();
2442 for (it; it != edgeList.end(); ++it)
2444 if (!(*it)->isDirected().has_value() && !(*it)->isWeighted().has_value())
2449 else if (((*it)->isDirected().has_value() && (*it)->isDirected().value()) && ((*it)->isWeighted().has_value() && (*it)->isWeighted().value()))
2451 os << dynamic_cast<const DirectedWeightedEdge<T> &>(*it) <<
"\n";
2453 else if (((*it)->isDirected().has_value() && (*it)->isDirected().value()) && !((*it)->isWeighted().has_value() && (*it)->isWeighted().value()))
2455 os << dynamic_cast<const DirectedEdge<T> &>(*it) <<
"\n";
2457 else if (!(it->isDirected().has_value() && it->isDirected().value()) && (it->isWeighted().has_value() && it->isWeighted().value()))
2459 os << dynamic_cast<const UndirectedWeightedEdge<T> &>(*it) <<
"\n";
2461 else if (!(it->isDirected().has_value() && it->isDirected().value()) && !(it->isWeighted().has_value() && it->isWeighted().value()))
2463 os << dynamic_cast<const UndirectedEdge<T> &>(*it) <<
"\n";
2473 template <
typename T>
2474 std::ostream &operator<<(std::ostream &os,
const AdjacencyMatrix<T> &adj)
2476 os <<
"Adjacency Matrix:\n";
2477 unsigned long max_column = 0;
2478 for (
const auto &it : adj)
2480 if (it.second.size() > max_column)
2482 max_column = it.second.size();
2485 if (max_column == 0)
2487 os <<
"ERROR in Print\n";
2493 for (
int i = 0; i < max_column; ++i)
2498 for (
const auto &it : adj)
2500 os <<
"|N" << it.first->getId() <<
"|";
2501 for (
const auto &it2 : it.second)
2503 os <<
"N" << it2.first->getId() <<
",E" << it2.second->getId() <<
"|";
2506 for (
int i = 0; i < max_column; ++i)
Definition: DirectedEdge.hpp:39
Definition: DirectedWeightedEdge.hpp:42
Class that implement the Graph. ( This class is not Thread Safe )
Definition: Graph.hpp:91
virtual const FWResult floydWarshall() const
Function runs the floyd-warshall algorithm and returns the shortest distance of all pair of nodes....
Definition: Graph.hpp:1231
virtual const std::vector< Node< T > > depth_first_search(const Node< T > &start) const
Function performs the depth first search algorithm over the graph Note: No Thread Safe.
Definition: Graph.hpp:1610
virtual unsigned long long setFind(std::unordered_map< unsigned long long, Subset > *, const unsigned long long elem) const
This function finds the subset of given a nodeId Subset is stored in a map where keys are the hash-id...
Definition: Graph.hpp:911
virtual bool isUndirectedGraph() const
This function checks if a graph is undirected Note: No Thread Safe.
Definition: Graph.hpp:1860
virtual bool isConnectedGraph() const
This function checks if the graph is connected or not Applicable for Undirected Graph,...
Definition: Graph.hpp:1876
virtual const MstResult prim() const
Function runs the prim algorithm and returns the minimum spanning tree if the graph is undirected....
Definition: Graph.hpp:1311
virtual bool isStronglyConnectedGraph() const
This function checks if the graph is strongly connected or not Applicable for Directed Graph,...
Definition: Graph.hpp:1924
virtual std::vector< Node< T > > eulerianPath() const
This function finds the eulerian path of a directed graph using hierholzers algorithm.
Definition: Graph.hpp:944
virtual double fordFulkersonMaxFlow(const Node< T > &source, const Node< T > &target) const
Function runs the Ford-Fulkerson algorithm for some source node and target node in the graph and retu...
Definition: Graph.hpp:2199
virtual bool isCyclicDirectedGraphBFS() const
This function uses BFS to check for cycle in the graph. Pay Attention, this function work only with d...
Definition: Graph.hpp:1775
virtual bool containsCycle(const T_EdgeSet< T > *) const
This function checks if the given set of edges forms a cycle or not using union-find method.
Definition: Graph.hpp:1732
virtual std::vector< std::vector< Node< T > > > kosaraju() const
This function performs performs the kosaraju algorthm on the graph to find the strongly connected com...
Definition: Graph.hpp:1975
virtual int writeToFile(InputOutputFormat format=InputOutputFormat::STANDARD_CSV, const std::string &workingDir=".", const std::string &OFileName="graph", bool compress=false, bool writeNodeFeat=false, bool writeEdgeWeight=false) const
This function write the graph in an output file Note: No Thread Safe.
Definition: Graph.hpp:2310
virtual bool isDirectedGraph() const
This function checks if a graph is directed Note: No Thread Safe.
Definition: Graph.hpp:1844
virtual const std::optional< const Edge< T > * > getEdge(unsigned long long edgeId) const
Function that return an Edge with specific ID if Exist in the Graph Note: No Thread Safe.
Definition: Graph.hpp:561
virtual void setUnion(std::unordered_map< unsigned long long, Subset > *, const unsigned long long set1, const unsigned long long elem2) const
This function modifies the original subset array such that it the union of two sets a and b.
Definition: Graph.hpp:924
virtual const DialResult dial(const Node< T > &source, int maxWeight) const
This function write the graph in an output file Note: No Thread Safe.
Definition: Graph.hpp:2071
virtual PartitionMap< T > partitionGraph(PARTITIONING::PartitionAlgorithm algorithm, unsigned int numberOfPartitions, double param1=0.0, double param2=0.0, double param3=0.0, unsigned int numberOfthreads=std::thread::hardware_concurrency()) const
This function partition a graph in a set of partitions Note: No Thread Safe.
Definition: Graph.hpp:2423
virtual const std::vector< Node< T > > graph_slicing(const Node< T > &start) const
This function performs Graph Slicing based on connectivity.
Definition: Graph.hpp:2271
virtual void setEdgeSet(T_EdgeSet< T > &edgeSet)
Function set the Edge Set of the Graph Note: No Thread Safe.
Definition: Graph.hpp:489
virtual const T_EdgeSet< T > & getEdgeSet() const
Function that return the Edge set of the Graph Note: No Thread Safe.
Definition: Graph.hpp:483
virtual const DijkstraResult dijkstra(const Node< T > &source, const Node< T > &target) const
Function runs the dijkstra algorithm for some source node and target node in the graph and returns th...
Definition: Graph.hpp:1007
virtual const MstResult boruvka() const
Function runs the boruvka algorithm and returns the minimum spanning tree & cost if the graph is undi...
Definition: Graph.hpp:1403
virtual bool isCyclicDirectedGraphDFS() const
This function uses DFS to check for cycle in the graph. Pay Attention, this function work only with d...
Definition: Graph.hpp:1642
virtual void addEdge(const Edge< T > *edge)
Function add an Edge to the Graph Edge Set Note: No Thread Safe.
Definition: Graph.hpp:506
virtual int readFromFile(InputOutputFormat format=InputOutputFormat::STANDARD_CSV, const std::string &workingDir=".", const std::string &OFileName="graph", bool compress=false, bool readNodeFeat=false, bool readEdgeWeight=false)
This function read the graph from an input file Note: No Thread Safe.
Definition: Graph.hpp:2371
virtual void removeEdge(unsigned long long edgeId)
Function remove an Edge from the Graph Edge Set Note: No Thread Safe.
Definition: Graph.hpp:519
virtual const MstResult kruskal() const
Function runs the kruskal algorithm and returns the minimum spanning tree if the graph is undirected....
Definition: Graph.hpp:1508
virtual const AdjacencyMatrix< T > getAdjMatrix() const
This function generate a list of adjacency matrix with every element of the matrix contain the node w...
Definition: Graph.hpp:976
virtual const BellmanFordResult bellmanford(const Node< T > &source, const Node< T > &target) const
Function runs the bellman-ford algorithm for some source node and target node in the graph and return...
Definition: Graph.hpp:1123
virtual const std::vector< Node< T > > breadth_first_search(const Node< T > &start) const
Function performs the breadth first search algorithm over the graph Note: No Thread Safe.
Definition: Graph.hpp:1570
virtual const std::set< const Node< T > * > getNodeSet() const
Function that return the Node Set of the Graph Note: No Thread Safe.
Definition: Graph.hpp:533
Definition: CoordinatedPartitionState.hpp:41
Definition: Globals.hpp:32
Definition: Partitioner.hpp:43
Definition: UndirectedEdge.hpp:39
Definition: UndirectedWeightedEdge.hpp:43
Definition: Weighted.hpp:28
Struct that contains the information about Dijsktra's Algorithm results.
Definition: Typedef.hpp:79
Struct that contains the information about Dijsktra's Algorithm results.
Definition: Typedef.hpp:130
Struct that contains the information about Dijsktra's Algorithm results.
Definition: Typedef.hpp:70
Struct that contains the information about Floyd-Warshall Algorithm results.
Definition: Typedef.hpp:110
Struct that contains the information about Prim, Boruvka & Kruskal Algorithm results.
Definition: Typedef.hpp:120
Struct useful for union-find operations.
Definition: Typedef.hpp:62
Definition: Graph.hpp:665
Definition: Typedef.hpp:99