digiKam
itemhistorygraph_boost.h
Go to the documentation of this file.
1 /* ============================================================
2  *
3  * This file is a part of digiKam project
4  * https://www.digikam.org
5  *
6  * Date : 2010-10-22
7  * Description : Boost Graph Library: a graph class
8  *
9  * Copyright (C) 2010-2011 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
10  *
11  * This program is free software; you can redistribute it
12  * and/or modify it under the terms of the GNU General
13  * Public License as published by the Free Software Foundation;
14  * either version 2, or (at your option)
15  * any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20  * GNU General Public License for more details.
21  *
22  * ============================================================ */
23 
24 #ifndef DIGIKAM_ITEM_HISTORY_GRAPH_BOOST_H
25 #define DIGIKAM_ITEM_HISTORY_GRAPH_BOOST_H
26 
27 // To include pragma directives for MSVC
28 #include "digikam_config.h"
29 
30 #ifdef Q_CC_MSVC
31 # include <ciso646>
32 # pragma warning(disable : 4267)
33 #endif
34 
35 #if !defined(Q_OS_DARWIN) && defined(Q_CC_GNU)
36 # pragma GCC diagnostic push
37 # pragma GCC diagnostic ignored "-Wdeprecated-declarations"
38 # pragma GCC diagnostic ignored "-Wunused-local-typedefs"
39 #endif
40 
41 #if defined(Q_CC_CLANG)
42 # pragma clang diagnostic push
43 # pragma clang diagnostic ignored "-Wdeprecated-declarations"
44 # pragma clang diagnostic ignored "-Wundef"
45 # pragma clang diagnostic ignored "-Wunused-parameter"
46 # pragma clang diagnostic ignored "-Wcast-align"
47 # pragma clang diagnostic ignored "-Wunused-local-typedef"
48 #endif
49 
50 // C++ includes
51 
52 #include <utility>
53 #include <algorithm>
54 #include <vector>
55 #include <stdbool.h>
56 
57 // Boost includes
58 
59 // Prohibit boost using deprecated header files
60 #define BOOST_NO_HASH
61 #define BOOST_BIND_GLOBAL_PLACEHOLDERS
62 #define BOOST_ALLOW_DEPRECATED_HEADERS
63 
64 #include <boost/graph/transitive_closure.hpp>
65 #include <boost/graph/adjacency_list.hpp>
66 #include <boost/graph/topological_sort.hpp>
67 #include <boost/graph/graph_utility.hpp>
68 #include <boost/graph/dag_shortest_paths.hpp>
69 #include <boost/graph/dijkstra_shortest_paths.hpp>
70 #include <boost/graph/reverse_graph.hpp>
71 #include <boost/graph/dominator_tree.hpp>
72 #include <boost/graph/depth_first_search.hpp>
73 #include <boost/graph/breadth_first_search.hpp>
74 #include <boost/graph/transitive_reduction.hpp>
75 
76 // Local includes
77 
78 #include "digikam_debug.h"
79 #include "digikam_export.h"
80 
86 
87 namespace boost
88 {
89  BOOST_INSTALL_PROPERTY(vertex, properties);
90  BOOST_INSTALL_PROPERTY(edge, properties);
91 }
92 
93 namespace Digikam
94 {
95 
100 template <typename Key, typename Value>
101 class QMapForAdaptors : public QMap<Key, Value>
102 {
103 public:
104 
105  typedef Key key_type;
106  typedef Value data_type;
107  typedef typename std::pair<const Key, Value> value_type;
108 
110  {
111  }
112 };
113 
120 {
123 };
124 
128 template <class VertexProperties, class EdgeProperties>
129 class DIGIKAM_DATABASE_EXPORT Graph // clazy:exclude=missing-typeinfo,copyable-polymorphic
130 {
131 public:
132 
133  typedef boost::adjacency_list<
134  boost::vecS,
135  boost::vecS,
136  boost::bidirectionalS,
137  boost::property<boost::vertex_index_t, int,
138  boost::property<vertex_properties_t, VertexProperties> >,
139  boost::property<edge_properties_t, EdgeProperties>
141 
145  typedef typename boost::graph_traits<GraphContainer> graph_traits;
146 
147  typedef typename graph_traits::vertex_descriptor vertex_t;
148  typedef typename graph_traits::edge_descriptor edge_t;
149 
150  typedef typename graph_traits::vertex_iterator vertex_iter;
151  typedef typename graph_traits::edge_iterator edge_iter;
152  typedef typename graph_traits::adjacency_iterator adjacency_iter;
153  typedef typename graph_traits::out_edge_iterator out_edge_iter;
154  typedef typename graph_traits::in_edge_iterator in_edge_iter;
155  typedef typename boost::inv_adjacency_iterator_generator<GraphContainer,
156  vertex_t,
158 
159  typedef typename graph_traits::degree_size_type degree_t;
160 
161  typedef std::pair<adjacency_iter, adjacency_iter> adjacency_vertex_range_t;
162  typedef std::pair<inv_adjacency_iter, inv_adjacency_iter> inv_adjacency_vertex_range_t;
163  typedef std::pair<out_edge_iter, out_edge_iter> out_edge_range_t;
164  typedef std::pair<vertex_iter, vertex_iter> vertex_range_t;
165  typedef std::pair<edge_iter, edge_iter> edge_range_t;
166 
167  typedef typename boost::property_map<GraphContainer, boost::vertex_index_t>::type vertex_index_map_t;
168  typedef typename boost::property_map<GraphContainer, boost::vertex_index_t>::const_type const_vertex_index_map_t;
169  typedef typename boost::property_map<GraphContainer, vertex_properties_t>::type vertex_property_map_t;
170  typedef typename boost::property_map<GraphContainer, vertex_properties_t>::const_type const_vertex_property_map_t;
171  typedef typename boost::property_map<GraphContainer, edge_properties_t>::type edge_property_map_t;
172  typedef typename boost::property_map<GraphContainer, edge_properties_t>::const_type const_edge_property_map_t;
173 
178  class DIGIKAM_DATABASE_EXPORT Vertex // clazy:exclude=missing-typeinfo
179  {
180  public:
181 
183  : v(graph_traits::null_vertex())
184  {
185  }
186 
187  // cppcheck-suppress noExplicitConstructor
188  Vertex(const vertex_t& v) // krazy:exclude=explicit
189  : v(v)
190  {
191  }
192 
193  Vertex& operator=(const vertex_t& other)
194  {
195  v = other;
196 
197  return *this;
198  }
199 
200  operator const vertex_t&() const
201  {
202  return v;
203  }
204 
205  operator vertex_t&()
206  {
207  return v;
208  }
209 
210  bool operator==(const vertex_t& other) const
211  {
212  return (v == other);
213  }
214 
215  bool isNull() const
216  {
217  return (v == graph_traits::null_vertex());
218  }
219 
220  protected:
221 
223  };
224 
225  class DIGIKAM_DATABASE_EXPORT Edge // clazy:exclude=missing-typeinfo
226  {
227  public:
228 
230  : null(true)
231  {
232  }
233 
234  // cppcheck-suppress noExplicitConstructor
235  Edge(const edge_t& e) // krazy:exclude=explicit
236  : e (e),
237  null(false)
238  {
239  }
240 
241  Edge& operator=(const edge_t& other)
242  {
243  e = other;
244  null = false;
245 
246  return *this;
247  }
248 
249  operator const edge_t&() const
250  {
251  return e;
252  }
253 
254  operator edge_t&()
255  {
256  return e;
257  }
258 
259  const edge_t& toEdge() const
260  {
261  return e;
262  }
263 
265  {
266  return e;
267  }
268 
269  bool operator==(const edge_t& other) const
270  {
271  return (e == other);
272  }
273 
274  bool isNull() const
275  {
276  return null;
277  }
278 
279  protected:
280 
282 
284  bool null;
285  };
286 
287 public:
288 
289  typedef QPair<Vertex, Vertex> VertexPair;
290  typedef QPair<Edge, Edge> EdgePair;
291 
294 
295  typedef boost::associative_property_map<VertexVertexMap> VertexVertexMapAdaptor;
296  typedef boost::associative_property_map<VertexIntMap> VertexIntMapAdaptor;
297 
298 public:
299 
300  explicit Graph(MeaningOfDirection direction = ParentToChild)
301  : direction(direction)
302  {
303  }
304 
305  Graph(const Graph& g)
306  : graph (g.graph),
307  direction(g.direction)
308  {
309  }
310 
311  virtual ~Graph()
312  {
313  }
314 
315  Graph& operator=(const Graph& other)
316  {
317  graph = other.graph;
318  direction = other.direction;
319 
320  return *this;
321  }
322 
324  {
325  return direction;
326  }
327 
328  void clear()
329  {
330  graph.clear();
331  }
332 
334  {
335  Vertex v = boost::add_vertex(graph);
336 
337  return v;
338  }
339 
340  Vertex addVertex(const VertexProperties& properties)
341  {
342  Vertex v = addVertex();
343  setProperties(v, properties);
344 
345  return v;
346  }
347 
348  void remove(const Vertex& v)
349  {
350  if (v.isNull())
351  {
352  return;
353  }
354 
355  boost::clear_vertex(v, graph);
356  boost::remove_vertex(v, graph);
357  }
358 
359  Edge addEdge(const Vertex& v1, const Vertex& v2)
360  {
361  Edge e = edge(v1, v2);
362 
363  if (e.isNull())
364  {
365  e = boost::add_edge(v1, v2, graph).first;
366  }
367 
368  return e;
369  }
370 
371  Edge edge(const Vertex& v1, const Vertex& v2) const
372  {
373  std::pair<edge_t, bool> pair = boost::edge(v1, v2, graph);
374 
375  if (pair.second)
376  {
377  return pair.first;
378  }
379 
380  return Edge();
381  }
382 
383  bool hasEdge(const Vertex& v1, const Vertex& v2) const
384  {
385  return boost::edge(v1, v2, graph).second;
386  }
387 
389  bool isConnected(const Vertex& v1, const Vertex& v2) const
390  {
391  if (boost::edge(v1, v2, graph).second)
392  {
393  return true;
394  }
395 
396  if (boost::edge(v2, v1, graph).second)
397  {
398  return true;
399  }
400 
401  return false;
402  }
403 
404  void setProperties(const Vertex& v, const VertexProperties& props)
405  {
406  boost::put(vertex_properties, graph, v, props);
407  }
408 
409  const VertexProperties& properties(const Vertex& v) const
410  {
411  return boost::get(vertex_properties, graph, v);
412  }
413 
414  VertexProperties& properties(const Vertex& v)
415  {
416  return boost::get(vertex_properties, graph, v);
417  }
418 
419  void setProperties(const Edge& e, const EdgeProperties& props)
420  {
421  boost::put(edge_properties, graph, e, props);
422  }
423 
424  template <class T>
426  {
427  vertex_range_t range = boost::vertices(graph);
428 
429  for (vertex_iter it = range.first ; it != range.second ; ++it)
430  {
431  const VertexProperties& props = properties(*it);
432 
433  // must implement operator==(const T&)
434 
435  if (props == value)
436  {
437  return *it;
438  }
439  }
440 
441  return Vertex();
442  }
443 
444  EdgeProperties properties(const Vertex& v1, const Vertex& v2) const
445  {
446  Edge e = edge(v1, v2);
447 
448  if (e.isNull())
449  {
450  return EdgeProperties();
451  }
452 
453  return properties(e);
454  }
455 
456  const EdgeProperties& properties(const Edge& e) const
457  {
458  return boost::get(edge_properties, graph, e);
459  }
460 
461  EdgeProperties& properties(const Edge& e)
462  {
463  return boost::get(edge_properties, graph, e);
464  }
465 
469  const GraphContainer& getGraph() const
470  {
471  return graph;
472  }
473 
475  {
476  return toVertexList(boost::vertices(graph));
477  }
478 
480  {
481  OutboundEdges = 1 << 0,
482  InboundEdges = 1 << 1,
483 
485  EdgesToLeaf = 1 << 2,
486  EdgesToRoot = 1 << 3,
487  AllEdges = InboundEdges | OutboundEdges
488  };
489 
490  QList<Vertex> adjacentVertices(const Vertex& v, AdjacencyFlags flags = AllEdges) const
491  {
492  if (flags & EdgesToLeaf)
493  {
494  flags = (AdjacencyFlags)(flags | ((direction == ParentToChild) ? OutboundEdges
495  : InboundEdges));
496  }
497 
498  if (flags & EdgesToRoot)
499  {
500  flags = (AdjacencyFlags)(flags | ((direction == ParentToChild) ? InboundEdges
501  : OutboundEdges));
502  }
503 
504  QList<Vertex> verticesLst;
505 
506  if (flags & OutboundEdges)
507  {
508  verticesLst << toVertexList(boost::adjacent_vertices(v, graph));
509  }
510 
511  if (flags & InboundEdges)
512  {
513  verticesLst << toVertexList(boost::inv_adjacent_vertices(v, graph));
514  }
515 
516  return verticesLst;
517  }
518 
520  int vertexCount() const
521  {
522  return (int)boost::num_vertices(graph);
523  }
524 
525  bool isEmpty() const
526  {
527  return isEmptyRange(boost::vertices(graph));
528  }
529 
530  int outDegree(const Vertex& v) const
531  {
532  return (int)boost::out_degree(v, graph);
533  }
534 
535  int inDegree(const Vertex& v) const
536  {
537  return boost::in_degree(v, graph);
538  }
539 
540  bool isRoot(const Vertex& v) const
541  {
542  return !hasEdges(v, EdgesToRoot);
543  }
544 
545  bool isLeaf(const Vertex& v) const
546  {
547  return !hasEdges(v, EdgesToLeaf);
548  }
549 
550  Vertex source(const Edge& e) const
551  {
552  return boost::source(e.toEdge(), graph);
553  }
554 
555  Vertex target(const Edge& e) const
556  {
557  return boost::target(e.toEdge(), graph);
558  }
559 
560  QList<Edge> edges(const Vertex& v, AdjacencyFlags flags = AllEdges) const
561  {
562  if (flags & EdgesToLeaf)
563  {
564  flags = (AdjacencyFlags)(flags | ((direction == ParentToChild) ? OutboundEdges
565  : InboundEdges));
566  }
567 
568  if (flags & EdgesToRoot)
569  {
570  flags = (AdjacencyFlags)(flags | ((direction == ParentToChild) ? InboundEdges
571  : OutboundEdges));
572  }
573 
574  QList<Edge> es;
575 
576  if (flags & OutboundEdges)
577  {
578  es << toEdgeList(boost::out_edges(v, graph));
579  }
580 
581  if (flags & InboundEdges)
582  {
583  es << toEdgeList(boost::in_edges(v, graph));
584  }
585 
586  return es;
587  }
588 
589  int edgeCount() const
590  {
591  return boost::num_edges(graph);
592  }
593 
594  bool hasEdges(const Vertex& v, AdjacencyFlags flags = AllEdges) const
595  {
596  if (flags & EdgesToLeaf)
597  {
598  flags = (AdjacencyFlags)(flags | ((direction == ParentToChild) ? OutboundEdges
599  : InboundEdges));
600  }
601 
602  if (flags & EdgesToRoot)
603  {
604  flags = (AdjacencyFlags)(flags | ((direction == ParentToChild) ? InboundEdges
605  : OutboundEdges));
606  }
607 
608  if (flags & OutboundEdges)
609  {
610  if (!isEmptyRange(boost::out_edges(v, graph)))
611  {
612  return true;
613  }
614  }
615 
616  if (flags & InboundEdges)
617  {
618  if (!isEmptyRange(boost::in_edges(v, graph)))
619  {
620  return true;
621  }
622  }
623 
624  return false;
625  }
626 
627  bool hasEdges() const
628  {
629  return !isEmptyRange(boost::edges(graph));
630  }
631 
633  {
634  return toEdgeList(boost::edges(graph));
635  }
636 
638  {
639  QList<VertexPair> pairs;
640  edge_range_t range = boost::edges(graph);
641 
642  for (edge_iter it = range.first ; it != range.second ; ++it)
643  {
644  pairs << VertexPair(boost::source(*it, graph), boost::target(*it, graph));
645  }
646 
647  return pairs;
648  }
649 
650  /* ---- Algorithms ---- */
651 
656  {
657  std::list<Vertex> verticesLst;
658 
659  try
660  {
661  boost::topological_sort(graph, std::back_inserter(verticesLst));
662  }
663  catch (boost::bad_graph& e)
664  {
665  qCDebug(DIGIKAM_DATABASE_LOG) << e.what();
666 
667  return QList<Vertex>();
668  }
669 
670  typedef typename std::list<Vertex>::iterator vertex_list_iter;
671 
672  return toVertexList(std::pair<vertex_list_iter, vertex_list_iter>(verticesLst.begin(), verticesLst.end()));
673  }
674 
676  {
677  CopyVertexProperties = 1 << 0,
678  CopyEdgeProperties = 1 << 1,
679  CopyAllProperties = CopyVertexProperties | CopyEdgeProperties
680  };
681 
685  Graph transitiveClosure(GraphCopyFlags flags = CopyAllProperties) const
686  {
687  // make_iterator_property_map:
688  // 1. The second parameter, our verteX_index map, converts the key (Vertex) into an index
689  // 2. The index is used to store the value (Vertex) in the first argument, which is our vector
690 
691  std::vector<vertex_t> copiedVertices(vertexCount(), Vertex());
692  Graph closure;
693 
694  try
695  {
696  boost::transitive_closure(
697  graph,
698  closure.graph,
699  orig_to_copy(make_iterator_property_map(copiedVertices.begin(),
700  get(boost::vertex_index, graph)))
701  );
702  }
703  catch (boost::bad_graph& e)
704  {
705  qCDebug(DIGIKAM_DATABASE_LOG) << e.what();
706 
707  return Graph();
708  }
709 
710  copyProperties(closure, flags, copiedVertices);
711 
712  return closure;
713  }
714 
719  Graph transitiveReduction(QList<Edge>* removedEdges = 0, GraphCopyFlags flags = CopyAllProperties) const
720  {
721  std::vector<vertex_t> copiedVertices(vertexCount(), Vertex());
722  Graph reduction;
723 
724  // NOTE: named parameters is not implemented
725 
726  try
727  {
728  boost::transitive_reduction(graph, reduction.graph,
729  make_iterator_property_map(copiedVertices.begin(), get(boost::vertex_index, graph)),
730  get(boost::vertex_index, graph));
731  }
732  catch (boost::bad_graph& e)
733  {
734  qCDebug(DIGIKAM_DATABASE_LOG) << e.what();
735 
736  return Graph();
737  }
738 
739  copyProperties(reduction, flags, copiedVertices);
740 
741  if (removedEdges)
742  {
743  *removedEdges = edgeDifference(reduction, copiedVertices);
744  }
745 
746  return reduction;
747  }
748 
754  {
755  return findZeroDegree(direction == ParentToChild ? true : false);
756  }
757 
763  QList<Vertex> rootsOf(const Vertex& v) const
764  {
765  return findZeroDegreeFrom(v, direction == ParentToChild ? true : false);
766  }
767 
773  {
774  return findZeroDegree((direction == ParentToChild) ? false : true);
775  }
776 
778  {
779  return findZeroDegreeFrom(v, (direction == ParentToChild) ? false : true);
780  }
781 
782  template <typename T> static bool alwaysFalse(const T&, const T&)
783  {
784  return false;
785  }
786 
794  {
795  return longestPathTouching(v, alwaysFalse<Vertex>);
796  }
797 
798  template <typename LessThan>
800  {
801  if (v.isNull())
802  {
803  return QList<Vertex>();
804  }
805 
806  QList<Vertex> fromRoot;
807  QList<Vertex> toLeave;
808  Path path;
809 
810  path.longestPath(boost::make_reverse_graph(graph), v);
811 
812  QList<Vertex> rootCandidates = mostRemoteNodes(path.distances);
813 
814  if (!rootCandidates.isEmpty())
815  {
816  std::stable_sort(rootCandidates.begin(), rootCandidates.end(), lessThan);
817  Vertex root = rootCandidates.first();
818  fromRoot << listPath(root, v, path.predecessors, ChildToParent);
819  }
820 
821  path.longestPath(graph, v);
822 
823  QList<Vertex> leaveCandidates = mostRemoteNodes(path.distances);
824 
825  if (!leaveCandidates.isEmpty())
826  {
827  std::stable_sort(leaveCandidates.begin(), leaveCandidates.end(), lessThan);
828  Vertex leave = leaveCandidates.first();
829  toLeave << listPath(leave, v, path.predecessors);
830  }
831 
832  if (direction == ParentToChild)
833  {
834  return (fromRoot << v << toLeave);
835  }
836  else
837  {
838  return (toLeave << v << fromRoot);
839  }
840  }
841 
848  QList<Vertex> shortestPath(const Vertex& v1, const Vertex& v2) const
849  {
850  if (v1.isNull() || v2.isNull())
851  {
852  return QList<Vertex>();
853  }
854 
855  QList<Vertex> verticesLst;
856 
857  Path path;
858  path.shortestPath(graph, v1);
859 
860  if (path.isReachable(v2))
861  {
862  verticesLst = listPath(v2, v1, path.predecessors, ChildToParent);
863  verticesLst.prepend(v1);
864  }
865  else
866  {
867  // assume inverted parameters
868 
869  path.shortestPath(graph, v2);
870 
871  if (path.isReachable(v1))
872  {
873  verticesLst = listPath(v1, v2, path.predecessors);
874  verticesLst.append(v2);
875  }
876  }
877 
878  return verticesLst;
879  }
880 
885  QMap<Vertex, int> shortestDistancesFrom(const Vertex& v) const
886  {
887  Path path;
888 
889  if (direction == ParentToChild)
890  {
891  path.shortestPath(graph, v);
892  }
893  else
894  {
895  path.shortestPath(boost::make_reverse_graph(graph), v);
896  }
897 
898  // Change 2147483647 to -1
899 
900  typename QMap<Vertex, int>::iterator it;
901 
902  for (it = path.distances.begin() ; it != path.distances.end() ; ++it)
903  {
904  if (it.value() == std::numeric_limits<int>::max())
905  {
906  it.value() = -1;
907  }
908  }
909 
910  return path.distances;
911  }
912 
914  {
916  DepthFirstOrder
917  };
918 
925  const Vertex& root,
926  ReturnOrder order = BreadthFirstOrder) const
927  {
928  if (v.isNull() || isEmpty())
929  {
930  return QList<Vertex>();
931  }
932 
933  GraphSearch search;
934 
935  if (order == BreadthFirstOrder)
936  {
937  search.breadthFirstSearch(graph, root, (direction == ChildToParent));
938  }
939  else
940  {
941  search.depthFirstSearch(graph, root, (direction == ChildToParent));
942  }
943 
944  return verticesDominatedBy(v, root, search.vertices);
945  }
946 
952  template <typename LessThan>
954  const Vertex& root,
955  LessThan lessThan) const
956  {
957  return verticesDominatedBy(v, root, verticesDepthFirstSorted(root, lessThan));
958  }
959 
968  const Vertex& root,
969  const QList<Vertex>& presortedVertices) const
970  {
971  if (v.isNull() || isEmpty())
972  {
973  return QList<Vertex>();
974  }
975 
976  DominatorTree tree;
977  tree.enter(graph, root, direction);
978 
979  QList<Vertex> dominatedTree = treeFromPredecessors(v, tree.predecessors);
980 
982 
983  QList<Vertex> orderedTree;
984 
985  foreach (const Vertex& vv, presortedVertices)
986  {
987  if (dominatedTree.contains(vv))
988  {
989  orderedTree << vv;
990  }
991  }
992 
993  return orderedTree;
994  }
995 
1002  {
1003  if (isEmpty())
1004  {
1005  return QList<Vertex>();
1006  }
1007 
1008  Vertex ref(givenRef);
1009 
1010  if (ref.isNull())
1011  {
1012  ref = roots().first();
1013  }
1014 
1015  QList<Vertex> verticesLst;
1016  verticesLst << rootsOf(ref);
1017 
1018  if (verticesLst.size() == vertexCount())
1019  {
1020  return verticesLst;
1021  }
1022 
1023  GraphSearch search;
1024  search.breadthFirstSearch(graph, verticesLst.first(), direction == ChildToParent);
1025  QList<Vertex> bfs = search.verticesLst;
1026 
1027  foreach (const Vertex& v, verticesLst)
1028  {
1029  bfs.removeOne(v);
1030  }
1031 
1032  verticesLst << bfs;
1033 
1034  if (verticesLst.size() == vertexCount())
1035  {
1036  return verticesLst;
1037  }
1038 
1039  // Sort in any so far unreachable nodes
1040 
1041  vertex_range_t range = boost::vertices(graph);
1042 
1043  for (vertex_iter it = range.first ; it != range.second ; ++it)
1044  {
1045  if (!verticesLst.contains(*it))
1046  {
1047  GraphSearch childSearch;
1048  childSearch.breadthFirstSearch(graph, *it, direction == ChildToParent);
1049  QList<Vertex> childBfs = childSearch.vertices;
1050  QList<Vertex> toInsert;
1051 
1052  // Any item reachable from *it should come after it
1053 
1054  int minIndex = verticesLst.size();
1055 
1056  foreach (const Vertex& c, childBfs)
1057  {
1058  int foundAt = verticesLst.indexOf(c);
1059 
1060  if (foundAt == -1)
1061  {
1062  toInsert << c;
1063  }
1064  else
1065  {
1066  minIndex = qMin(foundAt, minIndex);
1067  }
1068  }
1069 
1070  foreach (const Vertex& c, toInsert)
1071  {
1072  verticesLst.insert(minIndex++, c);
1073  }
1074  }
1075  }
1076 
1077  return verticesLst;
1078  }
1079 
1086  template <typename LessThan>
1087  QList<Vertex> verticesDepthFirstSorted(const Vertex& givenRef, LessThan lessThan) const
1088  {
1089  if (isEmpty())
1090  {
1091  return QList<Vertex>();
1092  }
1093 
1094  Vertex ref(givenRef);
1095 
1096  if (ref.isNull())
1097  {
1098  ref = roots().first();
1099  }
1100 
1101  QList<Vertex> verticesLst;
1102  verticesLst = rootsOf(ref);
1103 
1104  if ((verticesLst.size() == vertexCount()) || verticesLst.isEmpty())
1105  {
1106  return verticesLst;
1107  }
1108 
1109  GraphSearch search;
1110  search.depthFirstSearchSorted(graph, verticesLst.first(), direction == ChildToParent, lessThan);
1111  QList<Vertex> dfs = search.vertices;
1112 
1113  foreach (const Vertex& v, verticesLst)
1114  {
1115  dfs.removeOne(v);
1116  }
1117 
1118  verticesLst << dfs;
1119 
1120  return search.vertices;
1121  }
1122 
1123 protected:
1124 
1125  QList<Vertex> treeFromPredecessors(const Vertex& v, const VertexVertexMap& predecessors) const
1126  {
1127  QList<Vertex> verticesLst;
1128  verticesLst << v;
1129  treeFromPredecessorsRecursive(v, verticesLst, predecessors);
1130 
1131  return verticesLst;
1132  }
1133 
1135  QList<Vertex>& vertices,
1136  const VertexVertexMap& predecessors) const
1137  {
1138  QList<Vertex> children = predecessors.keys(v);
1139  vertices << children;
1140 
1141  foreach (const Vertex& child, children)
1142  {
1143  treeFromPredecessorsRecursive(child, vertices, predecessors);
1144  }
1145  }
1146 
1150  template <typename Value, typename range_t>
1151  static QList<Value> toList(const range_t& range)
1152  {
1153  typedef typename range_t::first_type iterator_t;
1154  QList<Value> list;
1155 
1156  for (iterator_t it = range.first ; it != range.second ; ++it)
1157  {
1158  list << *it;
1159  }
1160 
1161  return list;
1162  }
1163 
1164  template <typename range_t> static QList<Vertex> toVertexList(const range_t& range)
1165  {
1166  return toList<Vertex, range_t>(range);
1167  }
1168 
1169  template <typename range_t> static QList<Edge> toEdgeList(const range_t& range)
1170  {
1171  return toList<Edge, range_t>(range);
1172  }
1173 
1174  template <typename range_t>
1175  static bool isEmptyRange(const range_t& range)
1176  {
1177  return (range.first == range.second);
1178  }
1179 
1184  void copyProperties(Graph& other, GraphCopyFlags flags, const std::vector<vertex_t>& copiedVertices) const
1185  {
1186  other.direction = direction;
1187 
1188  if (flags & CopyVertexProperties)
1189  {
1190  vertex_index_map_t indexMap = boost::get(boost::vertex_index, graph);
1191  vertex_range_t range = boost::vertices(graph);
1192 
1193  for (vertex_iter it = range.first ; it != range.second ; ++it)
1194  {
1195  Vertex copiedVertex = copiedVertices[boost::get(indexMap, *it)];
1196 
1197  if (copiedVertex.isNull())
1198  {
1199  continue;
1200  }
1201 
1202  other.setProperties(copiedVertex, properties(*it));
1203  }
1204  }
1205 
1206  if (flags & CopyEdgeProperties)
1207  {
1208  vertex_index_map_t indexMap = boost::get(boost::vertex_index, graph);
1209  edge_range_t range = boost::edges(graph);
1210 
1211  for (edge_iter it = range.first ; it != range.second ; ++it)
1212  {
1213  Vertex s = boost::source(*it, graph);
1214  Vertex t = boost::target(*it, graph);
1215  Vertex copiedS = copiedVertices[boost::get(indexMap, s)];
1216  Vertex copiedT = copiedVertices[boost::get(indexMap, t)];
1217 
1218  if (copiedS.isNull() || copiedT.isNull())
1219  {
1220  continue;
1221  }
1222 
1223  Edge copiedEdge = other.edge(copiedS, copiedT);
1224 
1225  if (!copiedEdge.isNull())
1226  {
1227  other.setProperties(copiedEdge, properties(s, t));
1228  }
1229  }
1230  }
1231  }
1232 
1237  QList<Edge> edgeDifference(const Graph& other, const std::vector<vertex_t>& copiedVertices) const
1238  {
1239  QList<Edge> removed;
1240  vertex_index_map_t indexMap = boost::get(boost::vertex_index, graph);
1241  edge_range_t range = boost::edges(graph);
1242 
1243  for (edge_iter it = range.first ; it != range.second ; ++it)
1244  {
1245  Vertex s = boost::source(*it, graph);
1246  Vertex t = boost::target(*it, graph);
1247  Vertex copiedS = copiedVertices[boost::get(indexMap, s)];
1248  Vertex copiedT = copiedVertices[boost::get(indexMap, t)];
1249 
1250  if (copiedS.isNull() || copiedT.isNull())
1251  {
1252  continue;
1253  }
1254 
1255  Edge copiedEdge = other.edge(copiedS, copiedT);
1256 
1257  if (copiedEdge.isNull())
1258  {
1259  removed << *it;
1260  }
1261  }
1262 
1263  return removed;
1264  }
1265 
1269  QList<Vertex> findZeroDegree(bool inOrOut) const
1270  {
1271  QList<Vertex> verticesLst;
1272  vertex_range_t range = boost::vertices(graph);
1273 
1274  for (vertex_iter it = range.first ; it != range.second ; ++it)
1275  {
1276  if ((inOrOut ? in_degree(*it, graph)
1277  : out_degree(*it, graph)) == 0)
1278  {
1279  verticesLst << *it;
1280  }
1281  }
1282 
1283  return verticesLst;
1284  }
1285 
1286  QList<Vertex> findZeroDegreeFrom(const Vertex& v, bool inOrOut) const
1287  {
1288  bool invertGraph = (direction == ChildToParent);
1289 
1290  if (!inOrOut)
1291  {
1292  invertGraph = !invertGraph;
1293  }
1294 
1295  GraphSearch search;
1296  search.breadthFirstSearch(graph, v, invertGraph);
1297 
1298  QList<Vertex> verticesLst;
1299 
1300  foreach (const Vertex& candidate, search.vertices)
1301  {
1302  if ((inOrOut ? in_degree(candidate, graph)
1303  : out_degree(candidate, graph)) == 0)
1304  {
1305  verticesLst << candidate;
1306  }
1307  }
1308 
1309  return verticesLst;
1310  }
1311 
1316  class Path
1317  {
1318  public:
1319 
1320  template <class GraphType>
1321  void shortestPath(const GraphType& graph, const Vertex& v)
1322  {
1323  int weight = 1;
1324 
1325  try
1326  {
1327  boost::dag_shortest_paths(graph, v,
1329  weight_map(boost::ref_property_map<typename boost::graph_traits<GraphType>::edge_descriptor,int>(weight)).
1330 
1332  distance_map(VertexIntMapAdaptor(distances)).
1333  predecessor_map(VertexVertexMapAdaptor(predecessors))
1334  );
1335  }
1336  catch (boost::bad_graph& e)
1337  {
1338  qCDebug(DIGIKAM_DATABASE_LOG) << e.what();
1339  }
1340  }
1341 
1342  template <class GraphType>
1343  void longestPath(const GraphType& graph, const Vertex& v)
1344  {
1345  int weight = 1;
1346 
1347  try
1348  {
1349  boost::dag_shortest_paths(graph, v,
1351  weight_map(boost::ref_property_map<typename boost::graph_traits<GraphType>::edge_descriptor,int>(weight)).
1352 
1354  distance_compare(std::greater<int>()).
1355 
1357  distance_inf(-1).
1358 
1360  distance_map(VertexIntMapAdaptor(distances)).
1361  predecessor_map(VertexVertexMapAdaptor(predecessors))
1362  );
1363  }
1364  catch (boost::bad_graph& e)
1365  {
1366  qCDebug(DIGIKAM_DATABASE_LOG) << e.what();
1367  }
1368  }
1369 
1370  bool isReachable(const Vertex& v) const
1371  {
1372  return (predecessors.value(v, v) != v);
1373  }
1374 
1377  };
1378 
1380  {
1381  public:
1382 
1383  template <class GraphType>
1384  void enter(const GraphType& graph, const Vertex& v, MeaningOfDirection direction = ParentToChild)
1385  {
1386  try
1387  {
1388  if (direction == ParentToChild)
1389  {
1390  boost::lengauer_tarjan_dominator_tree(graph, v, VertexVertexMapAdaptor(predecessors));
1391  }
1392  else
1393  {
1394  boost::lengauer_tarjan_dominator_tree(boost::make_reverse_graph(graph), v,
1395  VertexVertexMapAdaptor(predecessors));
1396  }
1397  }
1398  catch (boost::bad_graph& e)
1399  {
1400  qCDebug(DIGIKAM_DATABASE_LOG) << e.what();
1401  }
1402  }
1403 
1405  };
1406 
1408  {
1409  public:
1410 
1411  template <class GraphType>
1412  void depthFirstSearch(const GraphType& graph, const Vertex& v, bool invertGraph)
1413  {
1414  // remember that the visitor is passed by value
1415 
1416  DepthFirstSearchVisitor vis(this);
1417 
1418  try
1419  {
1420  if (invertGraph)
1421  {
1422  boost::depth_first_search(boost::make_reverse_graph(graph), visitor(vis).root_vertex(v));
1423  }
1424  else
1425  {
1426  boost::depth_first_search(graph, visitor(vis).root_vertex(v));
1427  }
1428  }
1429  catch (boost::bad_graph& e)
1430  {
1431  qCDebug(DIGIKAM_DATABASE_LOG) << e.what();
1432  }
1433  }
1434 
1435  template <class GraphType, typename LessThan>
1436  void depthFirstSearchSorted(const GraphType& graph, const Vertex& v, bool invertGraph, LessThan lessThan)
1437  {
1438  // Remember that the visitor is passed by value
1439 
1440  DepthFirstSearchVisitor vis(this);
1441  std::vector<boost::default_color_type> color_vec(boost::num_vertices(graph), boost::white_color);
1442 
1443  try
1444  {
1445  if (invertGraph)
1446  {
1447  depth_first_search_sorted(boost::make_reverse_graph(graph), v, vis,
1448  make_iterator_property_map(color_vec.begin(), get(boost::vertex_index, graph)), lessThan);
1449  }
1450  else
1451  {
1452  depth_first_search_sorted(graph, v, vis,
1453  make_iterator_property_map(color_vec.begin(), get(boost::vertex_index, graph)), lessThan);
1454  }
1455  }
1456  catch (boost::bad_graph& e)
1457  {
1458  qCDebug(DIGIKAM_DATABASE_LOG) << e.what();
1459  }
1460  }
1461 
1462  template <class GraphType>
1463  void breadthFirstSearch(const GraphType& graph, const Vertex& v, bool invertGraph)
1464  {
1465  BreadthFirstSearchVisitor vis(this);
1466 
1467  try
1468  {
1469  if (invertGraph)
1470  {
1471  boost::breadth_first_search(boost::make_reverse_graph(graph), v, visitor(vis));
1472  }
1473  else
1474  {
1475  boost::breadth_first_search(graph, v, visitor(vis));
1476  }
1477  }
1478  catch (boost::bad_graph& e)
1479  {
1480  qCDebug(DIGIKAM_DATABASE_LOG) << e.what();
1481  }
1482  }
1483 
1485  {
1486  protected:
1487 
1488  explicit CommonVisitor(GraphSearch* const q)
1489  : q(q)
1490  {
1491  }
1492 
1493  void record(const Vertex& v) const
1494  {
1495  q->vertices << v;
1496  }
1497 
1498  GraphSearch* const q;
1499  };
1500 
1501  class DepthFirstSearchVisitor : public boost::default_dfs_visitor,
1502  public CommonVisitor
1503  {
1504  public:
1505 
1507  : CommonVisitor(q)
1508  {
1509  }
1510 
1511  template <typename VertexType, typename GraphType>
1512  void discover_vertex(VertexType u, const GraphType&) const
1513  {
1514  this->record(u);
1515  }
1516  };
1517 
1518  class BreadthFirstSearchVisitor : public boost::default_bfs_visitor,
1519  public CommonVisitor
1520  {
1521  public:
1522 
1524  : CommonVisitor(q)
1525  {
1526  }
1527 
1528  template <typename VertexType, typename GraphType>
1529  void discover_vertex(VertexType u, const GraphType&) const
1530  {
1531  this->record(u);
1532  }
1533  };
1534 
1536 
1537  protected:
1538 
1539  template <class GraphType, typename VertexLessThan>
1541  {
1542  typedef typename boost::graph_traits<GraphType>::edge_descriptor edge_descriptor;
1543 
1544  public:
1545 
1546  lessThanMapEdgeToTarget(const GraphType& g, VertexLessThan vertexLessThan)
1547  : g (g),
1548  vertexLessThan(vertexLessThan)
1549  {
1550  }
1551 
1552  bool operator()(const edge_descriptor& a, const edge_descriptor& b)
1553  {
1554  return vertexLessThan(boost::target(a, g), boost::target(b, g));
1555  }
1556 
1557  public:
1558 
1559  const GraphType& g;
1560  VertexLessThan vertexLessThan;
1561  };
1562 
1564  template <class IncidenceGraph, class DFSVisitor, class ColorMap, typename LessThan>
1565  void depth_first_search_sorted(const IncidenceGraph& g,
1566  Vertex u,
1567  DFSVisitor& vis,
1568  ColorMap color,
1569  LessThan lessThan)
1570  {
1571  //typedef std::pair<Vertex, QList<Edge> > VertexInfo;
1572 
1573  typedef typename boost::graph_traits<IncidenceGraph>::edge_descriptor edge_descriptor;
1574  QList<edge_descriptor> outEdges;
1575 /*
1576  std::vector<VertexInfo> stack;
1577 */
1578  boost::put(color, u, boost::gray_color);
1579  vis.discover_vertex(u, g);
1580 
1581  outEdges = toList<edge_descriptor>(boost::out_edges(u, g));
1582 
1587  std::sort(outEdges.begin(),
1588  outEdges.end(),
1590 
1591  foreach (const edge_descriptor& e, outEdges)
1592  {
1593  Vertex v = boost::target(e, g);
1594  vis.examine_edge(e, g);
1595  boost::default_color_type v_color = boost::get(color, v);
1596 
1597  if (v_color == boost::white_color)
1598  {
1599  vis.tree_edge(e, g);
1600  depth_first_search_sorted(g, v, vis, color, lessThan);
1601  }
1602  else if (v_color == boost::gray_color)
1603  {
1604  vis.back_edge(e, g);
1605  }
1606  else
1607  {
1608  vis.forward_or_cross_edge(e, g);
1609  }
1610  }
1611 
1612  put(color, u, boost::black_color);
1613  vis.finish_vertex(u, g);
1614  }
1615  };
1616 
1621  {
1622  typename VertexIntMap::const_iterator it;
1623  int maxDist = 1;
1624  QList<Vertex> candidates;
1625 
1626  for (it = distances.begin() ; it != distances.end() ; ++it)
1627  {
1628  if (it.value() > maxDist)
1629  {
1630  maxDist = it.value();
1631 
1632  //qDebug() << "Increasing maxDist to" << maxDist;
1633 
1634  candidates.clear();
1635  }
1636 
1637  if (it.value() >= maxDist)
1638  {
1639  //qDebug() << "Adding candidate" << id(it.key()) << "at distance" << maxDist;
1640 
1641  candidates << it.key();
1642  }
1643 
1644 /*
1645  if (it.value() == -1)
1646  {
1647  qDebug() << id(it.key()) << "unreachable";
1648  }
1649  else
1650  {
1651  qDebug() << "Distance to" << id(it.key()) << "is" << it.value();
1652  }
1653 */
1654  }
1655 
1656  return candidates;
1657  }
1658 
1664  const Vertex& target,
1665  const VertexVertexMap& predecessors,
1666  MeaningOfDirection dir = ParentToChild) const
1667  {
1668  QList<Vertex> verticesLst;
1669 
1670  for (Vertex v = root ; v != target ; v = predecessors.value(v))
1671  {
1672  //qDebug() << "Adding waypoint" << id(v);
1673 
1674  if (dir == ParentToChild)
1675  {
1676  verticesLst.append(v);
1677  }
1678  else
1679  {
1680  verticesLst.prepend(v);
1681  }
1682 
1683  // If a node is not reachable, it seems its entry in the predecessors map is itself
1684  // Avoid endless loop
1685 
1686  if (predecessors.value(v) == v)
1687  {
1688  break;
1689  }
1690  }
1691 
1692  return verticesLst;
1693  }
1694 
1695 protected:
1696 
1699 };
1700 
1701 } // namespace Digikam
1702 
1703 // Restore warnings
1704 #if !defined(Q_OS_DARWIN) && defined(Q_CC_GNU)
1705 # pragma GCC diagnostic pop
1706 #endif
1707 
1708 #if defined(Q_CC_CLANG)
1709 # pragma clang diagnostic pop
1710 #endif
1711 
1712 #endif // DIGIKAM_ITEM_HISTORY_GRAPH_BOOST_H
Definition: itemhistorygraph_boost.h:1380
VertexVertexMap predecessors
Definition: itemhistorygraph_boost.h:1404
void enter(const GraphType &graph, const Vertex &v, MeaningOfDirection direction=ParentToChild)
Definition: itemhistorygraph_boost.h:1384
Definition: itemhistorygraph_boost.h:226
Edge(const edge_t &e)
Definition: itemhistorygraph_boost.h:235
const edge_t & toEdge() const
Definition: itemhistorygraph_boost.h:259
edge_t & toEdge()
Definition: itemhistorygraph_boost.h:264
edge_t e
Definition: itemhistorygraph_boost.h:281
Edge & operator=(const edge_t &other)
Definition: itemhistorygraph_boost.h:241
bool operator==(const edge_t &other) const
Definition: itemhistorygraph_boost.h:269
bool isNull() const
Definition: itemhistorygraph_boost.h:274
Edge()
Definition: itemhistorygraph_boost.h:229
Definition: itemhistorygraph_boost.h:1520
void discover_vertex(VertexType u, const GraphType &) const
Definition: itemhistorygraph_boost.h:1529
BreadthFirstSearchVisitor(GraphSearch *const q)
Definition: itemhistorygraph_boost.h:1523
Definition: itemhistorygraph_boost.h:1485
CommonVisitor(GraphSearch *const q)
Definition: itemhistorygraph_boost.h:1488
void record(const Vertex &v) const
Definition: itemhistorygraph_boost.h:1493
GraphSearch *const q
Definition: itemhistorygraph_boost.h:1498
Definition: itemhistorygraph_boost.h:1503
void discover_vertex(VertexType u, const GraphType &) const
Definition: itemhistorygraph_boost.h:1512
DepthFirstSearchVisitor(GraphSearch *const q)
Definition: itemhistorygraph_boost.h:1506
Definition: itemhistorygraph_boost.h:1541
VertexLessThan vertexLessThan
Definition: itemhistorygraph_boost.h:1560
bool operator()(const edge_descriptor &a, const edge_descriptor &b)
Definition: itemhistorygraph_boost.h:1552
const GraphType & g
Definition: itemhistorygraph_boost.h:1559
lessThanMapEdgeToTarget(const GraphType &g, VertexLessThan vertexLessThan)
Definition: itemhistorygraph_boost.h:1546
Definition: itemhistorygraph_boost.h:1408
void depth_first_search_sorted(const IncidenceGraph &g, Vertex u, DFSVisitor &vis, ColorMap color, LessThan lessThan)
This is boost's simple, old, recursive DFS algorithm adapted with lessThan.
Definition: itemhistorygraph_boost.h:1565
QList< Vertex > vertices
Definition: itemhistorygraph_boost.h:1535
void depthFirstSearchSorted(const GraphType &graph, const Vertex &v, bool invertGraph, LessThan lessThan)
Definition: itemhistorygraph_boost.h:1436
void breadthFirstSearch(const GraphType &graph, const Vertex &v, bool invertGraph)
Definition: itemhistorygraph_boost.h:1463
void depthFirstSearch(const GraphType &graph, const Vertex &v, bool invertGraph)
Definition: itemhistorygraph_boost.h:1412
Definition: itemhistorygraph_boost.h:1317
VertexIntMap distances
Definition: itemhistorygraph_boost.h:1376
VertexVertexMap predecessors
Definition: itemhistorygraph_boost.h:1375
void longestPath(const GraphType &graph, const Vertex &v)
Definition: itemhistorygraph_boost.h:1343
bool isReachable(const Vertex &v) const
Definition: itemhistorygraph_boost.h:1370
void shortestPath(const GraphType &graph, const Vertex &v)
Definition: itemhistorygraph_boost.h:1321
Definition: itemhistorygraph_boost.h:179
Vertex()
Definition: itemhistorygraph_boost.h:182
vertex_t v
Definition: itemhistorygraph_boost.h:222
Vertex(const vertex_t &v)
Definition: itemhistorygraph_boost.h:188
bool operator==(const vertex_t &other) const
Definition: itemhistorygraph_boost.h:210
Vertex & operator=(const vertex_t &other)
Definition: itemhistorygraph_boost.h:193
bool isNull() const
Definition: itemhistorygraph_boost.h:215
Definition: itemhistorygraph_boost.h:130
std::pair< vertex_iter, vertex_iter > vertex_range_t
Definition: itemhistorygraph_boost.h:164
void clear()
Definition: itemhistorygraph_boost.h:328
boost::adjacency_list< boost::vecS, boost::vecS, boost::bidirectionalS, boost::property< boost::vertex_index_t, int, boost::property< vertex_properties_t, VertexProperties > >, boost::property< edge_properties_t, EdgeProperties > > GraphContainer
Definition: itemhistorygraph_boost.h:140
QList< Vertex > longestPathTouching(const Vertex &v, LessThan lessThan) const
Definition: itemhistorygraph_boost.h:799
QList< Vertex > mostRemoteNodes(const VertexIntMap &distances) const
Definition: itemhistorygraph_boost.h:1620
QMapForAdaptors< Vertex, Vertex > VertexVertexMap
Definition: itemhistorygraph_boost.h:292
QList< Vertex > longestPathTouching(const Vertex &v) const
Definition: itemhistorygraph_boost.h:793
Graph(const Graph &g)
Definition: itemhistorygraph_boost.h:305
bool hasEdge(const Vertex &v1, const Vertex &v2) const
Definition: itemhistorygraph_boost.h:383
bool isEmpty() const
Definition: itemhistorygraph_boost.h:525
MeaningOfDirection meaningOfDirection() const
Definition: itemhistorygraph_boost.h:323
VertexProperties & properties(const Vertex &v)
Definition: itemhistorygraph_boost.h:414
QList< Vertex > verticesDominatedBy(const Vertex &v, const Vertex &root, const QList< Vertex > &presortedVertices) const
Definition: itemhistorygraph_boost.h:967
QMap< Vertex, int > shortestDistancesFrom(const Vertex &v) const
Definition: itemhistorygraph_boost.h:885
QList< Vertex > findZeroDegree(bool inOrOut) const
Definition: itemhistorygraph_boost.h:1269
QPair< Edge, Edge > EdgePair
Definition: itemhistorygraph_boost.h:290
boost::property_map< GraphContainer, vertex_properties_t >::const_type const_vertex_property_map_t
Definition: itemhistorygraph_boost.h:170
void remove(const Vertex &v)
Definition: itemhistorygraph_boost.h:348
bool isLeaf(const Vertex &v) const
Definition: itemhistorygraph_boost.h:545
boost::property_map< GraphContainer, edge_properties_t >::const_type const_edge_property_map_t
Definition: itemhistorygraph_boost.h:172
QList< Vertex > findZeroDegreeFrom(const Vertex &v, bool inOrOut) const
Definition: itemhistorygraph_boost.h:1286
QList< VertexPair > edgePairs() const
Definition: itemhistorygraph_boost.h:637
Vertex target(const Edge &e) const
Definition: itemhistorygraph_boost.h:555
QList< Vertex > treeFromPredecessors(const Vertex &v, const VertexVertexMap &predecessors) const
Definition: itemhistorygraph_boost.h:1125
boost::property_map< GraphContainer, vertex_properties_t >::type vertex_property_map_t
Definition: itemhistorygraph_boost.h:169
std::pair< edge_iter, edge_iter > edge_range_t
Definition: itemhistorygraph_boost.h:165
AdjacencyFlags
Definition: itemhistorygraph_boost.h:480
GraphCopyFlags
Definition: itemhistorygraph_boost.h:676
QList< Vertex > roots() const
Definition: itemhistorygraph_boost.h:753
const VertexProperties & properties(const Vertex &v) const
Definition: itemhistorygraph_boost.h:409
graph_traits::vertex_descriptor vertex_t
Definition: itemhistorygraph_boost.h:147
boost::inv_adjacency_iterator_generator< GraphContainer, vertex_t, in_edge_iter >::type inv_adjacency_iter
Definition: itemhistorygraph_boost.h:157
QList< Edge > edgeDifference(const Graph &other, const std::vector< vertex_t > &copiedVertices) const
Definition: itemhistorygraph_boost.h:1237
QList< Vertex > topologicalSort() const
Definition: itemhistorygraph_boost.h:655
boost::graph_traits< GraphContainer > graph_traits
Definition: itemhistorygraph_boost.h:145
static QList< Edge > toEdgeList(const range_t &range)
Definition: itemhistorygraph_boost.h:1169
void setProperties(const Vertex &v, const VertexProperties &props)
Definition: itemhistorygraph_boost.h:404
int edgeCount() const
Definition: itemhistorygraph_boost.h:589
boost::property_map< GraphContainer, boost::vertex_index_t >::const_type const_vertex_index_map_t
Definition: itemhistorygraph_boost.h:168
int outDegree(const Vertex &v) const
Definition: itemhistorygraph_boost.h:530
Edge edge(const Vertex &v1, const Vertex &v2) const
Definition: itemhistorygraph_boost.h:371
QList< Vertex > leaves() const
Definition: itemhistorygraph_boost.h:772
EdgeProperties properties(const Vertex &v1, const Vertex &v2) const
Definition: itemhistorygraph_boost.h:444
graph_traits::vertex_iterator vertex_iter
Definition: itemhistorygraph_boost.h:150
QMapForAdaptors< Vertex, int > VertexIntMap
Definition: itemhistorygraph_boost.h:293
QList< Vertex > rootsOf(const Vertex &v) const
Definition: itemhistorygraph_boost.h:763
MeaningOfDirection direction
Definition: itemhistorygraph_boost.h:1698
bool isRoot(const Vertex &v) const
Definition: itemhistorygraph_boost.h:540
void treeFromPredecessorsRecursive(const Vertex &v, QList< Vertex > &vertices, const VertexVertexMap &predecessors) const
Definition: itemhistorygraph_boost.h:1134
std::pair< inv_adjacency_iter, inv_adjacency_iter > inv_adjacency_vertex_range_t
Definition: itemhistorygraph_boost.h:162
QList< Vertex > vertices() const
Definition: itemhistorygraph_boost.h:474
graph_traits::edge_iterator edge_iter
Definition: itemhistorygraph_boost.h:151
QPair< Vertex, Vertex > VertexPair
Definition: itemhistorygraph_boost.h:289
static QList< Value > toList(const range_t &range)
Definition: itemhistorygraph_boost.h:1151
bool hasEdges() const
Definition: itemhistorygraph_boost.h:627
int inDegree(const Vertex &v) const
Definition: itemhistorygraph_boost.h:535
Graph transitiveClosure(GraphCopyFlags flags=CopyAllProperties) const
Definition: itemhistorygraph_boost.h:685
std::pair< out_edge_iter, out_edge_iter > out_edge_range_t
Definition: itemhistorygraph_boost.h:163
QList< Vertex > verticesDominatedBy(const Vertex &v, const Vertex &root, ReturnOrder order=BreadthFirstOrder) const
Definition: itemhistorygraph_boost.h:924
graph_traits::out_edge_iterator out_edge_iter
Definition: itemhistorygraph_boost.h:153
graph_traits::degree_size_type degree_t
Definition: itemhistorygraph_boost.h:159
QList< Vertex > verticesBreadthFirst(const Vertex &givenRef=Vertex()) const
Definition: itemhistorygraph_boost.h:1001
void copyProperties(Graph &other, GraphCopyFlags flags, const std::vector< vertex_t > &copiedVertices) const
Definition: itemhistorygraph_boost.h:1184
int vertexCount() const
NOTE: for "hasAdjacentVertices", simply use hasEdges(v, flags)
Definition: itemhistorygraph_boost.h:520
static QList< Vertex > toVertexList(const range_t &range)
Definition: itemhistorygraph_boost.h:1164
Vertex findVertexByProperties(const T &value) const
Definition: itemhistorygraph_boost.h:425
boost::property_map< GraphContainer, boost::vertex_index_t >::type vertex_index_map_t
Definition: itemhistorygraph_boost.h:167
std::pair< adjacency_iter, adjacency_iter > adjacency_vertex_range_t
Definition: itemhistorygraph_boost.h:161
boost::associative_property_map< VertexIntMap > VertexIntMapAdaptor
Definition: itemhistorygraph_boost.h:296
boost::property_map< GraphContainer, edge_properties_t >::type edge_property_map_t
Definition: itemhistorygraph_boost.h:171
Edge addEdge(const Vertex &v1, const Vertex &v2)
Definition: itemhistorygraph_boost.h:359
ReturnOrder
Definition: itemhistorygraph_boost.h:914
@ BreadthFirstOrder
Definition: itemhistorygraph_boost.h:915
bool hasEdges(const Vertex &v, AdjacencyFlags flags=AllEdges) const
Definition: itemhistorygraph_boost.h:594
bool isConnected(const Vertex &v1, const Vertex &v2) const
Does not care for direction.
Definition: itemhistorygraph_boost.h:389
void setProperties(const Edge &e, const EdgeProperties &props)
Definition: itemhistorygraph_boost.h:419
static bool alwaysFalse(const T &, const T &)
Definition: itemhistorygraph_boost.h:782
graph_traits::edge_descriptor edge_t
Definition: itemhistorygraph_boost.h:148
GraphContainer graph
Definition: itemhistorygraph_boost.h:1697
boost::associative_property_map< VertexVertexMap > VertexVertexMapAdaptor
Definition: itemhistorygraph_boost.h:295
QList< Vertex > shortestPath(const Vertex &v1, const Vertex &v2) const
Definition: itemhistorygraph_boost.h:848
Graph(MeaningOfDirection direction=ParentToChild)
Definition: itemhistorygraph_boost.h:300
graph_traits::in_edge_iterator in_edge_iter
Definition: itemhistorygraph_boost.h:154
const EdgeProperties & properties(const Edge &e) const
Definition: itemhistorygraph_boost.h:456
EdgeProperties & properties(const Edge &e)
Definition: itemhistorygraph_boost.h:461
QList< Vertex > verticesDepthFirstSorted(const Vertex &givenRef, LessThan lessThan) const
Definition: itemhistorygraph_boost.h:1087
static bool isEmptyRange(const range_t &range)
Definition: itemhistorygraph_boost.h:1175
Vertex addVertex(const VertexProperties &properties)
Definition: itemhistorygraph_boost.h:340
graph_traits::adjacency_iterator adjacency_iter
Definition: itemhistorygraph_boost.h:152
QList< Vertex > adjacentVertices(const Vertex &v, AdjacencyFlags flags=AllEdges) const
Definition: itemhistorygraph_boost.h:490
const GraphContainer & getGraph() const
Definition: itemhistorygraph_boost.h:469
QList< Vertex > leavesFrom(const Vertex &v) const
Definition: itemhistorygraph_boost.h:777
QList< Vertex > verticesDominatedByDepthFirstSorted(const Vertex &v, const Vertex &root, LessThan lessThan) const
Definition: itemhistorygraph_boost.h:953
virtual ~Graph()
Definition: itemhistorygraph_boost.h:311
Graph & operator=(const Graph &other)
Definition: itemhistorygraph_boost.h:315
QList< Vertex > listPath(const Vertex &root, const Vertex &target, const VertexVertexMap &predecessors, MeaningOfDirection dir=ParentToChild) const
Definition: itemhistorygraph_boost.h:1663
Vertex addVertex()
Definition: itemhistorygraph_boost.h:333
QList< Edge > edges() const
Definition: itemhistorygraph_boost.h:632
QList< Edge > edges(const Vertex &v, AdjacencyFlags flags=AllEdges) const
Definition: itemhistorygraph_boost.h:560
Graph transitiveReduction(QList< Edge > *removedEdges=0, GraphCopyFlags flags=CopyAllProperties) const
Definition: itemhistorygraph_boost.h:719
Vertex source(const Edge &e) const
Definition: itemhistorygraph_boost.h:550
Definition: itemhistorygraph_boost.h:102
Key key_type
Definition: itemhistorygraph_boost.h:105
QMapForAdaptors()
Definition: itemhistorygraph_boost.h:109
Value data_type
Definition: itemhistorygraph_boost.h:106
std::pair< const Key, Value > value_type
Definition: itemhistorygraph_boost.h:107
Definition: piwigotalker.h:48
edge_properties_t
Definition: itemhistorygraph_boost.h:85
@ edge_properties
Definition: itemhistorygraph_boost.h:85
vertex_properties_t
Definition: itemhistorygraph_boost.h:84
@ vertex_properties
Definition: itemhistorygraph_boost.h:84
qulonglong value
Definition: itemviewutilities.cpp:592
#define T
@ LessThan
Definition: coredbsearchxml.h:71
Definition: datefolderview.cpp:43
MeaningOfDirection
Definition: itemhistorygraph_boost.h:120
@ ParentToChild
Edges are directed from a parent to its child.
Definition: itemhistorygraph_boost.h:121
@ ChildToParent
Edges are direct from a child to its parent.
Definition: itemhistorygraph_boost.h:122