Fishnet 2.0.1
Framework for Graph-Based Analysis of GIS Vector Data
Loading...
Searching...
No Matches
ConnectedComponents.hpp
Go to the documentation of this file.
1#pragma once
2#include "SearchResult.hpp"
3#include <unordered_map>
6
7namespace fishnet::graph{
8
9namespace __impl{
16template<typename N,util::HashFunction<N> Hash=std::hash<N>, fishnet::util::BiPredicate<N> Equal = std::equal_to<N>>
17class AbstractConnectedComponents: public SearchResult<AbstractConnectedComponents<N,Hash,Equal>,N,Hash,Equal> {
18private:
19 size_t index;
20 int openClosedCounter;
21protected:
22 virtual void onComponentClose(size_t component_index) noexcept = 0;
23
24 virtual void onComponentOpen(size_t component_index) noexcept = 0;
25
26 virtual void onNodeOpen(const N & node, size_t component_index) noexcept = 0;
27
28 virtual void onEdgeOpen(const N & from, const N & to, size_t component_index) noexcept = 0;
29public:
30 AbstractConnectedComponents(): SearchResult<AbstractConnectedComponents<N,Hash,Equal>,N,Hash,Equal>(){
31 this->index = 0;
32 this->openClosedCounter = 0;
33 }
34
35 void onOpen(const N & node) noexcept {
36 // if openClosedCounter == 0, the BFS search from single vertex is finished, revealing the complete connected component
37 if(this->openClosedCounter == 0) {
38 this->onComponentOpen(this->index);
39 }
40 this->openClosedCounter++;
41 onNodeOpen(node, this->index);
42 }
43
44 void onClose(const N & node) noexcept {
45 this->openClosedCounter--;
46 // if openClosedCounter <= 0, the BFS search from single vertex is finished, revealing the complete connected component
47 if(this->openClosedCounter <= 0) {
48 onComponentClose(this->index); // utilized by concurrent implementation, to fill the queue with components incrementally
49 this->index++;
50 }
51 }
52
53 void onEdge(const N & from, const N & to) noexcept {
54 onEdgeOpen(from,to,this->index);
55 }
56
57 bool stop() const noexcept{
58 return false;
59 }
60
61 virtual ~AbstractConnectedComponents() = default;
62};
63} // namespace __impl
64
71template<typename N,util::HashFunction<N> Hash=std::hash<N>, fishnet::util::BiPredicate<N> Equal = std::equal_to<N>>
72class ConnectedComponents: public __impl::AbstractConnectedComponents<N,Hash,Equal>
73{
74protected:
75 std::vector<std::vector<N>> components;
76
77 void onComponentOpen([[maybe_unused]] size_t component_index) noexcept override {
78 this->components.push_back(std::vector<N>());
79 }
80
81 void onComponentClose([[maybe_unused]] size_t component_index) noexcept override {
82 return;
83 }
84
85 void onNodeOpen(const N & node, size_t component_index) noexcept override {
86 this->components[component_index].push_back(node);
87 }
88
89 void onEdgeOpen([[maybe_unused]] const N & from, [[maybe_unused]] const N & to, [[maybe_unused]] size_t component_index) noexcept override {
90 return;
91 }
92
93public:
94 using node_type = N;
95 ConnectedComponents(): __impl::AbstractConnectedComponents<N,Hash,Equal>(){
96 this->components = std::vector<std::vector<N>>();
97 }
98
99 std::vector<std::vector<N>> get() const noexcept{
100 return this->components;
101 }
102
108 std::unordered_map<size_t,std::vector<N>> getAsMap() & noexcept {
109 std::unordered_map<size_t,std::vector<N>> map;
110 size_t component_number = 0;
111 for(const auto & component : components) {
112 map.try_emplace(component_number,component);
113 component_number++;
114 }
115 return map;
116 }
122 std::unordered_map<size_t,std::vector<N>> getAsMap() && noexcept {
123 std::unordered_map<size_t,std::vector<N>> map;
124 size_t component_number = 0;
125 for(auto && component : components) {
126 map.try_emplace(component_number,std::move(component));
127 component_number++;
128 }
129 return map;
130 }
131
137 std::unordered_map<N,int,Hash,Equal> nodeMap() const noexcept {
138 std::unordered_map<N,int,Hash,Equal> map;
139 for(size_t component_number=0; component_number < components.size(); component_number++) {
140 for(auto & node : components[component_number]) {
141 map.try_emplace(node,component_number);
142 }
143 }
144 return map;
145 }
146
148};
149
157template<typename N, util::HashFunction<N> Hash= std::hash<N>,fishnet::util::BiPredicate<N> Equal = std::equal_to<N>>
159{
160private:
161 using QueuePtr = std::shared_ptr<fishnet::util::BlockingQueue<std::pair<int,std::vector<N>>>>;
163 QueuePtr queue;
164protected:
165 void onComponentClose(size_t component_index) noexcept override {
166 this->queue->put(std::make_pair(component_index,this->components.back())); // add connected component to blocking queue on close
167 }
168public:
169 ConcurrentConnectedComponents(QueuePtr q):ConnectedComponents<N,Hash,Equal>(),queue(q){};
170
172};
173
174template<Graph G>
175class Subgraphs: public __impl::AbstractConnectedComponents<typename G::node_type,typename G::adj_container_type::hash_function,typename G::adj_container_type::equality_predicate>{
176private:
177 std::vector<G> subgraphs;
178 fishnet::util::Producer_t<G> graphProducer;
179 using Base =__impl::AbstractConnectedComponents<typename G::node_type,typename G::adj_container_type::hash_function,typename G::adj_container_type::equality_predicate>;
180 using N = typename G::node_type;
181protected:
182 void onComponentOpen([[maybe_unused]] size_t component_index) noexcept override {
183 this->subgraphs.push_back(graphProducer());
184 }
185
186 void onComponentClose([[maybe_unused]] size_t component_index) noexcept override {
187 return;
188 }
189
190 void onNodeOpen(const N & node, size_t component_index) noexcept override {
191 this->subgraphs[component_index].addNode(node);
192 }
193
194 void onEdgeOpen(const N & from, const N & to, size_t component_index) noexcept override {
195 this->subgraphs[component_index].addEdge(from,to);
196 }
197
198public:
199 Subgraphs() requires std::is_default_constructible_v<G>:Base(),graphProducer([](){return G();}){}
200
201 Subgraphs(fishnet::util::Producer<G> auto emptyGraphProducer):Base(),graphProducer(std::move(emptyGraphProducer)){}
202
203 std::vector<G> get() const noexcept{
204 return this->subgraphs;
205 }
206};
207
208} // namespace fishnet::graph
Concurrent specialization for computing connected components.
Definition ConnectedComponents.hpp:159
void onComponentClose(size_t component_index) noexcept override
Definition ConnectedComponents.hpp:165
ConcurrentConnectedComponents(QueuePtr q)
Definition ConnectedComponents.hpp:169
Search Result for Connected Components.
Definition ConnectedComponents.hpp:73
void onNodeOpen(const N &node, size_t component_index) noexcept override
Definition ConnectedComponents.hpp:85
std::vector< std::vector< N > > components
Definition ConnectedComponents.hpp:75
std::unordered_map< size_t, std::vector< N > > getAsMap() &&noexcept
Get connected components as a Map: ID -> std::vector<N>
Definition ConnectedComponents.hpp:122
void onComponentClose(size_t component_index) noexcept override
Definition ConnectedComponents.hpp:81
N node_type
Definition ConnectedComponents.hpp:94
std::unordered_map< N, int, Hash, Equal > nodeMap() const noexcept
Get connected components as a Map: Node -> component-id.
Definition ConnectedComponents.hpp:137
void onEdgeOpen(const N &from, const N &to, size_t component_index) noexcept override
Definition ConnectedComponents.hpp:89
ConnectedComponents()
Definition ConnectedComponents.hpp:95
std::unordered_map< size_t, std::vector< N > > getAsMap() &noexcept
Get connected components as a Map: ID -> std::vector<N>
Definition ConnectedComponents.hpp:108
std::vector< std::vector< N > > get() const noexcept
Definition ConnectedComponents.hpp:99
void onComponentOpen(size_t component_index) noexcept override
Definition ConnectedComponents.hpp:77
void onOpen(const N &node)
Definition SearchResult.hpp:26
SearchResult()
Definition SearchResult.hpp:22
bool stop() const
Definition SearchResult.hpp:38
void onEdge(const N &from, const N &to)
Definition SearchResult.hpp:34
void onClose(const N &node)
Definition SearchResult.hpp:30
Definition ConnectedComponents.hpp:175
void onComponentOpen(size_t component_index) noexcept override
Definition ConnectedComponents.hpp:182
void onNodeOpen(const N &node, size_t component_index) noexcept override
Definition ConnectedComponents.hpp:190
Subgraphs()
Definition ConnectedComponents.hpp:199
Subgraphs(fishnet::util::Producer< G > auto emptyGraphProducer)
Definition ConnectedComponents.hpp:201
void onEdgeOpen(const N &from, const N &to, size_t component_index) noexcept override
Definition ConnectedComponents.hpp:194
std::vector< G > get() const noexcept
Definition ConnectedComponents.hpp:203
void onComponentClose(size_t component_index) noexcept override
Definition ConnectedComponents.hpp:186
Definition FunctionalConcepts.hpp:48
Definition AdjacencyContainer.hpp:4
std::function< T()> Producer_t
Definition FunctionalConcepts.hpp:51
STL namespace.