/* -*- C++ -*- * lemon/smart_graph.h - Part of LEMON, a generic C++ optimization library * * Copyright (C) 2005 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 UndirSmartGraph 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 ClearableUndirGraphExtender< ExtendableUndirGraphExtender< MappableUndirGraphExtender< IterableUndirGraphExtender< AlterableUndirGraphExtender< UndirGraphExtender > > > > > ExtendedUndirSmartGraphBase; ///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::UndirGraph "UndirGraph" concept. ///\sa concept::UndirGraph. /// ///\todo Snapshot hasn't been implemented yet. /// class UndirSmartGraph : public ExtendedUndirSmartGraphBase { }; class SmartUndirBipartiteGraphBase { public: class NodeSetError : public LogicError { virtual const char* exceptionName() const { return "lemon::FullUndirBipartiteGraph::NodeSetError"; } }; protected: struct NodeT { int first; NodeT() {} NodeT(int _first) : first(_first) {} }; struct EdgeT { int upper, next_down; int lower, next_up; }; std::vector upperNodes; std::vector lowerNodes; std::vector edges; public: class Node { friend class SmartUndirBipartiteGraphBase; 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 * upperNodes.size() - 2; } else { node.id = 2 * lowerNodes.size() - 1; } } void next(Node& node) const { node.id -= 2; if (node.id == -2) { node.id = 2 * lowerNodes.size() - 1; } } void first(Edge& edge) const { edge.id = edges.size() - 1; } void next(Edge& edge) const { --edge.id; } void firstDown(Edge& edge, const Node& node) const { LEMON_ASSERT((node.id & 1) == 0, NodeSetError()); edge.id = upperNodes[node.id >> 1].first; } void nextDown(Edge& edge) const { edge.id = edges[edge.id].next_down; } void firstUp(Edge& edge, const Node& node) const { LEMON_ASSERT((node.id & 1) == 1, NodeSetError()); edge.id = lowerNodes[node.id >> 1].first; } void nextUp(Edge& edge) const { edge.id = edges[edge.id].next_up; } static int id(const Node& node) { return node.id; } static Node nodeFromId(int id) { return Node(id); } int maxNodeId() const { return upperNodes.size() > lowerNodes.size() ? upperNodes.size() * 2 - 2 : lowerNodes.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 upperId(const Node& node) { return node.id >> 1; } static Node fromUpperId(int id, Node) { return Node(id << 1); } int maxUpperId() const { return upperNodes.size(); } static int lowerId(const Node& node) { return node.id >> 1; } static Node fromLowerId(int id) { return Node((id << 1) + 1); } int maxLowerId() const { return lowerNodes.size(); } Node upperNode(const Edge& edge) const { return Node(edges[edge.id].upper); } Node lowerNode(const Edge& edge) const { return Node(edges[edge.id].lower); } static bool upper(const Node& node) { return (node.id & 1) == 0; } static bool lower(const Node& node) { return (node.id & 1) == 1; } Node addUpperNode() { NodeT nodeT; nodeT.first = -1; upperNodes.push_back(nodeT); return Node(upperNodes.size() * 2 - 2); } Node addLowerNode() { NodeT nodeT; nodeT.first = -1; lowerNodes.push_back(nodeT); return Node(lowerNodes.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.upper = source.id; edgeT.lower = target.id; } else { edgeT.upper = target.id; edgeT.lower = source.id; } edgeT.next_down = upperNodes[edgeT.upper >> 1].first; upperNodes[edgeT.upper >> 1].first = edges.size(); edgeT.next_up = lowerNodes[edgeT.lower >> 1].first; lowerNodes[edgeT.lower >> 1].first = edges.size(); edges.push_back(edgeT); return Edge(edges.size() - 1); } void clear() { upperNodes.clear(); lowerNodes.clear(); edges.clear(); } }; typedef ClearableUndirBipartiteGraphExtender< ExtendableUndirBipartiteGraphExtender< MappableUndirBipartiteGraphExtender< IterableUndirBipartiteGraphExtender< AlterableUndirBipartiteGraphExtender< UndirBipartiteGraphExtender < SmartUndirBipartiteGraphBase> > > > > > ExtendedSmartUndirBipartiteGraphBase; class SmartUndirBipartiteGraph : public ExtendedSmartUndirBipartiteGraphBase { }; /// @} } //namespace lemon #endif //LEMON_SMART_GRAPH_H