COIN-OR::LEMON - Graph Library

source: lemon-0.x/src/lemon/concept/graph_component.h @ 962:1a770e9f80b2

Last change on this file since 962:1a770e9f80b2 was 962:1a770e9f80b2, checked in by Mihaly Barasz, 15 years ago

Undirect graph implementation.
Not yet done, untested.

File size: 21.3 KB
Line 
1/* -*- C++ -*-
2 * src/lemon/concept/graph_component.h - Part of LEMON, a generic C++ optimization library
3 *
4 * Copyright (C) 2004 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
5 * (Egervary Combinatorial Optimization Research Group, EGRES).
6 *
7 * Permission to use, modify and distribute this software is granted
8 * provided that this copyright notice appears in all copies. For
9 * precise terms see the accompanying LICENSE file.
10 *
11 * This software is provided "AS IS" with no warranty of any kind,
12 * express or implied, and with no claim as to its suitability for any
13 * purpose.
14 *
15 */
16
17///\ingroup concept
18///\file
19///\brief The graph components.
20
21
22#ifndef LEMON_CONCEPT_GRAPH_COMPONENT_H
23#define LEMON_CONCEPT_GRAPH_COMPONENT_H
24
25#include <lemon/invalid.h>
26#include <lemon/concept/maps.h>
27
28namespace lemon {
29  namespace concept {
30
31
32    /****************   Graph iterator concepts   ****************/
33
34    /// Skeleton class for graph Node and Edge
35
36    /// \note Because Node and Edge are forbidden to inherit from the same
37    /// base class, this is a template. For Node you shoul instantiate it
38    /// with character 'n' and for Edge with 'e'.
39
40    template<char Ch>
41    class GraphItem {
42    public:
43      GraphItem() {}
44      GraphItem(Invalid) {}
45
46      // We explicitely list these:
47      GraphItem(GraphItem const&) {}
48      GraphItem& operator=(GraphItem const&) { return *this; }
49
50      bool operator==(GraphItem) const { return false; }
51      bool operator!=(GraphItem) const { return false; }
52
53      // Technical requirement. Do we really need this?
54      bool operator<(GraphItem) const { return false; }
55    };
56
57
58    template<typename GI>
59    struct GraphItemConcept {
60      void constraints() {
61        GI i1;
62        GI i2 = i1;
63        GI i3 = INVALID;
64       
65        i1 = i2 = i3;
66
67        bool b;
68        b = (ia == ib) && (ia != ib) && (ia < ib);
69        b = (ia == INVALID) && (ib != INVALID);
70      }
71
72      const GI &ia;
73      const GI &ib;
74    };
75
76
77    template<typename Iter, typename Graph, typename BaseItem>
78    struct GraphIteratorConcept {
79      void constraints() {
80        function_requires< GraphItemConcept<Iter> >();
81        Iter it1(g);
82
83        /// \todo Do we need NodeIt(Node) kind of constructor?
84        //      Iter it2(bj);
85        Iter it2;
86
87        it2 = ++it1;
88        ++it2 = it1;
89        ++(++it1);
90        /// \bug This should be: is_base_and_derived<BaseItem, Iter>
91        BaseItem bi = it1;
92        bi = it2;
93      }
94
95      BaseItem bj;
96      Graph g;
97    };
98
99    template<typename Iter, typename Graph>
100    struct GraphIncIteratorConcept {
101      typedef typename Graph::Node Node;
102      typedef typename Graph::Edge Edge;
103      void constraints() {
104        function_requires< GraphItemConcept<Iter> >();
105        Iter it1(graph, node);
106        /// \todo Do we need OutEdgeIt(Edge) kind of constructor?
107        //      Iter it2(edge);
108        Iter it2;
109
110        it2 = ++it1;
111        ++it2 = it1;
112        ++(++it1);
113        Edge e = it1;
114        e = it2;
115      }
116
117      Edge edge;
118      Node node;
119      Graph graph;
120    };
121
122
123
124    /// An empty base graph class.
125 
126    /// This class provides the minimal set of features needed for a graph
127    /// structure. All graph concepts have to be conform to this base
128    /// graph.
129    ///
130    /// \bug This is not true. The minimal graph concept is the
131    /// BaseIterableGraphComponent.
132
133    class BaseGraphComponent {
134    public:
135
136      typedef BaseGraphComponent Graph;
137     
138      /// Node class of the graph.
139
140      /// This class represents the Nodes of the graph.
141      ///
142      class Node {
143      public:
144
145        /// Default constructor.
146
147        /// @warning The default constructor sets the iterator
148        /// to an undefined value.
149
150        Node() {}
151        /// Copy constructor.
152
153        /// Copy constructor.
154        ///
155        Node(const Node&) {}
156
157        /// Invalid constructor \& conversion.
158
159        /// This constructor initializes the iterator to be invalid.
160        /// \sa Invalid for more details.
161        Node(Invalid) {}
162
163
164        Node& operator=(const Node&) { return *this;}
165
166        /// Equality operator.
167
168        /// Two iterators are equal if and only if they represents the
169        /// same node in the graph or both are invalid.
170        bool operator==(const Node&) const { return true;}
171
172
173        /// Inequality operator.
174       
175        /// \sa operator==(const Node& n)
176        ///
177        bool operator!=(const Node&) const { return true;}
178
179        /// Comparison operator.
180
181        /// This is a strict ordering between the nodes.
182        ///
183        /// This ordering can be different from the iterating order of nodes.
184        /// \todo Possibly we don't need it.
185        bool operator<(const Node&) const { return true;}
186      };
187
188      /// Edge class of the graph.
189
190      /// This class represents the Edges of the graph.
191      ///
192      class Edge {
193      public:
194
195        /// Default constructor.
196
197        /// @warning The default constructor sets the iterator
198        /// to an undefined value.
199
200        Edge() {}
201        /// Copy constructor.
202
203        /// Copy constructor.
204        ///
205        Edge(const Edge&) {}
206
207        /// Invalid constructor \& conversion.
208
209        /// This constructor initializes the iterator to be invalid.
210        /// \sa Invalid for more details.
211        Edge(Invalid) {}
212
213
214        Edge& operator=(const Edge&) { return *this;}
215
216        /// Equality operator.
217
218        /// Two iterators are equal if and only if they represents the
219        /// same edge in the graph or both are invalid.
220        bool operator==(const Edge&) const { return true;}
221
222
223        /// Inequality operator.
224       
225        /// \sa operator==(const Edge& n)
226        ///
227        bool operator!=(const Edge&) const { return true;}
228
229        /// Comparison operator.
230
231        /// This is a strict ordering between the edges.
232        ///
233        /// This ordering can be different from the iterating order of edges.
234        /// \todo Possibly we don't need it.
235        bool operator<(const Edge&) const { return true;}
236      };
237
238      ///Gives back the head node of an edge.
239
240      ///Gives back the head node of an edge.
241      ///
242      Node head(const Edge&) const { return INVALID;}
243
244      ///Gives back the tail node of an edge.
245
246      ///Gives back the tail node of an edge.
247      ///
248      Node tail(const Edge&) const { return INVALID;}
249    };
250
251
252    /// Concept check structure for BaseGraph.
253
254    /// Concept check structure for BaseGraph.
255    ///
256
257    template <typename Graph>
258    struct BaseGraphComponentConcept {
259      typedef typename Graph::Node Node;
260      typedef typename Graph::Edge Edge;
261     
262      void constraints() {
263        function_requires< GraphItemConcept<Node> >();
264        function_requires< GraphItemConcept<Edge> >();
265        {
266          Node n;
267          Edge e;
268          n = graph.tail(e);
269          n = graph.head(e);
270        }     
271      }
272     
273      const Graph& graph;
274    };
275
276    /// An empty iterable base graph class.
277 
278    /// This class provides beside the core graph features
279    /// core iterable interface for the graph structure.
280    /// Most of the base graphs should be conform to this concept.
281
282    class BaseIterableGraphComponent : virtual public BaseGraphComponent {
283    public:
284
285      typedef BaseGraphComponent::Node Node;
286      typedef BaseGraphComponent::Edge Edge;
287
288      /// Gives back the first Node in the iterating order.
289     
290      /// Gives back the first Node in the iterating order.
291      ///     
292      void first(Node&) const {}
293
294      /// Gives back the next Node in the iterating order.
295     
296      /// Gives back the next Node in the iterating order.
297      ///     
298      void next(Node&) const {}
299
300      /// Gives back the first Edge in the iterating order.
301     
302      /// Gives back the first Edge in the iterating order.
303      ///     
304      void first(Edge&) const {}
305      /// Gives back the next Edge in the iterating order.
306     
307      /// Gives back the next Edge in the iterating order.
308      ///     
309      void next(Edge&) const {}
310
311
312      /// Gives back the first of the Edges point to the given Node.
313     
314      /// Gives back the first of the Edges point to the given Node.
315      ///     
316      void firstIn(Edge&, const Node&) const {}
317
318      /// Gives back the next of the Edges points to the given Node.
319
320
321      /// Gives back the next of the Edges points to the given Node.
322      ///
323      void nextIn(Edge&) const {}
324
325      /// Gives back the first of the Edges start from the given Node.
326     
327      /// Gives back the first of the Edges start from the given Node.
328      ///     
329      void firstOut(Edge&, const Node&) const {}
330
331      /// Gives back the next of the Edges start from the given Node.
332     
333      /// Gives back the next of the Edges start from the given Node.
334      ///     
335      void nextOut(Edge&) const {}
336    };
337
338
339    /// Concept check structure for IterableBaseGraph.
340
341    /// Concept check structure for IterableBaseGraph.
342    ///
343    template <typename Graph>
344    struct BaseIterableGraphComponentConcept {
345     
346      void constraints() {
347        function_requires< BaseGraphComponentConcept<Graph> >();
348        typename Graph::Node node;     
349        typename Graph::Edge edge;
350        {
351          graph.first(node);
352          graph.next(node);
353        }
354        {
355          graph.first(edge);
356          graph.next(edge);
357        }
358        {
359          graph.firstIn(edge, node);
360          graph.nextIn(edge);
361        }
362        {
363          graph.firstOut(edge, node);
364          graph.nextOut(edge);
365        }
366      }
367
368      const Graph& graph;
369    };
370
371    /// An empty idable base graph class.
372 
373    /// This class provides beside the core graph features
374    /// core id functions for the graph structure.
375    /// The most of the base graphs should be conform to this concept.
376    /// The id's are unique and immutable.
377
378    class IDableGraphComponent : virtual public BaseGraphComponent {
379    public:
380
381      typedef BaseGraphComponent::Node Node;
382      typedef BaseGraphComponent::Edge Edge;
383
384      /// Gives back an unique integer id for the Node.
385
386      /// Gives back an unique integer id for the Node.
387      ///
388      int id(const Node&) const { return -1;}
389
390      /// Gives back an unique integer id for the Edge.
391
392      /// Gives back an unique integer id for the Edge.
393      ///
394      int id(const Edge&) const { return -1;}
395    };
396
397
398    /// Concept check structure for IdableBaseGraph.
399
400    /// Concept check structure for IdableBaseGraph.
401    ///
402    template <typename Graph>
403    struct IDableGraphComponentConcept {
404
405      void constraints() {
406        function_requires< BaseGraphComponentConcept<Graph> >();
407        typename Graph::Node node;
408        int nid = graph.id(node);
409        nid = graph.id(node);
410        typename Graph::Edge edge;
411        int eid = graph.id(edge);
412        eid = graph.id(edge);
413      }
414
415      const Graph& graph;
416    };
417
418
419    /// An empty max-idable base graph class.
420 
421    /// This class provides beside the core graph features
422    /// core max id functions for the graph structure.
423    /// The most of the base graphs should be conform to this concept.
424    /// The id's are unique and immutable.
425    class MaxIDableGraphComponent : virtual public BaseGraphComponent {
426    public:
427
428      /// Gives back an integer greater or equal to the maximum Node id.
429
430      /// Gives back an integer greater or equal to the maximum Node id.
431      ///
432      int maxEdgeId() const { return -1;}
433
434      /// Gives back an integer greater or equal to the maximum Edge id.
435
436      /// Gives back an integer greater or equal to the maximum Edge id.
437      ///
438      int maxNodeId() const { return -1;}
439    };
440
441    /// Concept check structure for MaxIdableBaseGraph.
442
443    /// Concept check structure for MaxIdableBaseGraph.
444    ///
445    template <typename Graph>
446    struct MaxIDableGraphComponentConcept {
447
448      void constraints() {
449        function_requires< BaseGraphComponentConcept<Graph> >();
450        int nid = graph.maxEdgeId();
451        ignore_unused_variable_warning(nid);
452        int eid = graph.maxNodeId();
453        ignore_unused_variable_warning(eid);
454      }
455
456      const Graph& graph;
457    };
458
459    /// An empty extendable base graph class.
460 
461    /// This class provides beside the core graph features
462    /// core graph extend interface for the graph structure.
463    /// The most of the base graphs should be conform to this concept.
464    class BaseExtendableGraphComponent : virtual public BaseGraphComponent {
465    public:
466
467      typedef BaseGraphComponent::Node Node;
468      typedef BaseGraphComponent::Edge Edge;
469
470      /// Adds a new Node to the graph.
471
472      /// Adds a new Node to the graph.
473      ///
474      Node addNode() {
475        return INVALID;
476      }
477   
478      /// Adds a new Edge connects the two Nodes to the graph.
479
480      /// Adds a new Edge connects the two Nodes to the graph.
481      ///
482      Edge addEdge(const Node& from, const Node& to) {
483        return INVALID;
484      }
485
486    };
487
488    /// Concept check structure for ExtendableBaseGraph.
489
490    /// Concept check structure for ExtendableBaseGraph.
491    ///
492    template <typename Graph>
493    struct BaseExtendableGraphComponentConcept {
494      void constraints() {
495        function_requires< BaseGraphComponentConcept<Graph> >();
496        typename Graph::Node node_a, node_b;
497        node_a = graph.addNode();
498        typename Graph::Edge edge;
499        edge = graph.addEdge(node_a, node_b);
500      }
501
502      Graph& graph;
503    };
504
505    /// An empty erasable base graph class.
506 
507    /// This class provides beside the core graph features
508    /// core erase functions for the graph structure.
509    /// The most of the base graphs should be conform to this concept.
510    class BaseErasableGraphComponent : virtual public BaseGraphComponent {
511    public:
512
513      typedef BaseGraphComponent::Node Node;
514      typedef BaseGraphComponent::Edge Edge;
515
516      /// Erase a Node from the graph.
517     
518      /// Erase a Node from the graph. This function should not
519      /// erase edges connecting to the Node.
520      void erase(const Node&) {}   
521
522      /// Erase an Edge from the graph.
523
524      /// Erase an Edge from the graph.
525      ///
526      void erase(const Edge&) {}
527
528    };
529
530    /// Concept check structure for ErasableBaseGraph.
531
532    /// Concept check structure for ErasableBaseGraph.
533    ///
534    template <typename Graph>
535    struct BaseErasableGraphComponentConcept {
536      void constraints() {
537        function_requires< BaseGraphComponentConcept<Graph> >();
538        typename Graph::Node node;
539        graph.erase(node);
540        typename Graph::Edge edge;
541        graph.erase(edge);
542      }
543
544      Graph& graph;
545    };
546
547    /// An empty clearable base graph class.
548 
549    /// This class provides beside the core graph features
550    /// core clear functions for the graph structure.
551    /// The most of the base graphs should be conform to this concept.
552    class BaseClearableGraphComponent : virtual public BaseGraphComponent {
553    public:
554
555      /// Erase all the Nodes and Edges from the graph.
556
557      /// Erase all the Nodes and Edges from the graph.
558      ///
559      void clear() {}   
560    };
561
562    /// Concept check function for ErasableBaseGraph.
563
564    /// Concept check function for ErasableBaseGraph.
565    ///
566    template <typename Graph>
567    struct BaseClearableGraphComponentConcept {
568      void constraints() {
569        function_requires< BaseGraphComponentConcept<Graph> >();
570        graph.clear();
571      }
572
573      Graph& graph;
574    };
575
576
577    class IterableGraphComponent :
578      virtual public BaseIterableGraphComponent {
579
580    public:
581   
582      typedef IterableGraphComponent Graph;
583
584      typedef BaseGraphComponent::Node Node;
585      typedef BaseGraphComponent::Edge Edge;
586
587      class NodeIt : public Node {
588      public:
589        NodeIt() {}
590        NodeIt(Invalid) {}
591        // explicit NodeIt(Node) {}
592        explicit NodeIt(const Graph&) {}
593
594        NodeIt& operator++() { return *this; }
595        //      Node operator*() const { return INVALID; }
596
597        bool operator==(const NodeIt&) const { return true;}
598        bool operator!=(const NodeIt&) const { return true;}
599      };
600
601      class EdgeIt : public Edge {
602      public:
603        EdgeIt() {}
604        EdgeIt(Invalid) {}
605        // explicit EdgeIt(Edge) {}
606        explicit EdgeIt(const Graph&) {}
607
608        EdgeIt& operator++() { return *this; }
609        //      Edge operator*() const { return INVALID; }
610
611        bool operator==(const EdgeIt&) const { return true;}
612        bool operator!=(const EdgeIt&) const { return true;}
613      };
614
615      class InEdgeIt : public Edge {
616      public:
617        InEdgeIt() {}
618        InEdgeIt(Invalid) {}
619        // explicit InEdgeIt(Edge) {}
620        explicit InEdgeIt(const Graph&, const Node&) {}
621
622        InEdgeIt& operator++() { return *this; }
623        //      Edge operator*() const { return INVALID; }
624
625        bool operator==(const InEdgeIt&) const { return true;}
626        bool operator!=(const InEdgeIt&) const { return true;}
627      };
628
629      class OutEdgeIt : public Edge {
630      public:
631        OutEdgeIt() {}
632        OutEdgeIt(Invalid) {}
633        // explicit OutEdgeIt(Edge) {}
634        explicit OutEdgeIt(const Graph&, const Node&) {}
635
636        OutEdgeIt& operator++() { return *this; }
637        //      Edge operator*() const { return INVALID; }
638
639        bool operator==(const OutEdgeIt&) const { return true;}
640        bool operator!=(const OutEdgeIt&) const { return true;}
641      };
642
643    };
644   
645    template <typename Graph>
646    struct IterableGraphComponentConcept {
647      void constraints() {
648        function_requires< BaseIterableGraphComponentConcept<Graph> >();
649
650        typedef typename Graph::Node Node;
651        typedef typename Graph::NodeIt NodeIt;
652        typedef typename Graph::Edge Edge;
653        typedef typename Graph::EdgeIt EdgeIt;
654        typedef typename Graph::InEdgeIt InEdgeIt;
655        typedef typename Graph::OutEdgeIt OutEdgeIt;
656 
657        function_requires< GraphIteratorConcept<NodeIt, Graph, Node> >();
658        function_requires< GraphIteratorConcept<EdgeIt, Graph, Edge> >();
659        function_requires< GraphIncIteratorConcept<OutEdgeIt, Graph> >();
660        function_requires< GraphIncIteratorConcept<InEdgeIt, Graph> >();
661      }
662    };
663
664
665    class IdMappableGraphComponent : virtual public BaseGraphComponent {
666
667      typedef IdMappableGraphComponent Graph;
668
669    public:
670
671      typedef BaseGraphComponent::Node Node;
672      typedef BaseGraphComponent::Edge Edge;
673
674      class NodeIdMap : public ReadMap<Node, int> {
675      public:
676        NodeIdMap(const Graph&) {}
677        int maxId() const { return -1;}
678      };
679
680      class EdgeIdMap : public ReadMap<Edge, int> {
681      public:
682        EdgeIdMap(const Graph&) {}
683        int maxId() const { return -1;}
684      };
685
686    };
687   
688    template <typename Graph>
689    struct IdMappableGraphComponentConcept {
690      void constraints() {     
691        function_requires< BaseGraphComponentConcept<Graph> >();
692        {
693          typedef typename Graph::EdgeIdMap EdgeIdMap;
694          function_requires<ReadMapConcept<EdgeIdMap> >();
695          EdgeIdMap edge_map(graph);
696          int n = edge_map.maxId();
697          ignore_unused_variable_warning(n);
698        }
699        {
700          typedef typename Graph::NodeIdMap NodeIdMap;
701          function_requires<ReadMapConcept<NodeIdMap> >();
702          NodeIdMap node_map(graph);
703          int n = node_map.maxId();
704          ignore_unused_variable_warning(n);
705        }
706      }
707      Graph& graph;
708    };
709
710
711    class MappableGraphComponent : virtual public BaseGraphComponent {
712    public:
713
714      typedef MappableGraphComponent Graph;
715
716      typedef BaseGraphComponent::Node Node;
717      typedef BaseGraphComponent::Edge Edge;
718
719      template <typename Value>
720      class NodeMap : public ReferenceMap<Node, Value> {
721      public:
722        NodeMap(const Graph&) {}
723        NodeMap(const Graph&, const Value&) {}
724        NodeMap(const NodeMap&) {}
725
726        NodeMap& operator=(const NodeMap&) { return *this;}
727       
728      };
729
730      template <typename Value>
731      class EdgeMap : public ReferenceMap<Edge, Value> {
732      public:
733        EdgeMap(const Graph&) {}
734        EdgeMap(const Graph&, const Value&) {}
735        EdgeMap(const EdgeMap&) {}
736
737        EdgeMap& operator=(const EdgeMap&) { return *this;}
738       
739      };
740
741    };
742
743    template <typename Graph>
744    struct MappableGraphComponentConcept {
745
746      struct Type {
747        int value;
748        Type() : value(0) {}
749        Type(int _v) : value(_v) {}
750      };
751
752      void constraints() {
753        function_requires< BaseGraphComponentConcept<Graph> >();
754        { // int map test
755          typedef typename Graph::template NodeMap<int> IntNodeMap;
756          function_requires<GraphMapConcept<IntNodeMap,Graph> >();
757        } { // bool map test
758          typedef typename Graph::template NodeMap<bool> BoolNodeMap;
759          function_requires<GraphMapConcept<BoolNodeMap,Graph> >();
760        } { // Type map test
761          typedef typename Graph::template NodeMap<Type> TypeNodeMap;
762          function_requires<GraphMapConcept<TypeNodeMap,Graph> >();
763        }
764
765        { // int map test
766          typedef typename Graph::template EdgeMap<int> IntEdgeMap;
767          function_requires<GraphMapConcept<IntEdgeMap,Graph> >();
768        } { // bool map test
769          typedef typename Graph::template EdgeMap<bool> BoolEdgeMap;
770          function_requires<GraphMapConcept<BoolEdgeMap,Graph> >();
771        } { // Type map test
772          typedef typename Graph::template EdgeMap<Type> TypeEdgeMap;
773          function_requires<GraphMapConcept<TypeEdgeMap,Graph> >();
774        }
775      }
776
777      Graph& graph;
778    };
779
780
781    class ExtendableGraphComponent : virtual public BaseGraphComponent {
782    public:
783
784      typedef ExtendableGraphComponent Graph;
785
786      typedef BaseGraphComponent::Node Node;
787      typedef BaseGraphComponent::Edge Edge;
788
789      Node addNode() {
790        return INVALID;
791      }
792   
793      Edge addEdge(const Node& from, const Node& to) {
794        return INVALID;
795      }
796
797    };
798
799    template <typename Graph>
800    struct ExtendableGraphComponentConcept {
801      void constraints() {
802        function_requires< BaseGraphComponentConcept<Graph> >();
803        typename Graph::Node node_a, node_b;
804        node_a = graph.addNode();
805        typename Graph::Edge edge;
806        edge = graph.addEdge(node_a, node_b);     
807      }
808      Graph& graph;
809    };
810
811    class ErasableGraphComponent : virtual public BaseGraphComponent {
812    public:
813
814      typedef ErasableGraphComponent Graph;
815
816      typedef BaseGraphComponent::Node Node;
817      typedef BaseGraphComponent::Edge Edge;
818
819      void erase(const Node&) {}   
820      void erase(const Edge&) {}
821
822    };
823
824    template <typename Graph>
825    struct ErasableGraphComponentConcept {
826      void constraints() {
827        function_requires< BaseGraphComponentConcept<Graph> >();
828        typename Graph::Node node;
829        graph.erase(node);
830        typename Graph::Edge edge;
831        graph.erase(edge);     
832      }
833
834      Graph& graph;
835    };
836
837    class ClearableGraphComponent : virtual public BaseGraphComponent {
838    public:
839
840      typedef ClearableGraphComponent Graph;
841
842      typedef BaseGraphComponent::Node Node;
843      typedef BaseGraphComponent::Edge Edge;
844
845      void clear() {}   
846
847    };
848
849    template <typename Graph>
850    struct ClearableGraphComponentConcept {
851      void constraints() {
852        function_requires< BaseGraphComponentConcept<Graph> >();
853        graph.clear();
854      }
855      Graph& graph;
856    };
857
858  }
859
860}
861
862#endif
Note: See TracBrowser for help on using the repository browser.