diff --git a/src/graphFile b/src/graphFile new file mode 100644 index 0000000..66c8345 Binary files /dev/null and b/src/graphFile differ diff --git a/src/lib/SoDA/inc/algorithm/CBFS.h b/src/lib/SoDA/inc/algorithm/CBFS.h new file mode 100644 index 0000000..4891de2 --- /dev/null +++ b/src/lib/SoDA/inc/algorithm/CBFS.h @@ -0,0 +1,99 @@ +/* + * Copyright (C): 2013-2014 Department of Software Engineering, University of Szeged + * + * Author: David Imre Adam + * + * This file is part of SoDA. + * + * SoDA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * SoDA 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with SoDA. If not, see . + */ + +#include "data/SoDALibDefs.h" +#include "data/Node.h" + +#ifndef CBFS_H +#define CBFS_H + +using namespace std; + +namespace soda +{ + /** + * @brief The CBFS class stores the Breadth First Search related algorithms + */ + class CBFS + { + private: + /** + * @brief Vector of vectors of edges + */ + vector>* m_edges; + + /** + * @brief An ordering of edges + */ + vector* m_bfsOrder; + + /** + * @brief Creates an ordering of m_edges by BFS algorithm + * @param v The current root element + * @param root The helper container for the visited edges + */ + void BFS(int v, bool visited[]); + + /** + * @brief Creates the reversed order of chainElements from root with ending with endNode + * @param root The startpoint + * @param root The ending Node + * @param root The starting point + * @return list of reversed order + */ + list* scrollBackSingleChain(vector* chainElements, Node* endNode, IndexType root); + + public: + /** + * @brief Constructor of CBFS + * @param m_edges The edges. + */ + CBFS(vector>& m_edges); + + /** + * @brief Default destructor + */ + ~CBFS(); + + /** + * @brief Creates an ordering of m_edges by BFS algorithm + * @param root The startpoint + * @return The BFS order + */ + vector* getBFS(IndexType root); + + /** + * @brief Creates a list of paths on the m_edges those contains all of the vertices + * @param rootElementId The starting elementId of a vertex + * @return Vector of paths + */ + vector*>* getPaths(IndexType rootElementId); + + /** + * @brief Checks any nodes have more thane one in degree + * @param root The startpoint + * @return A boolean answer value + */ + bool inDegreeGTOne(IndexType root); + }; +} + +#endif diff --git a/src/lib/SoDA/inc/algorithm/CDFS.h b/src/lib/SoDA/inc/algorithm/CDFS.h new file mode 100644 index 0000000..c162e61 --- /dev/null +++ b/src/lib/SoDA/inc/algorithm/CDFS.h @@ -0,0 +1,85 @@ +/* + * Copyright (C): 2013-2014 Department of Software Engineering, University of Szeged + * + * Author: David Imre Adam + * + * This file is part of SoDA. + * + * SoDA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * SoDA 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with SoDA. If not, see . + */ + +#include "data/SoDALibDefs.h" +#include "data/CBitMatrix.h" + +#ifndef CDFS_H +#define CDFS_H + +using namespace std; + +namespace soda +{ + /** + * @brief The CDFS class stores the Depth First Search related algorithms + */ + class CDFS + { + private: + /** + * @brief Vector of vectors of edges + */ + vector>* m_edges; + + /** + * @brief An ordering of edges + */ + vector* m_dfsOrder; + + /** + * @brief Recursive helper. Executes visiting an a subgraph started with current item + * @param v The current root element + * @param visited The helper container for the visited edges + */ + void recursiveHelper(IndexType current, bool *visited); + + /** + * @brief Recursive helper. Executes a search for a circle on graph started by current, helped by visited nodes and recoderer routes. + * @param current The current root element + * @param visited A helper container for the visited nodes + * @param recorded A helper container for the building-up routes + */ + bool hasCycleHelper(IndexType current, bool visited[], bool *recorded); + + public: + + /** + * @brief Constructor of CDFS + * @param m_edges The edges. + */ + CDFS(vector> &m_edges); + ~CDFS(); + + /** + * @brief Gets the DFS ordering of elements. + * @param root The starting node. + */ + vector *getDFS(IndexType root); + + /** + * @brief Gets a logical decision, does graph have circle. + */ + bool hasCycle(); + }; +} + +#endif diff --git a/src/lib/SoDA/inc/data/CChain.h b/src/lib/SoDA/inc/data/CChain.h new file mode 100644 index 0000000..d10f7d8 --- /dev/null +++ b/src/lib/SoDA/inc/data/CChain.h @@ -0,0 +1,158 @@ +/* + * Copyright (C): 2013-2014 Department of Software Engineering, University of Szeged + * + * Author: David Imre Adam + * + * This file is part of SoDA. + * + * SoDA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * SoDA 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with SoDA. If not, see . + */ + +#include +#include +#include "data/CIDManager.h" +#include "interface/IIterators.h" +#include "interface/IChain.h" +#include "io/CJsonReader.h" + +#ifndef CCHAIN_H +#define CCHAIN_H + +using namespace std; + +namespace soda +{ + /** + * @brief The CChain class stores the Chain datastructure + */ + class CChain : public IChain + { + private: + + /** + * @brief SoDA container of elements + */ + IIDManager* m_codeElements; + + /** + * @brief The container of ordered elements. + */ + vector* m_order; + public: + + /** + * @brief Constructor + */ + CChain(); + + /** + * @brief Destructor + */ + ~CChain(); + + /** + * @brief Gets the count of elements + * @return count + */ + IndexType count(); + + /** + * @brief Clears the containers + */ + virtual void clear(); + + /** + * @brief Adds a new element + * @param n The new value of the element + */ + virtual void add(const String& n); + + /** + * @brief Adds a vector of new elements to the end of the chain + * @param codeElements The vector of elements + */ + virtual void add(const StringVector& codeElements); + + /** + * @brief Removes a value from the containers + * @param n The removable value + */ + virtual void remove(const String& n); + + /** + * @brief Does the chain contain the element. + * @param n The new value of the element + * @return the answer + */ + virtual bool contains(const String& n); + + /** + * @brief Gets the elementId of the value n + * @param n The requested value + * @return the index of the element + */ + virtual IndexType getId(const String& n); + + /** + * @brief Gets the value of the elementId n + * @param n The requested id + * @return the value + */ + virtual String getValue(const IndexType n); + + /** + * @brief Gets the first type iterator to the beginnig of chain + * @return the begin-iterator + */ + virtual vector::const_iterator first(); + + /** + * @brief Gets the last type iterator to the end of chain + * @return the end-iterator + */ + virtual vector::const_iterator end(); + + /** + * @brief Saves a chain as binary data to the out stream + * @param [IN] out The stream + */ + virtual void save(io::CBinaryIO *out) const; + + /** + * @brief Loads chain by binary data from in stream + * @param [IN] in The source stream + */ + virtual void load(io::CSoDAio *in); + + /** + * @brief Saves the chain to file + * @param [IN] in The filename + */ + virtual void save(const char * filename) const; + + /** + * @brief Loads chain from file + * @param [IN] filename The filename + */ + virtual void load(const char * filename); + + /** + * @brief Loads chain from JSON data file + * @param [IN] filename The requested id + */ + virtual void loadJson(const String& path); + }; +} + +#endif diff --git a/src/lib/SoDA/inc/data/CDAG.h b/src/lib/SoDA/inc/data/CDAG.h new file mode 100644 index 0000000..df32704 --- /dev/null +++ b/src/lib/SoDA/inc/data/CDAG.h @@ -0,0 +1,224 @@ +/* + * Copyright (C): 2013-2014 Department of Software Engineering, University of Szeged + * + * Author: David Imre Adam + * + * This file is part of SoDA. + * + * SoDA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * SoDA 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with SoDA. If not, see . + */ + +#include +#include +#include "data/CIDManager.h" +#include "data/CGraph.h" +#include "io/CJsonReader.h" +#include "interface/IDAG.h" + +#ifndef CDAG_H +#define CDAG_H + +using namespace std; + +namespace soda +{ + /** + * @brief DAG datastructure class + */ + class CDAG : public IDAG + { + protected: + + /** + * @brief SoDA container of elements + */ + IIDManager* m_codeElements; + + /** + * @brief The container of the DAG structure. + */ + vector>* m_structure; + + /** + * @brief The container of the mapping nodes. + */ + vector* m_nodes; + + public: + + /** + * @brief Constructor + */ + CDAG(); + + /** + * @brief Destructor + */ + ~CDAG(); + + /** + * @brief ChunkID for export / import functionality + */ + io::CSoDAio::ChunkID m_chunkId = io::CSoDAio::ChunkID::DAG; + + /** + * @brief Gets the count of mapping nodes + * @return count + */ + virtual IndexType nodeCount(); + + /** + * @brief Gets the count of edges + * @return count + */ + virtual IndexType edgeCount(); + + /** + * @brief Clears the containers + */ + virtual void clear(); + + /** + * @brief Adds a new node + * @param n The new value of the element + * @return the newly created Node + */ + virtual Node* addNode(const String& n); + + /** + * @brief Adds an exsisting element as a new node + * @param elemenId The exsisting elementId + * @return the newly created Node + */ + virtual Node* addNode(const IndexType elementId); + + /** + * @brief Adds an exsisting element as a new node to a parent + * @param elemenId The new value of the element + * @return the newly created Node + */ + virtual Node* addChild(const IndexType parentNodeId, const String& n); + + /** + * @brief Checks the DAG contains circle + * @param root The startin point of the check + * @return the answer + */ + virtual bool isValid(IndexType root); + + /** + * @brief Adds a new edge between exsisting nodes + * @param parentNodeId The parent node + * @param childNodeId The child node + */ + virtual void addEdge(const IndexType parentNodeId, const IndexType childNodeId); + + /** + * @brief Adds a new edge between exsisting nodes + * @param parentNode The parent node + * @param childNode The child node + */ + virtual void addEdge(Node* parent, Node* child); + + /** + * @brief Gets value of node + * @param node The node + * @return the value + */ + virtual String getNodeValue(Node* node); + + /** + * @brief Gets value of node by nodeId + * @param nodeId The node + * @return the value + */ + virtual String getNodeValue(IndexType nodeId); + + /** + * @brief Gets value of the element by elementId + * @param elementId The node + * @return the value + */ + virtual String getValue(IndexType elementId); + + /** + * @brief Gets value of the element by nodeId + * @param nodeId The node + * @return the vector of edges + */ + virtual vector& getEdges(const IndexType& nodeId); + + /** + * @brief Gets DFS order starting with nodeId + * @param i The node Id + * @return the vector of order + */ + virtual vector *getDFS(IndexType i); + + /** + * @brief Gets BFS order starting with nodeId + * @param i The node Id + * @return the vector of order + */ + virtual vector *getBFS(IndexType i); + + /** + * @brief Converts a DAG to chains + * @return the vector of orderlists + */ + virtual vector*> *convertToNodeIdChains(); + + /** + * @brief Saves a chain as binary data to the out stream + * @param out The stream + */ + virtual void save(io::CBinaryIO *out) const; + + /** + * @brief Loads chain by binary data from in stream + * @param in The source stream + */ + virtual void load(io::CSoDAio *in); + + /** + * @brief Saves the chain to file + * @param in The filename + */ + virtual void save(const char * filename) const; + + /** + * @brief Loads chain from file + * @param filename The filename + */ + virtual void load(const char * filename); + + /** + * @brief Loads chain from JSON data file + * @param filename The requested id + */ + virtual void loadJson(const String& path); + + /** + * @brief Converts a DAG to Graph + */ + virtual CGraph* toGraph(); + + /** + * @brief Converts a DAG to contracted DAG + */ + virtual CDAG* getContractedDAG(); + }; +} + +#endif diff --git a/src/lib/SoDA/inc/data/CGraph.h b/src/lib/SoDA/inc/data/CGraph.h new file mode 100644 index 0000000..4af1fa7 --- /dev/null +++ b/src/lib/SoDA/inc/data/CGraph.h @@ -0,0 +1,148 @@ +/* + * Copyright (C): 2013-2014 Department of Software Engineering, University of Szeged + * + * Author: David Imre Adam + * + * This file is part of SoDA. + * + * SoDA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * SoDA 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with SoDA. If not, see . + */ + +#include +#include +#include "data/CIDManager.h" +#include "interface/IGraph.h" +#include "io/CJsonReader.h" + +#ifndef CGRAPH_H +#define CGRAPH_H + +using namespace std; + +namespace soda +{ + /** + * @brief Graph datastructure class + */ + class CGraph : public IGraph + { + private: + + /** + * @brief SoDA container of elements + */ + IIDManager* m_codeElements; + + /** + * @brief The container of the edges + */ + vector>* m_edges; + + public: + + /** + * @brief Constructor + */ + CGraph(); + + /** + * @brief Destructor + */ + ~CGraph(); + + /** + * @brief Gets the count of mapping nodes + * @return count + */ + virtual IndexType nodeCount(); + + /** + * @brief Gets the count of edges + * @return count + */ + virtual IndexType edgeCount(); + + /** + * @brief Clears the containers + */ + virtual void clear(); + + /** + * @brief Adds a new node + * @param n The new value of the element + * @return the newly created elemntId + */ + virtual IndexType addNode(const String& n); + + /** + * @brief Adds an new edge between two elements + * @param i The exsisting elementId + * @param j The exsisting elementId + */ + virtual void addEdge(const IndexType i, IndexType j); + + /** + * @brief Gets value of the element by nodeId + * @param nodeId The node + * @return the vector of edges + */ + virtual vector& getEdges(const IndexType& i); + + /** + * @brief Gets DFS order starting with nodeId + * @param i The node Id + * @return the vector of order + */ + virtual vector* getDFS(const IndexType& i); + + /** + * @brief Gets BFS order starting with nodeId + * @param i The node Id + * @return the vector of order + */ + virtual vector* getBFS(const IndexType& i); + + /** + * @brief Saves a chain as binary data to the out stream + * @param [IN] out The stream + */ + virtual void save(io::CBinaryIO *out) const; + + /** + * @brief Loads chain by binary data from in stream + * @param [IN] in The source stream + */ + virtual void load(io::CSoDAio *in); + + /** + * @brief Saves the chain to file + * @param [IN] in The filename + */ + virtual void save(const char * filename) const; + + /** + * @brief Loads chain from file + * @param [IN] filename The filename + */ + virtual void load(const char * filename); + + /** + * @brief Loads chain from JSON data file + * @param [IN] filename The requested id + */ + virtual void loadJson(const String& path); + }; +} + +#endif diff --git a/src/lib/SoDA/inc/data/CTree.h b/src/lib/SoDA/inc/data/CTree.h new file mode 100644 index 0000000..a0b36f1 --- /dev/null +++ b/src/lib/SoDA/inc/data/CTree.h @@ -0,0 +1,76 @@ +/* + * Copyright (C): 2013-2014 Department of Software Engineering, University of Szeged + * + * Author: David Imre Adam + * + * This file is part of SoDA. + * + * SoDA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * SoDA 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with SoDA. If not, see . + */ + +#include +#include +#include "data/CDAG.h" + +#ifndef CTREE_H +#define CTREE_H + +using namespace std; + +namespace soda +{ + /** + * @brief Tree datastructure class + */ + class CTree : public CDAG + { + public: + + /** + * @brief Constructor + */ + CTree(); + + /** + * @brief Destructor + */ + ~CTree(); + + /** + * @brief ChunkID for export / import functionality + */ + const io::CSoDAio::ChunkID m_chunkId = io::CSoDAio::ChunkID::TREE; + + /** + * @brief Adds an exsisting element as a new node to a parent + * @param elemenId The new value of the element + * @return the newly created Node + */ + virtual Node* addChild(const IndexType parentNodeId, const String& n) override; + + /** + * @brief Checks the DAG contains circle + * @param root The startin point of the check + * @return the answer + */ + virtual bool isValid(IndexType root) override; + + /** + * @brief Converts a Tree to DAG + */ + virtual CDAG* toDAG(); + }; +} + +#endif diff --git a/src/lib/SoDA/inc/data/Node.h b/src/lib/SoDA/inc/data/Node.h new file mode 100644 index 0000000..1fec311 --- /dev/null +++ b/src/lib/SoDA/inc/data/Node.h @@ -0,0 +1,67 @@ +/* + * Copyright (C): 2013-2014 Department of Software Engineering, University of Szeged + * + * Author: David Imre Adam + * + * This file is part of SoDA. + * + * SoDA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * SoDA 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with SoDA. If not, see . + */ + +#include +#include +#include "data/SoDALibDefs.h" + +#ifndef NODE_H +#define NODE_H + +using namespace soda; + +namespace soda +{ + /** + * @brief Node item helper class + */ + class Node + { + public: + + /** + * @brief Id of node + */ + IndexType m_id; + + /** + * @brief Id of the element value + */ + IndexType m_elementId; + + /** + * @brief Constructor with default values + */ + Node(IndexType id, IndexType elementId) + { + m_id = id; + m_elementId = elementId; + } + + /** + * @brief Destructor + */ + ~Node() + {} + }; +} + +#endif diff --git a/src/lib/SoDA/inc/interface/IChain.h b/src/lib/SoDA/inc/interface/IChain.h new file mode 100644 index 0000000..f3fa347 --- /dev/null +++ b/src/lib/SoDA/inc/interface/IChain.h @@ -0,0 +1,134 @@ +/* + * Copyright (C): 2013-2014 Department of Software Engineering, University of Szeged + * + * Author: David Imre Adam + * + * This file is part of SoDA. + * + * SoDA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * SoDA 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with SoDA. If not, see . + */ + +#include +#include +#include "data/CIDManager.h" +#include "data/CBitMatrix.h" + +#ifndef ICHAIN_H +#define ICHAIN_H + +using namespace std; + +namespace soda +{ + /** + * @brief Interface for Chain class + */ + class IChain + { + public: + /** + * @brief Gets the count of elements + * @return count + */ + virtual IndexType count() = 0; + + /** + * @brief Clears the containers + */ + virtual void clear() = 0; + + /** + * @brief Adds a new element + * @param n The new value of the element + */ + virtual void add(const String& n) = 0; + + /** + * @brief Adds a vector of new elements to the end of the chain + * @param codeElements The vector of elements + */ + virtual void add(const StringVector& codeElements) = 0; + + /** + * @brief Removes a value from the containers + * @param n The removable value + */ + virtual void remove(const String& n) = 0; + + /** + * @brief Does the chain contain the element. + * @param n The new value of the element + * @return the answer + */ + virtual bool contains(const String& n) = 0; + + /** + * @brief Gets the elementId of the value n + * @param n The requested value + * @return the index of the element + */ + virtual IndexType getId(const String& n) = 0; + + /** + * @brief Gets the value of the elementId n + * @param n The requested id + * @return the value + */ + virtual String getValue(const IndexType n) = 0; + + /** + * @brief Gets the first type iterator to the beginnig of chain + * @return the begin-iterator + */ + virtual vector::const_iterator first() = 0; + + /** + * @brief Gets the last type iterator to the end of chain + * @return the end-iterator + */ + virtual vector::const_iterator end() = 0; + + /** + * @brief Saves a chain as binary data to the out stream + * @param [IN] out The stream + */ + virtual void save(io::CBinaryIO *out) const = 0; + + /** + * @brief Loads chain by binary data from in stream + * @param [IN] in The source stream + */ + virtual void load(io::CSoDAio *in) = 0; + + /** + * @brief Saves the chain to file + * @param [IN] in The filename + */ + virtual void save(const char * filename) const = 0; + + /** + * @brief Loads chain from file + * @param [IN] filename The filename + */ + virtual void load(const char * filename) = 0; + + /** + * @brief Loads chain from JSON data file + * @param [IN] filename The requested id + */ + virtual void loadJson(const String& path) = 0; + }; +} + +#endif diff --git a/src/lib/SoDA/inc/interface/IDAG.h b/src/lib/SoDA/inc/interface/IDAG.h new file mode 100644 index 0000000..2f56b5b --- /dev/null +++ b/src/lib/SoDA/inc/interface/IDAG.h @@ -0,0 +1,178 @@ +/* + * Copyright (C): 2013-2014 Department of Software Engineering, University of Szeged + * + * Author: David Imre Adam + * + * This file is part of SoDA. + * + * SoDA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * SoDA 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with SoDA. If not, see . + */ + +#include +#include +#include "data/CIDManager.h" +#include "interface/IGraph.h" +#include "data/Node.h" + +#ifndef IDAG_H +#define IDAG_H + +using namespace std; + +namespace soda +{ + class IDAG + { + public: + + /** + * @brief Gets the count of mapping nodes + * @return count + */ + virtual IndexType nodeCount() = 0; + + /** + * @brief Gets the count of edges + * @return count + */ + virtual IndexType edgeCount() = 0; + + /** + * @brief Clears the containers + */ + virtual void clear() = 0; + + /** + * @brief Adds a new node + * @param n The new value of the element + * @return the newly created Node + */ + virtual Node* addNode(const String& n) = 0; + + /** + * @brief Adds an exsisting element as a new node + * @param elemenId The exsisting elementId + * @return the newly created Node + */ + virtual Node* addNode(const IndexType i) = 0; + + /** + * @brief Adds an exsisting element as a new node to a parent + * @param elemenId The new value of the element + * @return the newly created Node + */ + virtual Node* addChild(const IndexType parentNodeId, const String& n) = 0; + + /** + * @brief Adds a new edge between exsisting nodes + * @param parentNodeId The parent node + * @param childNodeId The child node + */ + virtual void addEdge(const IndexType parentNodeId, const IndexType childNodeId) = 0; + + /** + * @brief Adds a new edge between exsisting nodes + * @param parentNode The parent node + * @param childNode The child node + */ + virtual void addEdge(Node* parent, Node* child) = 0; + + /** + * @brief Gets value of node + * @param node The node + * @return the value + */ + virtual bool isValid(IndexType root) = 0; + + /** + * @brief Gets value of node + * @param node The node + * @return the value + */ + virtual String getNodeValue(Node* node) = 0; + + /** + * @brief Gets value of node by nodeId + * @param nodeId The node + * @return the value + */ + virtual String getNodeValue(IndexType nodeId) = 0; + + /** + * @brief Gets value of the element by elementId + * @param elementId The node + * @return the value + */ + virtual String getValue(IndexType elementId) = 0; + + /** + * @brief Gets value of the element by nodeId + * @param nodeId The node + * @return the vector of edges + */ + virtual vector& getEdges(const IndexType& i) = 0; + + /** + * @brief Gets DFS order starting with nodeId + * @param i The node Id + * @return the vector of order + */ + virtual vector* getDFS(IndexType i) = 0; + + /** + * @brief Gets BFS order starting with nodeId + * @param i The node Id + * @return the vector of order + */ + virtual vector* getBFS(IndexType i) = 0; + + /** + * @brief Converts a DAG to chains + * @return the vector of orderlists + */ + virtual vector*>* convertToNodeIdChains() = 0; + + /** + * @brief Saves a chain as binary data to the out stream + * @param out The stream + */ + virtual void save(io::CBinaryIO* out) const = 0; + + /** + * @brief Loads chain by binary data from in stream + * @param in The source stream + */ + virtual void load(io::CSoDAio* in) = 0; + + /** + * @brief Saves the chain to file + * @param in The filename + */ + virtual void save(const char* filename) const = 0; + + /** + * @brief Loads chain from file + * @param filename The filename + */ + virtual void load(const char* filename) = 0; + + /** + * @brief Loads chain from JSON data file + * @param filename The requested id + */ + virtual void loadJson(const String& path) = 0; + }; +} + +#endif diff --git a/src/lib/SoDA/inc/interface/IGraph.h b/src/lib/SoDA/inc/interface/IGraph.h new file mode 100644 index 0000000..0f5cb47 --- /dev/null +++ b/src/lib/SoDA/inc/interface/IGraph.h @@ -0,0 +1,125 @@ +/* + * Copyright (C): 2013-2014 Department of Software Engineering, University of Szeged + * + * Author: David Imre Adam + * + * This file is part of SoDA. + * + * SoDA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * SoDA 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with SoDA. If not, see . + */ + +#include +#include +#include "data/CIDManager.h" + +#ifndef IGRAPH_H +#define IGRAPH_H + +using namespace std; +using namespace soda::io; + +namespace soda +{ + /** + * @brief Graph interface + */ + class IGraph + { + public: + + /** + * @brief Gets the count of mapping nodes + * @return count + */ + virtual IndexType nodeCount() = 0; + + /** + * @brief Gets the count of edges + * @return count + */ + virtual IndexType edgeCount() = 0; + + /** + * @brief Clears the containers + */ + virtual void clear() = 0; + + /** + * @brief Adds a new node + * @param n The new value of the element + * @return the newly created elemntId + */ + virtual IndexType addNode(const String& n) = 0; + + /** + * @brief Adds an new edge between two elements + * @param i The exsisting elementId + * @param j The exsisting elementId + */ + virtual void addEdge(const IndexType i, IndexType j) = 0; + + /** + * @brief Gets value of the element by nodeId + * @param nodeId The node + * @return the vector of edges + */ + virtual vector& getEdges(const IndexType& i) = 0; + + /** + * @brief Gets DFS order starting with nodeId + * @param i The node Id + * @return the vector of order + */ + virtual vector* getDFS(const IndexType& i) = 0; + + /** + * @brief Gets BFS order starting with nodeId + * @param i The node Id + * @return the vector of order + */ + virtual vector* getBFS(const IndexType& i) = 0; + + /** + * @brief Saves a chain as binary data to the out stream + * @param [IN] out The stream + */ + virtual void save(io::CBinaryIO *out) const = 0; + + /** + * @brief Loads chain by binary data from in stream + * @param [IN] in The source stream + */ + virtual void load(io::CSoDAio *in) = 0; + + /** + * @brief Saves the chain to file + * @param [IN] in The filename + */ + virtual void save(const char * filename) const = 0; + + /** + * @brief Loads chain from file + * @param [IN] filename The filename + */ + virtual void load(const char * filename) = 0; + + /** + * @brief Loads chain from JSON data file + * @param [IN] filename The requested id + */ + virtual void loadJson(const String& path) = 0; + }; +} + +#endif diff --git a/src/lib/SoDA/inc/io/CSoDAio.h b/src/lib/SoDA/inc/io/CSoDAio.h index 675ef6a..e036f80 100644 --- a/src/lib/SoDA/inc/io/CSoDAio.h +++ b/src/lib/SoDA/inc/io/CSoDAio.h @@ -3,6 +3,7 @@ * * Authors: László Langó <> * Tamás Gergely + * Dávid Imre Ádám * * This file is part of SoDA. * @@ -71,7 +72,11 @@ class CSoDAio : public io::CBinaryIO { CHANGESET, CODEELEMENT_TRACE, REVLIST, - BUGSET + BUGSET, + CHAIN, + GRAPH, + TREE, + DAG }; /** diff --git a/src/lib/SoDA/src/algorithm/CBFS.cpp b/src/lib/SoDA/src/algorithm/CBFS.cpp new file mode 100644 index 0000000..4db4540 --- /dev/null +++ b/src/lib/SoDA/src/algorithm/CBFS.cpp @@ -0,0 +1,163 @@ +/* + * Copyright (C): 2013-2014 Department of Software Engineering, University of Szeged + * + * Author: David Imre Adam + * + * This file is part of SoDA. + * + * SoDA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * SoDA 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with SoDA. If not, see . + */ + +#include "algorithm/CBFS.h" + +namespace soda +{ + CBFS::CBFS(vector>& edges) : + m_edges(&edges), + m_bfsOrder(new vector()) { }; + + CBFS::~CBFS(){ } + + vector *CBFS::getBFS(IndexType root) + { + IndexType edgeCount = m_edges->size(); + list queue; + bool *visited = new bool[edgeCount]; + + for(int i = 0; i < edgeCount; i++) + visited[i] = false; + + visited[root] = true; + queue.push_back(root); + + while(!queue.empty()) + { + IndexType s = queue.front(); + m_bfsOrder->push_back(s); + queue.pop_front(); + + for (std::vector::iterator i = m_edges->at(s).begin(); i != m_edges->at(s).end(); ++i) + { + if (!visited[*i]) + { + visited[*i] = true; + queue.push_back(*i); + } + } + } + + delete visited; + + return m_bfsOrder; + } + + bool CBFS::inDegreeGTOne(IndexType root) + { + //Is it possible to touch all of the nodes one-time only + IndexType nodeCount = m_edges->size(); + list queue; + bool *visited = new bool[nodeCount]; + + //Initialize bool[] with false values + for(int i = 0; i < nodeCount; i++) + visited[i] = false; + + //Starting with the Root node + visited[root] = true; + queue.push_back(root); + + while(!queue.empty()) + { + IndexType s = queue.front(); + queue.pop_front(); + + //Iterating edges to deepre-level nodes + for (std::vector::iterator i = m_edges->at(s).begin(); i != m_edges->at(s).end(); ++i) + { + if (!visited[*i]) + { + //Feeding the queue with untouched nodes + visited[*i] = true; + queue.push_back(*i); + } + else + { + return true; + } + } + } + + return false; + } + + list* CBFS::scrollBackSingleChain(vector* chainElements, Node* endNode, IndexType root) + { + list* chain = new list(); + + chain->push_front(endNode->m_elementId); + Node* n = chainElements->at(endNode->m_id); + + while(n->m_elementId != root) + { + chain->push_front(n->m_elementId); + n = chainElements->at(n->m_id); + } + + chain->push_front(n->m_elementId); + + return chain; + } + + vector*>* CBFS::getPaths(IndexType rootElementId) + { + auto chains = new vector*>(); + + vector* chainElements = new vector(); + list currentLevel; + IndexType index = 0; + + Node* rootNode = new Node(index,rootElementId); + + chainElements->push_back(rootNode); + currentLevel.push_back(0); + + while(!currentLevel.empty()) + { + IndexType parentIndex = currentLevel.front(); + currentLevel.pop_front(); + + for (std::vector::iterator i = m_edges->at(chainElements->at(parentIndex)->m_elementId).begin(); i != m_edges->at(chainElements->at(parentIndex)->m_elementId).end(); ++i) + { + Node* c = new Node(parentIndex, *i); + chainElements->push_back(c); + if(m_edges->at(*i).size() == 0) + { + chains->push_back(scrollBackSingleChain(chainElements, c, rootElementId)); + } + + currentLevel.push_back(++index); + } + } + + for(vector::iterator i = chainElements->begin(); i < chainElements->end(); i++) + { + delete *i; + *i = NULL; + } + + delete chainElements; + + return chains; + } +} diff --git a/src/lib/SoDA/src/algorithm/CDFS.cpp b/src/lib/SoDA/src/algorithm/CDFS.cpp new file mode 100644 index 0000000..a0a9993 --- /dev/null +++ b/src/lib/SoDA/src/algorithm/CDFS.cpp @@ -0,0 +1,116 @@ +/* + * Copyright (C): 2013-2014 Department of Software Engineering, University of Szeged + * + * Author: David Imre Adam + * + * This file is part of SoDA. + * + * SoDA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * SoDA 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with SoDA. If not, see . + */ + +#include +#include "algorithm/CDFS.h" + +namespace soda +{ + CDFS::CDFS(vector>& edges) : + m_edges(&edges), + m_dfsOrder(new vector()) { }; + + CDFS::~CDFS(){ } + + void CDFS::recursiveHelper(IndexType current, bool visited[]) + { + visited[current] = true; + + m_dfsOrder->push_back(current); + + for (std::vector::iterator i = m_edges->at(current).begin(); i != m_edges->at(current).end(); ++i) + { + if (!visited[*i]) + { + recursiveHelper(*i, visited); + } + } + } + + vector *CDFS::getDFS(IndexType root) + { + IndexType edgeCount = m_edges->size(); + bool *visited = new bool[edgeCount]; + + for (IndexType i = 0; i < edgeCount; i++) + { + visited[i] = false; + } + + recursiveHelper(root, visited); + + delete visited; + + return m_dfsOrder; + } + + bool CDFS::hasCycleHelper(IndexType v, bool visited[], bool *recorded) + { + if(visited[v] == false) + { + visited[v] = true; + recorded[v] = true; + + for(vector::iterator i = m_edges->at(v).begin(); i != m_edges->at(v).end(); ++i) + { + if (!visited[*i] && hasCycleHelper(*i, visited, recorded)) + { + return true; + } + else if (recorded[*i]) + { + return true; + } + } + } + + recorded[v] = false; + + return false; + } + + bool CDFS::hasCycle() + { + IndexType size = m_edges->size(); + + bool *visited = new bool[size]; + bool *recorded = new bool[size]; + + for(IndexType i = 0; i < size; i++) + { + visited[i] = false; + recorded[i] = false; + } + + for(IndexType i = 0; i < size; i++) + { + if (hasCycleHelper(i, visited, recorded)) + { + return true; + } + } + + delete visited; + delete recorded; + + return false; + } +} diff --git a/src/lib/SoDA/src/data/CChain.cpp b/src/lib/SoDA/src/data/CChain.cpp new file mode 100644 index 0000000..7777d4b --- /dev/null +++ b/src/lib/SoDA/src/data/CChain.cpp @@ -0,0 +1,177 @@ +/* + * Copyright (C): 2013-2014 Department of Software Engineering, University of Szeged + * + * Author: David Imre Adam + * + * This file is part of SoDA. + * + * SoDA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * SoDA 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with SoDA. If not, see . + */ + +#include +#include +#include +#include +#include "data/CIDManager.h" +#include "data/CChain.h" +#include "interface/IIterators.h" + +using namespace std; +using namespace soda::io; + +namespace soda +{ + CChain::CChain(): + m_codeElements(new CIDManager()), + m_order(new vector()) + {} + + CChain::~CChain() + { + delete m_codeElements; + m_codeElements = NULL; + delete m_order; + m_order = NULL; + } + + IndexType CChain::count() + { + return m_codeElements->size(); + } + + void CChain::clear() + { + m_codeElements->clear(); + m_order->clear(); + } + + void CChain::add(const String& n) + { + m_codeElements->add(n); + m_order->push_back(n); + } + + void CChain::add(const StringVector& codeElements) + { + std::copy ( codeElements.begin(), codeElements.end(), m_order->end() ); + + for(StringVector::const_iterator it = codeElements.begin(); it != codeElements.end(); ++it) { + m_codeElements->add(*it); + } + } + + void CChain::remove(const String& n) + { + m_codeElements->remove(n); + m_order->erase(std::remove(m_order->begin(), m_order->end(), n), m_order->end()); + } + + bool CChain::contains(const String& n) + { + return m_codeElements->containsValue(n); + } + + IndexType CChain::getId(const String& n) + { + return m_codeElements->getID(n); + } + + String CChain::getValue(const IndexType n) + { + return m_codeElements->getValue(n); + } + + vector::const_iterator CChain::first() + { + return m_order->begin(); + } + + vector::const_iterator CChain::end() + { + return m_order->end(); + } + + void CChain::save(io::CBinaryIO *out) const + { + IndexType size = m_order->size(); + unsigned long long int length = (1 + size) * sizeof(IndexType); + + //write IDManager + m_codeElements->save(out, io::CSoDAio::IDMANAGER); + //write ChunkID + out->writeUInt4(io::CSoDAio::CHAIN); + //write length + out->writeULongLong8(length); + //write the number of elements + out->writeLongLong8(size); + //write elements + for(vector::const_iterator it = m_order->begin() ; it != m_order->end(); ++it ) { + out->writeString(*it); + } + } + + void CChain::load(io::CSoDAio *in) + { + m_codeElements->clear(); + m_order->clear(); + + while(in->nextChunkID()) { + auto chunkId = in->getChunkID(); + + if(chunkId == io::CSoDAio::IDMANAGER) { + m_codeElements->load(in); + } + if(chunkId == io::CSoDAio::CHAIN){ + IndexType size = in->readLongLong8(); + + for (IndexType i = 0; i < size; ++i) { + String value = in->readString(); + + m_order->push_back(value); + } + } + } + } + + void CChain::save(const char * filename) const + { + io::CSoDAio *out = new io::CSoDAio(filename, io::CBinaryIO::omWrite); + save(out); + delete out; + } + + void CChain::load(const char * filename) + { + io::CSoDAio *in = new io::CSoDAio(filename, io::CBinaryIO::omRead); + load(in); + delete in; + } + + void CChain::loadJson(const String& path) + { + CJsonReader *reader = new CJsonReader(path); + + //Read IDManager elements + StringVector strings = reader->getStringVectorFromProperty("chain"); + for(IndexType i = 0; i < strings.size(); i++) + { + String value = strings[i]; + m_codeElements->add(value); + m_order->push_back(value); + } + + delete reader; + reader = 0; + } +} diff --git a/src/lib/SoDA/src/data/CDAG.cpp b/src/lib/SoDA/src/data/CDAG.cpp new file mode 100644 index 0000000..1cebca0 --- /dev/null +++ b/src/lib/SoDA/src/data/CDAG.cpp @@ -0,0 +1,382 @@ +/* + * Copyright (C): 2013-2014 Department of Software Engineering, University of Szeged + * + * Author: David Imre Adam + * + * This file is part of SoDA. + * + * SoDA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * SoDA 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with SoDA. If not, see . + */ + +#include "data/CDAG.h" +#include "data/Node.h" +#include "algorithm/CDFS.h" +#include "algorithm/CBFS.h" + +using namespace std; +using namespace soda::io; + +namespace soda +{ + CDAG::CDAG(): + m_codeElements(new CIDManager()), + m_structure(new vector>()), + m_nodes(new vector()) + {} + + CDAG::~CDAG() + { + delete m_codeElements; + m_codeElements = NULL; + delete m_structure; + m_structure = NULL; + + for(IndexType i = 0; i < m_nodes->size(); i++) + { + delete m_nodes->at(i); + m_nodes->at(i) = NULL; + } + + delete m_nodes; + m_nodes = NULL; + } + + void CDAG::clear() + { + m_codeElements->clear(); + m_structure->clear(); + + for(IndexType i = 0; i < m_nodes->size(); i++) + { + delete m_nodes->at(i); + m_nodes->at(i) = NULL; + } + + m_nodes->clear(); + } + + IndexType CDAG::nodeCount() + { + return m_nodes->size(); + } + + IndexType CDAG::edgeCount() + { + IndexType count = 0; + + for(vector>::iterator it = m_structure->begin(); it != m_structure->end(); it++) + { + count+= it->size(); + } + + return count; + } + + vector& CDAG::getEdges(const IndexType& nodeId) + { + return m_structure->at(nodeId); + } + + void CDAG::addEdge(Node* parent, Node* child) + { + addEdge(parent->m_id, child->m_id); + } + + Node* CDAG::addNode(const IndexType elementId) + { + IndexType newIndex = m_nodes->size() == 0 ? 0 : m_nodes->back()->m_id+1; + Node* n = new Node(newIndex, elementId); + + m_nodes->push_back(n); + m_structure->push_back(vector()); + + return n; + } + + Node* CDAG::addNode(const String& n) + { + m_codeElements->add(n); + + IndexType i = m_codeElements->getID(n); + + return addNode(i); + } + + Node* CDAG::addChild(const IndexType parentNodeId, const String& n) + { + Node* newNode = addNode(n); + m_structure->at(parentNodeId).push_back(newNode->m_id); + + return newNode; + } + + String CDAG::getNodeValue(Node* node) + { + return m_codeElements->getValue(node->m_elementId); + } + + String CDAG::getNodeValue(IndexType nodeId) + { + return m_codeElements->getValue(m_nodes->at(nodeId)->m_elementId); + } + + String CDAG::getValue(IndexType elementId) + { + return m_codeElements->getValue(elementId); + } + + bool CDAG::isValid(IndexType root) + { + return !CDFS(*m_structure).hasCycle(); + } + + void CDAG::addEdge(const IndexType parentNodeId, const IndexType childNodeId) + { + auto edges = m_structure->at(parentNodeId); + + bool exsistingEdge = std::find(edges.begin(), edges.end(), childNodeId) != edges.end(); + if(exsistingEdge || parentNodeId == childNodeId) + { + return; + } + + m_structure->at(parentNodeId).push_back(childNodeId); + + bool isValid = this->isValid(0); + + if (!isValid) + { + m_structure->at(parentNodeId).pop_back(); + throw logic_error("This edge cannot be applied. It creates a circle."); + } + } + + vector* CDAG::getDFS(IndexType i) + { + return CDFS(*m_structure).getDFS(i); + } + + vector* CDAG::getBFS(IndexType i) + { + return CBFS(*m_structure).getBFS(i); + } + + vector*> *CDAG::convertToNodeIdChains() + { + return CBFS(*m_structure).getPaths(0); + } + + void CDAG::save(io::CBinaryIO *out) const + { + //IDManager + m_codeElements->save(out, io::CSoDAio::IDMANAGER); + + //Tree + out->writeUInt4(m_chunkId); + + IndexType length = sizeof(IndexType); + + for(vector>::const_iterator rit = m_structure->begin() ; rit != m_structure->end(); ++rit ) + { + length += sizeof(IndexType); + + for(vector::const_iterator it = rit->begin() ; it != rit->end(); ++it ) + { + length += sizeof(IndexType); + } + } + + length += m_nodes->size() * sizeof(Node); + + out->writeULongLong8(length); + + //Count of nodes + IndexType nodesCount = m_nodes->size(); + out->writeULongLong8(nodesCount); + + //Nodes + for(vector::const_iterator it = m_nodes->begin() ; it != m_nodes->end(); ++it ) + { + out->writeULongLong8((*it)->m_id); + out->writeULongLong8((*it)->m_elementId); + } + + //Edges + for(vector>::const_iterator rit = m_structure->begin() ; rit != m_structure->end(); ++rit ) + { + IndexType edgeCount = rit->size(); + out->writeULongLong8(edgeCount); + + for(vector::const_iterator it = rit->begin() ; it != rit->end(); ++it ) + { + out->writeULongLong8(*it); + } + } + } + + void CDAG::load(io::CSoDAio *in) + { + m_codeElements->clear(); + m_structure->clear(); + m_nodes->clear(); + + while(in->nextChunkID()) { + auto chunkId = in->getChunkID(); + + if(chunkId == io::CSoDAio::IDMANAGER) + { + m_codeElements->load(in); + } + + if(m_chunkId == chunkId){ + IndexType nodeCount = in->readULongLong8(); + + for(IndexType i = 0; i < nodeCount; ++i) + { + IndexType mId = in->readULongLong8(); + IndexType mElementId = in->readULongLong8(); + + m_nodes->push_back(new Node(mId, mElementId)); + } + + for (IndexType e = 0; e < nodeCount; ++e) + { + IndexType edgeCount = in->readULongLong8(); + + vector edges; + + for (IndexType i = 0; i < edgeCount; ++i) + { + IndexType edge = in->readULongLong8(); + + edges.push_back(edge); + } + + m_structure->push_back(edges); + } + } + } + } + + void CDAG::save(const char * filename) const + { + io::CSoDAio *out = new io::CSoDAio(filename, io::CBinaryIO::omWrite); + save(out); + delete out; + } + + void CDAG::load(const char * filename) + { + io::CSoDAio *in = new io::CSoDAio(filename, io::CBinaryIO::omRead); + load(in); + delete in; + } + + void CDAG::loadJson(const String& path) + { + CJsonReader *reader = new CJsonReader(path); + + //Read IDManager elements + vector nodes = reader->getPropertyVectorFromProperty("nodes"); + vector edges = reader->getPropertyVectorFromProperty("edges"); + + for(IndexType i = 0; i < nodes.size(); i++) + { + IndexType nodeId = nodes[i].getIntFromProperty("id"); + String value = nodes[i].getStringFromProperty("value"); + + this->addNode(value); + } + + for(IndexType i = 0; i < edges.size(); i++) + { + IndexType nodeId = edges[i].getIntFromProperty("nodeId"); + vector values = edges[i].getIntVectorFromProperty("values"); + + for(vector::iterator v = values.begin(); v < values.end(); v++) + { + this->addEdge(nodeId, *v); + } + } + + delete reader; + reader = 0; + } + + CGraph* CDAG::toGraph() + { + CGraph* graph = new CGraph(); + + for(IndexType c = 0; c < m_codeElements->size(); c++) + { + graph->addNode(m_codeElements->getValue(c)); + } + + for(IndexType i = 0; i < m_nodes->size(); i++) + { + IndexType nodeElement = m_nodes->at(i)->m_elementId; + vector* neighbours = &(m_structure->at(i)); + + for(IndexType j = 0; j < neighbours->size(); j++) + { + IndexType neighbourElement = m_nodes->at(neighbours->at(j))->m_elementId; + graph->addEdge(nodeElement, neighbourElement); + } + } + + return graph; + } + + CDAG* CDAG::getContractedDAG() + { + auto paths = this->convertToNodeIdChains(); + + CDAG* newDAG = new CDAG(); + + for(IndexType chainId = 0; chainId < paths->size(); chainId++) + { + IndexType parentNodeId = 0; + IndexType currentNodeId = 0; + + for(list::iterator i = paths->at(chainId)->begin(); i != paths->at(chainId)->end(); i++) + { + String elementValue = m_codeElements->getValue(m_nodes->at(*i)->m_elementId); + + if(!newDAG->m_codeElements->containsValue(elementValue)) + { + //New node + if(i == paths->at(chainId)->begin()) + { + //Root + parentNodeId = newDAG->addNode(elementValue)->m_id; + } + else + { + //Leaf + parentNodeId = newDAG->addChild(m_nodes->at(parentNodeId)->m_id, elementValue)->m_id; + } + } + else if(i != paths->at(chainId)->begin()) + { + //New edge + currentNodeId = newDAG->m_codeElements->getID(elementValue); + newDAG->addEdge(parentNodeId, currentNodeId); + parentNodeId = currentNodeId; + } + } + } + + return newDAG; + } +} diff --git a/src/lib/SoDA/src/data/CGraph.cpp b/src/lib/SoDA/src/data/CGraph.cpp new file mode 100644 index 0000000..a4f6ae9 --- /dev/null +++ b/src/lib/SoDA/src/data/CGraph.cpp @@ -0,0 +1,225 @@ +/* + * Copyright (C): 2013-2014 Department of Software Engineering, University of Szeged + * + * Author: David Imre Adam + * + * This file is part of SoDA. + * + * SoDA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * SoDA 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with SoDA. If not, see . + */ + +#include "data/CGraph.h" +#include "algorithm/CDFS.h" +#include "algorithm/CBFS.h" + +using namespace std; +using namespace soda::io; + +namespace soda +{ + CGraph::CGraph(): + m_codeElements(new CIDManager()), + m_edges(new vector>()) + {} + + CGraph::~CGraph() + { + delete m_codeElements; + m_codeElements = NULL; + delete m_edges; + m_edges = NULL; + } + + IndexType CGraph::nodeCount() + { + return m_codeElements->size(); + } + + IndexType CGraph::edgeCount() + { + IndexType count = 0; + + for(vector>::iterator it = m_edges->begin(); it != m_edges->end(); it++) { + { + count+= it->size(); + } + } + + return count; + } + + void CGraph::clear() + { + m_codeElements->clear(); + m_edges->clear(); + } + + IndexType CGraph::addNode(const String& n) + { + //Check exsisting element + if(m_codeElements->containsValue(n)) + { + return m_codeElements->getID(n); + } + + m_codeElements->add(n); + IndexType i = m_codeElements->getID(n); + + m_edges->push_back(vector()); + + return i; + } + + void CGraph::addEdge(const IndexType i, const IndexType j) + { + IndexType ma = max(i,j); + + //Index check + if(ma >= m_codeElements->size()) + { + throw range_error("Invalid element index."); + } + + auto edges = m_edges->at(min(i,j)); + + //Checking exsistance + if(std::find(edges.begin(), edges.end(), ma) == edges.end()) + { + m_edges->at(i).push_back(j); + m_edges->at(j).push_back(i); + } + } + + vector& CGraph::getEdges(const IndexType& i) + { + return m_edges->at(i); + } + + vector *CGraph::getDFS(const IndexType& i) + { + return CDFS(*m_edges).getDFS(i); + } + + vector *CGraph::getBFS(const IndexType& i) + { + return CBFS(*m_edges).getBFS(i); + } + + void CGraph::save(io::CBinaryIO *out) const + { + //IDManager + m_codeElements->save(out, io::CSoDAio::IDMANAGER); + + //Graph + out->writeUInt4(io::CSoDAio::GRAPH); + + IndexType length = sizeof(IndexType); + + for(vector>::const_iterator rit = m_edges->begin() ; rit != m_edges->end(); ++rit ) + { + length += sizeof(IndexType); + + for(vector::const_iterator it = rit->begin() ; it != rit->end(); ++it ) + { + length += sizeof(IndexType); + } + } + out->writeULongLong8(length); + + //Count of nodes + IndexType size = m_edges->size(); + out->writeULongLong8(size); + + for(vector>::const_iterator rit = m_edges->begin() ; rit != m_edges->end(); ++rit ) + { + IndexType edgeCount = rit->size(); + out->writeULongLong8(edgeCount); + + for(vector::const_iterator it = rit->begin() ; it != rit->end(); ++it ) + { + out->writeULongLong8(*it); + } + } + } + + void CGraph::load(io::CSoDAio *in) + { + m_codeElements->clear(); + m_edges->clear(); + + while(in->nextChunkID()) { + auto chunkId = in->getChunkID(); + + if(chunkId == io::CSoDAio::IDMANAGER) { + m_codeElements->load(in); + } + + if(chunkId == io::CSoDAio::GRAPH){ + IndexType nodeCount = in->readULongLong8(); + + for (IndexType e = 0; e < nodeCount; ++e) { + IndexType edgeCount = in->readULongLong8(); + + vector edges; + + for (IndexType i = 0; i < edgeCount; ++i) { + IndexType edge = in->readULongLong8(); + edges.push_back(edge); + } + + m_edges->push_back(edges); + } + } + } + } + + void CGraph::save(const char * filename) const + { + io::CSoDAio *out = new io::CSoDAio(filename, io::CBinaryIO::omWrite); + save(out); + delete out; + } + + void CGraph::load(const char * filename) + { + io::CSoDAio *in = new io::CSoDAio(filename, io::CBinaryIO::omRead); + load(in); + delete in; + } + + void CGraph::loadJson(const String& path) + { + CJsonReader *reader = new CJsonReader(path); + + //Read IDManager elements + vector properties = reader->getPropertyVectorFromProperty("graph"); + for(IndexType i = 0; i < properties.size(); i++) + { + String nodeName = properties[i].getStringFromProperty("node"); + vector edges = properties[i].getStringVectorFromProperty("edges"); + + IndexType base = this->addNode(nodeName); + + for(StringVector::iterator i = edges.begin(); i< edges.end(); i++) + { + IndexType to = this->addNode(*i); + + this->addEdge(base, to); + } + } + + delete reader; + reader = 0; + } +} diff --git a/src/lib/SoDA/src/data/CTree.cpp b/src/lib/SoDA/src/data/CTree.cpp new file mode 100644 index 0000000..2135d56 --- /dev/null +++ b/src/lib/SoDA/src/data/CTree.cpp @@ -0,0 +1,67 @@ +/* + * Copyright (C): 2013-2014 Department of Software Engineering, University of Szeged + * + * Author: David Imre Adam + * + * This file is part of SoDA. + * + * SoDA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * SoDA 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with SoDA. If not, see . + */ + +#include "data/CTree.h" +#include "algorithm/CDFS.h" +#include "algorithm/CBFS.h" + +using namespace std; +using namespace soda::io; + +namespace soda +{ + CTree::CTree(): CDAG() + { + + } + + CTree::~CTree() + { + m_codeElements->clear(); + m_structure->clear(); + + for(IndexType i = 0; i < m_nodes->size(); i++) + { + delete m_nodes->at(i); + m_nodes->at(i) = NULL; + } + + m_nodes->clear(); + } + + Node* CTree::addChild(const IndexType parentNodeId, const String& n) + { + Node* newNode = addNode(n); + m_structure->at(parentNodeId).push_back(newNode->m_id); + + return newNode; + } + + bool CTree::isValid(IndexType root) + { + return !CBFS(*m_structure).inDegreeGTOne(root); + } + + CDAG* CTree::toDAG() + { + return (CDAG*)this; + } +} diff --git a/src/sample/cchain.json b/src/sample/cchain.json new file mode 100644 index 0000000..b8394ba --- /dev/null +++ b/src/sample/cchain.json @@ -0,0 +1,9 @@ +{ + "chain": [ + "Element1", + "Element2", + "Element3", + "Debug" + ] +} + diff --git a/src/sample/cdag.json b/src/sample/cdag.json new file mode 100644 index 0000000..13f001f --- /dev/null +++ b/src/sample/cdag.json @@ -0,0 +1,26 @@ +{ + "nodes":[ + {"id":"0", "value":"a"}, + {"id":"1", "value":"b"}, + {"id":"2", "value":"c"}, + {"id":"3", "value":"d"}, + {"id":"4", "value":"e"}, + {"id":"5", "value":"f"}, + {"id":"6", "value":"g"}, + {"id":"7", "value":"h"}, + {"id":"8", "value":"i"}, + {"id":"9", "value":"j"} + ], + "edges": [ + {"nodeId":"0", "values":["1","2","3"]}, + {"nodeId":"1", "values":["2","4","5"]}, + {"nodeId":"2", "values":["6"]}, + {"nodeId":"3", "values":["7"]}, + {"nodeId":"4", "values":[]}, + {"nodeId":"5", "values":["6"]}, + {"nodeId":"6", "values":["8"]}, + {"nodeId":"7", "values":["8","9"]}, + {"nodeId":"8", "values":[]}, + {"nodeId":"9", "values":[]} + ] +} diff --git a/src/sample/cdagChains.json b/src/sample/cdagChains.json new file mode 100644 index 0000000..31b954d --- /dev/null +++ b/src/sample/cdagChains.json @@ -0,0 +1,26 @@ +{ + "nodes":[ + {"id":"0", "value":"a"}, + {"id":"1", "value":"b"}, + {"id":"2", "value":"c"}, + {"id":"3", "value":"d"}, + {"id":"4", "value":"e"}, + {"id":"5", "value":"f"}, + {"id":"6", "value":"g"}, + {"id":"7", "value":"h"}, + {"id":"8", "value":"i"}, + {"id":"9", "value":"j"} + ], + "edges": [ + {"nodeId":"0", "values":["1","2","3"]}, + {"nodeId":"1", "values":["2","4","5"]}, + {"nodeId":"2", "values":["6"]}, + {"nodeId":"3", "values":["7"]}, + {"nodeId":"4", "values":[]}, + {"nodeId":"5", "values":["2"]}, + {"nodeId":"6", "values":["8"]}, + {"nodeId":"7", "values":["8","9"]}, + {"nodeId":"8", "values":[]}, + {"nodeId":"9", "values":[]} + ] +} diff --git a/src/sample/cgraph.json b/src/sample/cgraph.json new file mode 100644 index 0000000..d816a15 --- /dev/null +++ b/src/sample/cgraph.json @@ -0,0 +1,9 @@ +{ + "graph": [ + { "node" : "a", "edges" : ["b","c","d"]}, + { "node" : "c", "edges" : ["e", "f"]}, + { "node" : "d", "edges" : ["g"]}, + { "node" : "g", "edges" : ["a"]}, + { "node" : "a", "edges" : ["b","c","d"]} + ] +} diff --git a/src/sample/ctree.json b/src/sample/ctree.json new file mode 100644 index 0000000..2035fbd --- /dev/null +++ b/src/sample/ctree.json @@ -0,0 +1,26 @@ +{ + "nodes":[ + {"id":"0", "value":"a"}, + {"id":"1", "value":"b"}, + {"id":"2", "value":"c"}, + {"id":"3", "value":"d"}, + {"id":"4", "value":"e"}, + {"id":"5", "value":"f"}, + {"id":"6", "value":"g"}, + {"id":"7", "value":"h"}, + {"id":"8", "value":"i"}, + {"id":"9", "value":"j"} + ], + "edges": [ + {"nodeId":"0", "values":["1","2","3"]}, + {"nodeId":"1", "values":["4","5"]}, + {"nodeId":"2", "values":["6"]}, + {"nodeId":"3", "values":["7"]}, + {"nodeId":"4", "values":[]}, + {"nodeId":"5", "values":[]}, + {"nodeId":"6", "values":[]}, + {"nodeId":"7", "values":["8","9"]}, + {"nodeId":"8", "values":[]}, + {"nodeId":"9", "values":[]} + ] +} diff --git a/src/test/lib/SoDA/TestChain.cpp b/src/test/lib/SoDA/TestChain.cpp new file mode 100644 index 0000000..56eb880 --- /dev/null +++ b/src/test/lib/SoDA/TestChain.cpp @@ -0,0 +1,108 @@ +/* + * Copyright (C): 2013-2014 Department of Software Engineering, University of Szeged + * + * Author: David Imre Adam + * + * This file is part of SoDA. + * + * SoDA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * SoDA 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with SoDA. If not, see . + */ + +#include +#include "gtest/gtest.h" +#include "data/CChain.h" + +using namespace soda; + +TEST(Chain, BasicOperations) { + CChain s = CChain(); + vector sVector = vector(); + sVector.push_back("_0"); + sVector.push_back("_1"); + + ASSERT_EQ(s.count(), 0); + + s.add("_0"); + s.add("_1"); + s.add("_2"); + + ASSERT_TRUE(s.contains("_0")); + ASSERT_TRUE(s.contains("_1")); + ASSERT_TRUE(s.contains("_2")); + + ASSERT_TRUE(s.getId("_0") == 0); + ASSERT_TRUE(s.getId("_1") == 1); + ASSERT_TRUE(s.getId("_2") == 2); + ASSERT_EQ(s.count(), 3); + + s.remove("_1"); + + ASSERT_EQ(s.count(), 2); + ASSERT_FALSE(s.contains("_1")); + EXPECT_THROW(s.getId("_1"), std::out_of_range); + ASSERT_TRUE(s.getId("_2") == 2); + ASSERT_EQ(s.getValue(0), "_0"); + ASSERT_EQ(s.getValue(2), "_2"); + + s.clear(); + s.add("A"); + + ASSERT_EQ(s.count(), 1); + + s.add(sVector); + ASSERT_EQ(s.count(), 3); + + ASSERT_EQ(s.getValue(0), "A"); + ASSERT_EQ(s.getValue(1), "_0"); + ASSERT_EQ(s.getValue(2), "_1"); +} + +TEST(Chain, Iterators) +{ + CChain s = CChain(); + s.add("_0"); + s.add("_1"); + s.add("_2"); + + ASSERT_EQ(*(s.first()), "_0"); + ASSERT_EQ(*--s.end(), "_2"); +} + +TEST(Chain, BinarySaveLoad) +{ + CChain s = CChain(); + s.add("_0"); + s.add("_1"); + s.add("_2"); + s.save("chainFile"); + + CChain a = CChain(); + a.load("chainFile"); + + ASSERT_EQ(a.count(), 3); + ASSERT_EQ(*(a.first()), "_0"); + ASSERT_EQ(a.getValue(0), "_0"); + ASSERT_EQ(a.getValue(1), "_1"); + ASSERT_EQ(a.getValue(2), "_2"); +} + +TEST(Chain, JsonLoad) +{ + CChain s = CChain(); + s.loadJson("sample/cchain.json"); + + ASSERT_EQ(s.count(), 4); + ASSERT_EQ(*(s.first()), "Element1"); + ASSERT_EQ(*(s.end()-1), "Debug"); +} diff --git a/src/test/lib/SoDA/TestDAG.cpp b/src/test/lib/SoDA/TestDAG.cpp new file mode 100644 index 0000000..7765c36 --- /dev/null +++ b/src/test/lib/SoDA/TestDAG.cpp @@ -0,0 +1,397 @@ +/* + * Copyright (C): 2013-2014 Department of Software Engineering, University of Szeged + * + * Author: David Imre Adam + * + * This file is part of SoDA. + * + * SoDA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * SoDA 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with SoDA. If not, see . + */ + +#include +#include "gtest/gtest.h" +#include "data/CDAG.h" + +using namespace soda; + +TEST(DAG, BuildDAGByLinkingNodes) { + CDAG dag; + auto n0 = dag.addNode("A"); + auto n1 = dag.addNode("B"); + auto n2 = dag.addNode("C"); + auto n3 = dag.addNode("D"); + auto n4 = dag.addNode("E"); + auto n5 = dag.addNode("F"); + auto n6 = dag.addNode("G"); + auto n7 = dag.addNode("H"); + auto n8 = dag.addNode("I"); + auto n9 = dag.addNode("J"); + + ASSERT_TRUE(dag.edgeCount() == 0); + ASSERT_TRUE(dag.nodeCount() == 10); + + ASSERT_EQ(dag.getNodeValue(n0), "A"); + ASSERT_EQ(dag.getNodeValue(n1), "B"); + ASSERT_EQ(dag.getNodeValue(n2), "C"); + ASSERT_EQ(dag.getNodeValue(n3), "D"); + ASSERT_EQ(dag.getNodeValue(n4), "E"); + ASSERT_EQ(dag.getNodeValue(n5), "F"); + ASSERT_EQ(dag.getNodeValue(n6), "G"); + ASSERT_EQ(dag.getNodeValue(n7), "H"); + ASSERT_EQ(dag.getNodeValue(n8), "I"); + ASSERT_EQ(dag.getNodeValue(n9), "J"); + + dag.addEdge(n0, n1); + dag.addEdge(n0, n2); + dag.addEdge(n0, n3); + dag.addEdge(n1, n4); + dag.addEdge(n1, n5); + dag.addEdge(n2, n6); + dag.addEdge(n3, n7); + dag.addEdge(n7, n8); + dag.addEdge(n7, n9); + + ASSERT_TRUE(dag.edgeCount() == 9); +} + +TEST(DAG, BuildDAGByLinkingSubDAGs) +{ + CDAG dag; + auto n0 = dag.addNode("A"); + auto n1 = dag.addNode("B"); + auto n2 = dag.addNode("C"); + auto n3 = dag.addNode("D"); + auto n4 = dag.addNode("E"); + auto n5 = dag.addNode("F"); + auto n6 = dag.addNode("G"); + auto n7 = dag.addNode("H"); + auto n8 = dag.addNode("I"); + auto n9 = dag.addNode("J"); + + dag.addEdge(n7, n8); + dag.addEdge(n7, n9); + + dag.addEdge(n1, n4); + dag.addEdge(n1, n5); + + dag.addEdge(n2, n6); + + dag.addEdge(n3, n7); + + dag.addEdge(n0, n1); + dag.addEdge(n0, n2); + dag.addEdge(n0, n3); + + ASSERT_TRUE(dag.edgeCount() == 9); + ASSERT_TRUE(dag.nodeCount() == 10); +} + +TEST(DAG, BuildDAGByLeaves) +{ + CDAG dag; + auto n0 = dag.addNode("A"); //Root + auto n1 = dag.addChild(n0->m_id, "B"); + auto n2 = dag.addChild(n0->m_id, "C"); + auto n3 = dag.addChild(n0->m_id, "D"); + auto n4 = dag.addChild(n1->m_id, "E"); + auto n5 = dag.addChild(n1->m_id, "F"); + auto n6 = dag.addChild(n2->m_id, "G"); + auto n7 = dag.addChild(n3->m_id, "H"); + auto n8 = dag.addChild(n7->m_id, "I"); + auto n9 = dag.addChild(n7->m_id, "J"); + + ASSERT_TRUE(dag.nodeCount() == 10); + ASSERT_TRUE(dag.edgeCount() == 9); +} + +TEST(DAG, FormingCircleBySubDAGs) +{ + CDAG dag; + auto n0 = dag.addNode("A"); + auto n1 = dag.addNode("B"); + auto n2 = dag.addNode("C"); + auto n3 = dag.addNode("D"); + auto n4 = dag.addNode("E"); + + dag.addEdge(n0, n1); + dag.addEdge(n1, n2); + dag.addEdge(n2, n3); + dag.addEdge(n3, n4); + + EXPECT_THROW(dag.addEdge(n4, n0), logic_error); //additional enclosing edge + EXPECT_THROW(dag.addEdge(n2, n0), logic_error); //additional enclosing edge +} + +TEST(DAG, DFS) +{ + CDAG dag; + auto n0 = dag.addNode("A"); //Root + auto n1 = dag.addChild(n0->m_id, "B"); + auto n2 = dag.addChild(n0->m_id, "C"); + auto n3 = dag.addChild(n0->m_id, "D"); + auto n4 = dag.addChild(n1->m_id, "E"); + auto n5 = dag.addChild(n1->m_id, "F"); + auto n6 = dag.addChild(n2->m_id, "G"); + auto n7 = dag.addChild(n3->m_id, "H"); + auto n8 = dag.addChild(n7->m_id, "I"); + auto n9 = dag.addChild(n7->m_id, "J"); + + dag.addEdge(n1,n2); + dag.addEdge(n1,n6); + dag.addEdge(n5,n2); + dag.addEdge(n5,n6); + + vector* dfs0 = dag.getDFS(n0->m_id); + ASSERT_TRUE(dfs0->size() == 10); + + vector* dfs1 = dag.getDFS(n1->m_id); + ASSERT_TRUE(dfs1->size() == 5); + + vector* dfs2 = dag.getDFS(n6->m_id); + ASSERT_TRUE(dfs2->size() == 1); + + vector* dfs3 = dag.getDFS(n9->m_id); + ASSERT_TRUE(dfs3->size() == 1); +} + +TEST(DAG, BFS) +{ + CDAG dag; + auto n0 = dag.addNode("A"); //Root + auto n1 = dag.addChild(n0->m_id, "A"); + auto n2 = dag.addChild(n0->m_id, "A"); + auto n3 = dag.addChild(n0->m_id, "A"); + auto n4 = dag.addChild(n1->m_id, "A"); + auto n5 = dag.addChild(n1->m_id, "A"); + auto n6 = dag.addChild(n2->m_id, "A"); + auto n7 = dag.addChild(n3->m_id, "A"); + auto n8 = dag.addChild(n7->m_id, "A"); + auto n9 = dag.addChild(n7->m_id, "A"); + + vector* dfs0 = dag.getBFS(n0->m_id); + ASSERT_TRUE(dfs0->size() == 10); + + vector* dfs1 = dag.getBFS(n1->m_id); + ASSERT_TRUE(dfs1->size() == 3); + + vector* dfs2 = dag.getBFS(n6->m_id); + ASSERT_TRUE(dfs2->size() == 1); + + vector* dfs3 = dag.getBFS(n9->m_id); + ASSERT_TRUE(dfs3->size() == 1); +} + +TEST(DAG, BinarySaveLoad) +{ + CDAG dag; + + auto a = dag.addNode("a"); + auto b = dag.addNode("b"); + auto c = dag.addNode("c"); + auto d = dag.addNode("d"); + auto e = dag.addNode("e"); + auto f = dag.addNode("f"); + auto g = dag.addNode("g"); + dag.addEdge(a, b); + dag.addEdge(a, c); + dag.addEdge(a, d); + dag.addEdge(c, e); + dag.addEdge(c, f); + dag.addEdge(d, g); + + dag.save("treeFile"); + + CDAG loadedCDAG = CDAG(); + loadedCDAG.load("treeFile"); + + ASSERT_EQ(loadedCDAG.nodeCount(), 7); + ASSERT_EQ(loadedCDAG.edgeCount(), 6); +} + +TEST(DAG, JsonLoad) +{ + CDAG dag; + dag.loadJson("sample/cdag.json"); + + ASSERT_EQ(dag.nodeCount(), 10); // 0,1,2,3,4,5,6,7,8,9 + ASSERT_EQ(dag.edgeCount(), 12); // 0>1,0>2,0>3,1>2,1>4,1>5,2>6,3>7,5>6,6>8,7>8,7>9 + + auto aEdges = dag.getEdges(0); + ASSERT_EQ(aEdges.size(), 3); + ASSERT_TRUE(std::find(aEdges.begin(), aEdges.end(), 1) != aEdges.end()); + ASSERT_TRUE(std::find(aEdges.begin(), aEdges.end(), 2) != aEdges.end()); + ASSERT_TRUE(std::find(aEdges.begin(), aEdges.end(), 3) != aEdges.end()); + ASSERT_TRUE(std::find(aEdges.begin(), aEdges.end(), 10) == aEdges.end()); //control case + + auto bEdges = dag.getEdges(1); + ASSERT_EQ(bEdges.size(), 3); + ASSERT_TRUE(std::find(bEdges.begin(), bEdges.end(), 2) != bEdges.end()); + ASSERT_TRUE(std::find(bEdges.begin(), bEdges.end(), 4) != bEdges.end()); + ASSERT_TRUE(std::find(bEdges.begin(), bEdges.end(), 5) != bEdges.end()); + + auto cEdges = dag.getEdges(2); + ASSERT_EQ(cEdges.size(), 1); + ASSERT_TRUE(std::find(cEdges.begin(), cEdges.end(), 6) != cEdges.end()); + + auto dEdges = dag.getEdges(3); + ASSERT_EQ(dEdges.size(), 1); + ASSERT_TRUE(std::find(dEdges.begin(), dEdges.end(), 7) != dEdges.end()); + + auto eEdges = dag.getEdges(4); + ASSERT_EQ(eEdges.size(), 0); + + auto fEdges = dag.getEdges(5); + ASSERT_EQ(fEdges.size(), 1); + ASSERT_TRUE(std::find(fEdges.begin(), fEdges.end(), 6) != fEdges.end()); + + auto gEdges = dag.getEdges(6); + ASSERT_EQ(gEdges.size(), 1); + ASSERT_TRUE(std::find(gEdges.begin(), gEdges.end(), 8) != gEdges.end()); + + auto hEdges = dag.getEdges(7); + ASSERT_EQ(hEdges.size(), 2); + ASSERT_TRUE(std::find(hEdges.begin(), hEdges.end(), 8) != hEdges.end()); + ASSERT_TRUE(std::find(hEdges.begin(), hEdges.end(), 9) != hEdges.end()); + + auto iEdges = dag.getEdges(8); + ASSERT_EQ(iEdges.size(), 0); + + auto jEdges = dag.getEdges(9); + ASSERT_EQ(jEdges.size(), 0); +} + +TEST(DAG, convertToNodeIdChains) +{ + CDAG dag; + dag.loadJson("sample/cdagChains.json"); + + vector*>* chains = dag.convertToNodeIdChains(); + + //Chains: + //abe (014) + //acgi (0268) + //adhi (0378) + //adhj (0379) + //abcgi (01268) + //abfcgi (015368) + + ASSERT_EQ(chains->size(), 6); + + String chain0; + for(list::iterator c = chains->at(0)->begin(); c != chains->at(0)->end(); c++) + { + chain0.append(dag.getValue(*c)); + } + ASSERT_EQ(chain0, "abe"); + + String chain1; + for(list::iterator c = chains->at(1)->begin(); c != chains->at(1)->end(); c++) + { + chain1.append(dag.getValue(*c)); + } + ASSERT_EQ(chain1, "acgi"); + + String chain2; + for(list::iterator c = chains->at(2)->begin(); c != chains->at(2)->end(); c++) + { + chain2.append(dag.getValue(*c)); + } + ASSERT_EQ(chain2, "adhi"); + + String chain3; + for(list::iterator c = chains->at(3)->begin(); c != chains->at(3)->end(); c++) + { + chain3.append(dag.getValue(*c)); + } + ASSERT_EQ(chain3, "adhj"); + + String chain4; + for(list::iterator c = chains->at(4)->begin(); c != chains->at(4)->end(); c++) + { + chain4.append(dag.getValue(*c)); + } + ASSERT_EQ(chain4, "abcgi"); + + String chain5; + for(list::iterator c = chains->at(5)->begin(); c != chains->at(5)->end(); c++) + { + chain5.append(dag.getValue(*c)); + } + ASSERT_EQ(chain5, "abfcgi"); +} + +TEST(DAG, toGraph) +{ + CDAG dag; + auto n0 = dag.addNode("A"); //Root + auto n1 = dag.addChild(n0->m_id, "B"); + auto n2 = dag.addChild(n0->m_id, "C"); + auto n3 = dag.addChild(n0->m_id, "D"); + auto n4 = dag.addChild(n1->m_id, "A"); + auto n5 = dag.addChild(n1->m_id, "E"); + auto n6 = dag.addChild(n2->m_id, "F"); + auto n7 = dag.addChild(n3->m_id, "B"); + auto n8 = dag.addChild(n7->m_id, "C"); + auto n9 = dag.addChild(n7->m_id, "A"); + + //DAG edges: + // A0-B0,A0-C0,A0-D (01,02,03) + // B0-A0,B0-F (14,15) + // C0-G (26) + // D-B1 (37) + // B1-C1 (78) + // B1-A1 (79) + + //Graph edges: + // AB,AC,AD (01,02,03) + // BA,BC,BD,BE (10,12,13,14) + // CA,CB,CF (20,21,25) + // DA,DB (30,31) + // EB (41) + // FC (52) + + auto graph = dag.toGraph(); + + auto aEdges = graph->getEdges(0); + ASSERT_EQ(aEdges.size(), 3); + ASSERT_EQ(aEdges.at(0), 1); + ASSERT_EQ(aEdges.at(1), 2); + ASSERT_EQ(aEdges.at(2), 3); + + auto bEdges = graph->getEdges(1); + ASSERT_EQ(bEdges.size(), 4); + ASSERT_EQ(bEdges.at(0), 0); + ASSERT_EQ(bEdges.at(1), 4); + ASSERT_EQ(bEdges.at(2), 3); + ASSERT_EQ(bEdges.at(3), 2); + + auto cEdges = graph->getEdges(2); + ASSERT_EQ(cEdges.size(), 3); + ASSERT_EQ(cEdges.at(0), 0); + ASSERT_EQ(cEdges.at(1), 5); + ASSERT_EQ(cEdges.at(2), 1); + + auto dEdges = graph->getEdges(3); + ASSERT_EQ(dEdges.size(), 2); + ASSERT_EQ(dEdges.at(0), 0); + ASSERT_EQ(dEdges.at(1), 1); + + auto eEdges = graph->getEdges(4); + ASSERT_EQ(eEdges.size(), 1); + ASSERT_EQ(eEdges.at(0), 1); + + auto fEdges = graph->getEdges(5); + ASSERT_EQ(fEdges.size(), 1); + ASSERT_EQ(fEdges.at(0), 2); +} diff --git a/src/test/lib/SoDA/TestGraph.cpp b/src/test/lib/SoDA/TestGraph.cpp new file mode 100644 index 0000000..5b3ee67 --- /dev/null +++ b/src/test/lib/SoDA/TestGraph.cpp @@ -0,0 +1,184 @@ +/* + * Copyright (C): 2013-2014 Department of Software Engineering, University of Szeged + * + * Author: David Imre Adam + * + * This file is part of SoDA. + * + * SoDA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * SoDA 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with SoDA. If not, see . + */ + +#include +#include "gtest/gtest.h" +#include "data/CGraph.h" + +using namespace soda; + +TEST(Graph, BasicOperations) { + CGraph g = CGraph(); + IndexType a = g.addNode("a"); + IndexType b = g.addNode("b"); + IndexType c = g.addNode("c"); + + ASSERT_TRUE(g.edgeCount() == 0); + ASSERT_TRUE(g.nodeCount() == 3); + + g.addEdge(a, b); + g.addEdge(a, c); + + ASSERT_TRUE(g.edgeCount() == 4); +} + +TEST(Graph, DFS) +{ + CGraph graph = CGraph(); + + IndexType a = graph.addNode("a"); + IndexType b = graph.addNode("b"); + IndexType c = graph.addNode("c"); + IndexType d = graph.addNode("d"); + IndexType e = graph.addNode("e"); + IndexType f = graph.addNode("f"); + IndexType g = graph.addNode("g"); + graph.addEdge(a, b); + graph.addEdge(a, c); + graph.addEdge(a, d); + graph.addEdge(c, e); + graph.addEdge(c, f); + graph.addEdge(d, g); + + vector* dfs0 = graph.getDFS(0); + ASSERT_TRUE(dfs0->size() == 7); + + vector* dfs1 = graph.getDFS(1); + ASSERT_TRUE(dfs1->size() == 7); + + vector* dfs2 = graph.getDFS(2); + ASSERT_TRUE(dfs2->size() == 7); + + vector* dfs3 = graph.getDFS(3); + ASSERT_TRUE(dfs3->size() == 7); +} + +TEST(Graph, BFS) +{ + CGraph graph = CGraph(); + + IndexType a = graph.addNode("a"); + IndexType b = graph.addNode("b"); + IndexType c = graph.addNode("c"); + IndexType d = graph.addNode("d"); + IndexType e = graph.addNode("e"); + IndexType f = graph.addNode("f"); + IndexType g = graph.addNode("g"); + graph.addEdge(a, b); + graph.addEdge(a, c); + graph.addEdge(a, d); + graph.addEdge(c, e); + graph.addEdge(c, f); + graph.addEdge(d, g); + + vector* bfs0 = graph.getBFS(0); + ASSERT_TRUE(bfs0->size() == 7); + + vector* bfs1 = graph.getBFS(1); + ASSERT_TRUE(bfs1->size() == 7); + + vector* bfs2 = graph.getBFS(2); + ASSERT_TRUE(bfs2->size() == 7); + + vector* bfs3 = graph.getBFS(3); + ASSERT_TRUE(bfs3->size() == 7); +} + +TEST(Graph, BinarySaveLoad) +{ + CGraph graph = CGraph(); + + IndexType a = graph.addNode("a"); + IndexType b = graph.addNode("b"); + IndexType c = graph.addNode("c"); + IndexType d = graph.addNode("d"); + IndexType e = graph.addNode("e"); + IndexType f = graph.addNode("f"); + IndexType g = graph.addNode("g"); + graph.addEdge(a, b); + graph.addEdge(a, c); + graph.addEdge(a, d); + graph.addEdge(c, e); + graph.addEdge(c, f); + graph.addEdge(d, g); + + graph.save("graphFile"); + + CGraph loadedGraph = CGraph(); + loadedGraph.load("graphFile"); + + ASSERT_EQ(loadedGraph.nodeCount(), 7); + ASSERT_EQ(loadedGraph.edgeCount(), 12); +} + +TEST(Graph, JsonLoad) +{ + CGraph g = CGraph(); + g.loadJson("sample/cgraph.json"); + + //alias = index + //a = 0 + //b = 1 + //c = 2 + //d = 3 + //e = 4 + //f = 5 + //g = 6 + + ASSERT_EQ(g.nodeCount(), 7); // a,b,c,d,e,f,g + ASSERT_EQ(g.edgeCount(), 14); // ab,ac,ad,ce,cf,dg,ga (7*2) + + auto aEdges = g.getEdges(0); + ASSERT_EQ(aEdges.size(), 4); // 1(b), 2(c), 3(d), 4(g) + ASSERT_TRUE(std::find(aEdges.begin(), aEdges.end(), 1) != aEdges.end()); + ASSERT_TRUE(std::find(aEdges.begin(), aEdges.end(), 2) != aEdges.end()); + ASSERT_TRUE(std::find(aEdges.begin(), aEdges.end(), 3) != aEdges.end()); + ASSERT_TRUE(std::find(aEdges.begin(), aEdges.end(), 6) != aEdges.end()); + ASSERT_TRUE(std::find(aEdges.begin(), aEdges.end(), 10) == aEdges.end()); //control case + + auto bEdges = g.getEdges(1); + ASSERT_EQ(bEdges.size(), 1); //0(a) + ASSERT_TRUE(std::find(bEdges.begin(), bEdges.end(), 0) != bEdges.end()); + + auto cEdges = g.getEdges(2); + ASSERT_EQ(cEdges.size(), 3); //0(a), 4(e), 5(f) + ASSERT_TRUE(std::find(cEdges.begin(), cEdges.end(), 0) != cEdges.end()); + ASSERT_TRUE(std::find(cEdges.begin(), cEdges.end(), 4) != cEdges.end()); + ASSERT_TRUE(std::find(cEdges.begin(), cEdges.end(), 5) != cEdges.end()); + + auto dEdges = g.getEdges(3); + ASSERT_EQ(dEdges.size(), 2); //0(a), 6(g) + ASSERT_TRUE(std::find(dEdges.begin(), dEdges.end(), 0) != dEdges.end()); + ASSERT_TRUE(std::find(dEdges.begin(), dEdges.end(), 6) != dEdges.end()); + + auto eEdges = g.getEdges(4); + ASSERT_EQ(eEdges.size(), 1); //2(c) + ASSERT_TRUE(std::find(eEdges.begin(), eEdges.end(), 2) != eEdges.end()); + + auto fEdges = g.getEdges(5); + ASSERT_EQ(fEdges.size(), 1); //2(c) + ASSERT_TRUE(std::find(fEdges.begin(), fEdges.end(), 2) != fEdges.end()); + + auto gEdges = g.getEdges(6); + ASSERT_EQ(gEdges.size(), 2); //3(d), 0(a) + ASSERT_TRUE(std::find(gEdges.begin(), gEdges.end(), 3) != gEdges.end()); + ASSERT_TRUE(std::find(gEdges.begin(), gEdges.end(), 0) != gEdges.end()); +} diff --git a/src/test/lib/SoDA/TestTree.cpp b/src/test/lib/SoDA/TestTree.cpp new file mode 100644 index 0000000..4d2210b --- /dev/null +++ b/src/test/lib/SoDA/TestTree.cpp @@ -0,0 +1,385 @@ +/* + * Copyright (C): 2013-2014 Department of Software Engineering, University of Szeged + * + * Author: David Imre Adam + * + * This file is part of SoDA. + * + * SoDA is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * SoDA 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with SoDA. If not, see . + */ + +#include +#include "gtest/gtest.h" +#include "data/CTree.h" + +using namespace soda; + +TEST(Tree, BuildTreeByLinkingNodes) { + CTree tree = CTree(); + auto n0 = tree.addNode("A"); + auto n1 = tree.addNode("B"); + auto n2 = tree.addNode("C"); + auto n3 = tree.addNode("D"); + auto n4 = tree.addNode("E"); + auto n5 = tree.addNode("F"); + auto n6 = tree.addNode("G"); + auto n7 = tree.addNode("H"); + auto n8 = tree.addNode("I"); + auto n9 = tree.addNode("J"); + + ASSERT_TRUE(tree.edgeCount() == 0); + ASSERT_TRUE(tree.nodeCount() == 10); + + ASSERT_EQ(tree.getNodeValue(n0), "A"); + ASSERT_EQ(tree.getNodeValue(n1), "B"); + ASSERT_EQ(tree.getNodeValue(n2), "C"); + ASSERT_EQ(tree.getNodeValue(n3), "D"); + ASSERT_EQ(tree.getNodeValue(n4), "E"); + ASSERT_EQ(tree.getNodeValue(n5), "F"); + ASSERT_EQ(tree.getNodeValue(n6), "G"); + ASSERT_EQ(tree.getNodeValue(n7), "H"); + ASSERT_EQ(tree.getNodeValue(n8), "I"); + ASSERT_EQ(tree.getNodeValue(n9), "J"); + + tree.addEdge(n0, n1); + tree.addEdge(n0, n2); + tree.addEdge(n0, n3); + tree.addEdge(n1, n4); + tree.addEdge(n1, n5); + tree.addEdge(n2, n6); + tree.addEdge(n3, n7); + tree.addEdge(n7, n8); + tree.addEdge(n7, n9); + + ASSERT_TRUE(tree.edgeCount() == 9); +} + +TEST(Tree, BuildTreeByLinkingSubTrees) { + CTree tree = CTree(); + auto n0 = tree.addNode("A"); + auto n1 = tree.addNode("B"); + auto n2 = tree.addNode("C"); + auto n3 = tree.addNode("D"); + auto n4 = tree.addNode("E"); + auto n5 = tree.addNode("F"); + auto n6 = tree.addNode("G"); + auto n7 = tree.addNode("H"); + auto n8 = tree.addNode("I"); + auto n9 = tree.addNode("J"); + + tree.addEdge(n7, n8); + tree.addEdge(n7, n9); + + tree.addEdge(n1, n4); + tree.addEdge(n1, n5); + + tree.addEdge(n2, n6); + + tree.addEdge(n3, n7); + + tree.addEdge(n0, n1); + tree.addEdge(n0, n2); + tree.addEdge(n0, n3); + + ASSERT_TRUE(tree.edgeCount() == 9); + ASSERT_TRUE(tree.nodeCount() == 10); +} + +TEST(Tree, BuildTreeByLeaves) { + CTree tree = CTree(); + auto n0 = tree.addNode("A"); //Root + auto n1 = tree.addChild(n0->m_id, "B"); + auto n2 = tree.addChild(n0->m_id, "C"); + auto n3 = tree.addChild(n0->m_id, "D"); + auto n4 = tree.addChild(n1->m_id, "E"); + auto n5 = tree.addChild(n1->m_id, "F"); + auto n6 = tree.addChild(n2->m_id, "G"); + auto n7 = tree.addChild(n3->m_id, "H"); + auto n8 = tree.addChild(n7->m_id, "I"); + auto n9 = tree.addChild(n7->m_id, "J"); + + ASSERT_TRUE(tree.nodeCount() == 10); + ASSERT_TRUE(tree.edgeCount() == 9); +} + +TEST(Tree, FormingCircleBySubTrees) { + CTree tree = CTree(); + auto n0 = tree.addNode("A"); + auto n1 = tree.addNode("B"); + auto n2 = tree.addNode("C"); + auto n3 = tree.addNode("D"); + auto n4 = tree.addNode("E"); + auto n5 = tree.addNode("F"); + auto n6 = tree.addNode("G"); + auto n7 = tree.addNode("H"); + auto n8 = tree.addNode("I"); + auto n9 = tree.addNode("J"); + + tree.addEdge(n7, n8); + tree.addEdge(n7, n9); + + tree.addEdge(n1, n4); + tree.addEdge(n1, n5); + + tree.addEdge(n2, n6); + + tree.addEdge(n3, n7); + tree.addEdge(n0, n2); + tree.addEdge(n0, n3); + tree.addEdge(n0, n1); + + EXPECT_THROW(tree.addEdge(n7, n1), logic_error); //additional enclosing edge +} + +TEST(Tree, DFS) +{ + CTree tree = CTree(); + auto n0 = tree.addNode("A"); //Root + auto n1 = tree.addChild(n0->m_id, "B"); + auto n2 = tree.addChild(n0->m_id, "C"); + auto n3 = tree.addChild(n0->m_id, "D"); + auto n4 = tree.addChild(n1->m_id, "E"); + auto n5 = tree.addChild(n1->m_id, "F"); + auto n6 = tree.addChild(n2->m_id, "G"); + auto n7 = tree.addChild(n3->m_id, "H"); + auto n8 = tree.addChild(n7->m_id, "I"); + auto n9 = tree.addChild(n7->m_id, "J"); + + vector* dfs0 = tree.getDFS(n0->m_id); + ASSERT_TRUE(dfs0->size() == 10); + + vector* dfs1 = tree.getDFS(n1->m_id); + ASSERT_TRUE(dfs1->size() == 3); + + vector* dfs2 = tree.getDFS(n3->m_id); + ASSERT_TRUE(dfs2->size() == 4); + + vector* dfs3 = tree.getDFS(n9->m_id); + ASSERT_TRUE(dfs3->size() == 1); +} + +TEST(Tree, BFS) +{ + CTree tree = CTree(); + auto n0 = tree.addNode("A"); //Root + auto n1 = tree.addChild(n0->m_id, "A"); + auto n2 = tree.addChild(n0->m_id, "A"); + auto n3 = tree.addChild(n0->m_id, "A"); + auto n4 = tree.addChild(n1->m_id, "A"); + auto n5 = tree.addChild(n1->m_id, "A"); + auto n6 = tree.addChild(n2->m_id, "A"); + auto n7 = tree.addChild(n3->m_id, "A"); + auto n8 = tree.addChild(n7->m_id, "A"); + auto n9 = tree.addChild(n7->m_id, "A"); + + vector* dfs0 = tree.getBFS(n0->m_id); + ASSERT_TRUE(dfs0->size() == 10); + + vector* dfs1 = tree.getBFS(n1->m_id); + ASSERT_TRUE(dfs1->size() == 3); + + vector* dfs2 = tree.getBFS(n2->m_id); + ASSERT_TRUE(dfs2->size() == 2); + + vector* dfs3 = tree.getBFS(n9->m_id); + ASSERT_TRUE(dfs3->size() == 1); +} + +TEST(Tree, BinarySaveLoad) +{ + CTree tree = CTree(); + + auto a = tree.addNode("a"); + auto b = tree.addNode("b"); + auto c = tree.addNode("c"); + auto d = tree.addNode("d"); + auto e = tree.addNode("e"); + auto f = tree.addNode("f"); + auto g = tree.addNode("g"); + tree.addEdge(a, b); + tree.addEdge(a, c); + tree.addEdge(a, d); + tree.addEdge(c, e); + tree.addEdge(c, f); + tree.addEdge(d, g); + + tree.save("treeFile"); + + CTree loadedCTree = CTree(); + loadedCTree.load("treeFile"); + + ASSERT_EQ(loadedCTree.nodeCount(), 7); + ASSERT_EQ(loadedCTree.edgeCount(), 6); +} + +TEST(Tree, JsonLoad) +{ + CTree tree = CTree(); + tree.loadJson("sample/ctree.json"); + + ASSERT_EQ(tree.nodeCount(), 10); // 0,1,2,3,4,5,6,7,8,9 + ASSERT_EQ(tree.edgeCount(), 9); // 0>1,0>2,0>3,1>4,1>5,2>6,3>7,7>8,7>9 + + auto aEdges = tree.getEdges(0); + ASSERT_EQ(aEdges.size(), 3); + ASSERT_TRUE(std::find(aEdges.begin(), aEdges.end(), 1) != aEdges.end()); + ASSERT_TRUE(std::find(aEdges.begin(), aEdges.end(), 2) != aEdges.end()); + ASSERT_TRUE(std::find(aEdges.begin(), aEdges.end(), 3) != aEdges.end()); + ASSERT_TRUE(std::find(aEdges.begin(), aEdges.end(), 10) == aEdges.end()); //control case + + auto bEdges = tree.getEdges(1); + ASSERT_EQ(bEdges.size(), 2); + ASSERT_TRUE(std::find(bEdges.begin(), bEdges.end(), 4) != bEdges.end()); + ASSERT_TRUE(std::find(bEdges.begin(), bEdges.end(), 5) != bEdges.end()); + + auto cEdges = tree.getEdges(2); + ASSERT_EQ(cEdges.size(), 1); + ASSERT_TRUE(std::find(cEdges.begin(), cEdges.end(), 6) != cEdges.end()); + + auto dEdges = tree.getEdges(3); + ASSERT_EQ(dEdges.size(), 1); + ASSERT_TRUE(std::find(dEdges.begin(), dEdges.end(), 7) != dEdges.end()); + + auto eEdges = tree.getEdges(4); + ASSERT_EQ(eEdges.size(), 0); + + auto fEdges = tree.getEdges(5); + ASSERT_EQ(fEdges.size(), 0); + + auto gEdges = tree.getEdges(6); + ASSERT_EQ(gEdges.size(), 0); + + auto hEdges = tree.getEdges(7); + ASSERT_EQ(hEdges.size(), 2); + ASSERT_TRUE(std::find(hEdges.begin(), hEdges.end(), 8) != hEdges.end()); + ASSERT_TRUE(std::find(hEdges.begin(), hEdges.end(), 9) != hEdges.end()); + + auto iEdges = tree.getEdges(8); + ASSERT_EQ(iEdges.size(), 0); + + auto jEdges = tree.getEdges(9); + ASSERT_EQ(jEdges.size(), 0); + +} + +TEST(Tree, convertToNodeIdChains) +{ + CTree tree = CTree(); + auto n0 = tree.addNode("A"); //Root + auto n1 = tree.addChild(n0->m_id, "B"); + auto n2 = tree.addChild(n0->m_id, "C"); + auto n3 = tree.addChild(n0->m_id, "D"); + + auto n4 = tree.addChild(n1->m_id, "C"); + auto n5 = tree.addChild(n1->m_id, "E"); + auto n6 = tree.addChild(n1->m_id, "F"); + + auto n7 = tree.addChild(n4->m_id, "F"); + auto n8 = tree.addChild(n7->m_id, "I"); + + auto n9 = tree.addChild(n6->m_id, "C"); + auto n10 = tree.addChild(n9->m_id, "G"); + auto n11 = tree.addChild(n10->m_id, "I"); + + auto n12 = tree.addChild(n2->m_id, "G"); + auto n13 = tree.addChild(n12->m_id, "I"); + + auto n14 = tree.addChild(n3->m_id, "H"); + auto n15 = tree.addChild(n14->m_id, "I"); + auto n16 = tree.addChild(n14->m_id, "J"); + + + vector*>* nodeIdChains = tree.convertToNodeIdChains(); + + ASSERT_EQ(nodeIdChains->size(), 6); + + String chain0; + for(list::iterator c = nodeIdChains->at(0)->begin(); c != nodeIdChains->at(0)->end(); c++) + { + chain0.append(tree.getNodeValue(*c)); + } + ASSERT_EQ(chain0, "ABE"); + + String chain1; + for(list::iterator c = nodeIdChains->at(1)->begin(); c != nodeIdChains->at(1)->end(); c++) + { + chain1.append(tree.getNodeValue(*c)); + } + ASSERT_EQ(chain1, "ACGI"); + + String chain2; + for(list::iterator c = nodeIdChains->at(2)->begin(); c != nodeIdChains->at(2)->end(); c++) + { + chain2.append(tree.getNodeValue(*c)); + } + ASSERT_EQ(chain2, "ADHI"); + + String chain3; + for(list::iterator c = nodeIdChains->at(3)->begin(); c != nodeIdChains->at(3)->end(); c++) + { + chain3.append(tree.getNodeValue(*c)); + } + ASSERT_EQ(chain3, "ADHJ"); + + String chain4; + for(list::iterator c = nodeIdChains->at(4)->begin(); c != nodeIdChains->at(4)->end(); c++) + { + chain4.append(tree.getNodeValue(*c)); + } + ASSERT_EQ(chain4, "ABCFI"); + + String chain5; + for(list::iterator c = nodeIdChains->at(5)->begin(); c != nodeIdChains->at(5)->end(); c++) + { + chain5.append(tree.getNodeValue(*c)); + } + ASSERT_EQ(chain5, "ABFCGI"); +} + +TEST(Tree, toDAG) +{ + CTree tree = CTree(); + auto n0 = tree.addNode("A"); //Root + auto n1 = tree.addChild(n0->m_id, "B"); + auto n2 = tree.addChild(n0->m_id, "C"); + auto n3 = tree.addChild(n0->m_id, "D"); + + auto n4 = tree.addChild(n1->m_id, "C"); + auto n5 = tree.addChild(n1->m_id, "E"); + auto n6 = tree.addChild(n1->m_id, "F"); + + auto n7 = tree.addChild(n4->m_id, "G"); + auto n8 = tree.addChild(n7->m_id, "I"); + + auto n9 = tree.addChild(n6->m_id, "C"); + auto n10 = tree.addChild(n9->m_id, "G"); + auto n11 = tree.addChild(n10->m_id, "I"); + + auto n12 = tree.addChild(n2->m_id, "G"); + auto n13 = tree.addChild(n12->m_id, "I"); + + auto n14 = tree.addChild(n3->m_id, "H"); + auto n15 = tree.addChild(n14->m_id, "I"); + auto n16 = tree.addChild(n14->m_id, "J"); + + CDAG* dag = tree.toDAG(); + + ASSERT_EQ(dag->nodeCount(), 17); + ASSERT_EQ(dag->edgeCount(), 16); + + auto contractedDAG = dag->getContractedDAG(); + + ASSERT_EQ(contractedDAG->nodeCount(), 10); + ASSERT_EQ(contractedDAG->edgeCount(), 12); +} diff --git a/src/test/lib/sample/cchain.json b/src/test/lib/sample/cchain.json new file mode 100644 index 0000000..b8394ba --- /dev/null +++ b/src/test/lib/sample/cchain.json @@ -0,0 +1,9 @@ +{ + "chain": [ + "Element1", + "Element2", + "Element3", + "Debug" + ] +} + diff --git a/src/test/lib/sample/cdag.json b/src/test/lib/sample/cdag.json new file mode 100644 index 0000000..13f001f --- /dev/null +++ b/src/test/lib/sample/cdag.json @@ -0,0 +1,26 @@ +{ + "nodes":[ + {"id":"0", "value":"a"}, + {"id":"1", "value":"b"}, + {"id":"2", "value":"c"}, + {"id":"3", "value":"d"}, + {"id":"4", "value":"e"}, + {"id":"5", "value":"f"}, + {"id":"6", "value":"g"}, + {"id":"7", "value":"h"}, + {"id":"8", "value":"i"}, + {"id":"9", "value":"j"} + ], + "edges": [ + {"nodeId":"0", "values":["1","2","3"]}, + {"nodeId":"1", "values":["2","4","5"]}, + {"nodeId":"2", "values":["6"]}, + {"nodeId":"3", "values":["7"]}, + {"nodeId":"4", "values":[]}, + {"nodeId":"5", "values":["6"]}, + {"nodeId":"6", "values":["8"]}, + {"nodeId":"7", "values":["8","9"]}, + {"nodeId":"8", "values":[]}, + {"nodeId":"9", "values":[]} + ] +} diff --git a/src/test/lib/sample/cdagChains.json b/src/test/lib/sample/cdagChains.json new file mode 100644 index 0000000..31b954d --- /dev/null +++ b/src/test/lib/sample/cdagChains.json @@ -0,0 +1,26 @@ +{ + "nodes":[ + {"id":"0", "value":"a"}, + {"id":"1", "value":"b"}, + {"id":"2", "value":"c"}, + {"id":"3", "value":"d"}, + {"id":"4", "value":"e"}, + {"id":"5", "value":"f"}, + {"id":"6", "value":"g"}, + {"id":"7", "value":"h"}, + {"id":"8", "value":"i"}, + {"id":"9", "value":"j"} + ], + "edges": [ + {"nodeId":"0", "values":["1","2","3"]}, + {"nodeId":"1", "values":["2","4","5"]}, + {"nodeId":"2", "values":["6"]}, + {"nodeId":"3", "values":["7"]}, + {"nodeId":"4", "values":[]}, + {"nodeId":"5", "values":["2"]}, + {"nodeId":"6", "values":["8"]}, + {"nodeId":"7", "values":["8","9"]}, + {"nodeId":"8", "values":[]}, + {"nodeId":"9", "values":[]} + ] +} diff --git a/src/test/lib/sample/cgraph.json b/src/test/lib/sample/cgraph.json new file mode 100644 index 0000000..d816a15 --- /dev/null +++ b/src/test/lib/sample/cgraph.json @@ -0,0 +1,9 @@ +{ + "graph": [ + { "node" : "a", "edges" : ["b","c","d"]}, + { "node" : "c", "edges" : ["e", "f"]}, + { "node" : "d", "edges" : ["g"]}, + { "node" : "g", "edges" : ["a"]}, + { "node" : "a", "edges" : ["b","c","d"]} + ] +} diff --git a/src/test/lib/sample/ctree.json b/src/test/lib/sample/ctree.json new file mode 100644 index 0000000..2035fbd --- /dev/null +++ b/src/test/lib/sample/ctree.json @@ -0,0 +1,26 @@ +{ + "nodes":[ + {"id":"0", "value":"a"}, + {"id":"1", "value":"b"}, + {"id":"2", "value":"c"}, + {"id":"3", "value":"d"}, + {"id":"4", "value":"e"}, + {"id":"5", "value":"f"}, + {"id":"6", "value":"g"}, + {"id":"7", "value":"h"}, + {"id":"8", "value":"i"}, + {"id":"9", "value":"j"} + ], + "edges": [ + {"nodeId":"0", "values":["1","2","3"]}, + {"nodeId":"1", "values":["4","5"]}, + {"nodeId":"2", "values":["6"]}, + {"nodeId":"3", "values":["7"]}, + {"nodeId":"4", "values":[]}, + {"nodeId":"5", "values":[]}, + {"nodeId":"6", "values":[]}, + {"nodeId":"7", "values":["8","9"]}, + {"nodeId":"8", "values":[]}, + {"nodeId":"9", "values":[]} + ] +} diff --git a/src/treeFile b/src/treeFile new file mode 100644 index 0000000..43c6554 Binary files /dev/null and b/src/treeFile differ