Skip to content

Commit 2c3ccb4

Browse files
fixed bug : Floyd Warshall not working on undirectedEdge graph (#380)
1 parent 20d818c commit 2c3ccb4

File tree

1 file changed

+104
-91
lines changed

1 file changed

+104
-91
lines changed

include/CXXGraph/Graph/Graph.hpp

Lines changed: 104 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -201,8 +201,8 @@ class Graph {
201201
*
202202
*/
203203
template <typename T1, typename... Tn>
204-
std::enable_if<is_edge_ptr_v<T1> && (is_edge_ptr_v<Tn> && ...), void> addEdges(
205-
T1 edge, Tn... edges);
204+
std::enable_if<is_edge_ptr_v<T1> && (is_edge_ptr_v<Tn> && ...), void>
205+
addEdges(T1 edge, Tn... edges);
206206
/**
207207
* \brief
208208
* Function to add a Node to the Graph Node Set
@@ -239,8 +239,8 @@ class Graph {
239239
*
240240
*/
241241
template <typename T1, typename... Tn>
242-
std::enable_if<is_node_ptr_v<T1> && (is_node_ptr_v<Tn> && ...), void> addNodes(
243-
T1 node, Tn... nodes);
242+
std::enable_if<is_node_ptr_v<T1> && (is_node_ptr_v<Tn> && ...), void>
243+
addNodes(T1 node, Tn... nodes);
244244
/**
245245
* \brief
246246
* Function remove an Edge from the Graph Edge Set
@@ -349,28 +349,26 @@ class Graph {
349349

350350
virtual void cacheAdjMatrix();
351351
/**
352-
* @brief This function generates a list of the degree matrix with every element
353-
* of the matrix containing the node where the link is directed and the
354-
* corresponding edge to the link.
355-
* Note: No Thread Safe
356-
*/
352+
* @brief This function generates a list of the degree matrix with every
353+
* element of the matrix containing the node where the link is directed and
354+
* the corresponding edge to the link. Note: No Thread Safe
355+
*/
357356
virtual shared<DegreeMatrix<T>> getDegreeMatrix() const;
358357

359358
virtual void cacheDegreeMatrix();
360359
/**
361-
* @brief This function generates a list of the Laplacian matrix with every element
362-
* of the matrix containing the node connected to the current node and the
363-
* corresponding edge to the link.
364-
* Note: No Thread Safe
365-
*/
360+
* @brief This function generates a list of the Laplacian matrix with every
361+
* element of the matrix containing the node connected to the current node and
362+
* the corresponding edge to the link. Note: No Thread Safe
363+
*/
366364
virtual shared<LaplacianMatrix<T>> getLaplacianMatrix() const;
367365

368366
virtual void cacheLaplacianMatrix();
369367
/**
370-
* @brief This function generates a list of the transition matrix with every element
371-
* of the matrix containing the node that can be transitioned to from the
372-
* current node and the probability of the transition.
373-
* Note: No Thread Safe
368+
* @brief This function generates a list of the transition matrix with every
369+
* element of the matrix containing the node that can be transitioned to from
370+
* the current node and the probability of the transition. Note: No Thread
371+
* Safe
374372
*/
375373
virtual shared<TransitionMatrix<T>> getTransitionMatrix() const;
376374

@@ -1018,8 +1016,8 @@ void Graph<T>::addEdges() {
10181016

10191017
template <typename T>
10201018
template <typename T1, typename... Tn>
1021-
std::enable_if<is_edge_ptr_v<T1> && (is_edge_ptr_v<Tn> && ...), void> Graph<T>::addEdges(
1022-
T1 edge, Tn... edges) {
1019+
std::enable_if<is_edge_ptr_v<T1> && (is_edge_ptr_v<Tn> && ...), void>
1020+
Graph<T>::addEdges(T1 edge, Tn... edges) {
10231021
addEdge(edge);
10241022
addEdges(edges...);
10251023
}
@@ -1043,8 +1041,8 @@ void Graph<T>::addNodes() {
10431041

10441042
template <typename T>
10451043
template <typename T1, typename... Tn>
1046-
std::enable_if<is_node_ptr_v<T1> && (is_node_ptr_v<Tn> && ...), void> Graph<T>::addNodes(
1047-
T1 node, Tn... nodes) {
1044+
std::enable_if<is_node_ptr_v<T1> && (is_node_ptr_v<Tn> && ...), void>
1045+
Graph<T>::addNodes(T1 node, Tn... nodes) {
10481046
addNode(node);
10491047
addNodes(nodes...);
10501048
}
@@ -1777,18 +1775,19 @@ void Graph<T>::cacheAdjMatrix() {
17771775

17781776
template <typename T>
17791777
shared<DegreeMatrix<T>> Graph<T>::getDegreeMatrix() const {
1780-
auto degreeMatrix = std::make_shared<DegreeMatrix<T>>();
1778+
auto degreeMatrix = std::make_shared<DegreeMatrix<T>>();
17811779

1782-
for (const auto& nodePair : *this->cachedAdjMatrix) {
1783-
const shared<const Node<T>>& node = nodePair.first;
1784-
const std::vector<std::pair<shared<const Node<T>>, shared<const Edge<T>>>>& neighbors = nodePair.second;
1780+
for (const auto &nodePair : *this->cachedAdjMatrix) {
1781+
const shared<const Node<T>> &node = nodePair.first;
1782+
const std::vector<std::pair<shared<const Node<T>>, shared<const Edge<T>>>>
1783+
&neighbors = nodePair.second;
17851784

1786-
int degree = neighbors.size();
1785+
int degree = neighbors.size();
17871786

1788-
(*degreeMatrix)[node] = {degree};
1789-
}
1787+
(*degreeMatrix)[node] = {degree};
1788+
}
17901789

1791-
return degreeMatrix;
1790+
return degreeMatrix;
17921791
}
17931792

17941793
template <typename T>
@@ -1799,29 +1798,33 @@ void Graph<T>::cacheDegreeMatrix() {
17991798

18001799
template <typename T>
18011800
shared<LaplacianMatrix<T>> Graph<T>::getLaplacianMatrix() const {
1802-
const auto adjacencyMatrix = this->cachedAdjMatrix;
1803-
const auto degreeMatrix = this->cachedDegreeMatrix;
1801+
const auto adjacencyMatrix = this->cachedAdjMatrix;
1802+
const auto degreeMatrix = this->cachedDegreeMatrix;
18041803

1805-
auto laplacianMatrix = std::make_shared<LaplacianMatrix<T>>();
1806-
for (const auto& nodePair : *adjacencyMatrix) {
1807-
const shared<const Node<T>>& node = nodePair.first;
1808-
(*laplacianMatrix)[node] = std::vector<std::pair<shared<const Node<T>>, shared<const Edge<T>>>>();
1809-
}
1804+
auto laplacianMatrix = std::make_shared<LaplacianMatrix<T>>();
1805+
for (const auto &nodePair : *adjacencyMatrix) {
1806+
const shared<const Node<T>> &node = nodePair.first;
1807+
(*laplacianMatrix)[node] =
1808+
std::vector<std::pair<shared<const Node<T>>, shared<const Edge<T>>>>();
1809+
}
18101810

1811-
for (const auto& nodePair : *adjacencyMatrix) {
1812-
const shared<const Node<T>>& node = nodePair.first;
1813-
const std::vector<std::pair<shared<const Node<T>>, shared<const Edge<T>>>>& neighbors = nodePair.second;
1811+
for (const auto &nodePair : *adjacencyMatrix) {
1812+
const shared<const Node<T>> &node = nodePair.first;
1813+
const std::vector<std::pair<shared<const Node<T>>, shared<const Edge<T>>>>
1814+
&neighbors = nodePair.second;
18141815

1815-
int degree = neighbors.size();
1816+
int degree = neighbors.size();
18161817

1817-
(*laplacianMatrix)[node].emplace_back(node, nullptr); // Insere o nó na diagonal
1818-
for (const auto& neighborPair : neighbors) {
1819-
const shared<const Node<T>>& neighbor = neighborPair.first;
1820-
(*laplacianMatrix)[node].emplace_back(neighbor, neighborPair.second); // Insere os pares de vizinhos
1821-
}
1818+
(*laplacianMatrix)[node].emplace_back(node,
1819+
nullptr); // Insere o nó na diagonal
1820+
for (const auto &neighborPair : neighbors) {
1821+
const shared<const Node<T>> &neighbor = neighborPair.first;
1822+
(*laplacianMatrix)[node].emplace_back(
1823+
neighbor, neighborPair.second); // Insere os pares de vizinhos
18221824
}
1825+
}
18231826

1824-
return laplacianMatrix;
1827+
return laplacianMatrix;
18251828
}
18261829

18271830
template <typename T>
@@ -1832,29 +1835,31 @@ void Graph<T>::cacheLaplacianMatrix() {
18321835

18331836
template <typename T>
18341837
shared<TransitionMatrix<T>> Graph<T>::getTransitionMatrix() const {
1835-
const auto adjacencyMatrix = this->cachedAdjMatrix;
1838+
const auto adjacencyMatrix = this->cachedAdjMatrix;
18361839

1837-
auto transitionMatrix = std::make_shared<TransitionMatrix<T>>();
1838-
for (const auto& nodePair : *adjacencyMatrix) {
1839-
const shared<const Node<T>>& node = nodePair.first;
1840-
(*transitionMatrix)[node] = std::vector<std::pair<shared<const Node<T>>, double>>();
1841-
}
1840+
auto transitionMatrix = std::make_shared<TransitionMatrix<T>>();
1841+
for (const auto &nodePair : *adjacencyMatrix) {
1842+
const shared<const Node<T>> &node = nodePair.first;
1843+
(*transitionMatrix)[node] =
1844+
std::vector<std::pair<shared<const Node<T>>, double>>();
1845+
}
18421846

1843-
for (const auto& nodePair : *adjacencyMatrix) {
1844-
const shared<const Node<T>>& node = nodePair.first;
1845-
const std::vector<std::pair<shared<const Node<T>>, shared<const Edge<T>>>>& neighbors = nodePair.second;
1847+
for (const auto &nodePair : *adjacencyMatrix) {
1848+
const shared<const Node<T>> &node = nodePair.first;
1849+
const std::vector<std::pair<shared<const Node<T>>, shared<const Edge<T>>>>
1850+
&neighbors = nodePair.second;
18461851

1847-
int degree = neighbors.size();
1852+
int degree = neighbors.size();
18481853

1849-
double transitionProbability = 1.0 / degree;
1854+
double transitionProbability = 1.0 / degree;
18501855

1851-
for (const auto& neighborPair : neighbors) {
1852-
const shared<const Node<T>>& neighbor = neighborPair.first;
1853-
(*transitionMatrix)[node].emplace_back(neighbor, transitionProbability);
1854-
}
1856+
for (const auto &neighborPair : neighbors) {
1857+
const shared<const Node<T>> &neighbor = neighborPair.first;
1858+
(*transitionMatrix)[node].emplace_back(neighbor, transitionProbability);
18551859
}
1860+
}
18561861

1857-
return transitionMatrix;
1862+
return transitionMatrix;
18581863
}
18591864

18601865
template <typename T>
@@ -2245,7 +2250,7 @@ const FWResult Graph<T>::floydWarshall() const {
22452250
}
22462251

22472252
const auto &edgeSet = Graph<T>::getEdgeSet();
2248-
// update the weights of nodes
2253+
// update the weights of nodesfloydWarshall
22492254
// connected by edges
22502255
for (const auto &edge : edgeSet) {
22512256
const auto &elem = edge->getNodePair();
@@ -2255,6 +2260,11 @@ const FWResult Graph<T>::floydWarshall() const {
22552260
auto key =
22562261
std::make_pair(elem.first->getUserId(), elem.second->getUserId());
22572262
pairwise_dist[key] = edgeWeight;
2263+
if (edge->isDirected() == false) {
2264+
auto reverseKey =
2265+
std::make_pair(elem.second->getUserId(), elem.first->getUserId());
2266+
pairwise_dist[reverseKey] = edgeWeight;
2267+
}
22582268
} else {
22592269
// if an edge exists but has no weight associated
22602270
// with it, we return an error message
@@ -3489,39 +3499,38 @@ SCCResult<T> Graph<T>::kosaraju() const {
34893499

34903500
visited.clear();
34913501

3492-
std::function<void(shared<const Node<T>>, SCCResult<T>, int)>
3493-
dfs_helper1 =
3494-
[this, &rev, &visited, &dfs_helper1](shared<const Node<T>> source,
3495-
SCCResult<T> result, int sccLabel) {
3496-
// mark the vertex visited
3497-
visited[source->getId()] = true;
3498-
// Add the current vertex to the strongly connected
3499-
// component
3500-
//comp.push_back(*source);
3501-
result.sccMap[source->getId()] = sccLabel;
3502-
3503-
// travel the neighbors
3504-
for (int i = 0; i < rev[source].size(); i++) {
3505-
shared<const Node<T>> neighbor = rev[source].at(i).first;
3506-
if (visited[neighbor->getId()] == false) {
3507-
// make recursive call from neighbor
3508-
dfs_helper1(neighbor, result, sccLabel);
3509-
}
3510-
}
3511-
};
3502+
std::function<void(shared<const Node<T>>, SCCResult<T>, int)> dfs_helper1 =
3503+
[this, &rev, &visited, &dfs_helper1](
3504+
shared<const Node<T>> source, SCCResult<T> result, int sccLabel) {
3505+
// mark the vertex visited
3506+
visited[source->getId()] = true;
3507+
// Add the current vertex to the strongly connected
3508+
// component
3509+
// comp.push_back(*source);
3510+
result.sccMap[source->getId()] = sccLabel;
3511+
3512+
// travel the neighbors
3513+
for (int i = 0; i < rev[source].size(); i++) {
3514+
shared<const Node<T>> neighbor = rev[source].at(i).first;
3515+
if (visited[neighbor->getId()] == false) {
3516+
// make recursive call from neighbor
3517+
dfs_helper1(neighbor, result, sccLabel);
3518+
}
3519+
}
3520+
};
35123521

35133522
int sccLabel = 0;
35143523
while (st.size() != 0) {
35153524
auto rem = st.top();
35163525
st.pop();
35173526
if (visited[rem->getId()] == false) {
3518-
//std::vector<Node<T>> comp;
3527+
// std::vector<Node<T>> comp;
35193528
dfs_helper1(rem, result, sccLabel);
35203529
sccLabel++;
3521-
//result.stronglyConnectedComps.push_back(comp);
3530+
// result.stronglyConnectedComps.push_back(comp);
35223531
}
35233532
}
3524-
result.noOfComponents = sccLabel;
3533+
result.noOfComponents = sccLabel;
35253534
result.success = true;
35263535
return result;
35273536
}
@@ -4202,12 +4211,16 @@ std::ostream &operator<<(std::ostream &os, const Graph<T> &graph) {
42024211
!((*it)->isWeighted().has_value() &&
42034212
(*it)->isWeighted().value())) {
42044213
os << *std::static_pointer_cast<const DirectedEdge<T>>(*it) << "\n";
4205-
} else if (!((*it)->isDirected().has_value() && (*it)->isDirected().value()) &&
4206-
((*it)->isWeighted().has_value() && (*it)->isWeighted().value())) {
4214+
} else if (!((*it)->isDirected().has_value() &&
4215+
(*it)->isDirected().value()) &&
4216+
((*it)->isWeighted().has_value() &&
4217+
(*it)->isWeighted().value())) {
42074218
os << *std::static_pointer_cast<const UndirectedWeightedEdge<T>>(*it)
42084219
<< "\n";
4209-
} else if (!((*it)->isDirected().has_value() && (*it)->isDirected().value()) &&
4210-
!((*it)->isWeighted().has_value() && (*it)->isWeighted().value())) {
4220+
} else if (!((*it)->isDirected().has_value() &&
4221+
(*it)->isDirected().value()) &&
4222+
!((*it)->isWeighted().has_value() &&
4223+
(*it)->isWeighted().value())) {
42114224
os << *std::static_pointer_cast<const UndirectedEdge<T>>(*it) << "\n";
42124225
} else {
42134226
os << *it << "\n";

0 commit comments

Comments
 (0)