3 * This file is a part of LEMON, a generic C++ optimization library
5 * Copyright (C) 2003-2006
6 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7 * (Egervary Research Group on Combinatorial Optimization, EGRES).
9 * Permission to use, modify and distribute this software is granted
10 * provided that this copyright notice appears in all copies. For
11 * precise terms see the accompanying LICENSE file.
13 * This software is provided "AS IS" with no warranty of any kind,
14 * express or implied, and with no claim as to its suitability for any
19 #ifndef LEMON_GRAPH_EXTENDER_H
20 #define LEMON_GRAPH_EXTENDER_H
22 #include <lemon/invalid.h>
23 #include <lemon/error.h>
27 template <typename _Base>
28 class GraphExtender : public _Base {
32 typedef GraphExtender Graph;
34 typedef typename Parent::Node Node;
35 typedef typename Parent::Edge Edge;
37 int maxId(Node) const {
38 return Parent::maxNodeId();
41 int maxId(Edge) const {
42 return Parent::maxEdgeId();
45 Node fromId(int id, Node) const {
46 return Parent::nodeFromId(id);
49 Edge fromId(int id, Edge) const {
50 return Parent::edgeFromId(id);
53 Node oppositeNode(const Node &n, const Edge &e) const {
54 if (n == Parent::source(e))
55 return Parent::target(e);
56 else if(n==Parent::target(e))
57 return Parent::source(e);
64 template <typename _Base>
65 class UGraphExtender : public _Base {
67 typedef UGraphExtender Graph;
71 typedef typename Parent::Edge UEdge;
72 typedef typename Parent::Node Node;
74 class Edge : public UEdge {
75 friend class UGraphExtender;
78 // FIXME: Marci use opposite logic in his graph adaptors. It would
79 // be reasonable to syncronize...
82 Edge(const UEdge &ue, bool _forward) :
83 UEdge(ue), forward(_forward) {}
88 /// Invalid edge constructor
89 Edge(Invalid i) : UEdge(i), forward(true) {}
91 bool operator==(const Edge &that) const {
92 return forward==that.forward && UEdge(*this)==UEdge(that);
94 bool operator!=(const Edge &that) const {
95 return forward!=that.forward || UEdge(*this)!=UEdge(that);
97 bool operator<(const Edge &that) const {
98 return forward<that.forward ||
99 (!(that.forward<forward) && UEdge(*this)<UEdge(that));
104 /// \brief Edge of opposite direction.
106 /// Returns the Edge of opposite direction.
107 Edge oppositeEdge(const Edge &e) const {
108 return Edge(e,!e.forward);
112 /// \todo Shouldn't the "source" of an undirected edge be called "aNode"
114 using Parent::source;
116 /// Source of the given Edge.
117 Node source(const Edge &e) const {
118 return e.forward ? Parent::source(e) : Parent::target(e);
121 /// \todo Shouldn't the "target" of an undirected edge be called "bNode"
123 using Parent::target;
125 /// Target of the given Edge.
126 Node target(const Edge &e) const {
127 return e.forward ? Parent::target(e) : Parent::source(e);
130 Node oppositeNode(const Node &n, const UEdge &e) const {
131 if( n == Parent::source(e))
132 return Parent::target(e);
133 else if( n == Parent::target(e))
134 return Parent::source(e);
139 /// \brief Directed edge from an undirected edge and a source node.
141 /// Returns a (directed) Edge corresponding to the specified UEdge
144 Edge direct(const UEdge &ue, const Node &s) const {
145 return Edge(ue, s == source(ue));
148 /// \brief Directed edge from an undirected edge.
150 /// Returns a directed edge corresponding to the specified UEdge.
151 /// If the given bool is true the given undirected edge and the
152 /// returned edge have the same source node.
153 Edge direct(const UEdge &ue, bool d) const {
157 /// Returns whether the given directed edge is same orientation as the
158 /// corresponding undirected edge.
160 /// \todo reference to the corresponding point of the undirected graph
161 /// concept. "What does the direction of an undirected edge mean?"
162 bool direction(const Edge &e) const { return e.forward; }
166 void first(Edge &e) const {
172 void next(Edge &e) const {
184 void firstOut(Edge &e, const Node &n) const {
185 Parent::firstIn(e,n);
186 if( UEdge(e) != INVALID ) {
190 Parent::firstOut(e,n);
194 void nextOut(Edge &e) const {
196 Node n = Parent::target(e);
198 if( UEdge(e) == INVALID ) {
199 Parent::firstOut(e, n);
208 void firstIn(Edge &e, const Node &n) const {
209 Parent::firstOut(e,n);
210 if( UEdge(e) != INVALID ) {
214 Parent::firstIn(e,n);
218 void nextIn(Edge &e) const {
220 Node n = Parent::source(e);
222 if( UEdge(e) == INVALID ) {
223 Parent::firstIn(e, n);
232 void firstInc(UEdge &e, const Node &n) const {
233 Parent::firstOut(e, n);
234 if (e != INVALID) return;
235 Parent::firstIn(e, n);
237 void nextInc(UEdge &e, const Node &n) const {
238 if (Parent::source(e) == n) {
240 if (e != INVALID) return;
241 Parent::firstIn(e, n);
247 void firstInc(UEdge &e, bool &d, const Node &n) const {
249 Parent::firstOut(e, n);
250 if (e != INVALID) return;
252 Parent::firstIn(e, n);
254 void nextInc(UEdge &e, bool &d) const {
256 Node s = Parent::source(e);
258 if (e != INVALID) return;
260 Parent::firstIn(e, s);
266 // Miscellaneous stuff:
268 /// \todo these methods (id, maxEdgeId) should be moved into separate
272 // Using "using" is not a good idea, cause it could be that there is
273 // no "id" in Parent...
275 int id(const Node &n) const {
276 return Parent::id(n);
279 int id(const UEdge &e) const {
280 return Parent::id(e);
283 int id(const Edge &e) const {
284 return 2 * Parent::id(e) + int(e.forward);
287 int maxNodeId() const {
288 return Parent::maxNodeId();
291 int maxEdgeId() const {
292 return 2 * Parent::maxEdgeId() + 1;
295 int maxUEdgeId() const {
296 return Parent::maxEdgeId();
299 int maxId(Node) const {
303 int maxId(Edge) const {
306 int maxId(UEdge) const {
310 int edgeNum() const {
311 return 2 * Parent::edgeNum();
314 int uEdgeNum() const {
315 return Parent::edgeNum();
318 Node nodeFromId(int id) const {
319 return Parent::nodeFromId(id);
322 Edge edgeFromId(int id) const {
323 return direct(Parent::edgeFromId(id >> 1), bool(id & 1));
326 UEdge uEdgeFromId(int id) const {
327 return Parent::edgeFromId(id >> 1);
330 Node fromId(int id, Node) const {
331 return nodeFromId(id);
334 Edge fromId(int id, Edge) const {
335 return edgeFromId(id);
338 UEdge fromId(int id, UEdge) const {
339 return uEdgeFromId(id);
343 Edge findEdge(Node source, Node target, Edge prev) const {
344 if (prev == INVALID) {
345 UEdge edge = Parent::findEdge(source, target);
346 if (edge != INVALID) return direct(edge, true);
347 edge = Parent::findEdge(target, source);
348 if (edge != INVALID) return direct(edge, false);
349 } else if (direction(prev)) {
350 UEdge edge = Parent::findEdge(source, target, prev);
351 if (edge != INVALID) return direct(edge, true);
352 edge = Parent::findEdge(target, source);
353 if (edge != INVALID) return direct(edge, false);
355 UEdge edge = Parent::findEdge(target, source, prev);
356 if (edge != INVALID) return direct(edge, false);
361 UEdge findUEdge(Node source, Node target, UEdge prev) const {
362 if (prev == INVALID) {
363 UEdge edge = Parent::findEdge(source, target);
364 if (edge != INVALID) return edge;
365 edge = Parent::findEdge(target, source);
366 if (edge != INVALID) return edge;
367 } else if (Parent::source(prev) == source) {
368 UEdge edge = Parent::findEdge(source, target, prev);
369 if (edge != INVALID) return edge;
370 edge = Parent::findEdge(target, source);
371 if (edge != INVALID) return edge;
373 UEdge edge = Parent::findEdge(target, source, prev);
374 if (edge != INVALID) return edge;
382 template <typename _Base>
383 class BpUGraphExtender : public _Base {
385 typedef _Base Parent;
386 typedef BpUGraphExtender Graph;
388 typedef typename Parent::Node Node;
389 typedef typename Parent::Edge UEdge;
396 Node source(const UEdge& edge) const {
399 Node target(const UEdge& edge) const {
403 void firstInc(UEdge& edge, bool& direction, const Node& node) const {
404 if (Parent::aNode(node)) {
405 Parent::firstOut(edge, node);
408 Parent::firstIn(edge, node);
409 direction = static_cast<UEdge&>(edge) == INVALID;
412 void nextInc(UEdge& edge, bool& direction) const {
414 Parent::nextOut(edge);
416 Parent::nextIn(edge);
417 if (edge == INVALID) direction = true;
421 int maxUEdgeId() const {
422 return Parent::maxEdgeId();
425 UEdge uEdgeFromId(int id) const {
426 return Parent::edgeFromId(id);
429 class Edge : public UEdge {
430 friend class BpUGraphExtender;
434 Edge(const UEdge& edge, bool _forward)
435 : UEdge(edge), forward(_forward) {}
439 Edge (Invalid) : UEdge(INVALID), forward(true) {}
440 bool operator==(const Edge& i) const {
441 return UEdge::operator==(i) && forward == i.forward;
443 bool operator!=(const Edge& i) const {
444 return UEdge::operator!=(i) || forward != i.forward;
446 bool operator<(const Edge& i) const {
447 return UEdge::operator<(i) ||
448 (!(i.forward<forward) && UEdge(*this)<UEdge(i));
452 void first(Edge& edge) const {
453 Parent::first(static_cast<UEdge&>(edge));
457 void next(Edge& edge) const {
459 Parent::next(static_cast<UEdge&>(edge));
461 edge.forward = !edge.forward;
464 void firstOut(Edge& edge, const Node& node) const {
465 if (Parent::aNode(node)) {
466 Parent::firstOut(edge, node);
469 Parent::firstIn(edge, node);
470 edge.forward = static_cast<UEdge&>(edge) == INVALID;
473 void nextOut(Edge& edge) const {
475 Parent::nextOut(edge);
477 Parent::nextIn(edge);
478 edge.forward = static_cast<UEdge&>(edge) == INVALID;
482 void firstIn(Edge& edge, const Node& node) const {
483 if (Parent::bNode(node)) {
484 Parent::firstIn(edge, node);
487 Parent::firstOut(edge, node);
488 edge.forward = static_cast<UEdge&>(edge) == INVALID;
491 void nextIn(Edge& edge) const {
493 Parent::nextIn(edge);
495 Parent::nextOut(edge);
496 edge.forward = static_cast<UEdge&>(edge) == INVALID;
500 Node source(const Edge& edge) const {
501 return edge.forward ? Parent::aNode(edge) : Parent::bNode(edge);
503 Node target(const Edge& edge) const {
504 return edge.forward ? Parent::bNode(edge) : Parent::aNode(edge);
507 bool direction(const Edge& edge) const {
511 Edge direct(const UEdge& edge, const Node& node) const {
512 return Edge(edge, node == Parent::source(edge));
515 Edge direct(const UEdge& edge, bool direction) const {
516 return Edge(edge, direction);
519 Node oppositeNode(const UEdge& edge, const Node& node) const {
520 return source(edge) == node ?
521 target(edge) : source(edge);
524 Edge oppositeEdge(const Edge& edge) const {
525 return Edge(edge, !edge.forward);
528 int id(const Edge& edge) const {
529 return (Parent::id(edge) << 1) + (edge.forward ? 0 : 1);
531 Edge edgeFromId(int id) const {
532 return Edge(Parent::fromId(id >> 1, UEdge()), (id & 1) == 0);
534 int maxEdgeId() const {
535 return (Parent::maxId(UEdge()) << 1) + 1;
538 class ANode : public Node {
539 friend class BpUGraphExtender;
542 ANode(const Node& node) : Node(node) {
543 LEMON_ASSERT(Parent::aNode(node) || node == INVALID,
544 typename Parent::NodeSetError());
546 ANode(Invalid) : Node(INVALID) {}
549 void first(ANode& node) const {
550 Parent::firstANode(static_cast<Node&>(node));
552 void next(ANode& node) const {
553 Parent::nextANode(static_cast<Node&>(node));
556 int id(const ANode& node) const {
557 return Parent::aNodeId(node);
560 class BNode : public Node {
561 friend class BpUGraphExtender;
564 BNode(const Node& node) : Node(node) {
565 LEMON_ASSERT(Parent::bNode(node) || node == INVALID,
566 typename Parent::NodeSetError());
568 BNode(Invalid) : Node(INVALID) {}
571 void first(BNode& node) const {
572 Parent::firstBNode(static_cast<Node&>(node));
574 void next(BNode& node) const {
575 Parent::nextBNode(static_cast<Node&>(node));
578 int id(const BNode& node) const {
579 return Parent::aNodeId(node);
584 int maxId(Node) const {
585 return Parent::maxNodeId();
587 int maxId(BNode) const {
588 return Parent::maxBNodeId();
590 int maxId(ANode) const {
591 return Parent::maxANodeId();
593 int maxId(Edge) const {
596 int maxId(UEdge) const {
601 Node fromId(int id, Node) const {
602 return Parent::nodeFromId(id);
604 ANode fromId(int id, ANode) const {
605 return Parent::fromANodeId(id);
607 BNode fromId(int id, BNode) const {
608 return Parent::fromBNodeId(id);
610 Edge fromId(int id, Edge) const {
611 return edgeFromId(id);
613 UEdge fromId(int id, UEdge) const {
614 return uEdgeFromId(id);
621 #endif // LEMON_UNDIR_GRAPH_EXTENDER_H