# HG changeset patch # User Alpar Juttner # Date 2008-11-04 11:21:22 # Node ID 99f1bdf8f7dbb8c4ec605c08225df8ded1e730f2 # Parent c6c6e1d863c4594c319451f9984ecad3cf417e8a # Parent aa75d24ba7d085884a4f98a64cddfb7de1ab8925 Merge diff --git a/lemon/Makefile.am b/lemon/Makefile.am --- a/lemon/Makefile.am +++ b/lemon/Makefile.am @@ -28,6 +28,7 @@ lemon/dijkstra.h \ lemon/dim2.h \ lemon/error.h \ + lemon/full_graph.h \ lemon/graph_to_eps.h \ lemon/grid_graph.h \ lemon/kruskal.h \ diff --git a/lemon/full_graph.h b/lemon/full_graph.h new file mode 100644 --- /dev/null +++ b/lemon/full_graph.h @@ -0,0 +1,612 @@ +/* -*- mode: C++; indent-tabs-mode: nil; -*- + * + * This file is a part of LEMON, a generic C++ optimization library. + * + * Copyright (C) 2003-2008 + * 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_FULL_GRAPH_H +#define LEMON_FULL_GRAPH_H + +#include +#include + +///\ingroup graphs +///\file +///\brief FullGraph and FullDigraph classes. + +namespace lemon { + + class FullDigraphBase { + public: + + typedef FullDigraphBase Graph; + + class Node; + class Arc; + + protected: + + int _node_num; + int _arc_num; + + FullDigraphBase() {} + + void construct(int n) { _node_num = n; _arc_num = n * n; } + + public: + + typedef True NodeNumTag; + typedef True ArcNumTag; + + Node operator()(int ix) const { return Node(ix); } + int index(const Node& node) const { return node._id; } + + Arc arc(const Node& s, const Node& t) const { + return Arc(s._id * _node_num + t._id); + } + + int nodeNum() const { return _node_num; } + int arcNum() const { return _arc_num; } + + int maxNodeId() const { return _node_num - 1; } + int maxArcId() const { return _arc_num - 1; } + + Node source(Arc arc) const { return arc._id / _node_num; } + Node target(Arc arc) const { return arc._id % _node_num; } + + static int id(Node node) { return node._id; } + static int id(Arc arc) { return arc._id; } + + static Node nodeFromId(int id) { return Node(id);} + static Arc arcFromId(int id) { return Arc(id);} + + typedef True FindArcTag; + + Arc findArc(Node s, Node t, Arc prev = INVALID) const { + return prev == INVALID ? arc(s, t) : INVALID; + } + + class Node { + friend class FullDigraphBase; + + protected: + int _id; + Node(int id) : _id(id) {} + public: + Node() {} + Node (Invalid) : _id(-1) {} + bool operator==(const Node node) const {return _id == node._id;} + bool operator!=(const Node node) const {return _id != node._id;} + bool operator<(const Node node) const {return _id < node._id;} + }; + + class Arc { + friend class FullDigraphBase; + + protected: + int _id; // _node_num * source + target; + + Arc(int id) : _id(id) {} + + public: + Arc() { } + Arc (Invalid) { _id = -1; } + bool operator==(const Arc arc) const {return _id == arc._id;} + bool operator!=(const Arc arc) const {return _id != arc._id;} + bool operator<(const Arc arc) const {return _id < arc._id;} + }; + + void first(Node& node) const { + node._id = _node_num - 1; + } + + static void next(Node& node) { + --node._id; + } + + void first(Arc& arc) const { + arc._id = _arc_num - 1; + } + + static void next(Arc& arc) { + --arc._id; + } + + void firstOut(Arc& arc, const Node& node) const { + arc._id = (node._id + 1) * _node_num - 1; + } + + void nextOut(Arc& arc) const { + if (arc._id % _node_num == 0) arc._id = 0; + --arc._id; + } + + void firstIn(Arc& arc, const Node& node) const { + arc._id = _arc_num + node._id - _node_num; + } + + void nextIn(Arc& arc) const { + arc._id -= _node_num; + if (arc._id < 0) arc._id = -1; + } + + }; + + typedef DigraphExtender ExtendedFullDigraphBase; + + /// \ingroup graphs + /// + /// \brief A full digraph class. + /// + /// This is a simple and fast directed full graph implementation. + /// From each node go arcs to each node (including the source node), + /// therefore the number of the arcs in the digraph is the square of + /// the node number. This digraph type is completely static, so you + /// can neither add nor delete either arcs or nodes, and it needs + /// constant space in memory. + /// + /// This class conforms to the \ref concepts::Digraph "Digraph" concept + /// and it also has an important extra feature that its maps are + /// real \ref concepts::ReferenceMap "reference map"s. + /// + /// The \c FullDigraph and \c FullGraph classes are very similar, + /// but there are two differences. While this class conforms only + /// to the \ref concepts::Digraph "Digraph" concept, the \c FullGraph + /// class conforms to the \ref concepts::Graph "Graph" concept, + /// moreover \c FullGraph does not contain a loop arc for each + /// node as \c FullDigraph does. + /// + /// \sa FullGraph + class FullDigraph : public ExtendedFullDigraphBase { + public: + + typedef ExtendedFullDigraphBase Parent; + + /// \brief Constructor + FullDigraph() { construct(0); } + + /// \brief Constructor + /// + /// Constructor. + /// \param n The number of the nodes. + FullDigraph(int n) { construct(n); } + + /// \brief Resizes the digraph + /// + /// Resizes the digraph. The function will fully destroy and + /// rebuild the digraph. This cause that the maps of the digraph will + /// reallocated automatically and the previous values will be lost. + void resize(int n) { + Parent::notifier(Arc()).clear(); + Parent::notifier(Node()).clear(); + construct(n); + Parent::notifier(Node()).build(); + Parent::notifier(Arc()).build(); + } + + /// \brief Returns the node with the given index. + /// + /// Returns the node with the given index. Since it is a static + /// digraph its nodes can be indexed with integers from the range + /// [0..nodeNum()-1]. + /// \sa index() + Node operator()(int ix) const { return Parent::operator()(ix); } + + /// \brief Returns the index of the given node. + /// + /// Returns the index of the given node. Since it is a static + /// digraph its nodes can be indexed with integers from the range + /// [0..nodeNum()-1]. + /// \sa operator() + int index(const Node& node) const { return Parent::index(node); } + + /// \brief Returns the arc connecting the given nodes. + /// + /// Returns the arc connecting the given nodes. + Arc arc(const Node& u, const Node& v) const { + return Parent::arc(u, v); + } + + /// \brief Number of nodes. + int nodeNum() const { return Parent::nodeNum(); } + /// \brief Number of arcs. + int arcNum() const { return Parent::arcNum(); } + }; + + + class FullGraphBase { + int _node_num; + int _edge_num; + public: + + typedef FullGraphBase Graph; + + class Node; + class Arc; + class Edge; + + protected: + + FullGraphBase() {} + + void construct(int n) { _node_num = n; _edge_num = n * (n - 1) / 2; } + + int _uid(int e) const { + int u = e / _node_num; + int v = e % _node_num; + return u < v ? u : _node_num - 2 - u; + } + + int _vid(int e) const { + int u = e / _node_num; + int v = e % _node_num; + return u < v ? v : _node_num - 1 - v; + } + + void _uvid(int e, int& u, int& v) const { + u = e / _node_num; + v = e % _node_num; + if (u >= v) { + u = _node_num - 2 - u; + v = _node_num - 1 - v; + } + } + + void _stid(int a, int& s, int& t) const { + if ((a & 1) == 1) { + _uvid(a >> 1, s, t); + } else { + _uvid(a >> 1, t, s); + } + } + + int _eid(int u, int v) const { + if (u < (_node_num - 1) / 2) { + return u * _node_num + v; + } else { + return (_node_num - 1 - u) * _node_num - v - 1; + } + } + + public: + + Node operator()(int ix) const { return Node(ix); } + int index(const Node& node) const { return node._id; } + + Edge edge(const Node& u, const Node& v) const { + if (u._id < v._id) { + return Edge(_eid(u._id, v._id)); + } else if (u._id != v._id) { + return Edge(_eid(v._id, u._id)); + } else { + return INVALID; + } + } + + Arc arc(const Node& s, const Node& t) const { + if (s._id < t._id) { + return Arc((_eid(s._id, t._id) << 1) | 1); + } else if (s._id != t._id) { + return Arc(_eid(t._id, s._id) << 1); + } else { + return INVALID; + } + } + + typedef True NodeNumTag; + typedef True EdgeNumTag; + + int nodeNum() const { return _node_num; } + int arcNum() const { return 2 * _edge_num; } + int edgeNum() const { return _edge_num; } + + static int id(Node node) { return node._id; } + static int id(Arc arc) { return arc._id; } + static int id(Edge edge) { return edge._id; } + + int maxNodeId() const { return _node_num-1; } + int maxArcId() const { return 2 * _edge_num-1; } + int maxEdgeId() const { return _edge_num-1; } + + static Node nodeFromId(int id) { return Node(id);} + static Arc arcFromId(int id) { return Arc(id);} + static Edge edgeFromId(int id) { return Edge(id);} + + Node u(Edge edge) const { + return Node(_uid(edge._id)); + } + + Node v(Edge edge) const { + return Node(_vid(edge._id)); + } + + Node source(Arc arc) const { + return Node((arc._id & 1) == 1 ? + _uid(arc._id >> 1) : _vid(arc._id >> 1)); + } + + Node target(Arc arc) const { + return Node((arc._id & 1) == 1 ? + _vid(arc._id >> 1) : _uid(arc._id >> 1)); + } + + typedef True FindEdgeTag; + + Edge findEdge(Node u, Node v, Edge prev = INVALID) const { + return prev != INVALID ? INVALID : edge(u, v); + } + + Arc findArc(Node s, Node t, Arc prev = INVALID) const { + return prev != INVALID ? INVALID : arc(s, t); + } + + class Node { + friend class FullGraphBase; + + protected: + int _id; + Node(int id) : _id(id) {} + public: + Node() {} + Node (Invalid) { _id = -1; } + bool operator==(const Node node) const {return _id == node._id;} + bool operator!=(const Node node) const {return _id != node._id;} + bool operator<(const Node node) const {return _id < node._id;} + }; + + class Edge { + friend class FullGraphBase; + friend class Arc; + + protected: + int _id; + + Edge(int id) : _id(id) {} + + public: + Edge() { } + Edge (Invalid) { _id = -1; } + + bool operator==(const Edge edge) const {return _id == edge._id;} + bool operator!=(const Edge edge) const {return _id != edge._id;} + bool operator<(const Edge edge) const {return _id < edge._id;} + }; + + class Arc { + friend class FullGraphBase; + + protected: + int _id; + + Arc(int id) : _id(id) {} + + public: + Arc() { } + Arc (Invalid) { _id = -1; } + + operator Edge() const { return Edge(_id != -1 ? (_id >> 1) : -1); } + + bool operator==(const Arc arc) const {return _id == arc._id;} + bool operator!=(const Arc arc) const {return _id != arc._id;} + bool operator<(const Arc arc) const {return _id < arc._id;} + }; + + static bool direction(Arc arc) { + return (arc._id & 1) == 1; + } + + static Arc direct(Edge edge, bool dir) { + return Arc((edge._id << 1) | (dir ? 1 : 0)); + } + + void first(Node& node) const { + node._id = _node_num - 1; + } + + static void next(Node& node) { + --node._id; + } + + void first(Arc& arc) const { + arc._id = (_edge_num << 1) - 1; + } + + static void next(Arc& arc) { + --arc._id; + } + + void first(Edge& edge) const { + edge._id = _edge_num - 1; + } + + static void next(Edge& edge) { + --edge._id; + } + + void firstOut(Arc& arc, const Node& node) const { + int s = node._id, t = _node_num - 1; + if (s < t) { + arc._id = (_eid(s, t) << 1) | 1; + } else { + --t; + arc._id = (t != -1 ? (_eid(t, s) << 1) : -1); + } + } + + void nextOut(Arc& arc) const { + int s, t; + _stid(arc._id, s, t); + --t; + if (s < t) { + arc._id = (_eid(s, t) << 1) | 1; + } else { + if (s == t) --t; + arc._id = (t != -1 ? (_eid(t, s) << 1) : -1); + } + } + + void firstIn(Arc& arc, const Node& node) const { + int s = _node_num - 1, t = node._id; + if (s > t) { + arc._id = (_eid(t, s) << 1); + } else { + --s; + arc._id = (s != -1 ? (_eid(s, t) << 1) | 1 : -1); + } + } + + void nextIn(Arc& arc) const { + int s, t; + _stid(arc._id, s, t); + --s; + if (s > t) { + arc._id = (_eid(t, s) << 1); + } else { + if (s == t) --s; + arc._id = (s != -1 ? (_eid(s, t) << 1) | 1 : -1); + } + } + + void firstInc(Edge& edge, bool& dir, const Node& node) const { + int u = node._id, v = _node_num - 1; + if (u < v) { + edge._id = _eid(u, v); + dir = true; + } else { + --v; + edge._id = (v != -1 ? _eid(v, u) : -1); + dir = false; + } + } + + void nextInc(Edge& edge, bool& dir) const { + int u, v; + if (dir) { + _uvid(edge._id, u, v); + --v; + if (u < v) { + edge._id = _eid(u, v); + } else { + --v; + edge._id = (v != -1 ? _eid(v, u) : -1); + dir = false; + } + } else { + _uvid(edge._id, v, u); + --v; + edge._id = (v != -1 ? _eid(v, u) : -1); + } + } + + }; + + typedef GraphExtender ExtendedFullGraphBase; + + /// \ingroup graphs + /// + /// \brief An undirected full graph class. + /// + /// This is a simple and fast undirected full graph + /// implementation. From each node go edge to each other node, + /// therefore the number of edges in the graph is \f$n(n-1)/2\f$. + /// This graph type is completely static, so you can neither + /// add nor delete either edges or nodes, and it needs constant + /// space in memory. + /// + /// This class conforms to the \ref concepts::Graph "Graph" concept + /// and it also has an important extra feature that its maps are + /// real \ref concepts::ReferenceMap "reference map"s. + /// + /// The \c FullGraph and \c FullDigraph classes are very similar, + /// but there are two differences. While the \c FullDigraph class + /// conforms only to the \ref concepts::Digraph "Digraph" concept, + /// this class conforms to the \ref concepts::Graph "Graph" concept, + /// moreover \c FullGraph does not contain a loop arc for each + /// node as \c FullDigraph does. + /// + /// \sa FullDigraph + class FullGraph : public ExtendedFullGraphBase { + public: + + typedef ExtendedFullGraphBase Parent; + + /// \brief Constructor + FullGraph() { construct(0); } + + /// \brief Constructor + /// + /// Constructor. + /// \param n The number of the nodes. + FullGraph(int n) { construct(n); } + + /// \brief Resizes the graph + /// + /// Resizes the graph. The function will fully destroy and + /// rebuild the graph. This cause that the maps of the graph will + /// reallocated automatically and the previous values will be lost. + void resize(int n) { + Parent::notifier(Arc()).clear(); + Parent::notifier(Edge()).clear(); + Parent::notifier(Node()).clear(); + construct(n); + Parent::notifier(Node()).build(); + Parent::notifier(Edge()).build(); + Parent::notifier(Arc()).build(); + } + + /// \brief Returns the node with the given index. + /// + /// Returns the node with the given index. Since it is a static + /// graph its nodes can be indexed with integers from the range + /// [0..nodeNum()-1]. + /// \sa index() + Node operator()(int ix) const { return Parent::operator()(ix); } + + /// \brief Returns the index of the given node. + /// + /// Returns the index of the given node. Since it is a static + /// graph its nodes can be indexed with integers from the range + /// [0..nodeNum()-1]. + /// \sa operator() + int index(const Node& node) const { return Parent::index(node); } + + /// \brief Returns the arc connecting the given nodes. + /// + /// Returns the arc connecting the given nodes. + Arc arc(const Node& s, const Node& t) const { + return Parent::arc(s, t); + } + + /// \brief Returns the edge connects the given nodes. + /// + /// Returns the edge connects the given nodes. + Edge edge(const Node& u, const Node& v) const { + return Parent::edge(u, v); + } + + /// \brief Number of nodes. + int nodeNum() const { return Parent::nodeNum(); } + /// \brief Number of arcs. + int arcNum() const { return Parent::arcNum(); } + /// \brief Number of edges. + int edgeNum() const { return Parent::edgeNum(); } + + }; + + +} //namespace lemon + + +#endif //LEMON_FULL_GRAPH_H diff --git a/test/digraph_test.cc b/test/digraph_test.cc --- a/test/digraph_test.cc +++ b/test/digraph_test.cc @@ -19,7 +19,7 @@ #include #include #include -//#include +#include //#include #include "test_tools.h" @@ -79,6 +79,39 @@ } +void checkFullDigraph(int num) { + typedef FullDigraph Digraph; + DIGRAPH_TYPEDEFS(Digraph); + Digraph G(num); + + checkGraphNodeList(G, num); + checkGraphArcList(G, num * num); + + for (NodeIt n(G); n != INVALID; ++n) { + checkGraphOutArcList(G, n, num); + checkGraphInArcList(G, n, num); + } + + checkGraphConArcList(G, num * num); + + checkNodeIds(G); + checkArcIds(G); + checkGraphNodeMap(G); + checkGraphArcMap(G); + + for (int i = 0; i < G.nodeNum(); ++i) { + check(G.index(G(i)) == i, "Wrong index"); + } + + for (NodeIt s(G); s != INVALID; ++s) { + for (NodeIt t(G); t != INVALID; ++t) { + Arc a = G.arc(s, t); + check(G.source(a) == s && G.target(a) == t, "Wrong arc lookup"); + } + } + +} + void checkConcepts() { { // Checking digraph components @@ -109,9 +142,9 @@ checkConcept, SmartDigraph>(); checkConcept, SmartDigraph>(); } -// { // Checking FullDigraph -// checkConcept(); -// } + { // Checking FullDigraph + checkConcept(); + } // { // Checking HyperCubeDigraph // checkConcept(); // } @@ -176,6 +209,9 @@ checkDigraph(); checkDigraphValidity(); } + { // Checking FullDigraph + checkFullDigraph(8); + } } int main() { diff --git a/test/graph_test.cc b/test/graph_test.cc --- a/test/graph_test.cc +++ b/test/graph_test.cc @@ -19,7 +19,7 @@ #include #include #include -// #include +#include #include #include "test_tools.h" @@ -95,6 +95,53 @@ checkGraphEdgeMap(G); } +void checkFullGraph(int num) { + typedef FullGraph Graph; + GRAPH_TYPEDEFS(Graph); + + Graph G(num); + checkGraphNodeList(G, num); + checkGraphEdgeList(G, num * (num - 1) / 2); + + for (NodeIt n(G); n != INVALID; ++n) { + checkGraphOutArcList(G, n, num - 1); + checkGraphInArcList(G, n, num - 1); + checkGraphIncEdgeList(G, n, num - 1); + } + + checkGraphConArcList(G, num * (num - 1)); + checkGraphConEdgeList(G, num * (num - 1) / 2); + + checkArcDirections(G); + + checkNodeIds(G); + checkArcIds(G); + checkEdgeIds(G); + checkGraphNodeMap(G); + checkGraphArcMap(G); + checkGraphEdgeMap(G); + + + for (int i = 0; i < G.nodeNum(); ++i) { + check(G.index(G(i)) == i, "Wrong index"); + } + + for (NodeIt u(G); u != INVALID; ++u) { + for (NodeIt v(G); v != INVALID; ++v) { + Edge e = G.edge(u, v); + Arc a = G.arc(u, v); + if (u == v) { + check(e == INVALID, "Wrong edge lookup"); + check(a == INVALID, "Wrong arc lookup"); + } else { + check((G.u(e) == u && G.v(e) == v) || + (G.u(e) == v && G.v(e) == u), "Wrong edge lookup"); + check(G.source(a) == u && G.target(a) == v, "Wrong arc lookup"); + } + } + } +} + void checkConcepts() { { // Checking graph components checkConcept(); @@ -124,10 +171,9 @@ checkConcept, SmartGraph>(); checkConcept, SmartGraph>(); } -// { // Checking FullGraph -// checkConcept(); -// checkGraphIterators(); -// } + { // Checking FullGraph + checkConcept(); + } { // Checking GridGraph checkConcept(); } @@ -275,11 +321,10 @@ checkGraph(); checkGraphValidity(); } -// { // Checking FullGraph -// FullGraph g(5); -// checkGraphNodeList(g, 5); -// checkGraphEdgeList(g, 10); -// } + { // Checking FullGraph + checkFullGraph(7); + checkFullGraph(8); + } { // Checking GridGraph checkGridGraph(5, 8); checkGridGraph(8, 5);