/* -*- C++ -*- * lemon/smart_graph.h - Part of LEMON, a generic C++ optimization library * * Copyright (C) 2006 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport * (Egervary Research Group on Combinatorial Optimization, EGRES). * * Permission to use, modify and distribute this software is granted * provided that this copyright notice appears in all copies. For * precise terms see the accompanying LICENSE file. * * This software is provided "AS IS" with no warranty of any kind, * express or implied, and with no claim as to its suitability for any * purpose. * */ #ifndef LEMON_SMART_GRAPH_H #define LEMON_SMART_GRAPH_H ///\ingroup graphs ///\file ///\brief SmartGraph and SmartUGraph classes. #include #include #include #include #include #include #include #include #include #include namespace lemon { class SmartGraph; ///Base of SmartGraph ///Base of SmartGraph /// class SmartGraphBase { friend class SmatGraph; protected: struct NodeT { int first_in,first_out; NodeT() : first_in(-1), first_out(-1) {} }; struct EdgeT { int target, source, next_in, next_out; //FIXME: is this necessary? EdgeT() : next_in(-1), next_out(-1) {} }; std::vector nodes; std::vector edges; public: typedef SmartGraphBase Graph; class Node; class Edge; public: SmartGraphBase() : nodes(), edges() { } SmartGraphBase(const SmartGraphBase &_g) : nodes(_g.nodes), edges(_g.edges) { } typedef True NodeNumTag; typedef True EdgeNumTag; ///Number of nodes. int nodeNum() const { return nodes.size(); } ///Number of edges. int edgeNum() const { return edges.size(); } /// Maximum node ID. /// Maximum node ID. ///\sa id(Node) int maxNodeId() const { return nodes.size()-1; } /// Maximum edge ID. /// Maximum edge ID. ///\sa id(Edge) int maxEdgeId() const { return edges.size()-1; } Node source(Edge e) const { return edges[e.n].source; } Node target(Edge e) const { return edges[e.n].target; } /// Node ID. /// The ID of a valid Node is a nonnegative integer not greater than /// \ref maxNodeId(). The range of the ID's is not surely continuous /// and the greatest node ID can be actually less then \ref maxNodeId(). /// /// The ID of the \ref INVALID node is -1. ///\return The ID of the node \c v. static int id(Node v) { return v.n; } /// Edge ID. /// The ID of a valid Edge is a nonnegative integer not greater than /// \ref maxEdgeId(). The range of the ID's is not surely continuous /// and the greatest edge ID can be actually less then \ref maxEdgeId(). /// /// The ID of the \ref INVALID edge is -1. ///\return The ID of the edge \c e. static int id(Edge e) { return e.n; } static Node nodeFromId(int id) { return Node(id);} static Edge edgeFromId(int id) { return Edge(id);} Node addNode() { Node n; n.n=nodes.size(); nodes.push_back(NodeT()); //FIXME: Hmmm... return n; } Edge addEdge(Node u, Node v) { Edge e; e.n=edges.size(); edges.push_back(EdgeT()); //FIXME: Hmmm... edges[e.n].source=u.n; edges[e.n].target=v.n; edges[e.n].next_out=nodes[u.n].first_out; edges[e.n].next_in=nodes[v.n].first_in; nodes[u.n].first_out=nodes[v.n].first_in=e.n; return e; } void clear() { edges.clear(); nodes.clear(); } class Node { friend class SmartGraphBase; friend class SmartGraph; protected: int n; Node(int nn) {n=nn;} public: Node() {} Node (Invalid) { n=-1; } bool operator==(const Node i) const {return n==i.n;} bool operator!=(const Node i) const {return n!=i.n;} bool operator<(const Node i) const {return n > > > > > ExtendedSmartGraphBase; /// \ingroup graphs ///A smart graph class. ///This is a simple and fast graph implementation. ///It is also quite memory efficient, but at the price ///that it does support only limited (only stack-like) ///node and edge deletions. ///It conforms to ///the \ref concept::ExtendableGraph "ExtendableGraph" concept. ///\sa concept::ExtendableGraph. /// ///\author Alpar Juttner class SmartGraph : public ExtendedSmartGraphBase { public: class Snapshot; friend class Snapshot; protected: void restoreSnapshot(const Snapshot &s) { while(s.edge_numEdges ///referencing a moved edge remain ///valid. However InEdge's and OutEdge's ///may be invalidated. ///\warning This functionality cannot be used together with the Snapshot ///feature. ///\todo It could be implemented in a bit faster way. Node split(Node n, bool connect = true) { Node b = _split(n,connect); return b; } ///Class to make a snapshot of the graph and to restrore to it later. ///Class to make a snapshot of the graph and to restrore to it later. /// ///The newly added nodes and edges can be removed using the ///restore() function. ///\note After you restore a state, you cannot restore ///a later state, in other word you cannot add again the edges deleted ///by restore() using another Snapshot instance. /// class Snapshot { SmartGraph *g; protected: friend class SmartGraph; unsigned int node_num; unsigned int edge_num; public: ///Default constructor. ///Default constructor. ///To actually make a snapshot you must call save(). /// Snapshot() : g(0) {} ///Constructor that immediately makes a snapshot ///This constructor immediately makes a snapshot of the graph. ///\param _g The graph we make a snapshot of. Snapshot(SmartGraph &_g) :g(&_g) { node_num=g->nodes.size(); edge_num=g->edges.size(); } ///Make a snapshot. ///Make a snapshot of the graph. /// ///This function can be called more than once. In case of a repeated ///call, the previous snapshot gets lost. ///\param _g The graph we make the snapshot of. void save(SmartGraph &_g) { g=&_g; node_num=g->nodes.size(); edge_num=g->edges.size(); } ///Undo the changes until a snapshot. ///Undo the changes until a snapshot created by save(). /// ///\note After you restored a state, you cannot restore ///a later state, in other word you cannot add again the edges deleted ///by restore(). /// ///\todo This function might be called undo(). void restore() { g->restoreSnapshot(*this); } }; }; /**************** Undirected List Graph ****************/ typedef ClearableUGraphExtender< ExtendableUGraphExtender< MappableUGraphExtender< IterableUGraphExtender< AlterableUGraphExtender< UGraphExtender > > > > > ExtendedSmartUGraphBase; /// \ingroup graphs /// /// \brief A smart undirected graph class. /// /// This is a simple and fast undirected graph implementation. /// It is also quite memory efficient, but at the price /// that it does support only limited (only stack-like) /// node and edge deletions. /// Except from this it conforms to /// the \ref concept::UGraph "UGraph" concept. /// \sa concept::UGraph. /// /// \todo Snapshot hasn't been implemented yet. /// class SmartUGraph : public ExtendedSmartUGraphBase { }; class SmartBpUGraphBase { public: class NodeSetError : public LogicError { virtual const char* exceptionName() const { return "lemon::SmartBpUGraph::NodeSetError"; } }; protected: struct NodeT { int first; NodeT() {} NodeT(int _first) : first(_first) {} }; struct EdgeT { int aNode, next_out; int bNode, next_in; }; std::vector aNodes; std::vector bNodes; std::vector edges; public: class Node { friend class SmartBpUGraphBase; protected: int id; Node(int _id) : id(_id) {} public: Node() {} Node(Invalid) { id = -1; } bool operator==(const Node i) const {return id==i.id;} bool operator!=(const Node i) const {return id!=i.id;} bool operator<(const Node i) const {return id 0) { node.id = 2 * aNodes.size() - 2; } else { node.id = 2 * bNodes.size() - 1; } } void next(Node& node) const { node.id -= 2; if (node.id == -2) { node.id = 2 * bNodes.size() - 1; } } void first(Edge& edge) const { edge.id = edges.size() - 1; } void next(Edge& edge) const { --edge.id; } void firstOut(Edge& edge, const Node& node) const { LEMON_ASSERT((node.id & 1) == 0, NodeSetError()); edge.id = aNodes[node.id >> 1].first; } void nextOut(Edge& edge) const { edge.id = edges[edge.id].next_out; } void firstIn(Edge& edge, const Node& node) const { LEMON_ASSERT((node.id & 1) == 1, NodeSetError()); edge.id = bNodes[node.id >> 1].first; } void nextIn(Edge& edge) const { edge.id = edges[edge.id].next_in; } static int id(const Node& node) { return node.id; } static Node nodeFromId(int id) { return Node(id); } int maxNodeId() const { return aNodes.size() > bNodes.size() ? aNodes.size() * 2 - 2 : bNodes.size() * 2 - 1; } static int id(const Edge& edge) { return edge.id; } static Edge edgeFromId(int id) { return Edge(id); } int maxEdgeId() const { return edges.size(); } static int aNodeId(const Node& node) { return node.id >> 1; } static Node fromANodeId(int id, Node) { return Node(id << 1); } int maxANodeId() const { return aNodes.size(); } static int bNodeId(const Node& node) { return node.id >> 1; } static Node fromBNodeId(int id) { return Node((id << 1) + 1); } int maxBNodeId() const { return bNodes.size(); } Node aNode(const Edge& edge) const { return Node(edges[edge.id].aNode); } Node bNode(const Edge& edge) const { return Node(edges[edge.id].bNode); } static bool aNode(const Node& node) { return (node.id & 1) == 0; } static bool bNode(const Node& node) { return (node.id & 1) == 1; } Node addANode() { NodeT nodeT; nodeT.first = -1; aNodes.push_back(nodeT); return Node(aNodes.size() * 2 - 2); } Node addBNode() { NodeT nodeT; nodeT.first = -1; bNodes.push_back(nodeT); return Node(bNodes.size() * 2 - 1); } Edge addEdge(const Node& source, const Node& target) { LEMON_ASSERT(((source.id ^ target.id) & 1) == 1, NodeSetError()); EdgeT edgeT; if ((source.id & 1) == 0) { edgeT.aNode = source.id; edgeT.bNode = target.id; } else { edgeT.aNode = target.id; edgeT.bNode = source.id; } edgeT.next_out = aNodes[edgeT.aNode >> 1].first; aNodes[edgeT.aNode >> 1].first = edges.size(); edgeT.next_in = bNodes[edgeT.bNode >> 1].first; bNodes[edgeT.bNode >> 1].first = edges.size(); edges.push_back(edgeT); return Edge(edges.size() - 1); } void clear() { aNodes.clear(); bNodes.clear(); edges.clear(); } }; typedef ClearableBpUGraphExtender< ExtendableBpUGraphExtender< MappableBpUGraphExtender< IterableBpUGraphExtender< AlterableBpUGraphExtender< BpUGraphExtender < SmartBpUGraphBase> > > > > > ExtendedSmartBpUGraphBase; /// \ingroup graphs /// /// \brief A smart bipartite undirected graph class. /// /// This is a simple and fast bipartite undirected graph implementation. /// It is also quite memory efficient, but at the price /// that it does not support node and edge deletions. /// Except from this it conforms to /// the \ref concept::BpUGraph "BpUGraph" concept. /// \sa concept::BpUGraph. /// class SmartBpUGraph : public ExtendedSmartBpUGraphBase {}; /// @} } //namespace lemon #endif //LEMON_SMART_GRAPH_H