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>
22 #include <lemon/error.h>
26 template <typename _Base>
27 class GraphExtender : public _Base {
31 typedef GraphExtender Graph;
33 typedef typename Parent::Node Node;
34 typedef typename Parent::Edge Edge;
36 int maxId(Node) const {
37 return Parent::maxNodeId();
40 int maxId(Edge) const {
41 return Parent::maxEdgeId();
44 Node fromId(int id, Node) const {
45 return Parent::nodeFromId(id);
48 Edge fromId(int id, Edge) const {
49 return Parent::edgeFromId(id);
52 Node oppositeNode(const Node &n, const Edge &e) const {
53 if (n == Parent::source(e))
54 return Parent::target(e);
55 else if(n==Parent::target(e))
56 return Parent::source(e);
63 template <typename _Base>
64 class UndirGraphExtender : public _Base {
66 typedef UndirGraphExtender Graph;
70 typedef typename Parent::Edge UndirEdge;
71 typedef typename Parent::Node Node;
73 class Edge : public UndirEdge {
74 friend class UndirGraphExtender;
77 // FIXME: Marci use opposite logic in his graph adaptors. It would
78 // be reasonable to syncronize...
81 Edge(const UndirEdge &ue, bool _forward) :
82 UndirEdge(ue), forward(_forward) {}
87 /// Invalid edge constructor
88 Edge(Invalid i) : UndirEdge(i), forward(true) {}
90 bool operator==(const Edge &that) const {
91 return forward==that.forward && UndirEdge(*this)==UndirEdge(that);
93 bool operator!=(const Edge &that) const {
94 return forward!=that.forward || UndirEdge(*this)!=UndirEdge(that);
96 bool operator<(const Edge &that) const {
97 return forward<that.forward ||
98 (!(that.forward<forward) && UndirEdge(*this)<UndirEdge(that));
103 /// \brief Edge of opposite direction.
105 /// Returns the Edge of opposite direction.
106 Edge oppositeEdge(const Edge &e) const {
107 return Edge(e,!e.forward);
111 /// \todo Shouldn't the "source" of an undirected edge be called "aNode"
113 using Parent::source;
115 /// Source of the given Edge.
116 Node source(const Edge &e) const {
117 return e.forward ? Parent::source(e) : Parent::target(e);
120 /// \todo Shouldn't the "target" of an undirected edge be called "bNode"
122 using Parent::target;
124 /// Target of the given Edge.
125 Node target(const Edge &e) const {
126 return e.forward ? Parent::target(e) : Parent::source(e);
129 Node oppositeNode(const Node &n, const UndirEdge &e) const {
130 if( n == Parent::source(e))
131 return Parent::target(e);
132 else if( n == Parent::target(e))
133 return Parent::source(e);
138 /// \brief Directed edge from an undirected edge and a source node.
140 /// Returns a (directed) Edge corresponding to the specified UndirEdge
143 Edge direct(const UndirEdge &ue, const Node &s) const {
144 return Edge(ue, s == source(ue));
147 /// \brief Directed edge from an undirected edge.
149 /// Returns a directed edge corresponding to the specified UndirEdge.
150 /// If the given bool is true the given undirected edge and the
151 /// returned edge have the same source node.
152 Edge direct(const UndirEdge &ue, bool d) const {
156 /// Returns whether the given directed edge is same orientation as the
157 /// corresponding undirected edge.
159 /// \todo reference to the corresponding point of the undirected graph
160 /// concept. "What does the direction of an undirected edge mean?"
161 bool direction(const Edge &e) const { return e.forward; }
165 void first(Edge &e) const {
171 void next(Edge &e) const {
183 void firstOut(Edge &e, const Node &n) const {
184 Parent::firstIn(e,n);
185 if( UndirEdge(e) != INVALID ) {
189 Parent::firstOut(e,n);
193 void nextOut(Edge &e) const {
195 Node n = Parent::target(e);
197 if( UndirEdge(e) == INVALID ) {
198 Parent::firstOut(e, n);
207 void firstIn(Edge &e, const Node &n) const {
208 Parent::firstOut(e,n);
209 if( UndirEdge(e) != INVALID ) {
213 Parent::firstIn(e,n);
217 void nextIn(Edge &e) const {
219 Node n = Parent::source(e);
221 if( UndirEdge(e) == INVALID ) {
222 Parent::firstIn(e, n);
231 void firstInc(UndirEdge &e, const Node &n) const {
232 Parent::firstOut(e, n);
233 if (e != INVALID) return;
234 Parent::firstIn(e, n);
236 void nextInc(UndirEdge &e, const Node &n) const {
237 if (Parent::source(e) == n) {
239 if (e != INVALID) return;
240 Parent::firstIn(e, n);
246 void firstInc(UndirEdge &e, bool &d, const Node &n) const {
248 Parent::firstOut(e, n);
249 if (e != INVALID) return;
251 Parent::firstIn(e, n);
253 void nextInc(UndirEdge &e, bool &d) const {
255 Node s = Parent::source(e);
257 if (e != INVALID) return;
259 Parent::firstIn(e, s);
265 // Miscellaneous stuff:
267 /// \todo these methods (id, maxEdgeId) should be moved into separate
271 // Using "using" is not a good idea, cause it could be that there is
272 // no "id" in Parent...
274 int id(const Node &n) const {
275 return Parent::id(n);
278 int id(const UndirEdge &e) const {
279 return Parent::id(e);
282 int id(const Edge &e) const {
283 return 2 * Parent::id(e) + int(e.forward);
286 int maxNodeId() const {
287 return Parent::maxNodeId();
290 int maxEdgeId() const {
291 return 2 * Parent::maxEdgeId() + 1;
294 int maxUndirEdgeId() const {
295 return Parent::maxEdgeId();
298 int maxId(Node) const {
302 int maxId(Edge) const {
305 int maxId(UndirEdge) const {
306 return maxUndirEdgeId();
309 int edgeNum() const {
310 return 2 * Parent::edgeNum();
313 int undirEdgeNum() const {
314 return Parent::edgeNum();
317 Node nodeFromId(int id) const {
318 return Parent::nodeFromId(id);
321 Edge edgeFromId(int id) const {
322 return direct(Parent::edgeFromId(id >> 1), bool(id & 1));
325 UndirEdge undirEdgeFromId(int id) const {
326 return Parent::edgeFromId(id >> 1);
329 Node fromId(int id, Node) const {
330 return nodeFromId(id);
333 Edge fromId(int id, Edge) const {
334 return edgeFromId(id);
337 UndirEdge fromId(int id, UndirEdge) const {
338 return undirEdgeFromId(id);
342 Edge findEdge(Node source, Node target, Edge prev) const {
343 if (prev == INVALID) {
344 UndirEdge edge = Parent::findEdge(source, target);
345 if (edge != INVALID) return direct(edge, true);
346 edge = Parent::findEdge(target, source);
347 if (edge != INVALID) return direct(edge, false);
348 } else if (direction(prev)) {
349 UndirEdge edge = Parent::findEdge(source, target, prev);
350 if (edge != INVALID) return direct(edge, true);
351 edge = Parent::findEdge(target, source);
352 if (edge != INVALID) return direct(edge, false);
354 UndirEdge edge = Parent::findEdge(target, source, prev);
355 if (edge != INVALID) return direct(edge, false);
360 UndirEdge findUndirEdge(Node source, Node target, UndirEdge prev) const {
361 if (prev == INVALID) {
362 UndirEdge edge = Parent::findEdge(source, target);
363 if (edge != INVALID) return edge;
364 edge = Parent::findEdge(target, source);
365 if (edge != INVALID) return edge;
366 } else if (Parent::source(prev) == source) {
367 UndirEdge edge = Parent::findEdge(source, target, prev);
368 if (edge != INVALID) return edge;
369 edge = Parent::findEdge(target, source);
370 if (edge != INVALID) return edge;
372 UndirEdge edge = Parent::findEdge(target, source, prev);
373 if (edge != INVALID) return edge;
381 template <typename _Base>
382 class UndirBipartiteGraphExtender : public _Base {
384 typedef _Base Parent;
385 typedef UndirBipartiteGraphExtender Graph;
387 typedef typename Parent::Node Node;
388 typedef typename Parent::Edge UndirEdge;
395 Node source(const UndirEdge& edge) const {
396 return upperNode(edge);
398 Node target(const UndirEdge& edge) const {
399 return lowerNode(edge);
402 void firstInc(UndirEdge& edge, bool& direction, const Node& node) const {
403 if (Parent::upper(node)) {
404 Parent::firstDown(edge, node);
407 Parent::firstUp(edge, node);
408 direction = static_cast<UndirEdge&>(edge) == INVALID;
411 void nextInc(UndirEdge& edge, bool& direction) const {
413 Parent::nextDown(edge);
415 Parent::nextUp(edge);
416 if (edge == INVALID) direction = true;
420 int maxUndirEdgeId() const {
421 return Parent::maxEdgeId();
424 UndirEdge undirEdgeFromId(int id) const {
425 return Parent::edgeFromId(id);
428 class Edge : public UndirEdge {
429 friend class UndirBipartiteGraphExtender;
433 Edge(const UndirEdge& edge, bool _forward)
434 : UndirEdge(edge), forward(_forward) {}
438 Edge (Invalid) : UndirEdge(INVALID), forward(true) {}
439 bool operator==(const Edge& i) const {
440 return UndirEdge::operator==(i) && forward == i.forward;
442 bool operator!=(const Edge& i) const {
443 return UndirEdge::operator!=(i) || forward != i.forward;
445 bool operator<(const Edge& i) const {
446 return UndirEdge::operator<(i) ||
447 (!(i.forward<forward) && UndirEdge(*this)<UndirEdge(i));
451 void first(Edge& edge) const {
452 Parent::first(static_cast<UndirEdge&>(edge));
456 void next(Edge& edge) const {
458 Parent::next(static_cast<UndirEdge&>(edge));
460 edge.forward = !edge.forward;
463 void firstOut(Edge& edge, const Node& node) const {
464 if (Parent::upper(node)) {
465 Parent::firstDown(edge, node);
468 Parent::firstUp(edge, node);
469 edge.forward = static_cast<UndirEdge&>(edge) == INVALID;
472 void nextOut(Edge& edge) const {
474 Parent::nextDown(edge);
476 Parent::nextUp(edge);
477 edge.forward = static_cast<UndirEdge&>(edge) == INVALID;
481 void firstIn(Edge& edge, const Node& node) const {
482 if (Parent::lower(node)) {
483 Parent::firstUp(edge, node);
486 Parent::firstDown(edge, node);
487 edge.forward = static_cast<UndirEdge&>(edge) == INVALID;
490 void nextIn(Edge& edge) const {
492 Parent::nextUp(edge);
494 Parent::nextDown(edge);
495 edge.forward = static_cast<UndirEdge&>(edge) == INVALID;
499 Node source(const Edge& edge) const {
500 return edge.forward ? Parent::upperNode(edge) : Parent::lowerNode(edge);
502 Node target(const Edge& edge) const {
503 return edge.forward ? Parent::lowerNode(edge) : Parent::upperNode(edge);
506 bool direction(const Edge& edge) const {
510 Edge direct(const UndirEdge& edge, const Node& node) const {
511 return Edge(edge, node == Parent::source(edge));
514 Edge direct(const UndirEdge& edge, bool direction) const {
515 return Edge(edge, direction);
518 Node oppositeNode(const UndirEdge& edge, const Node& node) const {
519 return source(edge) == node ?
520 target(edge) : source(edge);
523 Edge oppositeEdge(const Edge& edge) const {
524 return Edge(edge, !edge.forward);
527 int id(const Edge& edge) const {
528 return (Parent::id(edge) << 1) + (edge.forward ? 0 : 1);
530 Edge edgeFromId(int id) const {
531 return Edge(Parent::fromId(id >> 1, UndirEdge()), (id & 1) == 0);
533 int maxEdgeId() const {
534 return (Parent::maxId(UndirEdge()) << 1) + 1;
537 class UpperNode : public Node {
538 friend class UndirBipartiteGraphExtender;
541 UpperNode(const Node& node) : Node(node) {
542 LEMON_ASSERT(Parent::upper(node) || node == INVALID,
543 typename Parent::NodeSetError());
545 UpperNode(Invalid) : Node(INVALID) {}
548 void first(UpperNode& node) const {
549 Parent::firstUpper(static_cast<Node&>(node));
551 void next(UpperNode& node) const {
552 Parent::nextUpper(static_cast<Node&>(node));
555 int id(const UpperNode& node) const {
556 return Parent::upperId(node);
559 class LowerNode : public Node {
560 friend class UndirBipartiteGraphExtender;
563 LowerNode(const Node& node) : Node(node) {
564 LEMON_ASSERT(Parent::lower(node) || node == INVALID,
565 typename Parent::NodeSetError());
567 LowerNode(Invalid) : Node(INVALID) {}
570 void first(LowerNode& node) const {
571 Parent::firstLower(static_cast<Node&>(node));
573 void next(LowerNode& node) const {
574 Parent::nextLower(static_cast<Node&>(node));
577 int id(const LowerNode& node) const {
578 return Parent::upperId(node);
583 int maxId(Node) const {
584 return Parent::maxNodeId();
586 int maxId(LowerNode) const {
587 return Parent::maxLowerId();
589 int maxId(UpperNode) const {
590 return Parent::maxUpperId();
592 int maxId(Edge) const {
595 int maxId(UndirEdge) const {
596 return maxUndirEdgeId();
600 Node fromId(int id, Node) const {
601 return Parent::nodeFromId(id);
603 UpperNode fromId(int id, UpperNode) const {
604 return Parent::fromUpperId(id);
606 LowerNode fromId(int id, LowerNode) const {
607 return Parent::fromLowerId(id);
609 Edge fromId(int id, Edge) const {
610 return edgeFromId(id);
612 UndirEdge fromId(int id, UndirEdge) const {
613 return undirEdgeFromId(id);
620 #endif // LEMON_UNDIR_GRAPH_EXTENDER_H