Loading [MathJax]/extensions/tex2jax.js
ug4
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
topological_ordering.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2022: G-CSC, Goethe University Frankfurt
3 * Author: Lukas Larisch
4 *
5 * This file is part of UG4.
6 *
7 * UG4 is free software: you can redistribute it and/or modify it under the
8 * terms of the GNU Lesser General Public License version 3 (as published by the
9 * Free Software Foundation) with the following additional attribution
10 * requirements (according to LGPL/GPL v3 §7):
11 *
12 * (1) The following notice must be displayed in the Appropriate Legal Notices
13 * of covered and combined works: "Based on UG4 (www.ug4.org/license)".
14 *
15 * (2) The following notice must be displayed at a prominent place in the
16 * terminal output of covered works: "Based on UG4 (www.ug4.org/license)".
17 *
18 * (3) The following bibliography is recommended for citation and must be
19 * preserved in all covered files:
20 * "Reiter, S., Vogel, A., Heppner, I., Rupp, M., and Wittum, G. A massively
21 * parallel geometric multigrid solver on hierarchically distributed grids.
22 * Computing and visualization in science 16, 4 (2013), 151-164"
23 * "Vogel, A., Reiter, S., Rupp, M., Nägel, A., and Wittum, G. UG4 -- a novel
24 * flexible software system for simulating pde based models on high performance
25 * computers. Computing and visualization in science 16, 4 (2013), 165-179"
26 *
27 * This program is distributed in the hope that it will be useful,
28 * but WITHOUT ANY WARRANTY; without even the implied warranty of
29 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30 * GNU Lesser General Public License for more details.
31 */
32
33#ifndef UG_BASE_LIB_ALGEBRA_ORDERING_STRATEGIES_ALGORITHMS_TOPOLOGICAL_ORDERING_H
34#define UG_BASE_LIB_ALGEBRA_ORDERING_STRATEGIES_ALGORITHMS_TOPOLOGICAL_ORDERING_H
35
36#include <boost/graph/adjacency_list.hpp>
37#include <boost/graph/graph_traits.hpp>
38#include <boost/graph/properties.hpp>
39
44
45#include <vector>
46#include <utility> //for pair
47#include <deque>
48
49#include "IOrderingAlgorithm.h"
50#include "util.h"
51
52//debug
53#include "common/error.h"
54#include "common/log.h"
55
56namespace ug{
57
58template <typename O_t, typename G_t>
59void topological_ordering_core_bidirectional(O_t& o, G_t& g, bool inverse){
60 typedef typename boost::graph_traits<G_t>::vertex_descriptor vd_t;
61 typedef typename boost::graph_traits<G_t>::edge_descriptor ed_t;
62 typedef typename boost::graph_traits<G_t>::vertex_iterator vIt_t;
63 typedef typename boost::graph_traits<G_t>::in_edge_iterator in_edge_iterator;
64
65 size_t n = boost::num_vertices(g);
66
67 if(n == 0){
68 UG_THROW("topological_ordering_core: Graph is empty!");
69 }
70
71 o.resize(n);
72 std::vector<int> indegs(n);
73 std::vector<BOOL> isindeq(n, false);
74 std::deque<vd_t> deq;
75
76 vIt_t vIt, vEnd;
77 for(boost::tie(vIt, vEnd) = boost::vertices(g); vIt != vEnd; ++vIt){
78 indegs[*vIt] = boost::out_degree(*vIt, g)-1; //self-loop
79 if(indegs[*vIt] == 0){
80 deq.push_front(*vIt);
81 isindeq[*vIt] = true;
82 }
83 }
84
85 if(deq.empty()){
86 UG_THROW("topological_ordering_core: Graph is not cycle-free [1]!\n");
87 }
88
89 std::pair<in_edge_iterator, in_edge_iterator> e;
90 vd_t cur_v;
91 size_t k = 0;
92 size_t miss = 0;
93 while(!deq.empty() && miss < deq.size()){
94 cur_v = deq.front();
95 deq.pop_front();
96
97 //rotate deque, there is a cycle iff miss==deq.size()
98 if(indegs[cur_v] > 0){
99 deq.push_back(cur_v);
100 ++miss;
101 continue;
102 }
103
104 miss = 0;
105
106 if(inverse){
107 o[k++] = cur_v;
108 }
109 else{
110 o[cur_v] = k++;
111 }
112
113 e = boost::in_edges(cur_v, g);
114 for(; e.first != e.second; ++e.first){
115 ed_t const& edg = *e.first;
116 auto t = boost::source(edg, g);
117
118 --indegs[t];
119
120 if(isindeq[t]){
121 continue;
122 }
123
124 if(indegs[t] == 0){
125 deq.push_front(t);
126 isindeq[t] = true;
127 }
128 else if(indegs[t] > 0){
129 deq.push_back(t);
130 isindeq[t] = true;
131 }
132 else{} //ignore vertex
133 }
134 }
135
136 if(!deq.empty()){
137 UG_THROW("topological_ordering_core: Graph is not cycle-free [2]!\n");
138 }
139}
140
141template <typename O_t, typename G_t>
142void topological_ordering_core_directed(O_t& o, G_t& g, bool inverse){
143 typedef typename boost::graph_traits<G_t>::vertex_descriptor vd_t;
144 typedef typename boost::graph_traits<G_t>::vertex_iterator vIt_t;
145 typedef typename boost::graph_traits<G_t>::adjacency_iterator nIt_t;
146
147 size_t n = boost::num_vertices(g);
148
149 if(n == 0){
150 UG_THROW("topological_ordering_core: Graph is empty!");
151 }
152
153 o.resize(n);
154 std::vector<int> indegs(n);
155 std::vector<BOOL> isindeq(n, false);
156 std::deque<vd_t> deq;
157
158
159 vIt_t vIt, vEnd;
160 nIt_t nIt, nEnd;
161 for(boost::tie(vIt, vEnd) = boost::vertices(g); vIt != vEnd; ++vIt){
162 for(boost::tie(nIt, nEnd) = boost::adjacent_vertices(*vIt, g); nIt != nEnd; ++nIt){
163 ++indegs[*nIt];
164 }
165 }
166
167 for(boost::tie(vIt, vEnd) = boost::vertices(g); vIt != vEnd; ++vIt){
168 if(indegs[*vIt] == 0){
169 deq.push_front(*vIt);
170 isindeq[*vIt] = true;
171 }
172 }
173
174 if(deq.empty()){
175 UG_THROW("topological_ordering_core: Graph is not cycle-free [1]!\n");
176 }
177
178 vd_t cur_v;
179 size_t k = 0;
180 size_t miss = 0;
181 while(!deq.empty() && miss < deq.size()){
182 cur_v = deq.front();
183 deq.pop_front();
184
185 //rotate deque, there is a cycle iff miss==deq.size()
186 if(indegs[cur_v] > 0){
187 deq.push_back(cur_v);
188 ++miss;
189 continue;
190 }
191
192 miss = 0;
193
194 if(inverse){
195 o[k++] = cur_v;
196 }
197 else{
198 o[cur_v] = k++;
199 }
200
201 for(boost::tie(nIt, nEnd) = boost::adjacent_vertices(cur_v, g); nIt != nEnd; ++nIt){
202 --indegs[*nIt];
203
204 if(isindeq[*nIt]){
205 continue;
206 }
207
208 if(indegs[*nIt] == 0){
209 deq.push_front(*nIt);
210 isindeq[*nIt] = true;
211 }
212 else if(indegs[*nIt] > 0){
213 deq.push_back(*nIt);
214 isindeq[*nIt] = true;
215 }
216 else{} //ignore vertex
217 }
218 }
219
220 if(!deq.empty()){
221 UG_THROW("topological_ordering_core: Graph is not cycle-free [2]!\n");
222 }
223}
224
225
226//for cycle-free matrices only
227template <typename TAlgebra, typename O_t>
228class TopologicalOrdering : public IOrderingAlgorithm<TAlgebra, O_t>
229{
230public:
231 typedef typename TAlgebra::matrix_type M_t;
232 typedef typename TAlgebra::vector_type V_t;
233 typedef typename boost::graph_traits<M_t>::vertex_descriptor vd_t;
235
237
241
246
247 void compute(){
248 topological_ordering_core_bidirectional(o, bidir, false); //false = do not compute inverse permutation
249
250 #ifdef UG_DEBUG
251 check();
252 #endif
253 }
254
255 void init(M_t* A, const V_t&){
256 init(A);
257 }
258
259 void init(M_t* A){
260 //TODO: replace this by UG_DLOG if permutation_util does not depend on this file anymore
261 #ifdef UG_ENABLE_DEBUG_LOGS
262 UG_LOG("Using " << name() << "\n");
263 #endif
264
266 }
267
268 void init(M_t*, const V_t&, const O_t&){
269 UG_THROW(name() << "::init: Algorithm does not support induced subgraph version!");
270 }
271
272 void init(M_t*, const O_t&){
273 UG_THROW(name() << "::init: Algorithm does not support induced subgraph version!");
274 }
275
276 void check(){
277 UG_COND_THROW(!is_permutation(o), name() << "::check: Not a permutation!");
278 }
279
280 O_t& ordering(){
281 return o;
282 }
283
284 virtual const char* name() const {return "TopologicalOrdering";}
285
286private:
288 O_t o;
289};
290
291}
292
293#endif
Definition smart_pointer.h:108
Definition bidirectional.h:47
Definition IOrderingAlgorithm.h:52
Definition topological_ordering.h:229
void init(M_t *, const O_t &)
Definition topological_ordering.h:272
TAlgebra::vector_type V_t
Definition topological_ordering.h:232
void check()
Definition topological_ordering.h:276
SmartPtr< IOrderingAlgorithm< TAlgebra, O_t > > clone()
Definition topological_ordering.h:242
TopologicalOrdering(const TopologicalOrdering< TAlgebra, O_t > &parent)
clone constructor
Definition topological_ordering.h:239
boost::graph_traits< M_t >::vertex_descriptor vd_t
Definition topological_ordering.h:233
O_t & ordering()
Definition topological_ordering.h:280
BidirectionalMatrix< M_t > bidir
Definition topological_ordering.h:287
virtual const char * name() const
Definition topological_ordering.h:284
TAlgebra::matrix_type M_t
Definition topological_ordering.h:231
void compute()
Definition topological_ordering.h:247
void init(M_t *A)
Definition topological_ordering.h:259
IOrderingAlgorithm< TAlgebra, O_t > baseclass
Definition topological_ordering.h:234
void init(M_t *, const V_t &, const O_t &)
Definition topological_ordering.h:268
void init(M_t *A, const V_t &)
Definition topological_ordering.h:255
TopologicalOrdering()
Definition topological_ordering.h:236
O_t o
Definition topological_ordering.h:288
virtual void init()
#define UG_THROW(msg)
Definition error.h:57
#define UG_LOG(msg)
Definition log.h:367
#define UG_COND_THROW(cond, msg)
UG_COND_THROW(cond, msg) : performs a UG_THROW(msg) if cond == true.
Definition error.h:61
std::pair< typename graph_traits< T >::adjacency_iterator, typename graph_traits< T >::adjacency_iterator > adjacent_vertices(size_t v, ug::BidirectionalMatrix< T > const &M)
Definition bidirectional_boost.h:108
int out_degree(int v, ug::BidirectionalMatrix< T > const &M)
Definition bidirectional_boost.h:76
std::pair< SM_out_edge_iterator< typename T::value_type, false >, SM_out_edge_iterator< typename T::value_type, false > > in_edges(size_t v, ug::BidirectionalMatrix< T > const &g)
Definition bidirectional_boost.h:147
std::pair< counting_iterator< size_t >, counting_iterator< size_t > > vertices(ug::BidirectionalMatrix< T > const &M)
Definition bidirectional_boost.h:60
int num_vertices(ug::BidirectionalMatrix< T > const &M)
Definition bidirectional_boost.h:70
size_t source(SM_edge< typename T::value_type > const &e, ug::BidirectionalMatrix< T > const &)
Definition bidirectional_boost.h:94
the ug namespace
void topological_ordering_core_bidirectional(O_t &o, G_t &g, bool inverse)
Definition topological_ordering.h:59
bool is_permutation(O_t &o)
Definition permutation_util.h:135
void topological_ordering_core_directed(O_t &o, G_t &g, bool inverse)
Definition topological_ordering.h:142
SmartPtr< T, FreePolicy > make_sp(T *inst)
returns a SmartPtr for the passed raw pointer
Definition smart_pointer.h:836