diff -r 123f08422c14 -r 7fe378247fea lemon/graph_adaptor.h --- a/lemon/graph_adaptor.h Fri May 12 09:54:58 2006 +0000 +++ b/lemon/graph_adaptor.h Fri May 12 09:56:14 2006 +0000 @@ -36,7 +36,7 @@ #include -#include +#include namespace lemon { @@ -256,9 +256,8 @@ ///\code /// RevGraphAdaptor ga(g); ///\endcode - ///implements the graph obtained from \c g by + /// implements the graph obtained from \c g by /// reversing the orientation of its edges. - template class RevGraphAdaptor : public GraphAdaptorExtender > { @@ -983,13 +982,13 @@ return EdgeSubGraphAdaptor(graph, efm); } - template + template class UndirGraphAdaptorBase : - public UGraphBaseExtender > { + public UndirGraphExtender > { public: typedef _Graph Graph; typedef UndirGraphAdaptorBase Adaptor; - typedef UGraphBaseExtender > Parent; + typedef UndirGraphExtender > Parent; protected: @@ -1103,38 +1102,50 @@ }; - template - class UndirGraphAdaptorBase< - _Graph, typename enable_if< - typename _Graph::EdgeNotifier::Notifier>::type > - : public UGraphBaseExtender > { + template + class AlterableUndirGraphAdaptor + : public UGraphAdaptorExtender > { + public: + typedef UGraphAdaptorExtender > Parent; + + protected: + + AlterableUndirGraphAdaptor() : Parent() {} + public: + typedef typename Parent::EdgeNotifier UEdgeNotifier; + typedef InvalidType EdgeNotifier; + + }; + + template + class AlterableUndirGraphAdaptor< + _Graph, + typename enable_if::type > + : public UGraphAdaptorExtender > { + public: + + typedef UGraphAdaptorExtender > Parent; typedef _Graph Graph; - typedef UndirGraphAdaptorBase Adaptor; - typedef UGraphBaseExtender > Parent; - + typedef typename _Graph::Edge GraphEdge; + protected: - UndirGraphAdaptorBase() - : edge_notifier(*this), edge_notifier_proxy(edge_notifier) {} + AlterableUndirGraphAdaptor() + : Parent(), edge_notifier(*this), edge_notifier_proxy(*this) {} void setGraph(_Graph& graph) { Parent::setGraph(graph); - edge_notifier_proxy.setUEdgeNotifier(graph.getNotifier(UEdge())); + edge_notifier_proxy.setNotifier(graph.getNotifier(GraphEdge())); } public: - ~UndirGraphAdaptorBase() { + ~AlterableUndirGraphAdaptor() { edge_notifier.clear(); } - int maxId(typename Parent::Edge) const { - return Parent::maxEdgeId(); - } - - typedef typename Parent::UEdge UEdge; typedef typename Parent::Edge Edge; @@ -1142,19 +1153,20 @@ using Parent::getNotifier; - typedef AlterationNotifier EdgeNotifier; + typedef AlterationNotifier EdgeNotifier; EdgeNotifier& getNotifier(Edge) const { return edge_notifier; } protected: - class NotifierProxy : public UEdgeNotifier::ObserverBase { + class NotifierProxy : public Graph::EdgeNotifier::ObserverBase { public: - typedef typename UEdgeNotifier::ObserverBase Parent; - typedef UndirGraphAdaptorBase AdaptorBase; + typedef typename Graph::EdgeNotifier::ObserverBase Parent; + typedef AlterableUndirGraphAdaptor AdaptorBase; - NotifierProxy(EdgeNotifier& _edge_notifier) - : Parent(), edge_notifier(_edge_notifier) { + NotifierProxy(const AdaptorBase& _adaptor) + : Parent(), adaptor(&_adaptor) { } virtual ~NotifierProxy() { @@ -1163,173 +1175,70 @@ } } - void setUEdgeNotifier(UEdgeNotifier& _uedge_notifier) { - Parent::attach(_uedge_notifier); + void setNotifier(typename Graph::EdgeNotifier& notifier) { + Parent::attach(notifier); } protected: - virtual void add(const UEdge& uedge) { + virtual void add(const GraphEdge& ge) { std::vector edges; - edges.push_back(AdaptorBase::Parent::direct(uedge, true)); - edges.push_back(AdaptorBase::Parent::direct(uedge, false)); - edge_notifier.add(edges); + edges.push_back(AdaptorBase::Parent::direct(ge, true)); + edges.push_back(AdaptorBase::Parent::direct(ge, false)); + adaptor->getNotifier(Edge()).add(edges); } - virtual void add(const std::vector& uedges) { + virtual void add(const std::vector& ge) { std::vector edges; - for (int i = 0; i < (int)uedges.size(); ++i) { - edges.push_back(AdaptorBase::Parent::direct(uedges[i], true)); - edges.push_back(AdaptorBase::Parent::direct(uedges[i], false)); + for (int i = 0; i < (int)ge.size(); ++i) { + edges.push_back(AdaptorBase::Parent::direct(ge[i], true)); + edges.push_back(AdaptorBase::Parent::direct(ge[i], false)); } - edge_notifier.add(edges); + adaptor->getNotifier(Edge()).add(edges); } - virtual void erase(const UEdge& uedge) { + virtual void erase(const GraphEdge& ge) { std::vector edges; - edges.push_back(AdaptorBase::Parent::direct(uedge, true)); - edges.push_back(AdaptorBase::Parent::direct(uedge, false)); - edge_notifier.erase(edges); + edges.push_back(AdaptorBase::Parent::direct(ge, true)); + edges.push_back(AdaptorBase::Parent::direct(ge, false)); + adaptor->getNotifier(Edge()).erase(edges); } - virtual void erase(const std::vector& uedges) { + virtual void erase(const std::vector& ge) { std::vector edges; - for (int i = 0; i < (int)uedges.size(); ++i) { - edges.push_back(AdaptorBase::Parent::direct(uedges[i], true)); - edges.push_back(AdaptorBase::Parent::direct(uedges[i], false)); + for (int i = 0; i < (int)ge.size(); ++i) { + edges.push_back(AdaptorBase::Parent::direct(ge[i], true)); + edges.push_back(AdaptorBase::Parent::direct(ge[i], false)); } - edge_notifier.erase(edges); + adaptor->getNotifier(Edge()).erase(edges); } virtual void build() { - edge_notifier.build(); + adaptor->getNotifier(Edge()).build(); } virtual void clear() { - edge_notifier.clear(); + adaptor->getNotifier(Edge()).clear(); } - EdgeNotifier& edge_notifier; + const AdaptorBase* adaptor; }; mutable EdgeNotifier edge_notifier; NotifierProxy edge_notifier_proxy; - private: - - template - class EdgeMapBase { - private: - - typedef typename _Graph::template EdgeMap<_Value> MapImpl; - - public: - - typedef typename MapTraits::ReferenceMapTag ReferenceMapTag; - - typedef _Value Value; - typedef Edge Key; - - EdgeMapBase(const Adaptor& adaptor) : - forward_map(*adaptor.graph), backward_map(*adaptor.graph) {} - - EdgeMapBase(const Adaptor& adaptor, const Value& v) - : forward_map(*adaptor.graph, v), backward_map(*adaptor.graph, v) {} - - void set(const Edge& e, const Value& a) { - if (Parent::direction(e)) { - forward_map.set(e, a); - } else { - backward_map.set(e, a); - } - } - - typename MapTraits::ConstReturnValue operator[](Edge e) const { - if (Parent::direction(e)) { - return forward_map[e]; - } else { - return backward_map[e]; - } - } - - typename MapTraits::ReturnValue operator[](Edge e) { - if (Parent::direction(e)) { - return forward_map[e]; - } else { - return backward_map[e]; - } - } - - protected: - - MapImpl forward_map, backward_map; - - }; - - public: - - template - class EdgeMap - : public SubMapExtender > - { - public: - typedef Adaptor Graph; - typedef SubMapExtender > Parent; - - EdgeMap(const Graph& graph) - : Parent(graph) {} - EdgeMap(const Graph& graph, const _Value& value) - : Parent(graph, value) {} - - EdgeMap& operator=(const EdgeMap& cmap) { - return operator=(cmap); - } - - template - EdgeMap& operator=(const CMap& cmap) { - Parent::operator=(cmap); - return *this; - } - }; - - template - class UEdgeMap : public Graph::template EdgeMap<_Value> { - public: - - typedef typename Graph::template EdgeMap<_Value> Parent; - - explicit UEdgeMap(const Adaptor& ga) - : Parent(*ga.graph) {} - - UEdgeMap(const Adaptor& ga, const _Value& value) - : Parent(*ga.graph, value) {} - - UEdgeMap& operator=(const UEdgeMap& cmap) { - return operator=(cmap); - } - - template - UEdgeMap& operator=(const CMap& cmap) { - Parent::operator=(cmap); - return *this; - } - - }; - }; - ///\brief An undirected graph is made from a directed graph by an adaptor - ///\ingroup graph_adaptors + + /// \brief An undirected graph is made from a directed graph by an adaptor + /// \ingroup graph_adaptors /// /// Undocumented, untested!!! /// If somebody knows nice demo application, let's polulate it. /// /// \author Marton Makai template - class UndirGraphAdaptor : - public UGraphAdaptorExtender< - UndirGraphAdaptorBase<_Graph> > { + class UndirGraphAdaptor : public AlterableUndirGraphAdaptor<_Graph> { public: typedef _Graph Graph; - typedef UGraphAdaptorExtender< - UndirGraphAdaptorBase<_Graph> > Parent; + typedef AlterableUndirGraphAdaptor<_Graph> Parent; protected: UndirGraphAdaptor() { } public: @@ -1694,371 +1603,977 @@ }; -// template -// class SplitGraphAdaptorBase -// : public GraphAdaptorBase<_Graph> { -// public: -// typedef GraphAdaptorBase<_Graph> Parent; + /// \brief Base class for split graph adaptor + /// + /// Base class of split graph adaptor. In most case you do not need to + /// use it directly but the documented member functions of this class can + /// be used with the SplitGraphAdaptor class. + /// \sa SplitGraphAdaptor + template + class SplitGraphAdaptorBase + : public GraphAdaptorBase { + public: -// class Node; -// class Edge; -// template class NodeMap; -// template class EdgeMap; + typedef _Graph Graph; + + typedef GraphAdaptorBase Parent; + + typedef typename Graph::Node GraphNode; + typedef typename Graph::Edge GraphEdge; + + class Node; + class Edge; + + template class NodeMap; + template class EdgeMap; -// class Node : public Parent::Node { -// friend class SplitGraphAdaptorBase; -// template friend class NodeMap; -// typedef typename Parent::Node NodeParent; -// private: + class Node : public GraphNode { + friend class SplitGraphAdaptorBase; + template friend class NodeMap; + private: -// bool entry; -// Node(typename Parent::Node _node, bool _entry) -// : Parent::Node(_node), entry(_entry) {} + bool in_node; + Node(GraphNode _node, bool _in_node) + : GraphNode(_node), in_node(_in_node) {} -// public: -// Node() {} -// Node(Invalid) : NodeParent(INVALID), entry(true) {} + public: -// bool operator==(const Node& node) const { -// return NodeParent::operator==(node) && entry == node.entry; -// } + Node() {} + Node(Invalid) : GraphNode(INVALID), in_node(true) {} + + bool operator==(const Node& node) const { + return GraphNode::operator==(node) && in_node == node.in_node; + } -// bool operator!=(const Node& node) const { -// return !(*this == node); -// } + bool operator!=(const Node& node) const { + return !(*this == node); + } -// bool operator<(const Node& node) const { -// return NodeParent::operator<(node) || -// (NodeParent::operator==(node) && entry < node.entry); -// } -// }; + bool operator<(const Node& node) const { + return GraphNode::operator<(node) || + (GraphNode::operator==(node) && in_node < node.in_node); + } + }; -// /// \todo May we want VARIANT/union type -// class Edge : public Parent::Edge { -// friend class SplitGraphAdaptorBase; -// template friend class EdgeMap; -// private: -// typedef typename Parent::Edge EdgeParent; -// typedef typename Parent::Node NodeParent; -// NodeParent bind; + class Edge { + friend class SplitGraphAdaptorBase; + template friend class EdgeMap; + private: + typedef BiVariant EdgeImpl; -// Edge(const EdgeParent& edge, const NodeParent& node) -// : EdgeParent(edge), bind(node) {} -// public: -// Edge() {} -// Edge(Invalid) : EdgeParent(INVALID), bind(INVALID) {} + explicit Edge(const GraphEdge& edge) : item(edge) {} + explicit Edge(const GraphNode& node) : item(node) {} + + EdgeImpl item; -// bool operator==(const Edge& edge) const { -// return EdgeParent::operator==(edge) && bind == edge.bind; -// } + public: + Edge() {} + Edge(Invalid) : item(GraphEdge(INVALID)) {} + + bool operator==(const Edge& edge) const { + if (item.firstState()) { + if (edge.item.firstState()) { + return item.first() == edge.item.first(); + } + } else { + if (edge.item.secondState()) { + return item.second() == edge.item.second(); + } + } + return false; + } -// bool operator!=(const Edge& edge) const { -// return !(*this == edge); -// } + bool operator!=(const Edge& edge) const { + return !(*this == edge); + } -// bool operator<(const Edge& edge) const { -// return EdgeParent::operator<(edge) || -// (EdgeParent::operator==(edge) && bind < edge.bind); -// } -// }; + bool operator<(const Edge& edge) const { + if (item.firstState()) { + if (edge.item.firstState()) { + return item.first() < edge.item.first(); + } + return false; + } else { + if (edge.item.secondState()) { + return item.second() < edge.item.second(); + } + return true; + } + } -// void first(Node& node) const { -// Parent::first(node); -// node.entry = true; -// } + operator GraphEdge() const { return item.first(); } + operator GraphNode() const { return item.second(); } -// void next(Node& node) const { -// if (node.entry) { -// node.entry = false; -// } else { -// node.entry = true; -// Parent::next(node); -// } -// } + }; -// void first(Edge& edge) const { -// Parent::first(edge); -// if ((typename Parent::Edge&)edge == INVALID) { -// Parent::first(edge.bind); -// } else { -// edge.bind = INVALID; -// } -// } + void first(Node& node) const { + Parent::first(node); + node.in_node = true; + } -// void next(Edge& edge) const { -// if ((typename Parent::Edge&)edge != INVALID) { -// Parent::next(edge); -// if ((typename Parent::Edge&)edge == INVALID) { -// Parent::first(edge.bind); -// } -// } else { -// Parent::next(edge.bind); -// } -// } + void next(Node& node) const { + if (node.in_node) { + node.in_node = false; + } else { + node.in_node = true; + Parent::next(node); + } + } -// void firstIn(Edge& edge, const Node& node) const { -// if (node.entry) { -// Parent::firstIn(edge, node); -// edge.bind = INVALID; -// } else { -// (typename Parent::Edge&)edge = INVALID; -// edge.bind = node; -// } -// } + void first(Edge& edge) const { + edge.item.setSecond(); + Parent::first(edge.item.second()); + if (edge.item.second() == INVALID) { + edge.item.setFirst(); + Parent::first(edge.item.first()); + } + } -// void nextIn(Edge& edge) const { -// if ((typename Parent::Edge&)edge != INVALID) { -// Parent::nextIn(edge); -// } else { -// edge.bind = INVALID; -// } -// } + void next(Edge& edge) const { + if (edge.item.secondState()) { + Parent::next(edge.item.second()); + if (edge.item.second() == INVALID) { + edge.item.setFirst(); + Parent::first(edge.item.first()); + } + } else { + Parent::next(edge.item.first()); + } + } -// void firstOut(Edge& edge, const Node& node) const { -// if (!node.entry) { -// Parent::firstOut(edge, node); -// edge.bind = INVALID; -// } else { -// (typename Parent::Edge&)edge = INVALID; -// edge.bind = node; -// } -// } + void firstOut(Edge& edge, const Node& node) const { + if (node.in_node) { + edge.item.setSecond(node); + } else { + edge.item.setFirst(); + Parent::firstOut(edge.item.first(), node); + } + } -// void nextOut(Edge& edge) const { -// if ((typename Parent::Edge&)edge != INVALID) { -// Parent::nextOut(edge); -// } else { -// edge.bind = INVALID; -// } -// } + void nextOut(Edge& edge) const { + if (!edge.item.firstState()) { + edge.item.setFirst(INVALID); + } else { + Parent::nextOut(edge.item.first()); + } + } -// Node source(const Edge& edge) const { -// if ((typename Parent::Edge&)edge != INVALID) { -// return Node(Parent::source(edge), false); -// } else { -// return Node(edge.bind, true); -// } -// } + void firstIn(Edge& edge, const Node& node) const { + if (!node.in_node) { + edge.item.setSecond(node); + } else { + edge.item.setFirst(); + Parent::firstIn(edge.item.first(), node); + } + } -// Node target(const Edge& edge) const { -// if ((typename Parent::Edge&)edge != INVALID) { -// return Node(Parent::target(edge), true); -// } else { -// return Node(edge.bind, false); -// } -// } + void nextIn(Edge& edge) const { + if (!edge.item.firstState()) { + edge.item.setFirst(INVALID); + } else { + Parent::nextIn(edge.item.first()); + } + } -// static bool entryNode(const Node& node) { -// return node.entry; -// } + Node source(const Edge& edge) const { + if (edge.item.firstState()) { + return Node(Parent::source(edge.item.first()), false); + } else { + return Node(edge.item.second(), true); + } + } -// static bool exitNode(const Node& node) { -// return !node.entry; -// } + Node target(const Edge& edge) const { + if (edge.item.firstState()) { + return Node(Parent::target(edge.item.first()), true); + } else { + return Node(edge.item.second(), false); + } + } -// static Node getEntry(const typename Parent::Node& node) { -// return Node(node, true); -// } + int id(const Node& node) const { + return (Parent::id(node) << 1) | (node.in_node ? 0 : 1); + } + Node nodeFromId(int id) const { + return Node(Parent::nodeFromId(id >> 1), (id & 1) == 0); + } + int maxNodeId() const { + return 2 * Parent::maxNodeId() + 1; + } -// static Node getExit(const typename Parent::Node& node) { -// return Node(node, false); -// } + int id(const Edge& edge) const { + if (edge.item.firstState()) { + return Parent::id(edge.item.first()) << 1; + } else { + return (Parent::id(edge.item.second()) << 1) | 1; + } + } + Edge edgeFromId(int id) const { + if ((id & 1) == 0) { + return Edge(Parent::edgeFromId(id >> 1)); + } else { + return Edge(Parent::nodeFromId(id >> 1)); + } + } + int maxEdgeId() const { + return std::max(Parent::maxNodeId() << 1, + (Parent::maxEdgeId() << 1) | 1); + } -// static bool originalEdge(const Edge& edge) { -// return (typename Parent::Edge&)edge != INVALID; -// } + /// \brief Returns true when the node is in-node. + /// + /// Returns true when the node is in-node. + static bool inNode(const Node& node) { + return node.in_node; + } -// static bool bindingEdge(const Edge& edge) { -// return edge.bind != INVALID; -// } + /// \brief Returns true when the node is out-node. + /// + /// Returns true when the node is out-node. + static bool outNode(const Node& node) { + return !node.in_node; + } -// static Node getBindedNode(const Edge& edge) { -// return edge.bind; -// } + /// \brief Returns true when the edge is edge in the original graph. + /// + /// Returns true when the edge is edge in the original graph. + static bool origEdge(const Edge& edge) { + return edge.item.firstState(); + } -// int nodeNum() const { -// return Parent::nodeNum() * 2; -// } + /// \brief Returns true when the edge binds an in-node and an out-node. + /// + /// Returns true when the edge binds an in-node and an out-node. + static bool bindEdge(const Edge& edge) { + return edge.item.secondState(); + } -// typedef True EdgeNumTag; + /// \brief Gives back the in-node created from the \c node. + /// + /// Gives back the in-node created from the \c node. + static Node inNode(const GraphNode& node) { + return Node(node, true); + } + + /// \brief Gives back the out-node created from the \c node. + /// + /// Gives back the out-node created from the \c node. + static Node outNode(const GraphNode& node) { + return Node(node, false); + } + + /// \brief Gives back the edge binds the two part of the node. + /// + /// Gives back the edge binds the two part of the node. + static Edge edge(const GraphNode& node) { + return Edge(node); + } + + /// \brief Gives back the edge of the original edge. + /// + /// Gives back the edge of the original edge. + static Edge edge(const GraphEdge& edge) { + return Edge(edge); + } + + typedef True NodeNumTag; + + int nodeNum() const { + return 2 * countNodes(*Parent::graph); + } + + typedef True EdgeNumTag; -// int edgeNum() const { -// return countEdges() + Parent::nodeNum(); -// } + int edgeNum() const { + return countEdges(*Parent::graph) + countNodes(*Parent::graph); + } -// Edge findEdge(const Node& source, const Node& target, -// const Edge& prev = INVALID) const { -// if (exitNode(source) && entryNode(target)) { -// return Parent::findEdge(source, target, prev); -// } else { -// if (prev == INVALID && entryNode(source) && exitNode(target) && -// (typename Parent::Node&)source == (typename Parent::Node&)target) { -// return Edge(INVALID, source); -// } else { -// return INVALID; -// } -// } -// } + typedef True FindEdgeTag; + + Edge findEdge(const Node& source, const Node& target, + const Edge& prev = INVALID) const { + if (inNode(source)) { + if (outNode(target)) { + if ((GraphNode&)source == (GraphNode&)target && prev == INVALID) { + return Edge(source); + } + } + } else { + if (inNode(target)) { + return Edge(findEdge(*Parent::graph, source, target, prev)); + } + } + return INVALID; + } -// template -// class NodeMap : public MapBase { -// typedef typename Parent::template NodeMap NodeImpl; -// public: -// NodeMap(const SplitGraphAdaptorBase& _graph) -// : entry(_graph), exit(_graph) {} -// NodeMap(const SplitGraphAdaptorBase& _graph, const T& t) -// : entry(_graph, t), exit(_graph, t) {} + template + class NodeMap : public MapBase { + typedef typename Parent::template NodeMap NodeImpl; + public: + NodeMap(const SplitGraphAdaptorBase& _graph) + : inNodeMap(_graph), outNodeMap(_graph) {} + NodeMap(const SplitGraphAdaptorBase& _graph, const T& t) + : inNodeMap(_graph, t), outNodeMap(_graph, t) {} -// void set(const Node& key, const T& val) { -// if (key.entry) { entry.set(key, val); } -// else {exit.set(key, val); } -// } + void set(const Node& key, const T& val) { + if (SplitGraphAdaptorBase::inNode(key)) { inNodeMap.set(key, val); } + else {outNodeMap.set(key, val); } + } -// typename MapTraits::ReturnValue -// operator[](const Node& key) { -// if (key.entry) { return entry[key]; } -// else { return exit[key]; } -// } + typename MapTraits::ReturnValue + operator[](const Node& key) { + if (SplitGraphAdaptorBase::inNode(key)) { return inNodeMap[key]; } + else { return outNodeMap[key]; } + } -// typename MapTraits::ConstReturnValue -// operator[](const Node& key) const { -// if (key.entry) { return entry[key]; } -// else { return exit[key]; } -// } + typename MapTraits::ConstReturnValue + operator[](const Node& key) const { + if (SplitGraphAdaptorBase::inNode(key)) { return inNodeMap[key]; } + else { return outNodeMap[key]; } + } -// private: -// NodeImpl entry, exit; -// }; + private: + NodeImpl inNodeMap, outNodeMap; + }; -// template -// class EdgeMap : public MapBase { -// typedef typename Parent::template NodeMap NodeImpl; -// typedef typename Parent::template EdgeMap EdgeImpl; -// public: -// EdgeMap(const SplitGraphAdaptorBase& _graph) -// : bind(_graph), orig(_graph) {} -// EdgeMap(const SplitGraphAdaptorBase& _graph, const T& t) -// : bind(_graph, t), orig(_graph, t) {} + template + class EdgeMap : public MapBase { + typedef typename Parent::template EdgeMap EdgeMapImpl; + typedef typename Parent::template NodeMap NodeMapImpl; + public: + + EdgeMap(const SplitGraphAdaptorBase& _graph) + : edge_map(_graph), node_map(_graph) {} + EdgeMap(const SplitGraphAdaptorBase& _graph, const T& t) + : edge_map(_graph, t), node_map(_graph, t) {} -// void set(const Edge& key, const T& val) { -// if ((typename Parent::Edge&)key != INVALID) { orig.set(key, val); } -// else {bind.set(key.bind, val); } -// } + void set(const Edge& key, const T& val) { + if (SplitGraphAdaptorBase::origEdge(key)) { + edge_map.set(key.item.first(), val); + } else { + node_map.set(key.item.second(), val); + } + } -// typename MapTraits::ReturnValue -// operator[](const Edge& key) { -// if ((typename Parent::Edge&)key != INVALID) { return orig[key]; } -// else {return bind[key.bind]; } -// } + typename MapTraits::ReturnValue + operator[](const Edge& key) { + if (SplitGraphAdaptorBase::origEdge(key)) { + return edge_map[key.item.first()]; + } else { + return node_map[key.item.second()]; + } + } -// typename MapTraits::ConstReturnValue -// operator[](const Edge& key) const { -// if ((typename Parent::Edge&)key != INVALID) { return orig[key]; } -// else {return bind[key.bind]; } -// } + typename MapTraits::ConstReturnValue + operator[](const Edge& key) const { + if (SplitGraphAdaptorBase::origEdge(key)) { + return edge_map[key.item.first()]; + } else { + return node_map[key.item.second()]; + } + } -// private: -// typename Parent::template NodeMap bind; -// typename Parent::template EdgeMap orig; -// }; + private: + typename Parent::template EdgeMap edge_map; + typename Parent::template NodeMap node_map; + }; -// template -// class CombinedNodeMap : public MapBase { -// public: -// typedef MapBase Parent; -// typedef typename Parent::Key Key; -// typedef typename Parent::Value Value; + }; -// CombinedNodeMap(EntryMap& _entryMap, ExitMap& _exitMap) -// : entryMap(_entryMap), exitMap(_exitMap) {} + template + class AlterableSplitGraphAdaptor + : public GraphAdaptorExtender > { + public: -// Value& operator[](const Key& key) { -// if (key.entry) { -// return entryMap[key]; -// } else { -// return exitMap[key]; -// } -// } + typedef GraphAdaptorExtender > Parent; + typedef _Graph Graph; -// Value operator[](const Key& key) const { -// if (key.entry) { -// return entryMap[key]; -// } else { -// return exitMap[key]; -// } -// } + typedef typename Graph::Node GraphNode; + typedef typename Graph::Node GraphEdge; -// void set(const Key& key, const Value& value) { -// if (key.entry) { -// entryMap.set(key, value); -// } else { -// exitMap.set(key, value); -// } -// } + protected: + + AlterableSplitGraphAdaptor() : Parent() {} + + public: + + typedef InvalidType NodeNotifier; + typedef InvalidType EdgeNotifier; + + }; + + template + class AlterableSplitGraphAdaptor< + _Graph, + typename enable_if::type, + EdgeEnable> + : public GraphAdaptorExtender > { + public: + + typedef GraphAdaptorExtender > Parent; + typedef _Graph Graph; + + typedef typename Graph::Node GraphNode; + typedef typename Graph::Edge GraphEdge; + + typedef typename Parent::Node Node; + typedef typename Parent::Edge Edge; + + protected: + + AlterableSplitGraphAdaptor() + : Parent(), node_notifier(*this), node_notifier_proxy(*this) {} + + void setGraph(_Graph& graph) { + Parent::setGraph(graph); + node_notifier_proxy.setNotifier(graph.getNotifier(GraphNode())); + } + + public: + + ~AlterableSplitGraphAdaptor() { + node_notifier.clear(); + } + + typedef AlterationNotifier NodeNotifier; + typedef InvalidType EdgeNotifier; + + NodeNotifier& getNotifier(Node) const { return node_notifier; } + + protected: + + class NodeNotifierProxy : public Graph::NodeNotifier::ObserverBase { + public: + + typedef typename Graph::NodeNotifier::ObserverBase Parent; + typedef AlterableSplitGraphAdaptor AdaptorBase; -// private: + NodeNotifierProxy(const AdaptorBase& _adaptor) + : Parent(), adaptor(&_adaptor) { + } + + virtual ~NodeNotifierProxy() { + if (Parent::attached()) { + Parent::detach(); + } + } + + void setNotifier(typename Graph::NodeNotifier& graph_notifier) { + Parent::attach(graph_notifier); + } + -// EntryMap& entryMap; -// ExitMap& exitMap; + protected: + + virtual void add(const GraphNode& gn) { + std::vector nodes; + nodes.push_back(AdaptorBase::Parent::inNode(gn)); + nodes.push_back(AdaptorBase::Parent::outNode(gn)); + adaptor->getNotifier(Node()).add(nodes); + } + + virtual void add(const std::vector& gn) { + std::vector nodes; + for (int i = 0; i < (int)gn.size(); ++i) { + nodes.push_back(AdaptorBase::Parent::inNode(gn[i])); + nodes.push_back(AdaptorBase::Parent::outNode(gn[i])); + } + adaptor->getNotifier(Node()).add(nodes); + } + + virtual void erase(const GraphNode& gn) { + std::vector nodes; + nodes.push_back(AdaptorBase::Parent::inNode(gn)); + nodes.push_back(AdaptorBase::Parent::outNode(gn)); + adaptor->getNotifier(Node()).erase(nodes); + } + + virtual void erase(const std::vector& gn) { + std::vector nodes; + for (int i = 0; i < (int)gn.size(); ++i) { + nodes.push_back(AdaptorBase::Parent::inNode(gn[i])); + nodes.push_back(AdaptorBase::Parent::outNode(gn[i])); + } + adaptor->getNotifier(Node()).erase(nodes); + } + virtual void build() { + adaptor->getNotifier(Node()).build(); + } + virtual void clear() { + adaptor->getNotifier(Node()).clear(); + } + + const AdaptorBase* adaptor; + }; + + + mutable NodeNotifier node_notifier; + + NodeNotifierProxy node_notifier_proxy; + + }; + + template + class AlterableSplitGraphAdaptor< + _Graph, + typename enable_if::type, + typename enable_if::type> + : public GraphAdaptorExtender > { + public: + + typedef GraphAdaptorExtender > Parent; + typedef _Graph Graph; + + typedef typename Graph::Node GraphNode; + typedef typename Graph::Edge GraphEdge; + + typedef typename Parent::Node Node; + typedef typename Parent::Edge Edge; + + protected: + + AlterableSplitGraphAdaptor() + : Parent(), node_notifier(*this), edge_notifier(*this), + node_notifier_proxy(*this), edge_notifier_proxy(*this) {} + + void setGraph(_Graph& graph) { + Parent::setGraph(graph); + node_notifier_proxy.setNotifier(graph.getNotifier(GraphNode())); + edge_notifier_proxy.setNotifier(graph.getNotifier(GraphEdge())); + } + + public: + + ~AlterableSplitGraphAdaptor() { + node_notifier.clear(); + edge_notifier.clear(); + } + + typedef AlterationNotifier NodeNotifier; + typedef AlterationNotifier EdgeNotifier; + + NodeNotifier& getNotifier(Node) const { return node_notifier; } + EdgeNotifier& getNotifier(Edge) const { return edge_notifier; } + + protected: + + class NodeNotifierProxy : public Graph::NodeNotifier::ObserverBase { + public: -// }; + typedef typename Graph::NodeNotifier::ObserverBase Parent; + typedef AlterableSplitGraphAdaptor AdaptorBase; + + NodeNotifierProxy(const AdaptorBase& _adaptor) + : Parent(), adaptor(&_adaptor) { + } -// template -// class CombinedEdgeMap : public MapBase { -// public: -// typedef MapBase Parent; + virtual ~NodeNotifierProxy() { + if (Parent::attached()) { + Parent::detach(); + } + } -// typedef typename Parent::Key Key; -// typedef typename Parent::Value Value; + void setNotifier(typename Graph::NodeNotifier& graph_notifier) { + Parent::attach(graph_notifier); + } -// CombinedEdgeMap(EdgeMap& _edgeMap, NodeMap& _nodeMap) -// : edgeMap(_edgeMap), nodeMap(_nodeMap) {} + + protected: -// void set(const Edge& edge, const Value& val) { -// if (SplitGraphAdaptorBase::originalEdge(edge)) { -// edgeMap.set(edge, val); -// } else { -// nodeMap.set(SplitGraphAdaptorBase::bindedNode(edge), val); -// } -// } + virtual void add(const GraphNode& gn) { + std::vector nodes; + nodes.push_back(AdaptorBase::Parent::inNode(gn)); + nodes.push_back(AdaptorBase::Parent::outNode(gn)); + adaptor->getNotifier(Node()).add(nodes); + adaptor->getNotifier(Edge()).add(AdaptorBase::Parent::edge(gn)); + } + virtual void add(const std::vector& gn) { + std::vector nodes; + std::vector edges; + for (int i = 0; i < (int)gn.size(); ++i) { + edges.push_back(AdaptorBase::Parent::edge(gn[i])); + nodes.push_back(AdaptorBase::Parent::inNode(gn[i])); + nodes.push_back(AdaptorBase::Parent::outNode(gn[i])); + } + adaptor->getNotifier(Node()).add(nodes); + adaptor->getNotifier(Edge()).add(edges); + } + virtual void erase(const GraphNode& gn) { + adaptor->getNotifier(Edge()).erase(AdaptorBase::Parent::edge(gn)); + std::vector nodes; + nodes.push_back(AdaptorBase::Parent::inNode(gn)); + nodes.push_back(AdaptorBase::Parent::outNode(gn)); + adaptor->getNotifier(Node()).erase(nodes); + } + virtual void erase(const std::vector& gn) { + std::vector nodes; + std::vector edges; + for (int i = 0; i < (int)gn.size(); ++i) { + edges.push_back(AdaptorBase::Parent::edge(gn[i])); + nodes.push_back(AdaptorBase::Parent::inNode(gn[i])); + nodes.push_back(AdaptorBase::Parent::outNode(gn[i])); + } + adaptor->getNotifier(Edge()).erase(edges); + adaptor->getNotifier(Node()).erase(nodes); + } + virtual void build() { + std::vector edges; + const typename Parent::Notifier* notifier = Parent::getNotifier(); + GraphNode it; + for (notifier->first(it); it != INVALID; notifier->next(it)) { + edges.push_back(AdaptorBase::Parent::edge(it)); + } + adaptor->getNotifier(Node()).build(); + adaptor->getNotifier(Edge()).add(edges); + } + virtual void clear() { + std::vector edges; + const typename Parent::Notifier* notifier = Parent::getNotifier(); + GraphNode it; + for (notifier->first(it); it != INVALID; notifier->next(it)) { + edges.push_back(AdaptorBase::Parent::edge(it)); + } + adaptor->getNotifier(Edge()).erase(edges); + adaptor->getNotifier(Node()).clear(); + } -// Value operator[](const Key& edge) const { -// if (SplitGraphAdaptorBase::originalEdge(edge)) { -// return edgeMap[edge]; -// } else { -// return nodeMap[SplitGraphAdaptorBase::bindedNode(edge)]; -// } -// } + const AdaptorBase* adaptor; + }; -// Value& operator[](const Key& edge) { -// if (SplitGraphAdaptorBase::originalEdge(edge)) { -// return edgeMap[edge]; -// } else { -// return nodeMap[SplitGraphAdaptorBase::bindedNode(edge)]; -// } -// } + class EdgeNotifierProxy : public Graph::EdgeNotifier::ObserverBase { + public: + + typedef typename Graph::EdgeNotifier::ObserverBase Parent; + typedef AlterableSplitGraphAdaptor AdaptorBase; -// private: -// EdgeMap& edgeMap; -// NodeMap& nodeMap; -// }; + EdgeNotifierProxy(const AdaptorBase& _adaptor) + : Parent(), adaptor(&_adaptor) { + } -// }; + virtual ~EdgeNotifierProxy() { + if (Parent::attached()) { + Parent::detach(); + } + } -// template -// class SplitGraphAdaptor -// : public GraphAdaptorExtender > { -// public: -// typedef GraphAdaptorExtender > Parent; + void setNotifier(typename Graph::EdgeNotifier& graph_notifier) { + Parent::attach(graph_notifier); + } -// SplitGraphAdaptor(_Graph& graph) { -// Parent::setGraph(graph); -// } + + protected: + virtual void add(const GraphEdge& ge) { + adaptor->getNotifier(Edge()).add(AdaptorBase::edge(ge)); + } + virtual void add(const std::vector& ge) { + std::vector edges; + for (int i = 0; i < (int)ge.size(); ++i) { + edges.push_back(AdaptorBase::edge(ge[i])); + } + adaptor->getNotifier(Edge()).add(edges); + } + virtual void erase(const GraphEdge& ge) { + adaptor->getNotifier(Edge()).erase(AdaptorBase::edge(ge)); + } + virtual void erase(const std::vector& ge) { + std::vector edges; + for (int i = 0; i < (int)ge.size(); ++i) { + edges.push_back(AdaptorBase::edge(ge[i])); + } + adaptor->getNotifier(Edge()).erase(edges); + } + virtual void build() { + std::vector edges; + const typename Parent::Notifier* notifier = Parent::getNotifier(); + GraphEdge it; + for (notifier->first(it); it != INVALID; notifier->next(it)) { + edges.push_back(AdaptorBase::Parent::edge(it)); + } + adaptor->getNotifier(Edge()).add(edges); + } + virtual void clear() { + std::vector edges; + const typename Parent::Notifier* notifier = Parent::getNotifier(); + GraphEdge it; + for (notifier->first(it); it != INVALID; notifier->next(it)) { + edges.push_back(AdaptorBase::Parent::edge(it)); + } + adaptor->getNotifier(Edge()).erase(edges); + } -// }; + const AdaptorBase* adaptor; + }; + + + mutable NodeNotifier node_notifier; + mutable EdgeNotifier edge_notifier; + + NodeNotifierProxy node_notifier_proxy; + EdgeNotifierProxy edge_notifier_proxy; + + }; + + /// \ingroup graph_adaptors + /// + /// \brief SplitGraphAdaptor class + /// + /// This is an graph adaptor which splits all node into an in-node + /// and an out-node. Formaly, the adaptor replaces each \f$ u \f$ + /// node in the graph with two node, \f$ u_{in} \f$ node and + /// \f$ u_{out} \f$ node. If there is an \f$ (v, u) \f$ edge in the + /// original graph the new target of the edge will be \f$ u_{in} \f$ and + /// similarly the source of the original \f$ (u, v) \f$ edge will be + /// \f$ u_{out} \f$. The adaptor will add for each node in the + /// original graph an additional edge which will connect + /// \f$ (u_{in}, u_{out}) \f$. + /// + /// The aim of this class is to run algorithm with node costs if the + /// algorithm can use directly just edge costs. In this case we should use + /// a \c SplitGraphAdaptor and set the node cost of the graph to the + /// bind edge in the adapted graph. + /// + /// By example a maximum flow algoritm can compute how many edge + /// disjoint paths are in the graph. But we would like to know how + /// many node disjoint paths are in the graph. First we have to + /// adapt the graph with the \c SplitGraphAdaptor. Then run the flow + /// algorithm on the adapted graph. The bottleneck of the flow will + /// be the bind edges which bounds the flow with the count of the + /// node disjoint paths. + /// + ///\code + /// + /// typedef SplitGraphAdaptor SGraph; + /// + /// SGraph sgraph(graph); + /// + /// typedef ConstMap SCapacity; + /// SCapacity scapacity(1); + /// + /// SGraph::EdgeMap sflow(sgraph); + /// + /// Preflow + /// spreflow(sgraph, SGraph::outNode(source),SGraph::inNode(target), + /// scapacity, sflow); + /// + /// spreflow.run(); + /// + ///\endcode + /// + /// The result of the mamixum flow on the original graph + /// shows the next figure: + /// + /// \image html edge_disjoint.png + /// \image latex edge_disjoint.eps "Edge disjoint paths" width=\textwidth + /// + /// And the maximum flow on the adapted graph: + /// + /// \image html node_disjoint.png + /// \image latex node_disjoint.eps "Node disjoint paths" width=\textwidth + /// + /// The second solution contains just 3 disjoint paths while the first 4. + /// + /// This graph adaptor is fully conform to the + /// \ref concept::StaticGraph "StaticGraph" concept and + /// contains some additional member functions and types. The + /// documentation of some member functions may be found just in the + /// SplitGraphAdaptorBase class. + /// + /// \sa SplitGraphAdaptorBase + template + class SplitGraphAdaptor : public AlterableSplitGraphAdaptor<_Graph> { + public: + typedef AlterableSplitGraphAdaptor<_Graph> Parent; + + typedef typename Parent::Node Node; + typedef typename Parent::Edge Edge; + + /// \brief Constructor of the adaptor. + /// + /// Constructor of the adaptor. + SplitGraphAdaptor(_Graph& graph) { + Parent::setGraph(graph); + } + + /// \brief NodeMap combined from two original NodeMap + /// + /// This class adapt two of the original graph NodeMap to + /// get a node map on the adapted graph. + template + class CombinedNodeMap { + public: + + typedef Node Key; + typedef typename InNodeMap::Value Value; + + /// \brief Constructor + /// + /// Constructor. + CombinedNodeMap(InNodeMap& _inNodeMap, OutNodeMap& _outNodeMap) + : inNodeMap(_inNodeMap), outNodeMap(_outNodeMap) {} + + /// \brief The subscript operator. + /// + /// The subscript operator. + Value& operator[](const Key& key) { + if (Parent::inNode(key)) { + return inNodeMap[key]; + } else { + return outNodeMap[key]; + } + } + + /// \brief The const subscript operator. + /// + /// The const subscript operator. + Value operator[](const Key& key) const { + if (Parent::inNode(key)) { + return inNodeMap[key]; + } else { + return outNodeMap[key]; + } + } + + /// \brief The setter function of the map. + /// + /// The setter function of the map. + void set(const Key& key, const Value& value) { + if (Parent::inNode(key)) { + inNodeMap.set(key, value); + } else { + outNodeMap.set(key, value); + } + } + + private: + + InNodeMap& inNodeMap; + OutNodeMap& outNodeMap; + + }; + + + /// \brief Just gives back a combined node map. + /// + /// Just gives back a combined node map. + template + static CombinedNodeMap + combinedNodeMap(InNodeMap& in_map, OutNodeMap& out_map) { + return CombinedNodeMap(in_map, out_map); + } + + template + static CombinedNodeMap + combinedNodeMap(const InNodeMap& in_map, OutNodeMap& out_map) { + return CombinedNodeMap(in_map, out_map); + } + + template + static CombinedNodeMap + combinedNodeMap(InNodeMap& in_map, const OutNodeMap& out_map) { + return CombinedNodeMap(in_map, out_map); + } + + template + static CombinedNodeMap + combinedNodeMap(const InNodeMap& in_map, const OutNodeMap& out_map) { + return CombinedNodeMap(in_map, out_map); + } + + /// \brief EdgeMap combined from an original EdgeMap and NodeMap + /// + /// This class adapt an original graph EdgeMap and NodeMap to + /// get an edge map on the adapted graph. + template + class CombinedEdgeMap + : public MapBase { + public: + typedef MapBase Parent; + + typedef typename Parent::Key Key; + typedef typename Parent::Value Value; + + /// \brief Constructor + /// + /// Constructor. + CombinedEdgeMap(GraphEdgeMap& _edge_map, GraphNodeMap& _node_map) + : edge_map(_edge_map), node_map(_node_map) {} + + /// \brief The subscript operator. + /// + /// The subscript operator. + void set(const Edge& edge, const Value& val) { + if (Parent::origEdge(edge)) { + edge_map.set(edge, val); + } else { + node_map.set(edge, val); + } + } + + /// \brief The const subscript operator. + /// + /// The const subscript operator. + Value operator[](const Key& edge) const { + if (Parent::origEdge(edge)) { + return edge_map[edge]; + } else { + return node_map[edge]; + } + } + + /// \brief The const subscript operator. + /// + /// The const subscript operator. + Value& operator[](const Key& edge) { + if (Parent::origEdge(edge)) { + return edge_map[edge]; + } else { + return node_map[edge]; + } + } + + private: + GraphEdgeMap& edge_map; + GraphNodeMap& node_map; + }; + + /// \brief Just gives back a combined edge map. + /// + /// Just gives back a combined edge map. + template + static CombinedEdgeMap + combinedEdgeMap(GraphEdgeMap& edge_map, GraphNodeMap& node_map) { + return CombinedEdgeMap(edge_map, node_map); + } + + template + static CombinedEdgeMap + combinedEdgeMap(const GraphEdgeMap& edge_map, GraphNodeMap& node_map) { + return CombinedEdgeMap(edge_map, node_map); + } + + template + static CombinedEdgeMap + combinedEdgeMap(GraphEdgeMap& edge_map, const GraphNodeMap& node_map) { + return CombinedEdgeMap(edge_map, node_map); + } + + template + static CombinedEdgeMap + combinedEdgeMap(const GraphEdgeMap& edge_map, + const GraphNodeMap& node_map) { + return CombinedEdgeMap(edge_map, node_map); + } + + }; + } //namespace lemon