Skip to content

Commit

Permalink
Feature getters for set of neighbors (#318)
Browse files Browse the repository at this point in the history
* Remove static_cast of 0 to template type T in best_first_search

* Change all the raw pointers in the library to smart pointers

* Rewrite tests to use smart pointers

* Finish converting tests to smart pointers

* Add setter for nodes in Edge nodePair

* Fix addition of edges and construction of adjacency matrix

* Add overloads of algorithms which take raw pointers to mantain interface

* Fix typos in tests

* Change dynamic_casts into dynamic_pointer_casts

* Decrease the number of random edges and nodes in RW and partition tests

* Add out/inOutEdges convenience methods for Graph

* Add tests for the out/inOutEdges methods

* Add overload of equality operators and hash functions for pointers of nodes

* Implement new hash functions for pointers of nodes and edges

* Increase number of nodes and edges in partition and RW tests

* Fix typo

* Use shared pointers in random node/edge generators

* Convert pointers in TransitiveReductionTest.cpp

* Add overload of addEdge for raw pointers

* Fix typo

* Fix edge insertion in FloydWarshall benchmark

* Fix typo in benchmark

* Remove all the calls to new in the tests

* Fix typo in benchmark FloydWarshall

Fix typo in benchmark FloydWarshall

* Conversion of example codes

* Formatting

* Add test for overloads of out/inOutEdges

* Change name of out/inOutEdges methods to out/inOutNeighbors

---------

Co-authored-by: sbaldu <simone.balducci@gmail.com>
  • Loading branch information
sbaldu and sbaldu committed Jun 5, 2023
1 parent 4569d22 commit 90a9973
Show file tree
Hide file tree
Showing 2 changed files with 357 additions and 56 deletions.
152 changes: 131 additions & 21 deletions include/Graph/Graph.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
#include "Partitioning/Utility/Globals.hpp"
#include "Utility/ConstString.hpp"
#include "Utility/ConstValue.hpp"
#include "Utility/PointerHash.hpp"
#include "Utility/Reader.hpp"
#include "Utility/ThreadSafe.hpp"
#include "Utility/Typedef.hpp"
Expand Down Expand Up @@ -209,7 +210,8 @@ class Graph {
* @returns a list of Nodes of the graph
*
*/
virtual const std::unordered_set<shared<const Node<T>>, nodeHash<T>> getNodeSet() const;
virtual const std::unordered_set<shared<const Node<T>>, nodeHash<T>>
getNodeSet() const;
/**
* \brief
* Function that sets the data contained in a node
Expand Down Expand Up @@ -244,6 +246,47 @@ class Graph {
* corrispondent to the link Note: No Thread Safe
*/
virtual const std::shared_ptr<AdjacencyMatrix<T>> getAdjMatrix() const;
/**
* \brief This function generates a set of nodes linked to the provided node in a
* directed graph
* Note: No Thread Safe
*
* @param Pointer to the node
*
*/
virtual const std::unordered_set<shared<const Node<T>>, nodeHash<T>> outNeighbors(
const Node<T> *node) const;
/**
* \brief This function generates a set of nodes linked to the provided node in a
* directed graph
* Note: No Thread Safe
*
* @param Pointer to the node
*
*/
virtual const std::unordered_set<shared<const Node<T>>, nodeHash<T>> outNeighbors(
shared<const Node<T>> node) const;
/**
* \brief This function generates a set of nodes linked to the provided node in
* any graph
* Note: No Thread Safe
*
* @param Pointer to the node
*
*/
virtual const std::unordered_set<shared<const Node<T>>, nodeHash<T>>
inOutNeighbors(const Node<T> *node) const;
/**
* \brief
* \brief This function generates a set of nodes linked to the provided node in
* any graph
* Note: No Thread Safe
*
* @param Pointer to the node
*
*/
virtual const std::unordered_set<shared<const Node<T>>, nodeHash<T>>
inOutNeighbors(shared<const Node<T>> node) const;
/**
* @brief This function finds the subset of given a nodeId
* Subset is stored in a map where keys are the hash-id of the node & values
Expand All @@ -261,7 +304,8 @@ class Graph {
* @brief This function finds the subset of given a nodeId
* Subset is stored in a map where keys are the hash-id of the node & values
* is the subset.
* @param shared pointer to subset query subset, we want to find target in this subset
* @param shared pointer to subset query subset, we want to find target in
* this subset
* @param elem elem that we wish to find in the subset
*
* @return parent node of elem
Expand Down Expand Up @@ -744,7 +788,8 @@ bool Graph<T>::findEdge(shared<const Node<T>> v1, shared<const Node<T>> v2,
}

template <typename T>
const std::unordered_set<shared<const Node<T>>, nodeHash<T>> Graph<T>::getNodeSet() const {
const std::unordered_set<shared<const Node<T>>, nodeHash<T>>
Graph<T>::getNodeSet() const {
std::unordered_set<shared<const Node<T>>, nodeHash<T>> nodeSet;
for (const auto &edgeSetIt : edgeSet) {
nodeSet.insert(edgeSetIt->getNodePair().first);
Expand Down Expand Up @@ -863,11 +908,11 @@ int Graph<T>::writeToDot(const std::string &workingDir,
}
if (edgePtr->isWeighted().has_value() && edgePtr->isWeighted().value()) {
// Weights in dot files must be integers
edgeLine +=
" [weight=" +
std::to_string(static_cast<int>(
std::dynamic_pointer_cast<const Weighted>(edgePtr)->getWeight())) +
']';
edgeLine += " [weight=" +
std::to_string(static_cast<int>(
std::dynamic_pointer_cast<const Weighted>(edgePtr)
->getWeight())) +
']';
}
edgeLine += ";\n";
ofileGraph << edgeLine;
Expand Down Expand Up @@ -917,7 +962,8 @@ void Graph<T>::writeGraphToStream(std::ostream &oGraph, std::ostream &oNodeFeat,
oEdgeWeight
<< edge->getId() << sep
<< (edge->isWeighted().has_value() && edge->isWeighted().value()
? (std::dynamic_pointer_cast<const Weighted>(edge))->getWeight()
? (std::dynamic_pointer_cast<const Weighted>(edge))
->getWeight()
: 0.0)
<< sep
<< (edge->isWeighted().has_value() && edge->isWeighted().value() ? 1
Expand Down Expand Up @@ -1179,7 +1225,8 @@ template <typename T>
unsigned long long Graph<T>::setFind(
std::unordered_map<unsigned long long, Subset> *subsets,
const unsigned long long nodeId) const {
auto subsets_ptr = make_shared<std::unordered_map<unsigned long long, Subset>>(*subsets);
auto subsets_ptr =
make_shared<std::unordered_map<unsigned long long, Subset>>(*subsets);
// find root and make root as parent of i
// (path compression)
if ((*subsets)[nodeId].parent != nodeId) {
Expand All @@ -1205,18 +1252,21 @@ unsigned long long Graph<T>::setFind(
}

template <typename T>
void Graph<T>::setUnion(
std::unordered_map<unsigned long long, Subset> *subsets,
const unsigned long long elem1, const unsigned long long elem2) const {
/* auto subsets_ptr = make_shared<std::unordered_map<unsigned long long, Subset>>(*subsets); */
void Graph<T>::setUnion(std::unordered_map<unsigned long long, Subset> *subsets,
const unsigned long long elem1,
const unsigned long long elem2) const {
/* auto subsets_ptr = make_shared<std::unordered_map<unsigned long long,
* Subset>>(*subsets); */
// if both sets have same parent
// then there's nothing to be done
/* if ((*subsets_ptr)[elem1].parent == (*subsets_ptr)[elem2].parent) return; */
/* if ((*subsets_ptr)[elem1].parent == (*subsets_ptr)[elem2].parent) return;
*/
/* auto elem1Parent = Graph<T>::setFind(subsets_ptr, elem1); */
/* auto elem2Parent = Graph<T>::setFind(subsets_ptr, elem2); */
/* if ((*subsets_ptr)[elem1Parent].rank < (*subsets_ptr)[elem2Parent].rank) */
/* (*subsets_ptr)[elem1].parent = elem2Parent; */
/* else if ((*subsets_ptr)[elem1Parent].rank > (*subsets_ptr)[elem2Parent].rank) */
/* else if ((*subsets_ptr)[elem1Parent].rank >
* (*subsets_ptr)[elem2Parent].rank) */
/* (*subsets_ptr)[elem2].parent = elem1Parent; */
/* else { */
/* (*subsets_ptr)[elem2].parent = elem1Parent; */
Expand Down Expand Up @@ -1329,6 +1379,59 @@ const std::shared_ptr<AdjacencyMatrix<T>> Graph<T>::getAdjMatrix() const {
return adj;
}

template <typename T>
const std::unordered_set<shared<const Node<T>>, nodeHash<T>> Graph<T>::outNeighbors(
const Node<T> *node) const {
auto node_shared = make_shared<const Node<T>>(*node);

return outNeighbors(node_shared);
}

template <typename T>
const std::unordered_set<shared<const Node<T>>, nodeHash<T>> Graph<T>::outNeighbors(
shared<const Node<T>> node) const {
auto adj = getAdjMatrix();
if (adj->find(node) == adj->end()) {
return std::unordered_set<shared<const Node<T>>, nodeHash<T>>();
}
auto nodeEdgePairs = adj->at(node);

std::unordered_set<shared<const Node<T>>, nodeHash<T>> outNeighbors;
for (auto pair : nodeEdgePairs) {
if (pair.second->isDirected().has_value() &&
pair.second->isDirected().value()) {
outNeighbors.insert(pair.first);
}
}

return outNeighbors;
}

template <typename T>
const std::unordered_set<shared<const Node<T>>, nodeHash<T>>
Graph<T>::inOutNeighbors(const Node<T> *node) const {
auto node_shared = make_shared<const Node<T>>(*node);

return inOutNeighbors(node_shared);
}

template <typename T>
const std::unordered_set<shared<const Node<T>>, nodeHash<T>>
Graph<T>::inOutNeighbors(shared<const Node<T>> node) const {
auto adj = Graph<T>::getAdjMatrix();
if (adj->find(node) == adj->end()) {
return std::unordered_set<shared<const Node<T>>, nodeHash<T>>();
}
auto nodeEdgePairs = adj->at(node);

std::unordered_set<shared<const Node<T>>, nodeHash<T>> inOutNeighbors;
for (auto pair : nodeEdgePairs) {
inOutNeighbors.insert(pair.first);
}

return inOutNeighbors;
}

template <typename T>
const DijkstraResult Graph<T>::dijkstra(const Node<T> &source,
const Node<T> &target) const {
Expand Down Expand Up @@ -1466,7 +1569,8 @@ const BellmanFordResult Graph<T>::bellmanford(const Node<T> &source,
return result;
}
// setting all the distances initially to INF_DOUBLE
std::unordered_map<shared<const Node<T>>, double, nodeHash<T>> dist, currentDist;
std::unordered_map<shared<const Node<T>>, double, nodeHash<T>> dist,
currentDist;
// n denotes the number of vertices in graph
auto n = nodeSet.size();
for (const auto &elem : nodeSet) {
Expand Down Expand Up @@ -1555,7 +1659,8 @@ const Graph<T> Graph<T>::transitiveReduction() const {
Graph<T> result(this->edgeSet);

unsigned long long edgeId = 0;
std::unordered_set<shared<const Node<T>>, nodeHash<T>> nodes = this->getNodeSet();
std::unordered_set<shared<const Node<T>>, nodeHash<T>> nodes =
this->getNodeSet();
for (auto x : nodes) {
for (auto y : nodes) {
if (this->findEdge(x, y, edgeId)) {
Expand Down Expand Up @@ -1849,7 +1954,8 @@ const MstResult Graph<T>::kruskal() const {
sortedEdges;
for (const auto &edge : edgeSet) {
if (edge->isWeighted().has_value() && edge->isWeighted().value()) {
auto weight = (std::dynamic_pointer_cast<const Weighted>(edge))->getWeight();
auto weight =
(std::dynamic_pointer_cast<const Weighted>(edge))->getWeight();
sortedEdges.push(std::make_pair(weight, edge));
} else {
// No Weighted Edge
Expand Down Expand Up @@ -2838,8 +2944,12 @@ double Graph<T>::fordFulkersonMaxFlow(const Node<T> &source,
return -1;
}
double maxFlow = 0;
std::unordered_map<shared<const Node<T>>, shared<const Node<T>>, nodeHash<T>> parent;
std::unordered_map<shared<const Node<T>>, std::unordered_map<shared<const Node<T>>, double, nodeHash<T>>, nodeHash<T>>
std::unordered_map<shared<const Node<T>>, shared<const Node<T>>, nodeHash<T>>
parent;
std::unordered_map<
shared<const Node<T>>,
std::unordered_map<shared<const Node<T>>, double, nodeHash<T>>,
nodeHash<T>>
weightMap;
// build weight map
auto edgeSet = this->getEdgeSet();
Expand Down
Loading

0 comments on commit 90a9973

Please sign in to comment.