Quetzal-CoaTL
The Coalescence Template Library
Loading...
Searching...
No Matches
cardinal_k_ary_tree.hpp
1//=======================================================================
2// Copyright 2018 Jeremy William Murphy
3//
4// Distributed under the Boost Software License, Version 1.0. (See
5// accompanying file LICENSE_1_0.txt or copy at
6// http://www.boost.org/LICENSE_1_0.txt)
7//=======================================================================
8
9// Copyright 2021 Arnaud Becheler <abechele@umich.edu>
10
18
19#ifndef BOOST_GRAPH_K_ARY_TREE
20#define BOOST_GRAPH_K_ARY_TREE
21
22#include <boost/config.hpp>
23
24#include <boost/graph/detail/indexed_properties.hpp>
25#include <boost/graph/graph_mutability_traits.hpp>
26#include <boost/graph/graph_selectors.hpp>
27#include <boost/graph/graph_traits.hpp>
28#include <boost/graph/named_function_params.hpp>
29#include <boost/property_map/property_map.hpp>
30
31#include <boost/concept/assert.hpp>
32#include <boost/graph/graph_concepts.hpp>
33#include <boost/iterator/iterator_facade.hpp>
34#include <boost/iterator/transform_iterator.hpp>
35#include <boost/range.hpp>
36#include <boost/range/adaptor/reversed.hpp>
37
38#include <stack>
39#include <utility>
40
41#include "concepts.hpp"
42#include "detail_k_ary_tree.hpp"
43#include "visit.hpp"
44
45namespace boost
46{
47template <typename Graph> bool empty(typename graph_traits<Graph>::vertex_descriptor u, Graph const &)
48{
49 return u == graph_traits<Graph>::null_vertex();
50}
51
59template <bool Predecessor, typename Vertex = std::size_t> class binary_tree;
60
68template <typename Vertex>
69class binary_tree<false, Vertex>
70 : public detail::binary_tree_base<Vertex, detail::binary_tree_forward_node<binary_tree<false, Vertex>>>
71{
72 private:
74
75 public:
77 using directed_category = directed_tag;
78
80 class traversal_category : public incidence_graph_tag, public vertex_list_graph_tag
81 {
82 };
83
85 using edge_descriptor = typename super_t::edge_descriptor;
86
88 using vertex_descriptor = typename super_t::vertex_descriptor;
89
91 using super_t::super_t;
92
99 {
100 BOOST_ASSERT(parent != child);
101
102 return g.add_left_edge(parent, child);
103 }
104
111 {
112 BOOST_ASSERT(parent != child);
113
114 return g.add_right_edge(parent, child);
115 }
116
119
128 friend std::pair<edge_descriptor, bool> add_edge(vertex_descriptor u, vertex_descriptor v, binary_tree &g)
129 {
130 return g.add_edge(u, v);
131 }
132
138 {
139 g.remove_edge(u, v);
140 }
141
146 {
147 remove_edge(e.first, e.second, g);
148 }
149
154 {
155 g.clear_vertex(u);
156 }
157
159}; // end class binary_tree<false, Vertex>
160
165template <typename Vertex>
166class binary_tree<true, Vertex>
167 : public detail::binary_tree_base<Vertex, detail::binary_tree_bidirectional_node<binary_tree<true, Vertex>>>
168{
170
171 public:
173 using directed_category = bidirectional_tag;
174
176 class traversal_category : public bidirectional_graph_tag, public vertex_list_graph_tag
177 {
178 };
179
181 using edge_descriptor = typename super_t::edge_descriptor;
182
184 using vertex_descriptor = typename super_t::vertex_descriptor;
185
187 using degree_size_type = typename super_t::degree_size_type;
188
189 using edge_parallel_category = typename super_t::edge_parallel_category;
190
192 using super_t::super_t;
193
200 {
201 BOOST_ASSERT(parent != child);
202 g.nodes[child].predecessor = parent;
203 return g.add_left_edge(parent, child);
204 }
205
212 {
213 BOOST_ASSERT(parent != child);
214 g.nodes[child].predecessor = parent;
215 return g.add_right_edge(parent, child);
216 }
217
224 {
225 BOOST_ASSERT(!empty(u, g));
226
227 while (has_predecessor(u, g))
228 {
229 u = predecessor(u, g);
230 }
231
232 BOOST_ASSERT(u != graph_traits<binary_tree>::null_vertex());
233 return u;
234 }
235
241 {
242 BOOST_ASSERT(!empty(u, g));
243 vertex_descriptor v = predecessor(u, g);
244 return left_successor(v, g) == u;
245 }
246
252 {
253 BOOST_ASSERT(!empty(u, g));
254
255 vertex_descriptor v = predecessor(u, g);
256 return right_successor(v, g) == u;
257 }
258
264 {
265 BOOST_ASSERT(!empty(u, g));
266 BOOST_ASSERT(u < g.nodes.size());
267 return g[u].predecessor != graph_traits<binary_tree>::null_vertex();
268 }
269
275 {
276 BOOST_ASSERT(!empty(u, g));
277 BOOST_ASSERT(u < g.nodes.size());
278
279 return g[u].predecessor;
280 }
281
284
285 private:
286 struct make_in_edge_descriptor
287 {
288 make_in_edge_descriptor(vertex_descriptor target) : target(target)
289 {
290 }
291
292 edge_descriptor operator()(vertex_descriptor source) const
293 {
294 return edge_descriptor(source, target);
295 }
296
297 vertex_descriptor target;
298 };
299
300 public:
302 using in_edge_iterator = transform_iterator<make_in_edge_descriptor, vertex_descriptor const *, edge_descriptor>;
303
309 friend std::pair<in_edge_iterator, in_edge_iterator> in_edges(vertex_descriptor u, binary_tree const &g)
310 {
311 auto const p = has_predecessor(u, g);
312 return std::make_pair(in_edge_iterator(&g.nodes[u].predecessor, make_in_edge_descriptor(u)),
313 in_edge_iterator(&g.nodes[u].predecessor + p, make_in_edge_descriptor(u)));
314 }
315
321 {
322 return has_predecessor(u, g);
323 }
324
330 {
331 return in_degree(u, g) + out_degree(u, g);
332 }
334
337
346 friend std::pair<edge_descriptor, bool> add_edge(vertex_descriptor u, vertex_descriptor v, binary_tree &g)
347 {
348 if (!g.add_vertex(v) && predecessor(v, g) != g.null_vertex())
349 return std::make_pair(edge_descriptor(), false);
350 g.add_vertex(u);
351
352 std::pair<edge_descriptor, bool> const result = g.add_edge_strict(u, v);
353 if (result.second)
354 g.nodes[v].predecessor = u;
355 return result;
356 }
357
363 {
364 BOOST_ASSERT(predecessor(v, g) == u);
365 g.remove_edge(u, v);
366 g.nodes[v].predecessor = super_t::null_vertex();
367 }
368
373 {
374 remove_edge(e.first, e.second, g);
375 }
376
381 {
382 g.clear_childrens_predecessor(u);
383 g.clear_vertex(u);
384 g.nodes[u].predecessor = super_t::null_vertex();
385 }
386
393 {
394 BOOST_ASSERT(in_degree(u, g) == 0);
395
396 g.remove_vertex(u);
397 }
398
400
404 {
405 for (int i = 0; i != 2; i++)
406 {
407 super_t::nodes[super_t::nodes[u].successors[i]].predecessor = super_t::null_vertex();
408 }
409 }
410};
411
414template <typename Vertex = std::size_t> using forward_binary_tree = binary_tree<false, Vertex>;
415
418template <typename Vertex = std::size_t> using bidirectional_binary_tree = binary_tree<true, Vertex>;
419
420// IncidenceGraph interface
421
422namespace detail
423{
424
425template <typename BinaryTree, typename Visitor>
426Visitor traverse_nonempty(vertex_descriptor_t<BinaryTree> u, BinaryTree const &g, Visitor vis)
427{
428 vis(visit::pre, u);
429 if (has_left_successor(u, g))
430 vis = traverse_nonempty(left_successor(u, g), g, vis);
431 vis(visit::in, u);
432 if (has_right_successor(u, g))
433 vis = traverse_nonempty(right_successor(u, g), g, vis);
434 vis(visit::post, u);
435 return vis;
436}
437
438template <typename BinaryTree> int traverse_step(visit &stage, vertex_descriptor_t<BinaryTree> &u, BinaryTree const &g)
439{
440 BOOST_CONCEPT_ASSERT((concepts::BidirectionalBinaryTreeConcept<BinaryTree>));
441
442 switch (stage)
443 {
444
445 case visit::pre:
446
447 if (has_left_successor(u, g))
448 {
449 u = left_successor(u, g);
450 return 1;
451 }
452
453 stage = visit::in;
454 return 0;
455
456 case visit::in:
457
458 if (has_right_successor(u, g))
459 {
460 stage = visit::pre;
461 u = right_successor(u, g);
462 return 1;
463 }
464
465 stage = visit::post;
466 return 0;
467
468 case visit::post:
469
470 if (is_left_successor(u, g))
471 {
472 stage = visit::in;
473 }
474 u = predecessor(u, g);
475 return -1;
476
477 default:
478 throw std::logic_error("Unexpected visit stage encountered");
479 }
480}
481
482template <typename BinaryTree, typename Visitor>
483Visitor traverse(vertex_descriptor_t<BinaryTree> u, BinaryTree const &g, Visitor vis)
484{
485 if (empty(u, g))
486 return vis;
487
488 auto root = u;
489
490 visit stage = visit::pre;
491 vis(stage, u);
492
493 do
494 {
495 traverse_step(stage, u, g);
496 vis(stage, u);
497 } while (u != root || stage != visit::post);
498
499 return vis;
500}
501
502template <typename BinaryTree0, typename BinaryTree1>
503bool bifurcate_isomorphic_nonempty(vertex_descriptor_t<BinaryTree0> u, BinaryTree0 const &g,
504 vertex_descriptor_t<BinaryTree1> v, BinaryTree1 const &h)
505{
506 BOOST_CONCEPT_ASSERT((concepts::ForwardBinaryTreeConcept<BinaryTree0>));
507 BOOST_CONCEPT_ASSERT((concepts::ForwardBinaryTreeConcept<BinaryTree1>));
508 BOOST_ASSERT(!empty(u, g));
509 BOOST_ASSERT(!empty(v, h));
510
511 if (has_left_successor(u, g))
512 {
513 if (has_left_successor(v, h))
514 {
515 if (!bifurcate_isomorphic_nonempty(left_successor(u, g), g, left_successor(v, h), h))
516 return false;
517 }
518 else
519 return false;
520 }
521 else if (has_left_successor(u, g))
522 return false;
523
524 if (has_right_successor(u, g))
525 {
526 if (has_right_successor(v, h))
527 {
528 if (!bifurcate_isomorphic_nonempty(right_successor(u, g), g, right_successor(v, h), h))
529 return false;
530 }
531 else
532 return false;
533 }
534 else if (has_right_successor(u, g))
535 return false;
536
537 return true;
538}
539
540template <typename BinaryTree0, typename BinaryTree1>
541bool bifurcate_isomorphic(vertex_descriptor_t<BinaryTree0> u, BinaryTree0 const &g, vertex_descriptor_t<BinaryTree1> v,
542 BinaryTree1 const &h)
543{
544 BOOST_CONCEPT_ASSERT((concepts::BidirectionalBinaryTreeConcept<BinaryTree0>));
545 BOOST_CONCEPT_ASSERT((concepts::BidirectionalBinaryTreeConcept<BinaryTree1>));
546
547 if (empty(u, g))
548 return empty(v, h);
549 if (empty(v, h))
550 return false;
551 auto root0 = u;
552 visit visit0 = visit::pre;
553 visit visit1 = visit::pre;
554 while (true)
555 {
556 traverse_step(visit0, u, g);
557 traverse_step(visit1, v, h);
558 if (visit0 != visit1)
559 return false;
560 if (u == root0 && visit0 == visit::post)
561 return true;
562 }
563}
564} // end namespace detail
565
572template <typename Vertex, typename DFSTreeVisitor>
574 DFSTreeVisitor &vis)
575{
576 if (!empty(s, g))
577 vis = detail::traverse_nonempty(s, g, vis);
578}
579
580template <typename Vertex, typename DFSTreeVisitor>
581void depth_first_search(binary_tree<false, Vertex> const &g, vertex_descriptor_t<binary_tree<false, Vertex>> s,
582 DFSTreeVisitor &vis)
583{
584 if (!empty(s, g))
585 vis = detail::traverse_nonempty(s, g, vis);
586}
587
594template <typename Vertex, typename DFSTreeVisitor>
596 DFSTreeVisitor &vis)
597{
598 vis = detail::traverse(s, g, vis);
599}
600
601template <typename Vertex, typename DFSTreeVisitor>
602void depth_first_search(binary_tree<true, Vertex> const &g, vertex_descriptor_t<binary_tree<true, Vertex>> s,
603 DFSTreeVisitor &vis)
604{
605 vis = detail::traverse(s, g, vis);
606}
607
615template <typename Vertex0, typename Vertex1>
617{
618 if (num_vertices(g) != num_vertices(h))
619 return false;
620 return num_vertices(g) == 0 || detail::bifurcate_isomorphic_nonempty(0, g, 0, h);
621}
622
630template <typename Vertex0, typename Vertex1>
632{
633 if (num_vertices(g) != num_vertices(h))
634 return false;
635 return num_vertices(g) == 0 || detail::bifurcate_isomorphic(0, g, 0, h);
636}
637} // namespace boost
638
639#endif // #ifndef BOOST_GRAPH_K_ARY_TREE
Forward Binary Tree.
Definition cardinal_k_ary_tree.hpp:71
directed_tag directed_category
Directed, undirected or bidirectional.
Definition cardinal_k_ary_tree.hpp:77
friend void remove_edge(vertex_descriptor u, vertex_descriptor v, binary_tree &g)
Remove the edge (u,v) from the graph.
Definition cardinal_k_ary_tree.hpp:137
friend void clear_vertex(vertex_descriptor u, binary_tree &g)
Remove all edges to and from vertex u from the graph.
Definition cardinal_k_ary_tree.hpp:153
friend void remove_edge(edge_descriptor e, binary_tree &g)
Remove the edge e from the graph.
Definition cardinal_k_ary_tree.hpp:145
typename super_t::edge_descriptor edge_descriptor
The type for the objects used to identify edges in the graph.
Definition cardinal_k_ary_tree.hpp:85
friend std::pair< edge_descriptor, bool > add_edge(vertex_descriptor u, vertex_descriptor v, binary_tree &g)
Inserts the edge (u,v) into the graph.
Definition cardinal_k_ary_tree.hpp:128
friend edge_descriptor add_left_edge(vertex_descriptor parent, vertex_descriptor child, binary_tree &g)
Add a left edge to the parent vertex.
Definition cardinal_k_ary_tree.hpp:98
typename super_t::vertex_descriptor vertex_descriptor
The type for the objects used to identity vertices in the graph.
Definition cardinal_k_ary_tree.hpp:88
friend edge_descriptor add_right_edge(vertex_descriptor parent, vertex_descriptor child, binary_tree &g)
Add a left edge to the parent vertex.
Definition cardinal_k_ary_tree.hpp:110
Bidirectional Binary Tree.
Definition cardinal_k_ary_tree.hpp:168
friend degree_size_type in_degree(vertex_descriptor u, binary_tree const &g)
Returns the number of in-edges of vertex v in graph g.
Definition cardinal_k_ary_tree.hpp:320
friend vertex_descriptor root(vertex_descriptor u, binary_tree const &g)
Finds the root of the tree graph starting from a vertex u.
Definition cardinal_k_ary_tree.hpp:223
friend bool is_left_successor(vertex_descriptor u, binary_tree const &g)
Evaluate if a vertex is a left successor (child)
Definition cardinal_k_ary_tree.hpp:240
friend bool is_right_successor(vertex_descriptor u, binary_tree const &g)
Evaluate if a vertex is a right successor (child)
Definition cardinal_k_ary_tree.hpp:251
friend bool has_predecessor(vertex_descriptor u, binary_tree const &g)
Evaluates if the vertex has a predecessor (parent)
Definition cardinal_k_ary_tree.hpp:263
friend void remove_edge(vertex_descriptor u, vertex_descriptor v, binary_tree &g)
Remove the edge (u,v) from the graph.
Definition cardinal_k_ary_tree.hpp:362
typename super_t::vertex_descriptor vertex_descriptor
The type for the objects used to identify vertices in the graph.
Definition cardinal_k_ary_tree.hpp:184
friend degree_size_type degree(vertex_descriptor u, binary_tree const &g)
Returns the number of in-edges plus out-edges.
Definition cardinal_k_ary_tree.hpp:329
friend void remove_vertex(vertex_descriptor u, binary_tree &g)
Remove u from the vertex set of the graph.
Definition cardinal_k_ary_tree.hpp:392
friend void clear_vertex(vertex_descriptor u, binary_tree &g)
Remove all edges to and from vertex u from the graph.
Definition cardinal_k_ary_tree.hpp:380
bidirectional_tag directed_category
Directed, undirected or bidirectional.
Definition cardinal_k_ary_tree.hpp:173
friend vertex_descriptor predecessor(vertex_descriptor u, binary_tree const &g)
The predecessor of a given vertex.
Definition cardinal_k_ary_tree.hpp:274
friend void remove_edge(edge_descriptor e, binary_tree &g)
Remove the edge e from the graph.
Definition cardinal_k_ary_tree.hpp:372
transform_iterator< make_in_edge_descriptor, vertex_descriptor const *, edge_descriptor > in_edge_iterator
Iterate through the in-edges.
Definition cardinal_k_ary_tree.hpp:302
typename super_t::edge_descriptor edge_descriptor
The type for the objects used to identify edges in the graph.
Definition cardinal_k_ary_tree.hpp:181
friend std::pair< in_edge_iterator, in_edge_iterator > in_edges(vertex_descriptor u, binary_tree const &g)
Provides iterators to iterate over the in-going edges of vertex u.
Definition cardinal_k_ary_tree.hpp:309
friend std::pair< edge_descriptor, bool > add_edge(vertex_descriptor u, vertex_descriptor v, binary_tree &g)
Inserts the edge (u,v) into the graph.
Definition cardinal_k_ary_tree.hpp:346
typename super_t::degree_size_type degree_size_type
The integer type for vertex degree.
Definition cardinal_k_ary_tree.hpp:187
friend edge_descriptor add_left_edge(vertex_descriptor parent, vertex_descriptor child, binary_tree &g)
Add a left edge to the parent vertex.
Definition cardinal_k_ary_tree.hpp:199
friend edge_descriptor add_right_edge(vertex_descriptor parent, vertex_descriptor child, binary_tree &g)
Add a right edge to the parent vertex.
Definition cardinal_k_ary_tree.hpp:211
void clear_childrens_predecessor(vertex_descriptor u)
Clears the children's predecessor.
Definition cardinal_k_ary_tree.hpp:403
Binary tree base definition for further specialization.
Definition cardinal_k_ary_tree.hpp:59
Definition detail_k_ary_tree.hpp:64
Definition cardinal_k_ary_tree.hpp:46
bool isomorphism(binary_tree< false, Vertex0 > const &g, binary_tree< false, Vertex1 > const &h)
Detects if there is a 1-to-1 mapping of the vertices in one graph to the vertices of another graph su...
Definition cardinal_k_ary_tree.hpp:616
void depth_first_search(binary_tree< false, Vertex > &g, vertex_descriptor_t< binary_tree< false, Vertex > > s, DFSTreeVisitor &vis)
performs a depth-first traversal of the vertices in a directed graph
Definition cardinal_k_ary_tree.hpp:573