diff --git a/include/CXXGraph/Graph/Algorithm/Dinic_impl.hpp b/include/CXXGraph/Graph/Algorithm/Dinic_impl.hpp new file mode 100644 index 000000000..0e68e1496 --- /dev/null +++ b/include/CXXGraph/Graph/Algorithm/Dinic_impl.hpp @@ -0,0 +1,87 @@ +#include +#include +#include +#include +#include +#include "Node_impl.h" +#include "CXXGraph/Graph/Graph_decl.h" + + +namespace CXXGraph { + +template +class Graph { +private: + std::unordered_map> nodes; + std::unordered_map> capacities; + std::unordered_map> flow; + + bool bfs(const CXXGraph::id_t& source, const CXXGraph::id_t& sink, std::unordered_map& distance) { + for (auto& pair : nodes) { + distance[pair.first] = -1; + } + distance[source] = 0; + + std::queue q; + q.push(source); + + while (!q.empty()) { + CXXGraph::id_t current = q.front(); + q.pop(); + for (auto& [neighbor_id, capacity] : capacities[current]) { + if (distance[neighbor_id] == -1 && flow[current][neighbor_id] < capacity) { + distance[neighbor_id] = distance[current] + 1; + q.push(neighbor_id); + } + } + } + + return distance[sink] != -1; + } + + int dfs(const CXXGraph::id_t& current, const CXXGraph::id_t& sink, int flow_value, std::unordered_map& distance) { + if (current == sink) { + return flow_value; + } + + for (auto& [neighbor_id, capacity] : capacities[current]) { + if (distance[neighbor_id] == distance[current] + 1 && flow[current][neighbor_id] < capacity) { + int new_flow = dfs(neighbor_id, sink, std::min(flow_value, capacity - flow[current][neighbor_id]), distance); + if (new_flow > 0) { + flow[current][neighbor_id] += new_flow; + flow[neighbor_id][current] -= new_flow; + return new_flow; + } + } + } + + return 0; + } + +public: + // Other graph methods... + + // Function to add an edge with capacity + void addEdge(const std::string& from_id, const std::string& to_id, int capacity) { + capacities[from_id][to_id] = capacity; + flow[from_id][to_id] = 0; + // Assuming nodes are already added to the graph + } + + // Dinic's algorithm to find maximum flow + int dinicsAlgorithm(const CXXGraph::id_t& source, const CXXGraph::id_t& sink) { + int max_flow = 0; + std::unordered_map distance; + + while (bfs(source, sink, distance)) { + int path_flow = 0; + while ((path_flow = dfs(source, sink, std::numeric_limits::max(), distance)) != 0) { + max_flow += path_flow; + } + } + + return max_flow; + } +}; + +} // namespace CXXGraph diff --git a/include/CXXGraph/Graph/Algorithm/Krager_impl.hpp b/include/CXXGraph/Graph/Algorithm/Krager_impl.hpp new file mode 100644 index 000000000..19f45988b --- /dev/null +++ b/include/CXXGraph/Graph/Algorithm/Krager_impl.hpp @@ -0,0 +1,66 @@ +#include +#include +#include +#include +#include +#include "Node_impl.h" +#include "CXXGraph/Graph/Graph_decl.h" + + +namespace CXXGraph { + +template +class Graph { +private: + std::unordered_map> nodes; + std::unordered_map> adjacency_list; + +public: + // Other graph methods... + + // Function to add an edge between two nodes + void addEdge(const std::string& from_id, const std::string& to_id) { + adjacency_list[from_id].insert(to_id); + adjacency_list[to_id].insert(from_id); + // Assuming nodes are already added to the graph + } + + // Krager's algorithm for graph partitioning + std::pair, std::unordered_set> kragersAlgorithm() { + // Initialize clusters + std::unordered_set cluster1; + std::unordered_set cluster2; + for (const auto& node_pair : nodes) { + cluster1.insert(node_pair.first); + } + + // Perform Krager's algorithm + std::random_device rd; + std::mt19937 gen(rd()); + while (cluster1.size() > 2) { + // Select a random edge + std::uniform_int_distribution dist(0, adjacency_list.size() - 1); + size_t rand_index = dist(gen); + auto it = std::next(std::begin(adjacency_list), rand_index); + CXXGraph::id_t u = it->first; + auto& neighbors = it->second; + std::uniform_int_distribution dist_neighbor(0, neighbors.size() - 1); + size_t rand_neighbor_index = dist_neighbor(gen); + auto neighbor_it = std::next(std::begin(neighbors), rand_neighbor_index); + CXXGraph::id_t v = *neighbor_it; + + // Merge clusters if the vertices belong to different clusters + if (cluster1.count(u) && cluster1.count(v)) { + cluster1.erase(v); + cluster2.insert(v); + } else if (cluster2.count(u) && cluster1.count(v)) { + cluster1.erase(v); + cluster2.insert(v); + } + } + + return {cluster1, cluster2}; + } +}; + +} // namespace CXXGraph diff --git a/include/CXXGraph/Node/Node_decl.h b/include/CXXGraph/Node/Node_decl.h index 0618f605e..6ef1982a0 100644 --- a/include/CXXGraph/Node/Node_decl.h +++ b/include/CXXGraph/Node/Node_decl.h @@ -49,6 +49,7 @@ class Node { const std::string &getUserId() const; const T &getData() const; void setData(T &&new_data); + // operator bool operator==(const Node &b) const; bool operator<(const Node &b) const; diff --git a/include/CXXGraph/Node/Node_impl.hpp b/include/CXXGraph/Node/Node_impl.hpp index eb6905c2c..8015c9d0d 100644 --- a/include/CXXGraph/Node/Node_impl.hpp +++ b/include/CXXGraph/Node/Node_impl.hpp @@ -70,6 +70,18 @@ void Node::setData(T &&new_data) { this->data = std::move(new_data); } + bool deleteNodeById(const std::string &id) { + auto it = std::find_if(nodes.begin(), nodes.end(), [&](const auto &pair) { + return pair.second.getUserId() == id; + }); + + if (it != nodes.end()) { + nodes.erase(it); + return true; // Node deleted successfully + } + return false; // Node not found + } + // The data type T must have an overload of the equality operator template bool Node::operator==(const Node &b) const {