src/work/marci/bipartite_graph_wrapper.h
author deba
Wed, 08 Sep 2004 12:06:45 +0000 (2004-09-08)
changeset 822 88226d9fe821
parent 762 511200bdb71f
child 902 309d81806228
permissions -rw-r--r--
The MapFactories have been removed from the code because
if we use macros then they increases only the complexity.

The pair iterators of the maps are separeted from the maps.

Some macros and comments has been changed.
marci@174
     1
// -*- c++ -*-
marci@496
     2
#ifndef HUGO_BIPARTITE_GRAPH_WRAPPER_H
marci@496
     3
#define HUGO_BIPARTITE_GRAPH_WRAPPER_H
marci@76
     4
klao@491
     5
///\ingroup gwrappers
alpar@457
     6
///\file
alpar@457
     7
///\brief Several graph wrappers.
alpar@457
     8
///
alpar@457
     9
///This file contains several useful graph wrapper functions.
alpar@457
    10
///
alpar@457
    11
///\author Marton Makai
alpar@457
    12
marci@555
    13
#include <hugo/invalid.h>
marci@368
    14
#include <iter_map.h>
marci@557
    15
#include <hugo/graph_wrapper.h>
marci@762
    16
#include <for_each_macros.h>
marci@174
    17
alpar@105
    18
