1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/src/hugo/smart_graph.h Thu May 06 13:21:24 2004 +0000
1.3 @@ -0,0 +1,614 @@
1.4 +// -*- mode:C++ -*-
1.5 +
1.6 +#ifndef HUGO_SMART_GRAPH_H
1.7 +#define HUGO_SMART_GRAPH_H
1.8 +
1.9 +///\ingroup graphs
1.10 +///\file
1.11 +///\brief SmartGraph and SymSmartGraph classes.
1.12 +
1.13 +#include <vector>
1.14 +#include <limits.h>
1.15 +
1.16 +#include "invalid.h"
1.17 +
1.18 +namespace hugo {
1.19 +
1.20 +/// \addtogroup graphs
1.21 +/// @{
1.22 + class SymSmartGraph;
1.23 +
1.24 + ///A smart graph class.
1.25 +
1.26 + ///This is a simple and fast graph implementation.
1.27 + ///It is also quite memory efficient, but at the price
1.28 + ///that <b> it does not support node and edge deletion</b>.
1.29 + ///It conforms to the graph interface documented under
1.30 + ///the description of \ref GraphSkeleton.
1.31 + ///\sa \ref GraphSkeleton.
1.32 + ///
1.33 + ///\todo Some member functions could be \c static.
1.34 + ///\author Alpar Juttner
1.35 + class SmartGraph {
1.36 +
1.37 + struct NodeT
1.38 + {
1.39 + int first_in,first_out;
1.40 + NodeT() : first_in(-1), first_out(-1) {}
1.41 + };
1.42 + struct EdgeT
1.43 + {
1.44 + int head, tail, next_in, next_out;
1.45 + //FIXME: is this necessary?
1.46 + EdgeT() : next_in(-1), next_out(-1) {}
1.47 + };
1.48 +
1.49 + std::vector<NodeT> nodes;
1.50 +
1.51 + std::vector<EdgeT> edges;
1.52 +
1.53 + protected:
1.54 +
1.55 + template <typename Key> class DynMapBase
1.56 + {
1.57 + protected:
1.58 + const SmartGraph* G;
1.59 + public:
1.60 + virtual void add(const Key k) = 0;
1.61 + virtual void erase(const Key k) = 0;
1.62 + DynMapBase(const SmartGraph &_G) : G(&_G) {}
1.63 + virtual ~DynMapBase() {}
1.64 + friend class SmartGraph;
1.65 + };
1.66 +
1.67 + public:
1.68 + template <typename T> class EdgeMap;
1.69 + template <typename T> class EdgeMap;
1.70 +
1.71 + class Node;
1.72 + class Edge;
1.73 +
1.74 + // protected:
1.75 + // HELPME:
1.76 + protected:
1.77 + ///\bug It must be public because of SymEdgeMap.
1.78 + ///
1.79 + mutable std::vector<DynMapBase<Node> * > dyn_node_maps;
1.80 + ///\bug It must be public because of SymEdgeMap.
1.81 + ///
1.82 + mutable std::vector<DynMapBase<Edge> * > dyn_edge_maps;
1.83 +
1.84 + public:
1.85 +
1.86 +
1.87 + class NodeIt;
1.88 + class EdgeIt;
1.89 + class OutEdgeIt;
1.90 + class InEdgeIt;
1.91 +
1.92 + template <typename T> class NodeMap;
1.93 + template <typename T> class EdgeMap;
1.94 +
1.95 + public:
1.96 +
1.97 + SmartGraph() : nodes(), edges() { }
1.98 + SmartGraph(const SmartGraph &_g) : nodes(_g.nodes), edges(_g.edges) { }
1.99 +
1.100 + ~SmartGraph()
1.101 + {
1.102 + for(std::vector<DynMapBase<Node> * >::iterator i=dyn_node_maps.begin();
1.103 + i!=dyn_node_maps.end(); ++i) (**i).G=NULL;
1.104 + for(std::vector<DynMapBase<Edge> * >::iterator i=dyn_edge_maps.begin();
1.105 + i!=dyn_edge_maps.end(); ++i) (**i).G=NULL;
1.106 + }
1.107 +
1.108 + int nodeNum() const { return nodes.size(); } //FIXME: What is this?
1.109 + int edgeNum() const { return edges.size(); } //FIXME: What is this?
1.110 +
1.111 + ///\bug This function does something different than
1.112 + ///its name would suggests...
1.113 + int maxNodeId() const { return nodes.size(); } //FIXME: What is this?
1.114 + ///\bug This function does something different than
1.115 + ///its name would suggests...
1.116 + int maxEdgeId() const { return edges.size(); } //FIXME: What is this?
1.117 +
1.118 + Node tail(Edge e) const { return edges[e.n].tail; }
1.119 + Node head(Edge e) const { return edges[e.n].head; }
1.120 +
1.121 + Node aNode(OutEdgeIt e) const { return edges[e.n].tail; }
1.122 + Node aNode(InEdgeIt e) const { return edges[e.n].head; }
1.123 +
1.124 + Node bNode(OutEdgeIt e) const { return edges[e.n].head; }
1.125 + Node bNode(InEdgeIt e) const { return edges[e.n].tail; }
1.126 +
1.127 + NodeIt& first(NodeIt& v) const {
1.128 + v=NodeIt(*this); return v; }
1.129 + EdgeIt& first(EdgeIt& e) const {
1.130 + e=EdgeIt(*this); return e; }
1.131 + OutEdgeIt& first(OutEdgeIt& e, const Node v) const {
1.132 + e=OutEdgeIt(*this,v); return e; }
1.133 + InEdgeIt& first(InEdgeIt& e, const Node v) const {
1.134 + e=InEdgeIt(*this,v); return e; }
1.135 +
1.136 +// template< typename It >
1.137 +// It first() const { It e; first(e); return e; }
1.138 +
1.139 +// template< typename It >
1.140 +// It first(Node v) const { It e; first(e,v); return e; }
1.141 +
1.142 + bool valid(Edge e) const { return e.n!=-1; }
1.143 + bool valid(Node n) const { return n.n!=-1; }
1.144 +
1.145 + ///\deprecated Use
1.146 + ///\code
1.147 + /// e=INVALID;
1.148 + ///\endcode
1.149 + ///instead.
1.150 + void setInvalid(Edge &e) { e.n=-1; }
1.151 + ///\deprecated Use
1.152 + ///\code
1.153 + /// e=INVALID;
1.154 + ///\endcode
1.155 + ///instead.
1.156 + void setInvalid(Node &n) { n.n=-1; }
1.157 +
1.158 + template <typename It> It getNext(It it) const
1.159 + { It tmp(it); return next(tmp); }
1.160 +
1.161 + NodeIt& next(NodeIt& it) const {
1.162 + it.n=(it.n+2)%(nodes.size()+1)-1;
1.163 + return it;
1.164 + }
1.165 + OutEdgeIt& next(OutEdgeIt& it) const
1.166 + { it.n=edges[it.n].next_out; return it; }
1.167 + InEdgeIt& next(InEdgeIt& it) const
1.168 + { it.n=edges[it.n].next_in; return it; }
1.169 + EdgeIt& next(EdgeIt& it) const { --it.n; return it; }
1.170 +
1.171 + int id(Node v) const { return v.n; }
1.172 + int id(Edge e) const { return e.n; }
1.173 +
1.174 + Node addNode() {
1.175 + Node n; n.n=nodes.size();
1.176 + nodes.push_back(NodeT()); //FIXME: Hmmm...
1.177 +
1.178 + for(std::vector<DynMapBase<Node> * >::iterator i=dyn_node_maps.begin();
1.179 + i!=dyn_node_maps.end(); ++i) (**i).add(n);
1.180 +
1.181 + return n;
1.182 + }
1.183 +
1.184 + Edge addEdge(Node u, Node v) {
1.185 + Edge e; e.n=edges.size(); edges.push_back(EdgeT()); //FIXME: Hmmm...
1.186 + edges[e.n].tail=u.n; edges[e.n].head=v.n;
1.187 + edges[e.n].next_out=nodes[u.n].first_out;
1.188 + edges[e.n].next_in=nodes[v.n].first_in;
1.189 + nodes[u.n].first_out=nodes[v.n].first_in=e.n;
1.190 +
1.191 + for(std::vector<DynMapBase<Edge> * >::iterator i=dyn_edge_maps.begin();
1.192 + i!=dyn_edge_maps.end(); ++i) (**i).add(e);
1.193 +
1.194 + return e;
1.195 + }
1.196 +
1.197 + void clear() {nodes.clear();edges.clear();}
1.198 +
1.199 + class Node {
1.200 + friend class SmartGraph;
1.201 + template <typename T> friend class NodeMap;
1.202 +
1.203 + friend class Edge;
1.204 + friend class OutEdgeIt;
1.205 + friend class InEdgeIt;
1.206 + friend class SymEdge;
1.207 +
1.208 + protected:
1.209 + int n;
1.210 + friend int SmartGraph::id(Node v) const;
1.211 + Node(int nn) {n=nn;}
1.212 + public:
1.213 + Node() {}
1.214 + Node (Invalid) { n=-1; }
1.215 + bool operator==(const Node i) const {return n==i.n;}
1.216 + bool operator!=(const Node i) const {return n!=i.n;}
1.217 + bool operator<(const Node i) const {return n<i.n;}
1.218 + };
1.219 +
1.220 + class NodeIt : public Node {
1.221 + friend class SmartGraph;
1.222 + public:
1.223 + NodeIt() : Node() { }
1.224 + NodeIt(Invalid i) : Node(i) { }
1.225 + NodeIt(const SmartGraph& G) : Node(G.nodes.size()?0:-1) { }
1.226 + };
1.227 +
1.228 + class Edge {
1.229 + friend class SmartGraph;
1.230 + template <typename T> friend class EdgeMap;
1.231 +
1.232 + //template <typename T> friend class SymSmartGraph::SymEdgeMap;
1.233 + //friend Edge SymSmartGraph::opposite(Edge) const;
1.234 +
1.235 + friend class Node;
1.236 + friend class NodeIt;
1.237 + protected:
1.238 + int n;
1.239 + friend int SmartGraph::id(Edge e) const;
1.240 +
1.241 + Edge(int nn) {n=nn;}
1.242 + public:
1.243 + Edge() { }
1.244 + Edge (Invalid) { n=-1; }
1.245 + bool operator==(const Edge i) const {return n==i.n;}
1.246 + bool operator!=(const Edge i) const {return n!=i.n;}
1.247 + bool operator<(const Edge i) const {return n<i.n;}
1.248 + ///\bug This is a workaround until somebody tells me how to
1.249 + ///make class \c SymSmartGraph::SymEdgeMap friend of Edge
1.250 + int &idref() {return n;}
1.251 + const int &idref() const {return n;}
1.252 + };
1.253 +
1.254 + class EdgeIt : public Edge {
1.255 + friend class SmartGraph;
1.256 + public:
1.257 + EdgeIt(const SmartGraph& G) : Edge(G.edges.size()-1) { }
1.258 + EdgeIt (Invalid i) : Edge(i) { }
1.259 + EdgeIt() : Edge() { }
1.260 + ///\bug This is a workaround until somebody tells me how to
1.261 + ///make class \c SymSmartGraph::SymEdgeMap friend of Edge
1.262 + int &idref() {return n;}
1.263 + };
1.264 +
1.265 + class OutEdgeIt : public Edge {
1.266 + friend class SmartGraph;
1.267 + public:
1.268 + OutEdgeIt() : Edge() { }
1.269 + OutEdgeIt (Invalid i) : Edge(i) { }
1.270 +
1.271 + OutEdgeIt(const SmartGraph& G,const Node v)
1.272 + : Edge(G.nodes[v.n].first_out) {}
1.273 + };
1.274 +
1.275 + class InEdgeIt : public Edge {
1.276 + friend class SmartGraph;
1.277 + public:
1.278 + InEdgeIt() : Edge() { }
1.279 + InEdgeIt (Invalid i) : Edge(i) { }
1.280 + InEdgeIt(const SmartGraph& G,Node v) :Edge(G.nodes[v.n].first_in){}
1.281 + };
1.282 +
1.283 + template <typename T> class NodeMap : public DynMapBase<Node>
1.284 + {
1.285 + std::vector<T> container;
1.286 +
1.287 + public:
1.288 + typedef T ValueType;
1.289 + typedef Node KeyType;
1.290 +
1.291 + NodeMap(const SmartGraph &_G) :
1.292 + DynMapBase<Node>(_G), container(_G.maxNodeId())
1.293 + {
1.294 + G->dyn_node_maps.push_back(this);
1.295 + }
1.296 + NodeMap(const SmartGraph &_G,const T &t) :
1.297 + DynMapBase<Node>(_G), container(_G.maxNodeId(),t)
1.298 + {
1.299 + G->dyn_node_maps.push_back(this);
1.300 + }
1.301 +
1.302 + NodeMap(const NodeMap<T> &m) :
1.303 + DynMapBase<Node>(*m.G), container(m.container)
1.304 + {
1.305 + G->dyn_node_maps.push_back(this);
1.306 + }
1.307 +
1.308 + template<typename TT> friend class NodeMap;
1.309 +
1.310 + ///\todo It can copy between different types.
1.311 + ///
1.312 + template<typename TT> NodeMap(const NodeMap<TT> &m) :
1.313 + DynMapBase<Node>(*m.G)
1.314 + {
1.315 + G->dyn_node_maps.push_back(this);
1.316 + typename std::vector<TT>::const_iterator i;
1.317 + for(typename std::vector<TT>::const_iterator i=m.container.begin();
1.318 + i!=m.container.end();
1.319 + i++)
1.320 + container.push_back(*i);
1.321 + }
1.322 + ~NodeMap()
1.323 + {
1.324 + if(G) {
1.325 + std::vector<DynMapBase<Node>* >::iterator i;
1.326 + for(i=G->dyn_node_maps.begin();
1.327 + i!=G->dyn_node_maps.end() && *i!=this; ++i) ;
1.328 + //if(*i==this) G->dyn_node_maps.erase(i); //FIXME: Way too slow...
1.329 + //A better way to do that: (Is this really important?)
1.330 + if(*i==this) {
1.331 + *i=G->dyn_node_maps.back();
1.332 + G->dyn_node_maps.pop_back();
1.333 + }
1.334 + }
1.335 + }
1.336 +
1.337 + void add(const Node k)
1.338 + {
1.339 + if(k.n>=int(container.size())) container.resize(k.n+1);
1.340 + }
1.341 +
1.342 + void erase(const Node) { }
1.343 +
1.344 + void set(Node n, T a) { container[n.n]=a; }
1.345 + //'T& operator[](Node n)' would be wrong here
1.346 + typename std::vector<T>::reference
1.347 + operator[](Node n) { return container[n.n]; }
1.348 + //'const T& operator[](Node n)' would be wrong here
1.349 + typename std::vector<T>::const_reference
1.350 + operator[](Node n) const { return container[n.n]; }
1.351 +
1.352 + ///\warning There is no safety check at all!
1.353 + ///Using operator = between maps attached to different graph may
1.354 + ///cause serious problem.
1.355 + ///\todo Is this really so?
1.356 + ///\todo It can copy between different types.
1.357 + const NodeMap<T>& operator=(const NodeMap<T> &m)
1.358 + {
1.359 + container = m.container;
1.360 + return *this;
1.361 + }
1.362 + template<typename TT>
1.363 + const NodeMap<T>& operator=(const NodeMap<TT> &m)
1.364 + {
1.365 + std::copy(m.container.begin(), m.container.end(), container.begin());
1.366 + return *this;
1.367 + }
1.368 +
1.369 + void update() {} //Useless for Dynamic Maps
1.370 + void update(T a) {} //Useless for Dynamic Maps
1.371 + };
1.372 +
1.373 + template <typename T> class EdgeMap : public DynMapBase<Edge>
1.374 + {
1.375 + std::vector<T> container;
1.376 +
1.377 + public:
1.378 + typedef T ValueType;
1.379 + typedef Edge KeyType;
1.380 +
1.381 + EdgeMap(const SmartGraph &_G) :
1.382 + DynMapBase<Edge>(_G), container(_G.maxEdgeId())
1.383 + {
1.384 + //FIXME: What if there are empty Id's?
1.385 + //FIXME: Can I use 'this' in a constructor?
1.386 + G->dyn_edge_maps.push_back(this);
1.387 + }
1.388 + EdgeMap(const SmartGraph &_G,const T &t) :
1.389 + DynMapBase<Edge>(_G), container(_G.maxEdgeId(),t)
1.390 + {
1.391 + G->dyn_edge_maps.push_back(this);
1.392 + }
1.393 + EdgeMap(const EdgeMap<T> &m) :
1.394 + DynMapBase<Edge>(*m.G), container(m.container)
1.395 + {
1.396 + G->dyn_edge_maps.push_back(this);
1.397 + }
1.398 +
1.399 + template<typename TT> friend class EdgeMap;
1.400 +
1.401 + ///\todo It can copy between different types.
1.402 + ///
1.403 + template<typename TT> EdgeMap(const EdgeMap<TT> &m) :
1.404 + DynMapBase<Edge>(*m.G)
1.405 + {
1.406 + G->dyn_edge_maps.push_back(this);
1.407 + typename std::vector<TT>::const_iterator i;
1.408 + for(typename std::vector<TT>::const_iterator i=m.container.begin();
1.409 + i!=m.container.end();
1.410 + i++)
1.411 + container.push_back(*i);
1.412 + }
1.413 + ~EdgeMap()
1.414 + {
1.415 + if(G) {
1.416 + std::vector<DynMapBase<Edge>* >::iterator i;
1.417 + for(i=G->dyn_edge_maps.begin();
1.418 + i!=G->dyn_edge_maps.end() && *i!=this; ++i) ;
1.419 + //if(*i==this) G->dyn_edge_maps.erase(i); //Way too slow...
1.420 + //A better way to do that: (Is this really important?)
1.421 + if(*i==this) {
1.422 + *i=G->dyn_edge_maps.back();
1.423 + G->dyn_edge_maps.pop_back();
1.424 + }
1.425 + }
1.426 + }
1.427 +
1.428 + void add(const Edge k)
1.429 + {
1.430 + if(k.n>=int(container.size())) container.resize(k.n+1);
1.431 + }
1.432 + void erase(const Edge) { }
1.433 +
1.434 + void set(Edge n, T a) { container[n.n]=a; }
1.435 + //T get(Edge n) const { return container[n.n]; }
1.436 + typename std::vector<T>::reference
1.437 + operator[](Edge n) { return container[n.n]; }
1.438 + typename std::vector<T>::const_reference
1.439 + operator[](Edge n) const { return container[n.n]; }
1.440 +
1.441 + ///\warning There is no safety check at all!
1.442 + ///Using operator = between maps attached to different graph may
1.443 + ///cause serious problem.
1.444 + ///\todo Is this really so?
1.445 + ///\todo It can copy between different types.
1.446 + const EdgeMap<T>& operator=(const EdgeMap<T> &m)
1.447 + {
1.448 + container = m.container;
1.449 + return *this;
1.450 + }
1.451 + template<typename TT>
1.452 + const EdgeMap<T>& operator=(const EdgeMap<TT> &m)
1.453 + {
1.454 + std::copy(m.container.begin(), m.container.end(), container.begin());
1.455 + return *this;
1.456 + }
1.457 +
1.458 + void update() {} //Useless for DynMaps
1.459 + void update(T a) {} //Useless for DynMaps
1.460 + };
1.461 +
1.462 + };
1.463 +
1.464 + ///Graph for bidirectional edges.
1.465 +
1.466 + ///The purpose of this graph structure is to handle graphs
1.467 + ///having bidirectional edges. Here the function \c addEdge(u,v) adds a pair
1.468 + ///of oppositely directed edges.
1.469 + ///There is a new edge map type called
1.470 + ///\ref SymSmartGraph::SymEdgeMap "SymEdgeMap"
1.471 + ///that complements this
1.472 + ///feature by
1.473 + ///storing shared values for the edge pairs. The usual
1.474 + ///\ref GraphSkeleton::EdgeMap "EdgeMap"
1.475 + ///can be used
1.476 + ///as well.
1.477 + ///
1.478 + ///The oppositely directed edge can also be obtained easily
1.479 + ///using \ref opposite.
1.480 + ///\warning It shares the similarity with \ref SmartGraph that
1.481 + ///it is not possible to delete edges or nodes from the graph.
1.482 + //\sa \ref SmartGraph.
1.483 +
1.484 + class SymSmartGraph : public SmartGraph
1.485 + {
1.486 + public:
1.487 + template<typename T> class SymEdgeMap;
1.488 + template<typename T> friend class SymEdgeMap;
1.489 +
1.490 + SymSmartGraph() : SmartGraph() { }
1.491 + SymSmartGraph(const SmartGraph &_g) : SmartGraph(_g) { }
1.492 + ///Adds a pair of oppositely directed edges to the graph.
1.493 + Edge addEdge(Node u, Node v)
1.494 + {
1.495 + Edge e = SmartGraph::addEdge(u,v);
1.496 + SmartGraph::addEdge(v,u);
1.497 + return e;
1.498 + }
1.499 +
1.500 + ///The oppositely directed edge.
1.501 +
1.502 + ///Returns the oppositely directed
1.503 + ///pair of the edge \c e.
1.504 + Edge opposite(Edge e) const
1.505 + {
1.506 + Edge f;
1.507 + f.idref() = e.idref() - 2*(e.idref()%2) + 1;
1.508 + return f;
1.509 + }
1.510 +
1.511 + ///Common data storage for the edge pairs.
1.512 +
1.513 + ///This map makes it possible to store data shared by the oppositely
1.514 + ///directed pairs of edges.
1.515 + template <typename T> class SymEdgeMap : public DynMapBase<Edge>
1.516 + {
1.517 + std::vector<T> container;
1.518 +
1.519 + public:
1.520 + typedef T ValueType;
1.521 + typedef Edge KeyType;
1.522 +
1.523 + SymEdgeMap(const SymSmartGraph &_G) :
1.524 + DynMapBase<Edge>(_G), container(_G.maxEdgeId()/2)
1.525 + {
1.526 + static_cast<const SymSmartGraph*>(G)->dyn_edge_maps.push_back(this);
1.527 + }
1.528 + SymEdgeMap(const SymSmartGraph &_G,const T &t) :
1.529 + DynMapBase<Edge>(_G), container(_G.maxEdgeId()/2,t)
1.530 + {
1.531 + G->dyn_edge_maps.push_back(this);
1.532 + }
1.533 +
1.534 + SymEdgeMap(const SymEdgeMap<T> &m) :
1.535 + DynMapBase<SymEdge>(*m.G), container(m.container)
1.536 + {
1.537 + G->dyn_node_maps.push_back(this);
1.538 + }
1.539 +
1.540 + // template<typename TT> friend class SymEdgeMap;
1.541 +
1.542 + ///\todo It can copy between different types.
1.543 + ///
1.544 +
1.545 + template<typename TT> SymEdgeMap(const SymEdgeMap<TT> &m) :
1.546 + DynMapBase<SymEdge>(*m.G)
1.547 + {
1.548 + G->dyn_node_maps.push_back(this);
1.549 + typename std::vector<TT>::const_iterator i;
1.550 + for(typename std::vector<TT>::const_iterator i=m.container.begin();
1.551 + i!=m.container.end();
1.552 + i++)
1.553 + container.push_back(*i);
1.554 + }
1.555 +
1.556 + ~SymEdgeMap()
1.557 + {
1.558 + if(G) {
1.559 + std::vector<DynMapBase<Edge>* >::iterator i;
1.560 + for(i=static_cast<const SymSmartGraph*>(G)->dyn_edge_maps.begin();
1.561 + i!=static_cast<const SymSmartGraph*>(G)->dyn_edge_maps.end()
1.562 + && *i!=this; ++i) ;
1.563 + //if(*i==this) G->dyn_edge_maps.erase(i); //Way too slow...
1.564 + //A better way to do that: (Is this really important?)
1.565 + if(*i==this) {
1.566 + *i=static_cast<const SymSmartGraph*>(G)->dyn_edge_maps.back();
1.567 + static_cast<const SymSmartGraph*>(G)->dyn_edge_maps.pop_back();
1.568 + }
1.569 + }
1.570 + }
1.571 +
1.572 + void add(const Edge k)
1.573 + {
1.574 + if(!k.idref()%2&&k.idref()/2>=int(container.size()))
1.575 + container.resize(k.idref()/2+1);
1.576 + }
1.577 + void erase(const Edge k) { }
1.578 +
1.579 + void set(Edge n, T a) { container[n.idref()/2]=a; }
1.580 + //T get(Edge n) const { return container[n.idref()/2]; }
1.581 + typename std::vector<T>::reference
1.582 + operator[](Edge n) { return container[n.idref()/2]; }
1.583 + typename std::vector<T>::const_reference
1.584 + operator[](Edge n) const { return container[n.idref()/2]; }
1.585 +
1.586 + ///\warning There is no safety check at all!
1.587 + ///Using operator = between maps attached to different graph may
1.588 + ///cause serious problem.
1.589 + ///\todo Is this really so?
1.590 + ///\todo It can copy between different types.
1.591 + const SymEdgeMap<T>& operator=(const SymEdgeMap<T> &m)
1.592 + {
1.593 + container = m.container;
1.594 + return *this;
1.595 + }
1.596 + template<typename TT>
1.597 + const SymEdgeMap<T>& operator=(const SymEdgeMap<TT> &m)
1.598 + {
1.599 + std::copy(m.container.begin(), m.container.end(), container.begin());
1.600 + return *this;
1.601 + }
1.602 +
1.603 + void update() {} //Useless for DynMaps
1.604 + void update(T a) {} //Useless for DynMaps
1.605 +
1.606 + };
1.607 +
1.608 + };
1.609 +
1.610 + /// @}
1.611 +
1.612 +} //namespace hugo
1.613 +
1.614 +
1.615 +
1.616 +
1.617 +#endif //SMART_GRAPH_H