2 * lemon/graph_extender.h - Part of LEMON, a generic C++ optimization library
4 * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi
5 * Kutatocsoport (Egervary Research Group on Combinatorial Optimization,
8 * Permission to use, modify and distribute this software is granted
9 * provided that this copyright notice appears in all copies. For
10 * precise terms see the accompanying LICENSE file.
12 * This software is provided "AS IS" with no warranty of any kind,
13 * express or implied, and with no claim as to its suitability for any
18 #ifndef LEMON_GRAPH_EXTENDER_H
19 #define LEMON_GRAPH_EXTENDER_H
21 #include <lemon/invalid.h>
25 template <typename _Base>
26 class GraphExtender : public _Base {
30 typedef GraphExtender Graph;
32 typedef typename Parent::Node Node;
33 typedef typename Parent::Edge Edge;
35 int maxId(Node) const {
36 return Parent::maxNodeId();
39 int maxId(Edge) const {
40 return Parent::maxEdgeId();
43 Node fromId(int id, Node) const {
44 return Parent::nodeFromId(id);
47 Edge fromId(int id, Edge) const {
48 return Parent::edgeFromId(id);
51 Node oppositeNode(const Node &n, const Edge &e) const {
52 if (n == Parent::source(e))
53 return Parent::target(e);
54 else if(n==Parent::target(e))
55 return Parent::source(e);
62 template <typename _Base>
63 class UndirGraphExtender : public _Base {
65 typedef UndirGraphExtender Graph;
69 typedef typename Parent::Edge UndirEdge;
70 typedef typename Parent::Node Node;
72 class Edge : public UndirEdge {
73 friend class UndirGraphExtender;
76 // FIXME: Marci use opposite logic in his graph adaptors. It would
77 // be reasonable to syncronize...
80 Edge(const UndirEdge &ue, bool _forward) :
81 UndirEdge(ue), forward(_forward) {}
86 /// Invalid edge constructor
87 Edge(Invalid i) : UndirEdge(i), forward(true) {}
89 bool operator==(const Edge &that) const {
90 return forward==that.forward && UndirEdge(*this)==UndirEdge(that);
92 bool operator!=(const Edge &that) const {
93 return forward!=that.forward || UndirEdge(*this)!=UndirEdge(that);
95 bool operator<(const Edge &that) const {
96 return forward<that.forward ||
97 (!(that.forward<forward) && UndirEdge(*this)<UndirEdge(that));
102 /// \brief Edge of opposite direction.
104 /// Returns the Edge of opposite direction.
105 Edge oppositeEdge(const Edge &e) const {
106 return Edge(e,!e.forward);
110 /// \todo Shouldn't the "source" of an undirected edge be called "aNode"
112 using Parent::source;
114 /// Source of the given Edge.
115 Node source(const Edge &e) const {
116 return e.forward ? Parent::source(e) : Parent::target(e);
119 /// \todo Shouldn't the "target" of an undirected edge be called "bNode"
121 using Parent::target;
123 /// Target of the given Edge.
124 Node target(const Edge &e) const {
125 return e.forward ? Parent::target(e) : Parent::source(e);
128 Node oppositeNode(const Node &n, const UndirEdge &e) const {
129 if( n == Parent::source(e))
130 return Parent::target(e);
131 else if( n == Parent::target(e))
132 return Parent::source(e);
137 /// \brief Directed edge from an undirected edge and a source node.
139 /// Returns a (directed) Edge corresponding to the specified UndirEdge
142 Edge direct(const UndirEdge &ue, const Node &s) const {
143 return Edge(ue, s == source(ue));
146 /// \brief Directed edge from an undirected edge.
148 /// Returns a directed edge corresponding to the specified UndirEdge.
149 /// If the given bool is true the given undirected edge and the
150 /// returned edge have the same source node.
151 Edge direct(const UndirEdge &ue, bool d) const {
155 /// Returns whether the given directed edge is same orientation as the
156 /// corresponding undirected edge.
158 /// \todo reference to the corresponding point of the undirected graph
159 /// concept. "What does the direction of an undirected edge mean?"
160 bool direction(const Edge &e) const { return e.forward; }
164 void first(Edge &e) const {
170 void next(Edge &e) const {
182 void firstOut(Edge &e, const Node &n) const {
183 Parent::firstIn(e,n);
184 if( UndirEdge(e) != INVALID ) {
188 Parent::firstOut(e,n);
192 void nextOut(Edge &e) const {
194 Node n = Parent::target(e);
196 if( UndirEdge(e) == INVALID ) {
197 Parent::firstOut(e, n);
206 void firstIn(Edge &e, const Node &n) const {
207 Parent::firstOut(e,n);
208 if( UndirEdge(e) != INVALID ) {
212 Parent::firstIn(e,n);
216 void nextIn(Edge &e) const {
218 Node n = Parent::source(e);
220 if( UndirEdge(e) == INVALID ) {
221 Parent::firstIn(e, n);
230 void firstInc(UndirEdge &e, const Node &n) const {
231 Parent::firstOut(e, n);
232 if (e != INVALID) return;
233 Parent::firstIn(e, n);
235 void nextInc(UndirEdge &e, const Node &n) const {
236 if (Parent::source(e) == n) {
238 if (e != INVALID) return;
239 Parent::firstIn(e, n);
245 void firstInc(UndirEdge &e, bool &d, const Node &n) const {
247 Parent::firstOut(e, n);
248 if (e != INVALID) return;
250 Parent::firstIn(e, n);
252 void nextInc(UndirEdge &e, bool &d) const {
254 Node s = Parent::source(e);
256 if (e != INVALID) return;
258 Parent::firstIn(e, s);
264 // Miscellaneous stuff:
266 /// \todo these methods (id, maxEdgeId) should be moved into separate
270 // Using "using" is not a good idea, cause it could be that there is
271 // no "id" in Parent...
273 int id(const Node &n) const {
274 return Parent::id(n);
277 int id(const UndirEdge &e) const {
278 return Parent::id(e);
281 int id(const Edge &e) const {
282 return 2 * Parent::id(e) + int(e.forward);
285 int maxNodeId() const {
286 return Parent::maxNodeId();
289 int maxEdgeId() const {
290 return 2 * Parent::maxEdgeId() + 1;
293 int maxUndirEdgeId() const {
294 return Parent::maxEdgeId();
297 int maxId(Node) const {
301 int maxId(Edge) const {
304 int maxId(UndirEdge) const {
305 return maxUndirEdgeId();
308 int edgeNum() const {
309 return 2 * Parent::edgeNum();
312 int undirEdgeNum() const {
313 return Parent::edgeNum();
316 Node nodeFromId(int id) const {
317 return Parent::nodeFromId(id);
320 Edge edgeFromId(int id) const {
321 return direct(Parent::edgeFromId(id >> 1), bool(id & 1));
324 UndirEdge undirEdgeFromId(int id) const {
325 return Parent::edgeFromId(id >> 1);
328 Node fromId(int id, Node) const {
329 return nodeFromId(id);
332 Edge fromId(int id, Edge) const {
333 return edgeFromId(id);
336 UndirEdge fromId(int id, UndirEdge) const {
337 return undirEdgeFromId(id);
341 Edge findEdge(Node source, Node target, Edge prev) const {
342 if (prev == INVALID) {
343 UndirEdge edge = Parent::findEdge(source, target);
344 if (edge != INVALID) return direct(edge, true);
345 edge = Parent::findEdge(target, source);
346 if (edge != INVALID) return direct(edge, false);
347 } else if (direction(prev)) {
348 UndirEdge edge = Parent::findEdge(source, target, prev);
349 if (edge != INVALID) return direct(edge, true);
350 edge = Parent::findEdge(target, source);
351 if (edge != INVALID) return direct(edge, false);
353 UndirEdge edge = Parent::findEdge(target, source, prev);
354 if (edge != INVALID) return direct(edge, false);
359 UndirEdge findUndirEdge(Node source, Node target, UndirEdge prev) const {
360 if (prev == INVALID) {
361 UndirEdge edge = Parent::findEdge(source, target);
362 if (edge != INVALID) return edge;
363 edge = Parent::findEdge(target, source);
364 if (edge != INVALID) return edge;
365 } else if (Parent::source(prev) == source) {
366 UndirEdge edge = Parent::findEdge(source, target, prev);
367 if (edge != INVALID) return edge;
368 edge = Parent::findEdge(target, source);
369 if (edge != INVALID) return edge;
371 UndirEdge edge = Parent::findEdge(target, source, prev);
372 if (edge != INVALID) return edge;
381 #endif // LEMON_UNDIR_GRAPH_EXTENDER_H