namespace hugo {
marci@76
    19
marci@641
    20
  /// \brief A wrapper for composing a bipartite graph from a graph 
marci@641
    21
  /// and from a node-map showing for any node which color class it belongs to.
marci@641
    22
  ///
marci@368
    23
  /// A wrapper for composing a bipartite graph.
marci@371
    24
  /// \c _graph have to be a reference to a graph of type \c Graph 
marci@371
    25
  /// and \c _s_false_t_true_map is an \c IterableBoolMap 
marci@368
    26
  /// reference containing the elements for the 
marci@371
    27
  /// color classes S and T. \c _graph is to be referred to an undirected 
marci@371
    28
  /// graph or a directed graph with edges oriented from S to T.
alpar@457
    29
  ///
marci@641
    30
  /// \author Marton Makai
marci@368
    31
  template<typename Graph> 
marci@368
    32
  class BipartiteGraphWrapper : public GraphWrapper<Graph> {
marci@768
    33
  public:
marci@389
    34
    typedef IterableBoolMap< typename Graph::template NodeMap<int> > 
marci@389
    35
    SFalseTTrueMap;
marci@768
    36
  protected:
marci@368
    37
    SFalseTTrueMap* s_false_t_true_map;
marci@393
    38
marci@501
    39
    BipartiteGraphWrapper() : GraphWrapper<Graph>()/*, 
marci@501
    40
						     S_CLASS(false), T_CLASS(true)*/ { }
marci@497
    41
    void setSFalseTTrueMap(SFalseTTrueMap& _s_false_t_true_map) { 
marci@499
    42
      s_false_t_true_map=&_s_false_t_true_map;
marci@497
    43
    }
marci@497
    44
marci@368
    45
  public:
marci@409
    46
    //marci
marci@409
    47
    //FIXME vhogy igy kellene, csak az en forditom nem eszi meg
marci@502
    48
    static const bool S_CLASS;
marci@502
    49
    static const bool T_CLASS;
marci@768
    50
marci@768
    51
    /// This method is to reach the iterable maps of the bipartite graph or 
marci@768
    52
    /// bipartite graph wrapper.
marci@768
    53
    const SFalseTTrueMap& sFalseTTrueMap() const { 
marci@768
    54
      return *s_false_t_true_map; 
marci@768
    55
    }
marci@379
    56
    
marci@501
    57
    //bool S_CLASS;
marci@501
    58
    //bool T_CLASS;
marci@409
    59
marci@368
    60
    BipartiteGraphWrapper(Graph& _graph, SFalseTTrueMap& _s_false_t_true_map) 
marci@500
    61
      : GraphWrapper<Graph>(_graph), 
marci@501
    62
	s_false_t_true_map(&_s_false_t_true_map)/*, 
marci@501
    63
						  S_CLASS(false), T_CLASS(true)*/ { }
marci@368
    64
    typedef typename GraphWrapper<Graph>::Node Node;
marci@368
    65
    //using GraphWrapper<Graph>::NodeIt;
marci@368
    66
    typedef typename GraphWrapper<Graph>::Edge Edge;
marci@368
    67
    //using GraphWrapper<Graph>::EdgeIt;
marci@393
    68
    class ClassNodeIt;
marci@393
    69
    friend class ClassNodeIt;
marci@393
    70
    class OutEdgeIt;
marci@393
    71
    friend class OutEdgeIt;
marci@393
    72
    class InEdgeIt;
marci@393
    73
    friend class InEdgeIt;
marci@379
    74
    class ClassNodeIt {
marci@393
    75
      friend class BipartiteGraphWrapper<Graph>;
marci@393
    76
    protected:
marci@368
    77
      Node n;
marci@368
    78
    public:
marci@379
    79
      ClassNodeIt() { }
marci@379
    80
      ClassNodeIt(const Invalid& i) : n(i) { }
marci@379
    81
      ClassNodeIt(const BipartiteGraphWrapper<Graph>& _G, bool _class) { 
marci@379
    82
	_G.s_false_t_true_map->first(n, _class); 
marci@368
    83
      }
marci@381
    84
      //FIXME needed in new concept, important here
marci@381
    85
      ClassNodeIt(const Node& _n) : n(_n) { }
marci@368
    86
      operator Node() const { return n; }
marci@368
    87
    };
marci@379
    88
//     class SNodeIt {
marci@379
    89
//       Node n;
marci@379
    90
//     public:
marci@379
    91
//       SNodeIt() { }
marci@379
    92
//       SNodeIt(const Invalid& i) : n(i) { }
marci@379
    93
//       SNodeIt(const BipartiteGraphWrapper<Graph>& _G) { 
marci@379
    94
// 	_G.s_false_t_true_map->first(n, false); 
marci@379
    95
//       }
marci@379
    96
//       operator Node() const { return n; }
marci@379
    97
//     };
marci@379
    98
//     class TNodeIt {
marci@379
    99
//       Node n;
marci@379
   100
//     public:
marci@379
   101
//       TNodeIt() { }
marci@379
   102
//       TNodeIt(const Invalid& i) : n(i) { }
marci@379
   103
//       TNodeIt(const BipartiteGraphWrapper<Graph>& _G) { 
marci@379
   104
// 	_G.s_false_t_true_map->first(n, true); 
marci@379
   105
//       }
marci@379
   106
//       operator Node() const { return n; }
marci@379
   107
//     };
marci@368
   108
    class OutEdgeIt { 
marci@393
   109
      friend class BipartiteGraphWrapper<Graph>;
marci@393
   110
    protected:
marci@368
   111
      typename Graph::OutEdgeIt e;
marci@368
   112
    public:
marci@368
   113
      OutEdgeIt() { }
marci@368
   114
      OutEdgeIt(const Invalid& i) : e(i) { }
marci@368
   115
      OutEdgeIt(const BipartiteGraphWrapper<Graph>& _G, const Node& _n) {
marci@368
   116
	if (!(*(_G.s_false_t_true_map))[_n]) 
marci@379
   117
	  e=typename Graph::OutEdgeIt(*(_G.graph), typename Graph::Node(_n));
marci@368
   118
	else 
marci@368
   119
	  e=INVALID;
marci@368
   120
      }
marci@368
   121
      operator Edge() const { return Edge(typename Graph::Edge(e)); }
marci@368
   122
    };
marci@368
   123
    class InEdgeIt { 
marci@393
   124
      friend class BipartiteGraphWrapper<Graph>;
marci@393
   125
    protected:
marci@368
   126
      typename Graph::InEdgeIt e;
marci@368
   127
    public:
marci@368
   128
      InEdgeIt() { }
marci@368
   129
      InEdgeIt(const Invalid& i) : e(i) { }
marci@368
   130
      InEdgeIt(const BipartiteGraphWrapper<Graph>& _G, const Node& _n) {
marci@368
   131
	if ((*(_G.s_false_t_true_map))[_n]) 
marci@379
   132
	  e=typename Graph::InEdgeIt(*(_G.graph), typename Graph::Node(_n));
marci@368
   133
	else 
marci@368
   134
	  e=INVALID;
marci@368
   135
      }
marci@368
   136
      operator Edge() const { return Edge(typename Graph::Edge(e)); }
marci@368
   137
    };
marci@368
   138
marci@368
   139
    using GraphWrapper<Graph>::first;
marci@379
   140
    ClassNodeIt& first(ClassNodeIt& n, bool _class) const { 
marci@393
   141
      n=ClassNodeIt(*this, _class) ; return n; }
marci@379
   142
//    SNodeIt& first(SNodeIt& n) const { n=SNodeIt(*this); return n; }
marci@379
   143
//    TNodeIt& first(TNodeIt& n) const { n=TNodeIt(*this); return n; }
marci@379
   144
    OutEdgeIt& first(OutEdgeIt& i, const Node& p) const { 
marci@379
   145
      i=OutEdgeIt(*this, p); return i;
marci@379
   146
    }
marci@379
   147
    InEdgeIt& first(InEdgeIt& i, const Node& p) const { 
marci@379
   148
      i=InEdgeIt(*this, p); return i;
marci@379
   149
    }
marci@368
   150
marci@368
   151
    using GraphWrapper<Graph>::next;
marci@379
   152
    ClassNodeIt& next(ClassNodeIt& n) const { 
marci@393
   153
      this->s_false_t_true_map->next(n.n); return n; 
marci@368
   154
    }
marci@379
   155
//     SNodeIt& next(SNodeIt& n) const { 
marci@379
   156
//       this->s_false_t_true_map->next(n); return n; 
marci@379
   157
//     }
marci@379
   158
//     TNodeIt& next(TNodeIt& n) const { 
marci@379
   159
//       this->s_false_t_true_map->next(n); return n; 
marci@379
   160
//     }
marci@389
   161
    OutEdgeIt& next(OutEdgeIt& i) const { this->graph->next(i.e); return i; }
marci@389
   162
    InEdgeIt& next(InEdgeIt& i) const { this->graph->next(i.e); return i; }
marci@368
   163
marci@368
   164
    Node tail(const Edge& e) { 
marci@368
   165
      if (!(*(this->s_false_t_true_map))[this->graph->tail(e)]) 
marci@368
   166
	return Node(this->graph->tail(e));
marci@368
   167
      else
marci@368
   168
	return Node(this->graph->head(e));	
marci@368
   169
    }
marci@368
   170
    Node head(const Edge& e) { 
marci@368
   171
      if (!(*(this->s_false_t_true_map))[this->graph->tail(e)]) 
marci@368
   172
	return Node(this->graph->head(e));
marci@368
   173
      else
marci@368
   174
	return Node(this->graph->tail(e));	
marci@368
   175
    }
marci@368
   176
marci@368
   177
    Node aNode(const OutEdgeIt& e) const { 
marci@368
   178
      return Node(this->graph->aNode(e.e)); 
marci@368
   179
    }
marci@368
   180
    Node aNode(const InEdgeIt& e) const { 
marci@368
   181
      return Node(this->graph->aNode(e.e)); 
marci@368
   182
    }
marci@368
   183
    Node bNode(const OutEdgeIt& e) const { 
marci@368
   184
      return Node(this->graph->bNode(e.e)); 
marci@368
   185
    }
marci@368
   186
    Node bNode(const InEdgeIt& e) const { 
marci@368
   187
      return Node(this->graph->bNode(e.e)); 
marci@368
   188
    }
marci@379
   189
marci@641
   190
    /// Returns true iff \c n is in S.
marci@379
   191
    bool inSClass(const Node& n) const {
marci@381
   192
      return !(*(this->s_false_t_true_map))[n];
marci@379
   193
    }
marci@641
   194
marci@641
   195
    /// Returns true iff \c n is in T.
marci@379
   196
    bool inTClass(const Node& n) const {
marci@381
   197
      return (*(this->s_false_t_true_map))[n];
marci@379
   198
    }
marci@368
   199
  };
marci@368
   200
marci@502
   201
marci@502
   202
  template<typename G>
marci@502
   203
  const bool BipartiteGraphWrapper<G>::S_CLASS=false;
marci@502
   204
  template<typename G>
marci@502
   205
  const bool BipartiteGraphWrapper<G>::T_CLASS=true;
marci@502
   206
marci@641
   207
  /// \brief A bipartite graph template class
marci@641
   208
  ///
marci@641
   209
  /// This class composes a bipartite graph over a directed or undirected 
marci@641
   210
  /// graph structure of type \c Graph.
marci@641
   211
  /// \c _graph have to be a reference to a graph of type \c Graph 
marci@641
   212
  /// and \c _s_false_t_true_map is an \c IterableBoolMap 
marci@641
   213
  /// reference containing the elements for the 
marci@641
   214
  /// color classes S and T. \c _graph is to be referred to an undirected 
marci@641
   215
  /// graph or a directed graph with edges oriented from S to T.
marci@641
   216
  ///
marci@641
   217
  ///\bug experimental. Do not use this while the bipartitemap augmentation 
marci@497
   218
  /// does not work well.
marci@497
   219
  template<typename Graph>
marci@497
   220
  class BipartiteGraph : public BipartiteGraphWrapper<Graph> {
marci@768
   221
//     typedef IterableBoolMap< typename Graph::template NodeMap<int> > 
marci@768
   222
//     SFalseTTrueMap;
marci@497
   223
    typedef BipartiteGraphWrapper<Graph> Parent;
marci@497
   224
  protected:
marci@497
   225
    Graph gr;
marci@497
   226
    typename Graph::template NodeMap<int> bipartite_map;
marci@768
   227
    typename Parent::SFalseTTrueMap s_false_t_true_map;
marci@497
   228
  public:
marci@497
   229
    typedef typename Parent::Node Node;
marci@497
   230
    typedef typename Parent::Edge Edge;
marci@499
   231
    BipartiteGraph() : BipartiteGraphWrapper<Graph>(), 
marci@500
   232
		       gr(), bipartite_map(gr, -1), 
marci@497
   233
		       s_false_t_true_map(bipartite_map) { 
marci@497
   234
      Parent::setGraph(gr); 
marci@499
   235
      Parent::setSFalseTTrueMap(s_false_t_true_map);
marci@497
   236
    }
marci@497
   237
marci@497
   238
    /// the \c bool parameter which can be \c S_Class or \c T_Class shows 
marci@497
   239
    /// the color class where the new node is to be inserted.
marci@498
   240
    Node addNode(bool b) {
marci@498
   241
      Node n=Parent::graph->addNode();
marci@498
   242
      bipartite_map.update();
marci@501
   243
      //bipartite_map.set(n, -1);
marci@498
   244
      s_false_t_true_map.insert(n, b);
marci@498
   245
      return n;
marci@498
   246
    }
marci@497
   247
marci@497
   248
    /// A new edge is inserted.
marci@497
   249
    ///\pre \c tail have to be in \c S_Class and \c head in \c T_Class.
marci@498
   250
    Edge addEdge(const Node& tail, const Node& head) {
marci@498
   251
      return Parent::graph->addEdge(tail, head);
marci@498
   252
    }
marci@497
   253
marci@498
   254
    void erase(const Node& n) {
marci@498
   255
      s_false_t_true_map.remove(n);
marci@498
   256
      Parent::graph->erase(n);
marci@498
   257
    }
marci@498
   258
    void erase(const Edge& e) {
marci@498
   259
      Parent::graph->erase(e);
marci@498
   260
    }
marci@497
   261
    
marci@497
   262
    void clear() {
marci@558
   263
      FOR_EACH_LOC(typename Parent::EdgeIt, e, *this) erase(e);
marci@558
   264
      FOR_EACH_LOC(typename Parent::NodeIt, n, *this) erase(n);
marci@497
   265
    }
marci@497
   266
  };
marci@497
   267
marci@768
   268
  template<typename Graph, typename sIterableMap, typename tIterableMap>
marci@768
   269
  class stGraphWrapper;
marci@497
   270
marci@768
   271
  /// Easier stuff for bipartite graphs.
marci@435
   272
  template<typename Graph>
marci@768
   273
  class stBipartiteGraphWrapper : public 
marci@768
   274
  stGraphWrapper<Graph, typename Graph::SFalseTTrueMap, 
marci@768
   275
		 typename Graph::SFalseTTrueMap> {
marci@768
   276
  public:
marci@768
   277
    typedef stGraphWrapper<Graph, typename Graph::SFalseTTrueMap, 
marci@768
   278
			   typename Graph::SFalseTTrueMap> Parent;
marci@768
   279
    stBipartiteGraphWrapper(Graph& _graph) : 
marci@768
   280
      Parent(_graph, _graph.sFalseTTrueMap(), _graph.sFalseTTrueMap()) { }
marci@768
   281
  };
marci@435
   282
marci@435
   283
//   template<typename Graph> 
marci@435
   284
//   std::ostream& 
marci@435
   285
//   operator<<(std::ostream& os, const typename stGraphWrapper<Graph>::Node& i) { 
marci@435
   286
//     os << "(node: " << typename Graph::Node(i) << " spec: " << i.spec <<")"; 
marci@435
   287
//     return os; 
marci@435
   288
//   }
marci@435
   289
//   template<typename Graph> 
marci@435
   290
//   std::ostream& 
marci@435
   291
//   operator<<(std::ostream& os, const typename stGraphWrapper<Graph>::Edge& i) { 
marci@435
   292
//     os << "(edge: " << typename Graph::Edge(i) << " spec: " << i.spec << 
marci@435
   293
//       " node: " << i.n << ")"; 
marci@435
   294
//     return os; 
marci@435
   295
//   }
marci@341
   296
marci@641
   297
  /// \brief A wrapper for adding extra nodes s and t to a bipartite graph
marci@641
   298
  /// and edges from s to each node of S and form each node of T to t.
marci@641
   299
  /// 
marci@641
   300
  /// A wrapper for adding extra nodes s and t to a bipartite graph
marci@641
   301
  /// and edges from s to each node of S and form each node of T to t.
marci@641
   302
  /// This class is very useful to reduce some matching or more
marci@641
   303
  /// generally, capacitataed b-matching problem to a flow problem.
marci@641
   304
  /// According to the bipartite graph concepts the bipartite 
marci@641
   305
  /// graph have to be oriented from S to T.
alpar@457
   306
  ///
marci@641
   307
  /// \author Marton Makai
marci@768
   308
  template<typename Graph, typename sIterableMap, typename tIterableMap>
marci@379
   309
  class stGraphWrapper : public GraphWrapper<Graph> {
marci@768
   310
  protected:    
marci@768
   311
    const sIterableMap* s_iterable_map;
marci@768
   312
    const tIterableMap* t_iterable_map;
marci@379
   313
  public:
marci@379
   314
    class Node; 
marci@381
   315
    friend class Node;
marci@379
   316
//GN, int
marci@768
   317
//0 normalis, 1 s, 2 t, ez az iteralasi sorrend, 
marci@379
   318
//es a vege a false azaz (invalid, 3)    
marci@379
   319
    class NodeIt;
marci@381
   320
    friend class NodeIt;
marci@379
   321
//GNI, int
marci@379
   322
    class Edge;
marci@381
   323
    friend class Edge;
marci@379
   324
//GE, int, GN
marci@379
   325
//0 normalis, 1 s->vmi, 2 vmi->t, ez a sorrend,
marci@379
   326
//invalid: (invalid, 3, invalid)
marci@379
   327
    class OutEdgeIt;
marci@381
   328
    friend class OutEdgeIt;
marci@379
   329
//GO, int, GNI
marci@379
   330
//normalis pontbol (first, 0, invalid), ..., (invalid, 2, vmi), ... (invalid, 3, invalid)
marci@379
   331
//s-bol (invalid, 1, first), ... (invalid, 3, invalid)
marci@379
   332
//t-bol (invalid, 3, invalid)
marci@379
   333
    class InEdgeIt;
marci@381
   334
    friend class InEdgeIt;
marci@379
   335
//GI, int, GNI
marci@379
   336
//normalis pontbol (first, 0, invalid), ..., (invalid, 1, vmi), ... (invalid, 3, invalid)
marci@379
   337
//s-be (invalid, 3, invalid)
marci@379
   338
//t-be (invalid, 2, first), ... (invalid, 3, invalid)
marci@379
   339
    class EdgeIt;
marci@381
   340
    friend class EdgeIt;
marci@379
   341
//(first, 0, invalid) ...
marci@379
   342
//(invalid, 1, vmi)
marci@379
   343
//(invalid, 2, vmi)
marci@379
   344
//invalid, 3, invalid)
marci@379
   345
    template <typename T> class NodeMap;
marci@510
   346
    template <typename T> class EdgeMap;
marci@341
   347
marci@379
   348
//    template <typename T> friend class NodeMap;
marci@379
   349
//    template <typename T> friend class EdgeMap;
marci@341
   350
marci@502
   351
    ///\todo FIXME ezt majd static-ra kell javitani
marci@379
   352
    const Node S_NODE;
marci@379
   353
    const Node T_NODE;
marci@341
   354
marci@379
   355
    static const bool S_CLASS=false;
marci@379
   356
    static const bool T_CLASS=true;
marci@341
   357
marci@768
   358
    // \bug not too nice constructor.
marci@768
   359
    stGraphWrapper(Graph& _graph, 
marci@768
   360
		   const sIterableMap& _s_iterable_map, 
marci@768
   361
		   const tIterableMap& _t_iterable_map) : 
marci@768
   362
      GraphWrapper<Graph>(_graph), 
marci@768
   363
      s_iterable_map(&_s_iterable_map), 
marci@768
   364
      t_iterable_map(&_t_iterable_map), 
marci@768
   365
      S_NODE(INVALID, 1), 
marci@768
   366
      T_NODE(INVALID, 2) { }
marci@341
   367
marci@435
   368
    
marci@435
   369
//    std::ostream& 
marci@435
   370
//    operator<<(std::ostream& os, const /*typename stGraphWrapper<Graph>::*/Node& i);
marci@435
   371
//    friend std::ostream& 
marci@435
   372
//    operator<<(std::ostream& os, const /*typename stGraphWrapper<Graph>::*/Node& i);
marci@435
   373
//    friend std::ostream& 
marci@435
   374
//    operator<<(std::ostream& os, const /*typename stGraphWrapper<Graph>::*/Edge& i);
marci@435
   375
marci@379
   376
    class Node : public Graph::Node {
marci@379
   377
    protected:
marci@379
   378
      friend class GraphWrapper<Graph>;
marci@768
   379
      friend class stGraphWrapper<Graph, sIterableMap, tIterableMap>;
marci@389
   380
      template <typename T> friend class NodeMap;
marci@380
   381
      friend class Edge;
marci@380
   382
      friend class OutEdgeIt;
marci@380
   383
      friend class InEdgeIt;
marci@380
   384
      friend class EdgeIt;
marci@379
   385
      int spec; 
marci@379
   386
    public:
marci@379
   387
      Node() { }
marci@379
   388
      Node(const typename Graph::Node& _n, int _spec=0) : 
marci@379
   389
	Graph::Node(_n), spec(_spec) { }
marci@379
   390
      Node(const Invalid& i) : Graph::Node(i), spec(3) { }
marci@379
   391
      friend bool operator==(const Node& u, const Node& v) { 
marci@379
   392
	return (u.spec==v.spec && 
marci@379
   393
		static_cast<typename Graph::Node>(u)==
marci@379
   394
		static_cast<typename Graph::Node>(v));
marci@379
   395
      } 
marci@379
   396
      friend bool operator!=(const Node& u, const Node& v) { 
marci@379
   397
	return (v.spec!=u.spec || 
marci@379
   398
		static_cast<typename Graph::Node>(u)!=
marci@379
   399
		static_cast<typename Graph::Node>(v));
marci@409
   400
      }
marci@435
   401
//      template<typename G> 
marci@435
   402
//      friend std::ostream& 
marci@435
   403
//      operator<<(std::ostream& os, const typename stGraphWrapper<G>::Node& i); 
marci@435
   404
      friend std::ostream& operator<< (std::ostream& os, const Node& i);
marci@379
   405
      int getSpec() const { return spec; }
marci@379
   406
    };
marci@409
   407
marci@379
   408
    class NodeIt { 
marci@379
   409
      friend class GraphWrapper<Graph>;
marci@768
   410
      friend class stGraphWrapper<Graph, sIterableMap, tIterableMap>;
marci@379
   411
      typename Graph::NodeIt n;
marci@379
   412
      int spec; 
marci@379
   413
     public:
marci@379
   414
      NodeIt() { }
marci@379
   415
      NodeIt(const typename Graph::NodeIt& _n, int _spec) : 
marci@379
   416
	n(_n), spec(_spec) { }
marci@379
   417
      NodeIt(const Invalid& i) : n(i), spec(3) { }
marci@768
   418
      NodeIt(const stGraphWrapper<Graph, sIterableMap, tIterableMap>& _G) 
marci@768
   419
	: n(*(_G.graph)), spec(0) { 
marci@409
   420
	if (!_G.graph->valid(n)) spec=1;
marci@379
   421
      }
marci@379
   422
      operator Node() const { return Node(n, spec); }
marci@379
   423
    };
marci@409
   424
marci@379
   425
    class Edge : public Graph::Edge {
marci@379
   426
      friend class GraphWrapper<Graph>;
marci@768
   427
      friend class stGraphWrapper<Graph, sIterableMap, tIterableMap>;
marci@510
   428
      template <typename T> friend class EdgeMap;
marci@379
   429
      int spec;
marci@379
   430
      typename Graph::Node n;
marci@379
   431
    public:
marci@379
   432
      Edge() { }
marci@379
   433
      Edge(const typename Graph::Edge& _e, int _spec, 
marci@379
   434
	   const typename Graph::Node& _n) : 
marci@379
   435
	Graph::Edge(_e), spec(_spec), n(_n) { 
marci@379
   436
      }
marci@379
   437
      Edge(const Invalid& i) : Graph::Edge(i), spec(3), n(i) { }
marci@379
   438
      friend bool operator==(const Edge& u, const Edge& v) { 
marci@379
   439
	return (u.spec==v.spec && 
marci@379
   440
		static_cast<typename Graph::Edge>(u)==
marci@379
   441
		static_cast<typename Graph::Edge>(v) && 
marci@379
   442
		u.n==v.n);
marci@379
   443
      } 
marci@379
   444
      friend bool operator!=(const Edge& u, const Edge& v) { 
marci@379
   445
	return (v.spec!=u.spec || 
marci@379
   446
		static_cast<typename Graph::Edge>(u)!=
marci@379
   447
		static_cast<typename Graph::Edge>(v) || 
marci@379
   448
		u.n!=v.n);
marci@379
   449
      } 
marci@435
   450
//      template<typename G> 
marci@435
   451
//      friend std::ostream& 
marci@435
   452
//      operator<<(std::ostream& os, const typename stGraphWrapper<G>::Edge& i); 
marci@435
   453
      friend std::ostream& operator<< (std::ostream& os, const Edge& i);
marci@379
   454
      int getSpec() const { return spec; }
marci@510
   455
      typename Graph::Node getNode() const { return n; }
marci@379
   456
    };
marci@409
   457
marci@379
   458
    class OutEdgeIt { 
marci@379
   459
      friend class GraphWrapper<Graph>;
marci@768
   460
      friend class stGraphWrapper<Graph, sIterableMap, tIterableMap>;
marci@379
   461
      typename Graph::OutEdgeIt e;
marci@379
   462
      int spec;
marci@379
   463
      typename Graph::ClassNodeIt n;
marci@379
   464
    public:
marci@379
   465
      OutEdgeIt() { }
marci@379
   466
      OutEdgeIt(const typename Graph::OutEdgeIt& _e, int _spec, 
marci@379
   467
		const typename Graph::ClassNodeIt& _n) : 
marci@379
   468
	e(_e), spec(_spec), n(_n) { 
marci@379
   469
      }
marci@379
   470
      OutEdgeIt(const Invalid& i) : e(i), spec(3), n(i) { }
marci@768
   471
      OutEdgeIt(const stGraphWrapper<Graph, sIterableMap, tIterableMap>& _G, 
marci@768
   472
		const Node& _n) {
marci@379
   473
	switch (_n.spec) {
marci@379
   474
	  case 0 : 
marci@381
   475
	    if (_G.graph->inSClass(_n)) { //S, van normalis kiel 
marci@379
   476
	      e=typename Graph::OutEdgeIt(*(_G.graph), 
marci@379
   477
					  typename Graph::Node(_n)); 
marci@379
   478
	      spec=0;
marci@379
   479
	      n=INVALID;
marci@379
   480
	      if (!_G.graph->valid(e)) spec=3;
marci@379
   481
	    } else { //T, specko kiel van
marci@379
   482
	      e=INVALID;
marci@379
   483
	      spec=2;
marci@379
   484
	      n=_n;
marci@379
   485
	    }
marci@379
   486
	    break;
marci@379
   487
	  case 1:
marci@379
   488
	    e=INVALID;
marci@379
   489
	    spec=1;
marci@379
   490
	    _G.graph->first(n, S_CLASS); //s->vmi;
marci@379
   491
	    if (!_G.graph->valid(n)) spec=3; //Ha S ures
marci@379
   492
	    break;
marci@379
   493
	  case 2:
marci@379
   494
	    e=INVALID;
marci@379
   495
	    spec=3;
marci@379
   496
	    n=INVALID;
marci@379
   497
	    break;
marci@379
   498
	}
marci@379
   499
      }
marci@379
   500
      operator Edge() const { return Edge(e, spec, n); }
marci@379
   501
    };
marci@409
   502
marci@379
   503
    class InEdgeIt { 
marci@379
   504
      friend class GraphWrapper<Graph>;
marci@768
   505
      friend class stGraphWrapper<Graph, sIterableMap, tIterableMap>;
marci@379
   506
      typename Graph::InEdgeIt e;
marci@379
   507
      int spec;
marci@379
   508
      typename Graph::ClassNodeIt n;
marci@379
   509
    public:
marci@379
   510
      InEdgeIt() { }
marci@379
   511
      InEdgeIt(const typename Graph::InEdgeIt& _e, int _spec, 
marci@379
   512
	       const typename Graph::ClassNodeIt& _n) : 
marci@379
   513
	e(_e), spec(_spec), n(_n) { 
marci@379
   514
      }
marci@379
   515
      InEdgeIt(const Invalid& i) : e(i), spec(3), n(i) { }
marci@768
   516
      InEdgeIt(const stGraphWrapper<Graph, sIterableMap, tIterableMap>& _G, 
marci@768
   517
	       const Node& _n) {
marci@379
   518
	switch (_n.spec) {
marci@379
   519
	  case 0 : 
marci@381
   520
	    if (_G.graph->inTClass(_n)) { //T, van normalis beel 
marci@379
   521
	      e=typename Graph::InEdgeIt(*(_G.graph), 
marci@379
   522
					 typename Graph::Node(_n)); 
marci@379
   523
	      spec=0;
marci@379
   524
	      n=INVALID;
marci@379
   525
	      if (!_G.graph->valid(e)) spec=3;
marci@379
   526
	    } else { //S, specko beel van
marci@379
   527
	      e=INVALID;
marci@379
   528
	      spec=1;
marci@379
   529
	      n=_n;
marci@379
   530
	    }
marci@379
   531
	    break;
marci@379
   532
	  case 1:
marci@379
   533
	    e=INVALID;
marci@379
   534
	    spec=3;
marci@379
   535
	    n=INVALID;
marci@409
   536
	    break;
marci@379
   537
	  case 2:
marci@379
   538
	    e=INVALID;
marci@409
   539
	    spec=2;
marci@379
   540
	    _G.graph->first(n, T_CLASS); //vmi->t;
marci@379
   541
	    if (!_G.graph->valid(n)) spec=3; //Ha T ures
marci@379
   542
	    break;
marci@379
   543
	}
marci@379
   544
      }
marci@379
   545
      operator Edge() const { return Edge(e, spec, n); }
marci@379
   546
    };
marci@409
   547
marci@379
   548
    class EdgeIt { 
marci@379
   549
      friend class GraphWrapper<Graph>;
marci@768
   550
      friend class stGraphWrapper<Graph, sIterableMap, tIterableMap>;
marci@379
   551
      typename Graph::EdgeIt e;
marci@379
   552
      int spec;
marci@379
   553
      typename Graph::ClassNodeIt n;
marci@379
   554
    public:
marci@379
   555
      EdgeIt() { }
marci@379
   556
      EdgeIt(const typename Graph::EdgeIt& _e, int _spec, 
marci@379
   557
	     const typename Graph::ClassNodeIt& _n) : 
marci@379
   558
	e(_e), spec(_spec), n(_n) { }
marci@379
   559
      EdgeIt(const Invalid& i) : e(i), spec(3), n(i) { }
marci@768
   560
      EdgeIt(const stGraphWrapper<Graph, sIterableMap, tIterableMap>& _G) : 
marci@379
   561
	e(*(_G.graph)), spec(0), n(INVALID) { 
marci@379
   562
	if (!_G.graph->valid(e)) {
marci@379
   563
	  spec=1;
marci@379
   564
	  _G.graph->first(n, S_CLASS);
marci@379
   565
	  if (!_G.graph->valid(n)) { //Ha S ures
marci@379
   566
	    spec=2;
marci@379
   567
	    _G.graph->first(n, T_CLASS);
marci@379
   568
	    if (!_G.graph->valid(n)) { //Ha T ures
marci@379
   569
	      spec=3;
marci@379
   570
	    }
marci@379
   571
	  }
marci@379
   572
	}
marci@379
   573
      }
marci@379
   574
      operator Edge() const { return Edge(e, spec, n); }
marci@379
   575
    };
marci@341
   576
   
marci@379
   577
    NodeIt& first(NodeIt& i) const { 
marci@379
   578
      i=NodeIt(*this); return i;
marci@379
   579
    }
marci@379
   580
    OutEdgeIt& first(OutEdgeIt& i, const Node& p) const { 
marci@379
   581
      i=OutEdgeIt(*this, p); return i;
marci@379
   582
    }
marci@379
   583
    InEdgeIt& first(InEdgeIt& i, const Node& p) const { 
marci@379
   584
      i=InEdgeIt(*this, p); return i;
marci@379
   585
    }
marci@379
   586
    EdgeIt& first(EdgeIt& i) const { 
marci@379
   587
      i=EdgeIt(*this); return i;
marci@379
   588
    }
marci@341
   589
marci@379
   590
    NodeIt& next(NodeIt& i) const { 
marci@379
   591
      switch (i.spec) {
marci@379
   592
	case 0:
marci@389
   593
	  this->graph->next(i.n);
marci@389
   594
	  if (!this->graph->valid(i.n)) {
marci@379
   595
	    i.spec=1;
marci@379
   596
	  }
marci@379
   597
	  break;
marci@379
   598
	case 1:
marci@379
   599
	  i.spec=2;
marci@379
   600
	  break;
marci@379
   601
	case 2:
marci@379
   602
	  i.spec=3;
marci@379
   603
	  break;
marci@379
   604
      }
marci@379
   605
      return i; 
marci@379
   606
    }
marci@379
   607
    OutEdgeIt& next(OutEdgeIt& i) const { 
marci@393
   608
      typename Graph::Node v;
marci@379
   609
      switch (i.spec) {
marci@379
   610
	case 0: //normal edge
marci@409
   611
	  v=this->graph->aNode(i.e);
marci@389
   612
	  this->graph->next(i.e);
marci@389
   613
	  if (!this->graph->valid(i.e)) { //Az igazi elek vegere ertunk
marci@389
   614
	    if (this->graph->inSClass(v)) { //S, nincs kiel
marci@379
   615
	      i.spec=3;
marci@379
   616
	      i.n=INVALID;
marci@379
   617
	    } else { //T, van kiel
marci@379
   618
	      i.spec=2; 
marci@379
   619
	      i.n=v;
marci@379
   620
	    }
marci@379
   621
	  }
marci@379
   622
	  break;
marci@379
   623
	case 1: //s->vmi
marci@389
   624
	  this->graph->next(i.n);
marci@389
   625
	  if (!this->graph->valid(i.n)) i.spec=3;
marci@379
   626
	  break;
marci@379
   627
	case 2: //vmi->t
marci@379
   628
	  i.spec=3;
marci@379
   629
	  i.n=INVALID;
marci@379
   630
	  break;
marci@379
   631
      }
marci@379
   632
      return i; 
marci@379
   633
    }
marci@379
   634
    InEdgeIt& next(InEdgeIt& i) const { 
marci@393
   635
      typename Graph::Node v;
marci@379
   636
      switch (i.spec) {
marci@379
   637
	case 0: //normal edge
marci@393
   638
	  v=this->graph->aNode(i.e);
marci@389
   639
	  this->graph->next(i.e);
marci@389
   640
	  if (!this->graph->valid(i.e)) { //Az igazi elek vegere ertunk
marci@389
   641
	    if (this->graph->inTClass(v)) { //S, nincs beel
marci@379
   642
	      i.spec=3;
marci@379
   643
	      i.n=INVALID;
marci@379
   644
	    } else { //S, van beel
marci@379
   645
	      i.spec=1; 
marci@379
   646
	      i.n=v;
marci@379
   647
	    }
marci@379
   648
	  }
marci@379
   649
	  break;
marci@379
   650
	case 1: //s->vmi
marci@379
   651
	  i.spec=3;
marci@379
   652
	  i.n=INVALID;
marci@379
   653
	  break;
marci@379
   654
	case 2: //vmi->t
marci@389
   655
	  this->graph->next(i.n);
marci@389
   656
	  if (!this->graph->valid(i.n)) i.spec=3;
marci@379
   657
	  break;
marci@379
   658
      }
marci@379
   659
      return i; 
marci@379
   660
    }
marci@341
   661
marci@379
   662
    EdgeIt& next(EdgeIt& i) const { 
marci@379
   663
      switch (i.spec) {
marci@379
   664
	case 0:
marci@389
   665
	  this->graph->next(i.e);
marci@389
   666
	  if (!this->graph->valid(i.e)) { 
marci@379
   667
	    i.spec=1;
marci@389
   668
	    this->graph->first(i.n, S_CLASS);
marci@389
   669
	    if (!this->graph->valid(i.n)) {
marci@379
   670
	      i.spec=2;
marci@389
   671
	      this->graph->first(i.n, T_CLASS);
marci@389
   672
	      if (!this->graph->valid(i.n)) i.spec=3;
marci@379
   673
	    }
marci@379
   674
	  }
marci@379
   675
	  break;
marci@379
   676
	case 1:
marci@389
   677
	  this->graph->next(i.n);
marci@389
   678
	  if (!this->graph->valid(i.n)) {
marci@379
   679
	    i.spec=2;
marci@389
   680
	    this->graph->first(i.n, T_CLASS);
marci@389
   681
	    if (!this->graph->valid(i.n)) i.spec=3;
marci@379
   682
	  }
marci@379
   683
	  break;
marci@379
   684
	case 2:
marci@389
   685
	  this->graph->next(i.n);
marci@389
   686
	  if (!this->graph->valid(i.n)) i.spec=3;
marci@379
   687
	  break;
marci@379
   688
      }
marci@379
   689
      return i; 
marci@379
   690
    }    
marci@341
   691
marci@379
   692
    Node tail(const Edge& e) const { 
marci@379
   693
      switch (e.spec) {
marci@393
   694
      case 0: 
marci@393
   695
	return Node(this->graph->tail(e));
marci@393
   696
	break;
marci@393
   697
      case 1:
marci@393
   698
	return S_NODE;
marci@393
   699
	break;
marci@393
   700
      case 2:
marci@393
   701
      default:
marci@393
   702
	return Node(e.n);
marci@393
   703
	break;
marci@379
   704
      }
marci@379
   705
    }
marci@379
   706
    Node head(const Edge& e) const { 
marci@379
   707
      switch (e.spec) {
marci@393
   708
      case 0: 
marci@393
   709
	return Node(this->graph->head(e));
marci@393
   710
	break;
marci@393
   711
      case 1:
marci@393
   712
	return Node(e.n);
marci@393
   713
	break;
marci@393
   714
      case 2:
marci@393
   715
      default:
marci@393
   716
	return T_NODE;
marci@393
   717
	break;
marci@379
   718
      }
marci@379
   719
    }
marci@341
   720
marci@379
   721
    bool valid(const Node& n) const { return (n.spec<3); }
marci@379
   722
    bool valid(const Edge& e) const { return (e.spec<3); }
marci@379
   723
marci@409
   724
    int nodeNum() const { return this->graph->nodeNum()+2; }
marci@409
   725
    int edgeNum() const { 
marci@409
   726
      return this->graph->edgeNum()+this->graph->nodeNum(); 
marci@409
   727
    }
marci@341
   728
  
marci@379
   729
    Node aNode(const OutEdgeIt& e) const { return tail(e); }
marci@379
   730
    Node aNode(const InEdgeIt& e) const { return head(e); }
marci@379
   731
    Node bNode(const OutEdgeIt& e) const { return head(e); }
marci@379
   732
    Node bNode(const InEdgeIt& e) const { return tail(e); }
marci@409
   733
marci@409
   734
    void addNode() const { }
marci@409
   735
    void addEdge() const { }
marci@409
   736
    
marci@389
   737
//    Node addNode() const { return Node(this->graph->addNode()); }
marci@379
   738
//    Edge addEdge(const Node& tail, const Node& head) const { 
marci@389
   739
//      return Edge(this->graph->addEdge(tail, head)); }
marci@341
   740
marci@389
   741
//    void erase(const Node& i) const { this->graph->erase(i); }
marci@389
   742
//    void erase(const Edge& i) const { this->graph->erase(i); }
marci@341
   743
  
marci@389
   744
//    void clear() const { this->graph->clear(); }
marci@341
   745
    
marci@389
   746
    template<typename T> class NodeMap : public GraphWrapper<Graph>::template NodeMap<T> { 
marci@389
   747
      typedef typename GraphWrapper<Graph>::template NodeMap<T> Parent;
marci@510
   748
    protected:
marci@379
   749
      T s_value, t_value;
marci@379
   750
    public:
marci@768
   751
      NodeMap(const stGraphWrapper<Graph, sIterableMap, tIterableMap>& _G) : 
marci@768
   752
	Parent(_G), 
marci@768
   753
	s_value(), 
marci@768
   754
	t_value() { }
marci@768
   755
      NodeMap(const stGraphWrapper<Graph, sIterableMap, tIterableMap>& _G, T a) 
marci@768
   756
	: Parent(_G, a), 
marci@768
   757
	  s_value(a), 
marci@768
   758
	  t_value(a) { }
marci@379
   759
      T operator[](const Node& n) const { 
marci@379
   760
	switch (n.spec) {
marci@393
   761
	case 0: 
marci@393
   762
	  return Parent::operator[](n);
marci@393
   763
	case 1:
marci@393
   764
	  return s_value;
marci@393
   765
	case 2: 
marci@393
   766
	default:
marci@393
   767
	  return t_value;
marci@379
   768
	}
marci@379
   769
      }
marci@379
   770
      void set(const Node& n, T t) { 
marci@379
   771
	switch (n.spec) {
marci@393
   772
	case 0: 
marci@393
   773
	  GraphWrapper<Graph>::template NodeMap<T>::set(n, t);
marci@393
   774
	  break;
marci@393
   775
	case 1:
marci@393
   776
	  s_value=t;
marci@393
   777
	  break;
marci@393
   778
	case 2:
marci@393
   779
	default:
marci@393
   780
	  t_value=t;
marci@393
   781
	  break;
marci@379
   782
	}
marci@379
   783
      }
marci@379
   784
    };
marci@341
   785
marci@510
   786
    /// This class is to wrap a node-map of \c Graph and two variables 
marci@510
   787
    /// storing values for \c S_NODE and \c T_NODE to a node-map of 
marci@768
   788
    /// stGraphWrapper<Graph, sIterableMap, tIterableMap>.
marci@510
   789
    template<typename NM> class NodeMapWrapper { 
marci@510
   790
    public:
marci@510
   791
      typedef Node KeyType;
marci@510
   792
      typedef typename NM::ValueType ValueType;
marci@510
   793
    protected:
marci@510
   794
      NM* nm;
marci@510
   795
      ValueType* s_value, t_value;
marci@510
   796
    public:
marci@510
   797
      NodeMapWrapper(NM& _nm, ValueType& _s_value, ValueType& _t_value) : 
marci@510
   798
	nm(&_nm), s_value(&_s_value), t_value(&_t_value) { }
marci@510
   799
      ValueType operator[](const Node& n) const { 
marci@510
   800
	switch (n.getSpec()) {
marci@510
   801
	case 0: 
marci@510
   802
	  return (*nm)[n];
marci@510
   803
	case 1:
marci@510
   804
	  return *s_value;
marci@510
   805
	case 2: 
marci@510
   806
	default:
marci@510
   807
	  return *t_value;
marci@510
   808
	}
marci@510
   809
      }
marci@510
   810
      void set(const Node& n, ValueType t) { 
marci@510
   811
	switch (n.getSpec()) {
marci@510
   812
	case 0: 
marci@510
   813
	  nm->set(n, t);
marci@510
   814
	  break;
marci@510
   815
	case 1:
marci@510
   816
	  *s_value=t;
marci@510
   817
	  break;
marci@510
   818
	case 2:
marci@510
   819
	default:
marci@510
   820
	  *t_value=t;
marci@510
   821
	  break;
marci@510
   822
	}
marci@510
   823
      }
marci@510
   824
    };
marci@510
   825
marci@510
   826
    template<typename T> 
marci@510
   827
    class EdgeMap : public GraphWrapper<Graph>::template EdgeMap<T> { 
marci@510
   828
      typedef typename GraphWrapper<Graph>::template EdgeMap<T> Parent;
marci@510
   829
    protected:
marci@389
   830
      typename GraphWrapper<Graph>::template NodeMap<T> node_value;
marci@379
   831
    public:
marci@768
   832
      EdgeMap(const stGraphWrapper<Graph, sIterableMap, tIterableMap>& _G) 
marci@768
   833
	: Parent(_G), 
marci@768
   834
	  node_value(_G) { }
marci@768
   835
      EdgeMap(const stGraphWrapper<Graph, sIterableMap, tIterableMap>& _G, T a) 
marci@768
   836
	: Parent(_G, a), 
marci@768
   837
	  node_value(_G, a) { }
marci@379
   838
      T operator[](const Edge& e) const { 
marci@379
   839
	switch (e.spec) {
marci@393
   840
	case 0: 
marci@393
   841
	  return Parent::operator[](e);
marci@393
   842
	case 1:
marci@393
   843
	  return node_value[e.n];
marci@393
   844
	case 2:
marci@393
   845
	default:
marci@393
   846
	  return node_value[e.n];
marci@379
   847
	}
marci@379
   848
      }
marci@379
   849
      void set(const Edge& e, T t) { 
marci@379
   850
	switch (e.spec) {
marci@393
   851
	case 0: 
marci@409
   852
	  Parent::set(e, t);
marci@393
   853
	  break;
marci@393
   854
	case 1:
marci@393
   855
	  node_value.set(e.n, t);
marci@393
   856
	  break;
marci@393
   857
	case 2:
marci@393
   858
	default:
marci@393
   859
	  node_value.set(e.n, t);
marci@393
   860
	  break;
marci@379
   861
	}
marci@379
   862
      }
marci@379
   863
    };
marci@409
   864
marci@510
   865
    /// This class is to wrap an edge-map and a node-map of \c Graph 
marci@768
   866
    /// to an edge-map of stGraphWrapper<Graph, sIterableMap, tIterableMap>.
marci@510
   867
    template<typename EM, typename NM> 
marci@510
   868
    class EdgeMapWrapper {
marci@510
   869
    public: 
marci@510
   870
      typedef Edge KeyType;
marci@510
   871
      typedef typename EM::ValueType ValueType;
marci@510
   872
    protected:
marci@510
   873
      EM* em;
marci@510
   874
      NM* nm;
marci@510
   875
    public:
marci@510
   876
      EdgeMapWrapper(EM& _em, NM& _nm) : em(&_em), nm(&_nm) { }
marci@510
   877
      ValueType operator[](const Edge& e) const { 
marci@510
   878
	switch (e.getSpec()) {
marci@510
   879
	case 0: 
marci@510
   880
	  return (*em)[e];
marci@510
   881
	case 1:
marci@510
   882
	  return (*nm)[e.getNode()];
marci@510
   883
	case 2:
marci@510
   884
	default:
marci@510
   885
	  return (*nm)[e.getNode()];
marci@510
   886
	}
marci@510
   887
      }
marci@510
   888
      void set(const Edge& e, ValueType t) { 
marci@510
   889
	switch (e.getSpec()) {
marci@510
   890
	case 0: 
marci@510
   891
	  em->set(e, t);
marci@510
   892
	  break;
marci@510
   893
	case 1:
marci@510
   894
	  nm->set(e.getNode(), t);
marci@510
   895
	  break;
marci@510
   896
	case 2:
marci@510
   897
	default:
marci@510
   898
	  nm->set(e.getNode(), t);
marci@510
   899
	  break;
marci@510
   900
	}
marci@510
   901
      }
marci@510
   902
    };
marci@510
   903
marci@409
   904
marci@435
   905
//  template<typename G> 
marci@435
   906
    friend std::ostream& 
marci@435
   907
    operator<<(std::ostream& os, const /*typename stGraphWrapper<Graph>::*/Node& i) { 
marci@409
   908
      os << "(node: " << typename Graph::Node(i) << " spec: " << i.spec <<")"; 
marci@409
   909
      return os; 
marci@409
   910
    }
marci@435
   911
//  template<typename G> 
marci@435
   912
    friend std::ostream& 
marci@435
   913
    operator<<(std::ostream& os, const /*typename stGraphWrapper<Graph>::*/Edge& i) { 
marci@409
   914
      os << "(edge: " << typename Graph::Edge(i) << " spec: " << i.spec << 
marci@409
   915
	" node: " << i.n << ")"; 
marci@409
   916
      return os; 
marci@409
   917
    }
marci@409
   918
marci@379
   919
  };
marci@379
   920
alpar@406
   921
  ///@}
marci@341
   922
alpar@105
   923
} //namespace hugo
marci@76
   924
alpar@406
   925
marci@510
   926
#endif //HUGO_BIPARTITE_GRAPH_WRAPPER_H
marci@76
   927