8#include <unordered_set>
12namespace fishnet::graph::__impl {
18using QueuePtr = std::shared_ptr<QueueType<N>>;
29template<
typename N,
typename R>
30static std::vector<std::pair<int,R>> mergeWorker(QueuePtr<N> queue, util::ReduceFunction<std::vector<N>,R>
auto const& reduceFunction){
31 std::vector<std::pair<int,R>> mergeResult;
34 current = queue->take();
36 queue->putPoisonPill();
39 const auto & [componentId, nodes] = current.value();
40 mergeResult.emplace_back(componentId, reduceFunction(std::move(nodes)));
54static std::vector<std::pair<int,N>> mergeWorker(QueuePtr<N> queue, util::ReduceFunction<std::vector<N>>
auto const& reduceFunction){
55 return mergeWorker(queue, reduceFunction,util::Identity());
58template<
typename N,
typename E>
59struct ContractionResult {
61 std::unordered_set<E> edges;
79template<Graph SourceGraphType, Graph TargetGraphType>
80auto contractImpl(
const SourceGraphType & source,
81 util::BiPredicate<typename SourceGraphType::node_type>
auto const & contractBiPredicate,
82 util::ReduceFunction<std::vector<typename SourceGraphType::node_type>,
typename TargetGraphType::node_type>
auto const & reduceFunction,
83 util::UnaryFunction<typename SourceGraphType::node_type,typename TargetGraphType::node_type>
auto const & mapper,
84 TargetGraphType & output,
87 using N = SourceGraphType::node_type;
88 using R = TargetGraphType::node_type;
91 auto queue = std::make_shared<__impl::QueueType<N>>();
92 std::vector<std::future<std::vector<std::pair<int,R>>>> futures;
93 futures.reserve(workers);
94 for(
int i = 0; i < workers; i++){
95 futures.emplace_back(std::async(std::launch::async,[queue,&reduceFunction](){
return __impl::mergeWorker<N,R>(queue,reduceFunction);}));
98 std::unordered_map<int,R> result;
99 queue->putPoisonPill();
100 result.reserve(componentsMap.size());
101 for(
auto & f: futures){
102 for(
auto & merged: f.get() ){
103 result.try_emplace(merged.first,merged.second);
106 std::vector<R> nodes;
107 for(
const auto & node: source.getNodes()){
109 nodes.emplace_back(mapper(node));
112 nodes.insert(nodes.end(), std::views::values(result).begin(), std::views::values(result).end());
114 std::unordered_set<typename TargetGraphType::edge_type> edges;
115 for(
const auto & edge: source.getEdges()){
116 if(componentsMap.at(edge.getFrom()) != componentsMap.at(edge.getTo())){
118 output.makeEdge(result.at(componentsMap.at(edge.getFrom())), result.at(componentsMap.at(edge.getTo())))
122 return ContractionResult<R,typename TargetGraphType::edge_type>{std::move(nodes), std::move(edges)};
126template<Graph SourceGraphType, Graph TargetGraphType>
127void contract(
const SourceGraphType & source,
128 util::BiPredicate<typename SourceGraphType::node_type>
auto const & contractBiPredicate,
129 util::ReduceFunction<std::vector<typename SourceGraphType::node_type>,
typename TargetGraphType::node_type>
auto const & reduceFunction,
130 util::UnaryFunction<typename SourceGraphType::node_type,typename TargetGraphType::node_type>
auto const & mapper,
131 TargetGraphType & output,
132 u_int8_t workers = 1)
134 auto [nodes, edges] = contractImpl(source,contractBiPredicate,reduceFunction,mapper,output,workers);
135 output.addNodes(nodes);
136 output.addEdges(edges);
140template<Graph SourceGraphType, Graph TargetGraphType>
141void contractInPlace(SourceGraphType & source,
142 util::BiPredicate<typename SourceGraphType::node_type>
auto const & contractBiPredicate,
143 util::ReduceFunction<std::vector<typename SourceGraphType::node_type>,
typename TargetGraphType::node_type>
auto const & reduceFunction,
144 util::UnaryFunction<typename SourceGraphType::node_type,typename TargetGraphType::node_type>
auto const & mapper,
145 TargetGraphType & output,
146 u_int8_t workers = 1)
148 auto [nodes, edges] = contractImpl(source,contractBiPredicate,reduceFunction,mapper,output,workers);
150 output.addNodes(nodes);
151 output.addEdges(edges);
174template<Graph SourceGraphType, Graph TargetGraphType>
178 using R =
typename TargetGraphType::node_type;
179 using N =
typename SourceGraphType::node_type;
180 auto reduceFunction = [&mapper,&mergeFunction](
const std::vector<N> & nodes){
181 R merged = mapper(nodes.front());
182 for(
size_t i = 1; i < nodes.size(); i++){
183 merged = mergeFunction(merged,mapper(nodes[i]));
187 __impl::contract(source,contractBiPredicate,reduceFunction,mapper,output,workers);
204template<Graph SourceGraphType, Graph TargetGraphType>
206 util::ReduceFunction<std::vector<typename SourceGraphType::node_type>,
typename TargetGraphType::node_type>
auto const & reduceFunction, TargetGraphType & output, u_int8_t workers = 1)
208 using N = SourceGraphType::node_type;
209 auto mapper = [&reduceFunction](
const N & node){
return reduceFunction(std::vector<N>({node}));};
210 __impl::contract(source,contractBiPredicate,reduceFunction,mapper,output,workers);
228template<Graph SourceGraphType, Graph TargetGraphType>
230 util::ReduceFunction<std::vector<typename SourceGraphType::node_type>,
typename TargetGraphType::node_type>
auto const & reduceFunction, TargetGraphType & output, u_int8_t workers = 1)
232 using N = SourceGraphType::node_type;
233 auto mapper = [&reduceFunction](
const N & node){
return reduceFunction(std::vector<N>({node}));};
234 __impl::contractInPlace(source,contractBiPredicate,reduceFunction,mapper,output,workers);
250template<Graph SourceGraphType>
252 util::ReduceFunction<std::vector<typename SourceGraphType::node_type>,
typename SourceGraphType::node_type>
auto const & reduceFunction, u_int8_t workers = 1)
254 using N = SourceGraphType::node_type;
255 auto mapper = [&reduceFunction](
const N & node){
return reduceFunction(std::vector<N>({node}));};
256 __impl::contractInPlace(graph,contractBiPredicate,reduceFunction,mapper,graph,workers);
269template<Graph G>
requires std::is_constructible_v<G>
286template<Graph G>
requires std::is_constructible_v<G>
289 contract(source,contractBiPredicate,reduceFunction,result,workers);
Blocking queue implementation. Blocks when no elements are present and take() is called until further...
Definition BlockingQueue.hpp:14
Definition FunctionalConcepts.hpp:15
Definition FunctionalConcepts.hpp:27
Definition FunctionalConcepts.hpp:42
Definition FunctionalConcepts.hpp:66
Definition FunctionalConcepts.hpp:9
auto connectedComponents(const G &graph, fishnet::util::BiPredicate< typename G::node_type > auto const &inRelation)
Compute connected components of the graph.
Definition BFSAlgorithm.hpp:95
Definition AdjacencyContainer.hpp:4
void contractInPlace(SourceGraphType &source, util::BiPredicate< typename SourceGraphType::node_type > auto const &contractBiPredicate, util::ReduceFunction< std::vector< typename SourceGraphType::node_type >, typename TargetGraphType::node_type > auto const &reduceFunction, TargetGraphType &output, u_int8_t workers=1)
Performs edge contraction algorithm. Edges between nodes fulfilling the contractBiPredicate get contr...
Definition Contraction.hpp:229
void contract(const SourceGraphType &source, util::BiPredicate< typename SourceGraphType::node_type > auto const &contractBiPredicate, util::BiFunction< typename SourceGraphType::node_type, typename SourceGraphType::node_type, typename TargetGraphType::node_type > auto const &mergeFunction, util::UnaryFunction< typename SourceGraphType::node_type, typename TargetGraphType::node_type > auto const &mapper, TargetGraphType &output, u_int8_t workers=1)
Performs edge contraction algorithm. Edges between nodes fulfilling the contractBiPredicate get contr...
Definition Contraction.hpp:175
constexpr size_t size(std::ranges::range auto &&range) noexcept
Definition CollectionConcepts.hpp:50
Definition FunctionalConcepts.hpp:95