/* ---- This file is part of SECONDO. Copyright (C) 2004, University in Hagen, Department of Computer Science, Database Systems for New Applications. SECONDO is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. SECONDO is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with SECONDO; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ---- //paragraph [1] Title: [{\Large \bf \begin {center}] [\end {center}}] //[TOC] [\tableofcontents] [1] Header File of the Graph Algebra February 2007, G. Barz, M. Stein, A. Ruloffs, A. Martin [TOC] 1 Overview This header file essentially contains the definition of the classes ~Vertex~, ~Edge~, ~Path~, and ~Graph~ used in the Graph Algebra. These classes respectively correspond to the memory representation for the type constructors ~vertex~, ~edge~, ~path~, and ~graph~. 2 Defines and includes */ #ifndef GRAPHALGEBRA_H_ #define GRAPHALGEBRA_H_ #include #include #include "Tools/Flob/DbArray.h" //needed in graph and path #include "Algebras/Spatial/SpatialAlgebra.h" //needed for Points #include "Algebra.h" //always needed in Algebras #include "NestedList.h" //always needed in Algebras #include "QueryProcessor.h" //always needed in Algebras #include "StandardTypes.h" //always needed in Algebras #include "StringUtils.h" extern NestedList* nl; extern QueryProcessor *qp; /* 3 Class Vertex */ class Vertex: public Attribute { public: /* 3.1 Constructors and Destructor */ Vertex(); Vertex(bool d):Attribute(d), key(0),pos(false,0,0) { } Vertex(int nKey, Point const & pntPos): Attribute(true),key(nKey), pos(pntPos){ } Vertex(int nKey, Coord coordX, Coord coordY): Attribute(true), key(nKey), pos(true,coordX,coordY){ } ~Vertex(); /* 3.2 Get functions 3.2.1 GetKey */ int GetKey() const{return key;} int GetIntval() const {return key;} /* 3.2.2 GetPos */ Point const & GetPos() const{return pos;} /* 3.3 Set functions 3.3.1 SetKey */ void SetKey(int nKey){key = nKey;} /* 3.3.2 SetPos */ void SetPos(Point const & pntPos){pos = pntPos;} void SetPos(Coord coordX, Coord coordY); /* 3.4 Functions needed to import the ~vertex~ data type to tuple There are totally 10 functions which are defined as virtual functions. They need to be defined here in order for the Point data type to be used in Tuple definition as an attribute. */ Vertex* Clone() const; int Compare(const Attribute*) const; bool Adjacent(const Attribute*) const; size_t Sizeof() const; size_t HashValue() const; void CopyFrom(const Attribute* arg); inline virtual std::ostream& Print( std::ostream& os ) const { if( IsDefined() ) { os << "Vertex: ( " << key << " @"; pos.Print(os); os << " )"; } else { os << "Vertex: ( undefined )"; } return os; } static const std::string BasicType() { return "vertex"; } static const bool checkType(const ListExpr type){ return listutils::isSymbol(type, BasicType()); } private: /* 3.5 Attributes */ int key; Point pos; }; /* 4 Class Edge */ class Edge: public Attribute { public: /* 4.1 Constructors and Destructor */ Edge(); Edge(bool d) { SetDefined(d);} Edge(int nSource, int nTarget, float fCost); ~Edge(); /* 4.2 Get functions 4.2.1 GetSource */ int GetSource() const{return source;} /* 4.2.2 GetTarget */ int GetTarget() const{return target;} /* 4.2.3 GetCost */ float GetCost() const{return cost;} /* 4.3 Set funtions 4.3.1 SetSource */ void SetSource(int nSource){source = nSource;} /* 4.3.2 SetTarget */ void SetTarget(int nTarget){target = nTarget;} /* 4.3.3 SetCost */ void SetCost(float fCost){cost = fCost;} /* 4.4 Functions needed to import the ~edge~ data type to tuple There are totally 10 functions which are defined as virtual functions. They need to be defined here in order for the Point data type to be used in Tuple definition as an attribute. */ //Implementations from Attribute: Edge* Clone() const; int Compare(const Attribute*) const; bool Adjacent(const Attribute*) const; size_t Sizeof() const; size_t HashValue() const; void CopyFrom(const Attribute* arg); inline virtual std::ostream& Print( std::ostream& os ) const { if(IsDefined()) os << "Edge: ( " << source << " --> " << target <<", " << cost << " )"; else os << "Edge: ( undefined )"; return os; } static const std::string BasicType() { return "edge"; } static const bool checkType(const ListExpr type){ return listutils::isSymbol(type, BasicType()); } private: /* 4.5 Attributes */ int source; int target; float cost; }; /* 5 Class Path 5.1 Struct pathStruct */ struct pathStruct { int key; Point pos; float cost; inline std::ostream& Print( std::ostream& os ) const { os << "pathStruct: ( " << key << " @"; pos.Print(os); os << ": " << cost << " )"; return os; } }; class Path: public Attribute { public: /* 5.2 Constructor and Destructor */ Path(); Path(bool bDefined); ~Path(); /* 5.2 Path query functions 5.2.1 IsEmpty */ bool IsEmpty() const{return myPath.Size() == 0;} /* 5.2.2 Clear This function removes all vertices from the path. */ void Clear(){ myPath.clean(); cost = 0.0; SetDefined(true); } /* 5.2.2 GetCost */ float GetCost() const; /* 5.2.3 GetNoPathStructs */ int GetNoPathStructs() const {return myPath.Size();} /* 5.2.4 GetPathStruct */ pathStruct GetPathStruct(int nIndex) const; /* 5.2.5 GetEdges */ std::vector* GetEdges() const; /* 5.2.6 GetVertices */ std::vector* GetVertices() const; /* 5.3 Path manipulation functions 5.3.1 Append */ void Append(const pathStruct& pathstruct){ cost += pathstruct.cost ; myPath.Append(pathstruct);} /* 5.3.2 Destroy */ void Destroy(){myPath.Destroy();} /* 5.3.3 EqualWay This function checks the equality of two path instances ignoring the costs for the edges and positions of the vertices. */ void EqualWay(const Path* P, CcBool& result) const; /* 5.4 Functions needed to import the ~path~ data type to tuple There are totally 10 functions which are defined as virtual functions. They need to be defined here in order for the Point data type to be used in Tuple definition as an attribute. */ int NumOfFLOBs() const; Flob *GetFLOB(const int i); Path* Clone() const; int Compare(const Attribute*) const; bool Adjacent(const Attribute*) const; size_t Sizeof() const; size_t HashValue() const; void CopyFrom(const Attribute* arg); inline virtual std::ostream& Print( std::ostream& os ) const { os << "Path: ( "; if (IsDefined()) { os << endl; for( int i = 0; i < myPath.Size(); i++) { pathStruct ps; myPath.Get(i, ps); os << "\t\t"; ps.Print(os); os << endl; } os << " Cost = " << cost << " )" << endl; } else { os << " undefined )" << endl; } return os; } static const std::string BasicType() { return "path"; } static const bool checkType(const ListExpr type){ return listutils::isSymbol(type, BasicType()); } protected: /* 5.5 Attributes */ DbArray myPath; float cost; }; /* 6 Struct AVLTree This structure provides static functions to store keys and additional information of a certain type T in AVL trees by using a DBArray. The DBArray must always be passed over as first argument and consists of node slots which can either be free or used by a node. Since the index of the root node is passed as additional argument it is possible to manage several AVL trees in the same DBArray. There is no mechanism to delete or reuse free node slots, every new node will be appended to the DBArray. 6.1 A template for the nodes */ template struct AVLNode { int key; /* The key of this node. */ T elem; /* The additional informations of this node are stored in this template class. */ int left; /* The DBArray index of the left son. The value must be -1 if this node has no left son. */ int right; /* The DBArray index of the right son. The value must be -1 if this node has no right son. */ int leftDepth; /* The depth of the left tree of this node. */ int rightDepth; /* The depth of the right tree of this node. */ bool free; /* A flag that tells if the DBArray index of this node is no longer used. */ inline int Balance() const; /* Returns the balance of the node. */ }; template std::ostream& operator <<( std::ostream& o, const AVLNode& n ); /* 6.2 Static functions for AVL tree management */ template struct AVLTree { public: /* 6.2.1 InsertKey */ static int InsertKey(DbArray >& tree, const int key, const T elem, const int index); /* Insert a new node with key ~key~ and additional informations ~elem~ in the tree with the root node at position ~index~ and returns the DBArray index of the new root node. The operation fails and returns -1 if there was already a node with that key in the tree. *Precondition*: -1 $\le$ index $<$ tree.Size() *Complexity*: $C(log n)$, where ~n~ is the number of nodes in the tree 6.2.2 UpdateKey */ static bool UpdateKey(DbArray >& tree, const int key, const T elem, const int index); /* Sets the additional informations of the node with the key ~key~ in the tree with the root node at DBArray position ~index~ to ~elem~ and returns if the operation was successful. The operation fails if there is no node with that key in the tree. *Precondition:* -1 $\le$ index $<$ tree.Size() *Complexity:* $C(log n)$, where ~n~ is the number of nodes in the tree 6.2.3 ReplaceKey */ static int ReplaceKey(DbArray >& tree, const int key, const int newKey, const int root); /* Replaces the key of the node with key ~key~ in the tree with the root node at DBArray position ~index~ by ~newKey~ and returns the index of the new root node. The operation fails and returns -2 if there is no node with this key. *Precondition:* -1 $\le$ root $<$ tree.Size() *Complexity:* $C(log n)$, where ~n~ is the number of nodes in the tree 6.2.4 DeleteKey */ static int DeleteKey(DbArray >& tree, const int key, const int index); /* Deletes the node with the key ~key~ in the tree with the root node at DBArray position ~index~ and returns the index of the new root node. The operation fails and returns -2 if there is no node with this key. *Precondition:* -1 $\le$ index $<$ tree.Size() *Complexity:* $C(log n)$, where ~n~ is the number of nodes in the tree 6.2.5 DeleteMinKey */ static int DeleteMinKey(DbArray >& tree, const int index, AVLNode& minNode); /* Deletes the node with the minimum key in the tree starting at DBArray position ~index~ and returns the index of the new root node and the node that contains the minimum key in ~minNode~. *Precondition:* 0 $\le$ index $<$ tree.Size() *Complexity:* $C(log n)$, where ~n~ is the number of nodes in the tree 6.2.6 DeleteKeys */ static void DeleteKeys(DbArray >& tree, const int index); /* Deletes all nodes of the tree starting at DBArray position ~index~. *Precondition:* -1 $\le$ index $<$ tree.Size() *Complexity:* $C(n)$, where ~n~ is the number of nodes in the tree 6.2.7 DeleteNode */ static bool DeleteNode(DbArray >& tree, const int index, const AVLNode* node = 0); /* Deletes the node at the DBArray position ~index~ and returns if the operation was successful. If ~node~ is 0 the node will be loaded from the DBArray, otherwise ~node~ is regarded to be the value of the node. The operation fails if the node is already deleted. *Precondition:* 0 $\le$ index $<$ tree.Size() *Complexity:* $C(1)$ 6.2.8 UpdateNode */ static void UpdateNode(DbArray >& tree, const int index, const T& elem); /* Sets the additional informations of the node at DBArray position ~index~ to ~elem~. *Precondition:* 0 $\le$ index $<$ tree.Size() *Complexity:* $C(1)$ 6.2.9 MapKeys */ static void MapKeys (DbArray >& tree, int& num, std::vector& v, const int index); /* Maps the keys of the tree with the root node at DBArray position ~index~ in ascending order to ~num~, ... ,~num~+n-1 and returns the mapping that was used in the vector ~v~. *Precondition:* -1 $\le$ index $<$ tree.Size() *Complexitiy:* $C(n)$ 6.2.10 HasKey */ static bool HasKey(const DbArray >& tree, const int key, const int index); /* Returns whether the tree with the root node at DBArray position ~index~ has a node with the key ~key~ or not. *Precondition:* -1 $\le$ index $<$ tree.Size() *Complexity:* $C(log n)$, where ~n~ is the number of nodes in the tree 6.2.11 ReadKeys */ static int ReadKeys(const DbArray >& tree, std::vector* v, const int index); /* Adds all keys from the tree with the root node at DBArray position ~index~ to the vector ~v~ and returns the number of elements added to the vector. The keys are sorted in ascending order. *Precondition:* -1 $\le$ index $<$ tree.Size() *Complexity:* $C(n)$, where ~n~ is the number of nodes in the tree 6.2.12 ReadNodes */ static int ReadNodes(const DbArray >& tree, std::vector >& v, const int index); /* Adds all nodes from the tree with the root node at DBArray position ~index~ to the vector ~v~ and returns the number of elements added to the vector. The nodes are sorted by their key in ascending order. *Precondition:* -1 $\le$ index $<$ tree.Size() *Complexity:* $C(n)$, where ~n~ is the number of nodes in the tree 6.2.13 ReadOptNodes */ static int ReadOptNodes(const DbArray >& tree, std::vector >& v, const int root); /* Adds all nodes from the tree with the root node at DBArray position ~index~ to the vector ~v~ and returns the number of elements added to the vector. The nodes will be stored in an optimized order that allows to rebuild the tree without rebalancing. *Precondition:* -1 $\le$ index $<$ tree.Size() *Complexity:* $C(n)$, where ~n~ is the number of nodes in the tree 6.2.14 ReadNode */ static int ReadNode(const DbArray >& tree, AVLNode& n, const int key, const int index); /* Copies the node with key ~key~ of the tree with the root node at DBArray position ~index~ to ~n~ and returns the index of this node. The operation fails and returns -1 if there is no node with this key in the tree. *Precondition:* -1 $\le$ index $<$ tree.Size() *Complexity:* $C(log n)$, where ~n~ is the number of nodes in the tree 6.2.15 NumNodes */ static inline int NumNodes(const DbArray >& tree); /* Returns the number of nodes stored in the DBArray. 6.2.16 NewNode */ static AVLNode NewNode (const int key, const T elem); /* Returns a new node with key ~key~ and additional informations ~elem~. */ static AVLNode NewNode (const AVLNode* n); /* Returns a new node which is a copy of the node ~n~. */ private: /* 6.2.17 Private functions */ static int Rebalance(DbArray >& tree, const int index); /* Rebalances the unbalanced node at DBArray position ~index~ and returns the index of the new root node. *Precondition:* 0 $\le$ index $<$ tree.Size() \&\& abs(tree[index].Balance()) == 2 *Complexity:* $C(1)$ */ static inline int BalancedTree(DbArray >& tree, const AVLNode& node, const int root); /* Returns ~root~ if the balance of ~node~ is ok, and otherwise the index of the new root node after rebalancing the tree. *Precondition:* 0 $\le$ root $<$ tree.Size() *Complexity:* $C(1)$ */ }; /* 6.3 Struct verticesStruct Used to store additional informations of a vertex. */ struct verticesStruct { Point pos; /* The position of this vertex. */ int succ; /* The DBArray index in adjlist where the root node of the AVL tree that contains the successors of this vertex is located. The value must be -1 if this vertex has no successors. */ int inDeg; /* The input degree of this vertex. */ int outDeg; /* The output degree of this vertex. */ }; std::ostream& operator<< (std::ostream& o, const verticesStruct& m); /* 6.4 Struct adjStruct Used to store additional information of an edge. */ struct adjStruct { float cost; /* The costs of this edge. */ int keyInt; /* The DBArray index in vertices that represents the target vertex of this edge. */ }; std::ostream& operator<< (std::ostream& o, const adjStruct& m); /* 7 Class Graph This class implements the memory representation of the ~graph~ type constructor. A graph value consists of 2 sets: a set of vertices and a set of directed and weightened edges between these vertices. Both sets are stored using AVL trees, that allows a graph construction in $C(n * log n)$. Each vertex has a unique integer as key, a pointer to the AVL tree that contains all outgoing edges (the adjacent list of the vertex) and a (optional) position of the vertex for the case that the graph should be displayed graphically. An edge is determined by its source and target vertex (resp. by the source and target keys) and has a real value as its costs. After the usage of delete operations on the graph, the Minimize() function should be called to minimize the size of the DBArrays that are used for the AVL trees. */ class Graph: public Attribute { public: /* 7.1 Constructors and Destructor There are three ways of constructing a graph: */ Graph(); /* This constructor should not be used. */ Graph(const bool Defined); /* This constructor createa a new empty graph if ~Defined~ is true, otherwise the graph is undefined. */ Graph(const Graph& g); /* This constructor creates a copy of the graph ~g~. */ void Destroy(); /* This function should be called before the destructor if one wants to destroy the persistent graph. It marks the persistent arrays for destroying. The destructor will perform the real destroying. */ ~Graph(); /* The destructor. 7.2 Functions for graph construction and manipulation 7.2.1 AddVertex */ bool AddVertex(const int key, const Point &pos); /* Adds a new vertex with number ~key~ and the position ~pos~ to the graph. Returns whether the operation was successful or not. The operation fails if there is already a key with that number in the graph. *Precondition:* the graph is defined. *Complexity:* $C(log n)$, where ~n~ is $|V|+|E|$ of the graph G=(V,E) 7.2.2 AddEdge */ bool AddEdge(const int sourceKey, const int targetKey, const float cost); /* Adds a new directed edge from ~sourceKey~ to ~targetKey~ and the costs ~cost~ to the graph. Returns whether the operation was successful or not. The operation fails if there is already a directed edge from ~sourceKey~ to ~targetKey~ in the graph, or if the graph doesn't have a one of the vertices with numbers ~targetkey~ or ~sourceKey~ *Precondition:* the graph is defined. *Complexity:* $C(log n)$, where ~n~ is $|V|+|E|$ of the graph G=(V,E) 7.2.3 Add */ bool Add(const Vertex& v); /* Adds a new vertex ~v~ to the graph. Returns whether the operation was successful or not. The operation fails if there is already a key with the same number as ~v~ in the graph. *Precondition:* the graph is defined. *Complexity:* $C(log n)$, where ~n~ is $|V|+|E|$ of the graph G=(V,E) */ bool Add(const Edge& e); /* Adds a new directed edge ~e~ to the graph. Returns whether the operation was successful or not. The operation fails if there is already a directed edge with the same source and target key as ~e~ in the graph, or if the graph doesn't have the source and target key of ~e~. *Precondition:* the graph is defined. *Complexity:* $C(log n)$, where ~n~ is $|V|+|E|$ of the graph G=(V,E) */ void Add(const Graph& g); /* Adds all missing vertices and edges of the graph ~g~ to the current graph. *Precondition:* ~g~ and the current graph are defined. *Complexity:* $C(n * log n)$, where ~n~ is $|V|+|E|$ of the graph ~g~ = (V,E) 7.2.4 DeleteVertex */ bool DeleteVertex (const int key); /* Deletes the vertex with the number ~key~ and all ingoing and outgoing edges from this vertex in the graph. Returns whether the operation was successful or not. The operation fails if there is no vertex with the number ~key~. *Precondition:* the graph is defined. *Complexity:* $C(n)$, where ~n~ is $|V|+|E|$ of the graph G=(V,E) 7.2.5 DeleteEdge */ bool DeleteEdge (const int sourceKey, const int targetKey); /* Deletes the directed edge from ~sourceKey~ to ~targetKey~. Returns whether the operation was successful or not. The operation fails if there is no edge from ~sourceKey~ to ~targetKey~ in the graph. *Precondition:* the graph is defined. *Complexity:* $C(log n)$, where ~n~ is $|V|+|E|$ of the graph G=(V,E) 7.2.6 Delete */ inline bool Delete(const Vertex& v); /* Deletes the vertex with the same key as the vertex ~v~ in the graph and all all ingoing and outgoing edges from this vertex. Returns whether the operation was successful or not. The operation fails if there is no vertex with the same key as ~v~. *Precondition:* the graph is defined. *Complexity:* $C(n)$, where ~n~ is $|V|+|E|$ of the graph G=(V,E) */ inline bool Delete(const Edge& e); /* Deletes the directed edge with the same source and target as the edge ~e~ in the graph. Returns whether the operation was successful or not. The operation fails if there is no edge with the same source and target as ~e~ the graph. *Precondition:* the graph is defined. *Complexity:* $C(log n)$, where ~n~ is $|V|+|E|$ of the graph G=(V,E) 7.2.7 SetPos */ bool SetPos(const int key, const Point &pos); /* Sets the vertex with the number ~key~ in the graph to the position of the point ~pos~. Returns whether the operation was successful or not. The operation fails if there is no vertex with number ~key~ in the graph. *Precondition:* the graph is defined. *Complexity:* $C(log n)$, where ~n~ is $|V|+|E|$ of the graph G=(V,E) 7.2.8 SetCost */ bool SetCost(const int sourceKey, const int targetKey, const float cost); /* Sets the costs of the directed edge from ~sourceKey~ to ~targetKey~ in the graph to ~cost~. Returns whether the operation was successful or not. The operation fails if there is no edge from ~sourceKey~ to ~targetKey~ in the graph. *Precondition:* the graph is defined. *Complexity:* $C(log n)$, where ~n~ is $|V|+|E|$ of the graph G=(V,E) 7.2.9 Update */ inline bool Update (const Vertex& v); /* Sets the position of the vertex with the same key as the vertex ~v~ to the position of ~v~. Returns whether the operation was successful or not. The operation fails if the graph has no vertex with the same key as ~v~. *Precondition:* the graph is defined. *Complexity:* $C(log n)$, where ~n~ is $|V|+|E|$ of the graph G=(V,E) */ inline bool Update (const Edge& e); /* Sets the costs of the directed edge with the same source and target as the edge ~e~ in the graph to the costs from ~e~. Returns whether the operation was successful or not. The operation fails if there is no edge with the same source and target as ~e~ in the graph. *Precondition:* the graph is defined. *Complexity:* $C(log n)$, where ~n~ is $|V|+|E|$ of the graph G=(V,E) 7.2.10 Clear */ inline void Clear(); /* Clears the sets of vertices and edges of the graph. 7.3 Functions for graph queries 7.3.2 EqualsWith */ bool EqualsWith(const Graph* other) const; /* Returns if the graph is equal to the other graph. *Precondition:* both graphs are defined. *Complexity:* $C(n)$, where ~n~ is $|V|+|E|$ of the graph G=(V,E) 7.3.3 IsEmpty */ inline bool IsEmpty() const; /* Returns wether the graph is empty or not. *Precondition:* the graph is defined. *Complexity:* $C(1)$ 7.3.1 PartOf */ bool PartOf(const Graph* mayPart) const; /* 7.3.4 GetVertex */ Vertex GetVertex(const int key) const; /* Returns the vertex of the graph with the number ~key~ or an undefined vertex if the graph has no vertex with this key. *Precondition:* the graph is defined. *Complexity:* $C(log n)$, where ~n~ is $|V|+|E|$ of the graph G=(V,E) 7.3.5 GetEdge */ Edge GetEdge(const int sourceKey, const int targetKey) const; /* Returns the directed edge of the graph going from ~sourceKey~ to ~targetKey~ or an undefined edge if the graph has no directed edge between the vertices with these keys. *Precondition:* the graph is defined. *Complexity:* $C(log n)$, where ~n~ is $|V|+|E|$ of the graph G=(V,E) 7.3.6 GetInDegFrom */ int GetInDegFrom(const int key) const; /* Returns the input degree of the vertex with the number ~key~ or -1 if the graph has no vertex with this key. *Precondition:* the graph is defined. *Complexity:* $C(log n)$, where ~n~ is $|V|+|E|$ of the graph G=(V,E) 7.3.7 GetOutDegFrom */ int GetOutDegFrom(const int key) const; /* Returns the output degree of the vertex with the number ~key~ or -1 if the graph has no vertex with this key. *Precondition:* the graph is defined. *Complexity:* $C(log n)$, where ~n~ is $|V|+|E|$ of the graph G=(V,E) 7.3.8 GetMaxDeg */ int GetMaxDeg(const bool out) const; /* Returns the maximum output degree of the graph if ~opt~ is true and otherwise the maximum input degree. *Precondition:* the graph is defined. *Complexity:* $C(n)$, where ~n~ is $|V|+|E|$ of the graph G=(V,E) 7.3.9 GetMinDeg */ int GetMinDeg(const bool out) const; /* Returns the minimum output degree of the graph if ~opt~ is true and otherwise the minimum input degree. *Precondition:* the graph is defined. *Complexity:* $C(n)$, where ~n~ is $|V|+|E|$ of the graph G=(V,E) 7.3.10 HasVertex */ bool HasVertex(const int key) const; /* Returns whether the graph has a vertex with the number ~key~ or not. *Precondition:* the graph is defined. *Complexity:* $C(log n)$, where ~n~ is $|V|+|E|$ of the graph G=(V,E) 7.3.11 HasEdge */ bool HasEdge(const int sourceKey, const int targetKey) const; /* Returns whether the graph has a directed edge going from ~sourceKey~ to ~targetKey~ or not. *Precondition:* the graph is defined. *Complexity:* $C(log n)$, where ~n~ is $|V|+|E|$ of the graph G=(V,E) 7.3.12 GetVertices */ std::vector* GetVertices(const bool opt = false) const; /* Returns all vertices of the graph as vector. If ~opt~ is false, the vertices are ordered by their key in ascending order, and if ~opt~ is true the vertices are stored in an optimized order that allows to build a graph without rebalancing the AVL tree. *Precondition:* the graph is defined. *Complexity:* $C(n)$, where ~n~ is $|V|+|E|$ of the graph G=(V,E) 7.3.13 GetEdges */ std::vector* GetEdges(const bool opt = false) const; /* Returns all edges of the graph as vector. If ~opt~ is false, the edges are ordered by their source and target key in ascending order, and if ~opt~ is true the edges are stored in an optimized order that allows to build a graph without rebalancing the AVL tree. *Precondition:* the graph is defined. *Complexity:* $C(n)$, where ~n~ is $|V|+|E|$ of the graph G=(V,E) 7.3.14 GetSuccFrom */ std::vector* GetSuccFrom(const int key) const; /* Returns a pointer to a vector with all vertices that are direct successors of the vertex with the number ~key~, or 0 if there is no vertex with this key. *Precondition:* the graph is defined. *Complexity:* $C(n)$, where ~n~ is $|V|+|E|$ of the graph G=(V,E) 7.3.15 GetPredFrom */ std::vector* GetPredFrom(const int key) const; /* Returns a pointer to a vector with all vertices that are direct predecessors of the vertex with the number ~key~, or 0 if there is no vertex with this key. *Precondition:* the graph is defined. *Complexity:* $C(n)$, where ~n~ is $|V|+|E|$ of the graph G=(V,E) 7.3.16 GetSuccKeysFrom */ std::vector* GetSuccKeysFrom(const int key) const; /* Returns a pointer to a vector with all keys that are direct successors of the vertex with the number ~key~, or 0 if there is no vertex with this key. *Precondition:* the graph is defined. *Complexity:* $C(n)$, where ~n~ is $|V|+|E|$ of the graph G=(V,E) 7.3.17 GetPredKeysFrom */ std::vector* GetPredKeysFrom(const int key) const; /* Returns a pointer to a vector with all keys that are direct predecessors of the vertex with the number ~key~, or 0 if there is no vertex with this key. *Precondition:* the graph is defined. *Complexity:* $C(n)$, where ~n~ is $|V|+|E|$ of the graph G=(V,E) 7.3.18 GetSuccEdgesFrom */ std::vector* GetSuccEdgesFrom(const int key) const; /* Returns a pointer to a vector with all outgoing edges of the of the vertex with the number ~key~, or 0 if there is no vertex with this key. *Precondition:* the graph is defined. *Complexity:* $C(n)$, where ~n~ is $|V|+|E|$ of the graph G=(V,E) 7.3.19 GetPredEdgesFrom */ std::vector* GetPredEdgesFrom(const int key) const; /* Returns a pointer to a vector with all ingoing edges of the of the vertex with the number ~key~, or 0 if there is no vertex with this key. *Precondition:* the graph is defined. *Complexity:* $C(n)$, where ~n~ is $|V|+|E|$ of the graph G=(V,E) 7.3.20 GetNumVertices */ inline int GetNumVertices() const; /* Returns the number of the vertices from the graph. *Precondition:* the graph is defined. *Complexity:* $C(1)$ 7.3.21 GetNumEdges */ inline int GetNumEdges() const; /* Returns the number of the edges from the graph. *Precondition:* the graph is defined. *Complexity:* $C(1)$ 7.3.22 GetStronglyConnectedComponents */ std::vector GetStronglyConnectedComponents() const; /* Returns a vector with all strongly connected components of the graph. *Precondition:* the graph is defined. *Complexity:* $C(n * log n)$, where ~n~ is $|V|+|E|$ of the graph G=(V,E) 7.3.1 GetShortestPath */ Path* GetShortestPath(const int from, const int to) const; void GetShortestPath(int start, int target, Path* solution) const; /* 7.3.23 GetMappedGraph */ Graph* GetMappedGraph(std::vector& map) const; /* Returns a pointer to a new copy of the graph where the vertex keys are mapped to 0..n-1 - the mapping that was used is returned in the vector ~map~. *Precondition:* the graph is defined. *Complexity:* $C(n)$, where ~n~ is $|V|+|E|$ of the graph G=(V,E) 7.3.24 GetCircle */ Graph* GetCircle(const int startKey, const float maxCost ) const; /* Returns all vertices (and connecting edges) whose network distance from the vertex with key ~startKey~ is not greater than ~maxCost~. The operation fails and returns an empty graph if ~startKey~ does not exist. *Precondition:* the graph is defined and maxCost $\ge$ 0 *Complexity:* $C(n^3 * log n)$, where ~n~ is $|V|+|E|$ of the graph G=(V,E) 7.3.25 Minimize */ inline void Minimize(); /* Minimizes the sizes of the DBArrays by deleting all free nodes. This function should be called after the execution of delete operations. *Precondition:* the graph is defined. *Complexity:* $C(n * log n)$, where ~n~ is $|V|+|E|$ of the graph G=(V,E) */ /* 7.4 Functions needed to import the ~graph~ data type to tuple There are totally 10 functions which are defined as virtual functions. They need to be defined here in order for the Point data type to be used in Tuple definition as an attribute. */ Graph* Clone() const; int Compare(const Attribute*) const; bool Adjacent(const Attribute*) const; size_t Sizeof() const; int NumOfFLOBs() const; Flob *GetFLOB(const int i); size_t HashValue() const; void CopyFrom(const Attribute* arg); static const std::string BasicType() { return "graph"; } static const bool checkType(const ListExpr type){ return listutils::isSymbol(type, BasicType()); } protected: /* 7.5 Attributes */ DbArray > vertices; /* The set of vertices the graph contains. */ DbArray > adjlist; /* The adjacent lists of the graph vertices. Each list element represents an edge. */ int verticesRoot; /* The DBArray index in vertices that contains the root node. verticeRoot must be -1 if the graph is empty. */ int numVertices; /* The number of vertices in the graph. */ int numEdges; /* The number of edges in the graph. */ /* A flag that tells whether the graph is defined or not. */ }; template std::ostream& operator <<( std::ostream& o, const AVLNode& n ) { if (n.free) o << "undefined"; else o << "Node " << n.key << "->" << n.elem << " : Left[" << n.leftDepth << "]: " << n.left << " / Right[" << n.rightDepth << "]: " << n.right << " / Balance = " << n.Balance(); return o; } template inline std::string Print(DbArray >& tree) { std::string s; const AVLNode* node; s = "--------------------------------------\n"; for (int i=0;i inline int AVLNode::Balance() const { return rightDepth-leftDepth; } template AVLNode AVLTree::NewNode (const int key, const T elem) { AVLNode n; n.key = key; n.elem = elem; n.left = -1; n.right = -1; n.leftDepth = 0; n.rightDepth = 0; n.free = false; return n; } template AVLNode AVLTree::NewNode (const AVLNode* n) { AVLNode node; node.key = n->key; node.elem = n->elem; node.left = n->left; node.right = n->right; node.leftDepth = n->leftDepth; node.rightDepth = n->rightDepth; node.free = n->free; return node; } template inline int AVLTree::BalancedTree(DbArray >& tree, const AVLNode& node, const int root) { assert((0 <= root) && (root < tree.Size())); return (abs(node.Balance())>1) ? AVLTree::Rebalance(tree,root) : root; } template inline int AVLTree::NumNodes(const DbArray >& tree) { return tree.Size(); } template bool AVLTree::DeleteNode(DbArray >& tree, const int index, const AVLNode* n) { assert((index >= 0) && (index < tree.Size())); AVLNode root; // no node parameter? if (n==0) { AVLNode node; tree.Get(index,node); root = AVLTree::NewNode(&node); } else root = AVLTree::NewNode(n); // node already deleted? if (root.free) return false; root.free = true; tree.Put(index,root); return true; } template void AVLTree::UpdateNode(DbArray >& tree, const int index, const T& elem) { assert((index >= 0) && (index < tree.Size())); AVLNode node; tree.Get(index,node); AVLNode root = AVLTree::NewNode(&node); root.elem = elem; tree.Put(index,root); } template bool AVLTree::HasKey(const DbArray >& tree, const int key, const int index) { assert((index >= -1) && (index < tree.Size())); // key not found? if (index == -1) return false; AVLNode node; tree.Get(index,node); // key found? if (key == node.key) return true; // key in left tree? if (key < node.key) // continue search in left tree return AVLTree::HasKey(tree,key,node.left); // continue search in right tree return AVLTree::HasKey(tree,key,node.right); } template bool AVLTree::UpdateKey(DbArray >& tree, const int key, const T elem, const int index) { assert((index >= -1) && (index < tree.Size())); // key not found? if (index == -1) return false; const AVLNode* node; tree.Get(index,node); // key found? if (key == node->key) { // update node AVLNode root = AVLTree::NewNode(node); root.elem = elem; tree.Put(index,root); return true; } // key in left tree? if (key < node->key) // continue search in left tree return AVLTree::UpdateKey(tree,key,elem,node->left); // continue search in right tree return AVLTree::UpdateKey(tree,key,elem,node->right); } template int AVLTree::Rebalance(DbArray >& tree, const int index) { assert((index >= 0) && (index < tree.Size())); AVLNode bNode; AVLNode son1; AVLNode son2; tree.Get(index,bNode); AVLNode rootNode = AVLTree::NewNode(&bNode); // node really unbalanced ? assert(abs(bNode.Balance())==2); int root = index; int sonIndex; if (bNode.Balance()==2) { // too much nodes on the right hand side sonIndex = bNode.right; tree.Get(sonIndex,son1); AVLNode rootSon = AVLTree::NewNode(&son1); // too much nodes on the right hand side of the son? if (son1.Balance()==1) { // start rotation rootNode.right = son1.left; rootNode.rightDepth = son1.leftDepth; rootSon.left = index; rootSon.leftDepth = std::max(bNode.leftDepth,son1.leftDepth)+1; root = sonIndex; // update nodes tree.Put(index,rootNode); tree.Put(root,rootSon); } else { // start double rotation tree.Get(son1.left,son2); AVLNode newRoot = AVLTree::NewNode(&son2); root = son1.left; newRoot.left = index; newRoot.leftDepth = std::max(bNode.leftDepth,son2.leftDepth)+1; newRoot.right = sonIndex; newRoot.rightDepth = std::max(son1.rightDepth,son2.rightDepth)+1; rootNode.right = son2.left; rootNode.rightDepth = son2.leftDepth; rootSon.left = son2.right; rootSon.leftDepth = son2.rightDepth; // update nodes tree.Put(index,rootNode); tree.Put(root,newRoot); tree.Put(sonIndex,rootSon); } } else { // too much nodes on the left hand side sonIndex = bNode.left; tree.Get(sonIndex,son1); AVLNode rootSon = AVLTree::NewNode(&son1); // too much nodes on the left hand side of the son? if (son1.Balance()==-1) { // start rotation rootNode.left = son1.right; rootNode.leftDepth = son1.rightDepth; rootSon.right = index; rootSon.rightDepth = std::max(bNode.rightDepth,son1.rightDepth)+1; root = sonIndex; // update nodes tree.Put(index,rootNode); tree.Put(root,rootSon); } else { // start double rotation tree.Get(son1.right,son2); AVLNode newRoot = AVLTree::NewNode(&son2); root = son1.right; newRoot.right = index; newRoot.rightDepth = std::max(bNode.rightDepth,son2.rightDepth)+1; newRoot.left = sonIndex; newRoot.leftDepth = std::max(son1.leftDepth,son2.leftDepth)+1; rootNode.left = son2.right; rootNode.leftDepth = son2.rightDepth; rootSon.right = son2.left; rootSon.rightDepth = son2.leftDepth; // update nodes tree.Put(index,rootNode); tree.Put(root,newRoot); tree.Put(sonIndex,rootSon); } } return root; } template int AVLTree::InsertKey(DbArray >& tree, const int key, const T elem, const int index) { assert((index >= -1) && (index < tree.Size())); AVLNode node; AVLNode son; // tree empty? if (index == -1) { tree.Append(AVLTree::NewNode(key,elem)); return tree.Size()-1; } tree.Get(index,node); // key already in tree? if (key == node.key) return -1; AVLNode thisNode = AVLTree::NewNode(&node); int newSon; int newDepth; // continue in left son? if (key < node.key) { // no left son? if (node.left == -1) { // insert key as new left son tree.Append(AVLTree::NewNode(key,elem)); thisNode.left = tree.Size()-1; thisNode.leftDepth = 1; tree.Put(index,thisNode); return index; } else { // try to insert key in left tree newSon = AVLTree::InsertKey(tree,key,elem,node.left); // insert failed? if (newSon == -1) return -1; // check left son tree.Get(newSon,son); newDepth = std::max(son.rightDepth,son.leftDepth)+1; // update required? if ((newSon != thisNode.left) || (newDepth != thisNode.leftDepth)) { thisNode.leftDepth = newDepth; thisNode.left = newSon; tree.Put(index,thisNode); // Node not balanced? return AVLTree::BalancedTree(tree,thisNode,index); } return index; } } // continue in right son else { // no right son? if (node.right == -1) { // insert key as new right son tree.Append(AVLTree::NewNode(key,elem)); thisNode.right = tree.Size()-1; thisNode.rightDepth = 1; tree.Put(index,thisNode); return index; } else { // try to insert key in right tree newSon = AVLTree::InsertKey(tree,key,elem,node.right); // insert failed? if (newSon == -1) return -1; // check right son tree.Get(newSon,son); newDepth = std::max(son.rightDepth,son.leftDepth)+1; // update required? if ((newSon != thisNode.right) || (newDepth != thisNode.rightDepth)) { thisNode.rightDepth = newDepth; thisNode.right = newSon; tree.Put(index,thisNode); // Node not balanced? return AVLTree::BalancedTree(tree,thisNode,index); } return index; } } } template int AVLTree::DeleteMinKey (DbArray >& tree, const int index, AVLNode& minNode) { assert((index >= 0) && (index < tree.Size())); AVLNode node; tree.Get(index,node); AVLNode root = AVLTree::NewNode(&node); // minimum in current node? if (node.left == -1) { // save and delete the minimum node minNode = root; AVLTree::DeleteNode(tree,index,&root); return minNode.right; } // continue in left son root.left = AVLTree::DeleteMinKey(tree,node.left,minNode); // left son not deleted? if (root.left != -1) { tree.Get(root.left,node); root.leftDepth = std::max(node.leftDepth,node.rightDepth)+1; } else root.leftDepth = 0; // update current node tree.Put(index,root); return AVLTree::BalancedTree(tree,root,index); } template int AVLTree::DeleteKey (DbArray >& tree, const int key, const int index) { assert((index >= -1) && (index < tree.Size())); // tree empty? if (index == -1) return -2; AVLNode node; AVLNode son; int newSon; int newDepth; tree.Get(index,node); AVLNode root = AVLTree::NewNode(&node); // key not in current node? if (key != node.key) { // continue search in left tree? if ((key < node.key) && (node.left != -1)) { newSon = AVLTree::DeleteKey(tree,key,node.left); // key not found? if (newSon == -2) return -2; // son not deleted? if (newSon != -1) { tree.Get(newSon,son); newDepth = std::max(son.leftDepth,son.rightDepth)+1; } else newDepth = 0; // update required? if ((newDepth != node.leftDepth) || (newSon != node.left)) { root.leftDepth = newDepth; root.left = newSon; tree.Put(index,root); // node not balanced? return AVLTree::BalancedTree(tree,root,index); } return index; } // continue search in right tree? if ((key > node.key) && (node.right != -1)) { newSon = AVLTree::DeleteKey(tree,key,node.right); // key not found? if (newSon == -2) return -2; // son not deleted? if (newSon != -1) { tree.Get(newSon,son); newDepth = std::max(son.rightDepth,son.leftDepth)+1; } else newDepth = 0; // update required? if ((newDepth != node.rightDepth) || (newSon != node.right)) { root.rightDepth = newDepth; root.right = newSon; tree.Put(index,root); // node not balanced? return AVLTree::BalancedTree(tree,root,index); } return index; } // error: key not found return -2; } // key found in current node // node is a leaf? if ((node.left == -1) && (node.right == -1)) { // delete leaf AVLTree::DeleteNode(tree,index,&root); return -1; } // node has 2 sons? if ((node.left != -1) && (node.right != -1)) { AVLNode min; tree.Get(node.right,son); root.right = AVLTree::DeleteMinKey(tree,node.right,min); // right son not deleted by DeleteMinKey? if (root.right != -1) { tree.Get(root.right, son); root.rightDepth = std::max(son.leftDepth,son.rightDepth)+1; } else root.rightDepth = 0; root.key = min.key; root.elem = min.elem; tree.Put(index,root); return index; } // node has only one son AVLTree::DeleteNode(tree,index,&root); return ((node.left != -1) ? node.left : node.right); } template void AVLTree::DeleteKeys(DbArray >& tree, const int index) { assert((index >= -1) && (index < tree.Size())); // tree empty? if (index == -1) return; const AVLNode* node; tree.Get(index,node); AVLNode root = AVLTree::NewNode(node); // nodes in left tree? if (node->left != -1) AVLTree::DeleteKeys(tree,node->left); // nodes in right tree? if (node->right != -1) AVLTree::DeleteKeys(tree,node->right); // delete current node AVLTree::DeleteNode(tree,index,&root); } template int AVLTree::ReadKeys (const DbArray >& tree, std::vector* v, const int index) { assert((index >= -1) && (index < tree.Size())); // tree empty? if (index == -1) return 0; AVLNode node; tree.Get(index,node); int n = 0; if (node.left != -1) n += AVLTree::ReadKeys(tree,v,node.left); v->push_back(node.key); n++; if (node.right != -1) n += AVLTree::ReadKeys(tree,v,node.right); return n; } template void AVLTree::MapKeys (DbArray >& tree, int& num, std::vector& v, const int index) { assert((index >= -1) && (index < tree.Size()) && (num >= 0)); // tree empty? if (index == -1) return; AVLNode node; tree.Get(index,node); if (node.left != -1) AVLTree::MapKeys(tree,num,v,node.left); AVLNode n = AVLTree::NewNode(&node); v.push_back(n.key); n.key = num; tree.Put(index,n); num++; if (node.right != -1) AVLTree::MapKeys(tree,num,v,node.right); } template int AVLTree::ReadOptNodes(const DbArray >& tree, std::vector >& v, const int root) { assert((root >= -1) && (root < tree.Size())); // tree empty? if (root == -1) return 0; AVLNode node; std::vector source(0); std::vector target(0); target.push_back(root); int n = 0; // any nodes on next level? while (target.size()>0) { source = target; target.clear(); // add all sons of source nodes to target for (unsigned int i = 0;i::NewNode(&node)); n++; // left son? if (node.left != -1) target.push_back(node.left); // right son? if (node.right != -1) target.push_back(node.right); } } return n; } template int AVLTree::ReadNodes (const DbArray >& tree, std::vector >& v, const int index) { assert((index >= -1) && (index < tree.Size())); // tree empty? if (index == -1) return 0; AVLNode node; tree.Get(index,node); int n = 0; if (node.left != -1) n += AVLTree::ReadNodes(tree,v,node.left); v.push_back(AVLTree::NewNode(&node)); n++; if (node.right != -1) n += AVLTree::ReadNodes(tree,v,node.right); return n; } template int AVLTree::ReadNode(const DbArray >& tree, AVLNode& n, const int key, const int index) { assert((index >= -1) && (index < tree.Size())); // key not found? if (index == -1) return -1; AVLNode node; tree.Get(index,node); // key found? if (key == node.key) { // copy node and return index n = node; return index; } // key in left tree? if (key < node.key) // continue search in left tree return AVLTree::ReadNode(tree,n,key,node.left); // continue search in right tree return AVLTree::ReadNode(tree,n,key,node.right); } template int AVLTree::ReplaceKey(DbArray >& tree, const int key, const int newKey, const int root) { assert((root >= -1) && (root < tree.Size())); AVLNode node; // key and newKey ok? if (AVLTree::HasKey(tree,newKey,root) || !AVLTree::ReadNode(tree,node,key,root)) return -2; int newRoot = AVLTree::DeleteKey(tree,key,root); // delete failed? if (newRoot == -2) return -2; return AVLTree::InsertKey(tree,newKey,node.elem,root); } /* 2 class EdgeDirection this local class is needed to check for parallel edges in a path */ class EdgeDirection { public: explicit EdgeDirection(int nSource, int nTarget) : m_nSource(nSource), m_nTarget(nTarget){} int GetSource() const{return m_nSource;} int GetTarget() const{return m_nTarget;} bool operator<(EdgeDirection const & edge) const { return m_nSource < edge.GetSource() || (m_nSource == edge.GetSource() && m_nTarget < edge.GetTarget()); } private: int m_nSource; int m_nTarget; }; #endif /*GRAPHALGEBRA_H_*/