Commit a684216a authored by Pierre Aubert's avatar Pierre Aubert
Browse files

Add abstract index in Graph and Node

parent c88f6827
......@@ -11,7 +11,7 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src)
phoenix_create_find(PhoenixGraph phoenix_graph Graph.h "")
phoenix_create_find_header(PhoenixGraph Graph.h "")
add_subdirectory(src)
......
project(Phoenix)
add_executable(test_graph_to_dot main.cpp)
target_link_libraries(test_graph_to_dot phoenix_graph)
add_test(NAME TestGraphToDot
COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test_graph_to_dot)
......
......@@ -8,7 +8,7 @@
///Test the graph conversion to dot
void testGraphToDot(){
Graph<bool> graph;
Graph<bool, long> graph;
long nodeA = graph.createNode(true, "a");
long nodeB = graph.createNode(true, "b");
......
project(Phoenix)
add_executable(test_graph_to_dot_loop main.cpp)
target_link_libraries(test_graph_to_dot_loop phoenix_graph)
add_test(NAME TestGraphToDotLoop
COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test_graph_to_dot_loop)
......
......@@ -8,7 +8,7 @@
///Test the graph conversion to dot
void testGraphToDot(){
Graph<bool> graph;
Graph<bool, long> graph;
long nodeA = graph.createNode(true, "a");
long nodeB = graph.createNode(true, "b");
......
project(Phoenix)
add_executable(test_graph_to_dot_remove main.cpp)
target_link_libraries(test_graph_to_dot_remove phoenix_graph)
add_test(NAME TestGraphToDotRemove
COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test_graph_to_dot_remove)
......
......@@ -8,7 +8,7 @@
///Test the graph conversion to dot
void testGraphToDot(){
Graph<bool> graph;
Graph<bool, long> graph;
long nodeA = graph.createNode(true, "a");
long nodeB = graph.createNode(true, "b");
......
project(Phoenix)
add_executable(test_graph_to_dot_total_loop main.cpp)
target_link_libraries(test_graph_to_dot_total_loop phoenix_graph)
add_test(NAME TestGraphToDotTotalLoop
COMMAND ${CMAKE_CURRENT_BINARY_DIR}/test_graph_to_dot_total_loop)
......
......@@ -8,7 +8,7 @@
///Test the graph conversion to dot
void testGraphToDot(){
Graph<bool> graph;
Graph<bool, long> graph;
long nodeA = graph.createNode(true, "a");
long nodeB = graph.createNode(true, "b");
......
project(Phoenix)
cmake_minimum_required(VERSION 3.0)
file(GLOB phoenix_graph_SRC "${CMAKE_CURRENT_SOURCE_DIR}/*.cpp")
add_library(phoenix_graph SHARED ${phoenix_graph_SRC})
install(TARGETS phoenix_graph LIBRARY DESTINATION ${LIBRARY_DIRECTORY} ARCHIVE DESTINATION ${LIBRARY_DIRECTORY})
file(GLOB headers "${CMAKE_CURRENT_SOURCE_DIR}/*.h")
install(FILES ${headers} DESTINATION include/PhoenixGraph)
......@@ -12,21 +12,27 @@
#include "Node.h"
///@brief Abstract Graph of Node
template<typename T>
/** T : type of the data to be connected in the graph
* UIdx : type of the index to be used to connect the Node together
*/
template<typename T, typename UIdx>
class Graph{
public:
Graph();
Graph(const Graph<T> & other);
Graph(const Graph<T, UIdx> & other);
virtual ~Graph();
Graph & operator = (const Graph<T> & other);
Graph & operator = (const Graph<T, UIdx> & other);
bool savePng(const std::string & fileNamePng) const;
bool saveDot(const std::string & fileName) const;
bool saveDot(std::ofstream & fs) const;
std::string toDot() const;
long createNode(const T & data, const std::string & name = "");
Node<T> * createNodePtr(const T & data, const std::string & name = "");
UIdx createNode(const T & data, const std::string & name = "");
Node<T, UIdx> * createNodePtr(const T & data, const std::string & name = "");
bool createNode(const T & data, const UIdx & index, const std::string & name = "");
Node<T, UIdx> * createNodePtr(const T & data, const UIdx & index, const std::string & name = "");
void clearIsUpdated();
void clearMapNode();
......@@ -34,31 +40,31 @@ class Graph{
void clearLastNode();
void clearAll();
void removeNode(long index);
void removeNode(UIdx index);
void updateFirstLastNode();
void connectNode(long parent, long child);
void connectNode(long parent, const ListIndex & listChildren);
void connectNode(UIdx parent, UIdx child);
void connectNode(UIdx parent, const std::list<UIdx> & listChildren);
const Node<T> * getNode(long index) const;
Node<T> * getNode(long index);
const Node<T, UIdx> * getNode(UIdx index) const;
Node<T, UIdx> * getNode(UIdx index);
bool isNodeExist(long index) const;
bool isNodeExist(UIdx index) const;
protected:
void copyGraph(const Graph<T> & other);
void copyGraph(const Graph<T, UIdx> & other);
private:
void initialisationGraph();
///Map of the Node
std::map<long, Node<T> > p_mapNode;
std::map<UIdx, Node<T, UIdx> > p_mapNode;
///List of the first Node (without parent)
ListIndex p_listFirstNode;
std::list<UIdx> p_listFirstNode;
///List of the last Node (without child)
ListIndex p_listLastNode;
std::list<UIdx> p_listLastNode;
};
#include "Graph_impl.h"
......
......@@ -13,22 +13,22 @@
#include "Graph.h"
///Default constructeur of Graph
template<typename T>
Graph<T>::Graph(){
template<typename T, typename UIdx>
Graph<T, UIdx>::Graph(){
initialisationGraph();
}
///Copy constructor of Graph
/** @param other : class to copy
*/
template<typename T>
Graph<T>::Graph(const Graph<T> & other){
template<typename T, typename UIdx>
Graph<T, UIdx>::Graph(const Graph<T, UIdx> & other){
copyGraph(other);
}
///Destructeur of Graph
template<typename T>
Graph<T>::~Graph(){
template<typename T, typename UIdx>
Graph<T, UIdx>::~Graph(){
}
......@@ -36,8 +36,8 @@ Graph<T>::~Graph(){
/** @param other : class to copy
* @return copied class
*/
template<typename T>
typename Graph<T>::Graph & Graph<T>::operator = (const Graph<T> & other){
template<typename T, typename UIdx>
typename Graph<T, UIdx>::Graph & Graph<T, UIdx>::operator = (const Graph<T, UIdx> & other){
copyGraph(other);
return *this;
}
......@@ -46,17 +46,17 @@ typename Graph<T>::Graph & Graph<T>::operator = (const Graph<T> & other){
/** @param fileNamePng : name of the png file
* @return true on success, false otherwise
*/
template<typename T>
bool Graph<T>::savePng(const std::string & fileNamePng) const{
template<typename T, typename UIdx>
bool Graph<T, UIdx>::savePng(const std::string & fileNamePng) const{
if(fileNamePng == "") return false;
std::string fileTxt("output.dot");
if(!saveDot(fileTxt)){
std::cerr << "Graph<T>::savePng : can't create file '" << fileTxt << "'" << std::endl;
std::cerr << "Graph<T, UIdx>::savePng : can't create file '" << fileTxt << "'" << std::endl;
return false;
}
std::string commande("dot -Tpng -o " + fileNamePng + " " + fileTxt);
if(system(commande.c_str()) != 0){
std::cerr << "Graph<T>::savePng : can't create png file '" << fileNamePng << "'" << std::endl;
std::cerr << "Graph<T, UIdx>::savePng : can't create png file '" << fileNamePng << "'" << std::endl;
return false;
}
return true;
......@@ -65,13 +65,13 @@ bool Graph<T>::savePng(const std::string & fileNamePng) const{
///Save the Graph in a dot file
/** @param fileName : name of the file to be created
*/
template<typename T>
bool Graph<T>::saveDot(const std::string & fileName) const{
template<typename T, typename UIdx>
bool Graph<T, UIdx>::saveDot(const std::string & fileName) const{
if(fileName == ""){return false;}
std::ofstream fs;
fs.open(fileName.c_str());
if(!fs.is_open()){
std::cerr << "Graph<T>::saveDot : can't open file '" << fileName << "'" << std::endl;
std::cerr << "Graph<T, UIdx>::saveDot : can't open file '" << fileName << "'" << std::endl;
return false;
}
bool b(saveDot(fs));
......@@ -82,8 +82,8 @@ bool Graph<T>::saveDot(const std::string & fileName) const{
///Save the Graph in a dot file
/** @param[out] fs : file stream to be modified
*/
template<typename T>
bool Graph<T>::saveDot(std::ofstream & fs) const{
template<typename T, typename UIdx>
bool Graph<T, UIdx>::saveDot(std::ofstream & fs) const{
fs << toDot();
return true;
}
......@@ -91,20 +91,20 @@ bool Graph<T>::saveDot(std::ofstream & fs) const{
///Convert the graph to dot language
/** @return dot
*/
template<typename T>
std::string Graph<T>::toDot() const{
template<typename T, typename UIdx>
std::string Graph<T, UIdx>::toDot() const{
std::string body("");
body += "digraph G{\n";
//save the node definition
for(typename std::map<long, Node<T> >::const_iterator it(p_mapNode.begin()); it != p_mapNode.end(); ++it){
for(typename std::map<UIdx, Node<T, UIdx> >::const_iterator it(p_mapNode.begin()); it != p_mapNode.end(); ++it){
body += it->second.getDotDefinition();
}
//save the connections between nodes
for(typename std::map<long, Node<T> >::const_iterator itNode(p_mapNode.begin()); itNode != p_mapNode.end(); ++itNode){
for(typename std::map<UIdx, Node<T, UIdx> >::const_iterator itNode(p_mapNode.begin()); itNode != p_mapNode.end(); ++itNode){
const std::string & parentNodeName(itNode->second.getDotName());
const ListIndex & listChild = itNode->second.getListChild();
for(ListIndex::const_iterator it(listChild.begin()); it != listChild.end(); ++it){
const Node<T> * childNode = getNode(*it);
const std::list<UIdx> & listChild = itNode->second.getListChild();
for(typename std::list<UIdx>::const_iterator it(listChild.begin()); it != listChild.end(); ++it){
const Node<T, UIdx> * childNode = getNode(*it);
if(childNode == NULL){continue;}
const std::string & childNodeName(childNode->getDotName());
body += "\t" + parentNodeName + " -> " + childNodeName + "[color=\"red\"];\n";
......@@ -119,13 +119,13 @@ std::string Graph<T>::toDot() const{
* @param name : name of the Node
* @return index of the Node
*/
template<typename T>
long Graph<T>::createNode(const T & data, const std::string & name){
Node<T> node(data, name);
long nodeIndex(p_mapNode.size());
template<typename T, typename UIdx>
UIdx Graph<T, UIdx>::createNode(const T & data, const std::string & name){
UIdx nodeIndex(p_mapNode.size());
while(getNode(nodeIndex) != NULL){
++nodeIndex;
}
Node<T, UIdx> node(data, name);
node.setIndex(nodeIndex);
p_mapNode[nodeIndex] = node;
return nodeIndex;
......@@ -136,35 +136,67 @@ long Graph<T>::createNode(const T & data, const std::string & name){
* @param name : name of the Node
* @return pointer of the Node
*/
template<typename T>
Node<T> * Graph<T>::createNodePtr(const T & data, const std::string & name){
long node = createNode(data, name);
template<typename T, typename UIdx>
Node<T, UIdx> * Graph<T, UIdx>::createNodePtr(const T & data, const std::string & name){
UIdx node = createNode(data, name);
return getNode(node);
}
///Create a node and get its index
/** @param data : data of the Node
* @param index : index of the Node
* @param name : name of the Node
* @return true if the node can be created, false if the index is already taken by an other Node
*/
template<typename T, typename UIdx>
bool Graph<T, UIdx>::createNode(const T & data, const UIdx & index, const std::string & name){
if(getNode(index) != NULL){ //Check if the Node already exists
return false;
}
Node<T, UIdx> node(data, name);
node.setIndex(index);
p_mapNode[index] = node;
return true;
}
///Create a node and get its pointer
/** @param data : data of the Node
* @param index : index of the Node
* @param name : name of the Node
* @return pointer of the Node
*/
template<typename T, typename UIdx>
Node<T, UIdx> * Graph<T, UIdx>::createNodePtr(const T & data, const UIdx & index, const std::string & name){
if(createNode(data, index, name)){
return getNode(index);
}else{
return NULL;
}
}
///Clear the isUpdated attriburte of the Node
template<typename T>
void Graph<T>::clearIsUpdated(){
for(typename std::map<long, Node<T> >::iterator it(p_mapNode.begin()); it != p_mapNode.end(); ++it){
template<typename T, typename UIdx>
void Graph<T, UIdx>::clearIsUpdated(){
for(typename std::map<UIdx, Node<T, UIdx> >::iterator it(p_mapNode.begin()); it != p_mapNode.end(); ++it){
it->second.setIsUpdated(false);
}
}
///Clear the map of Node
template<typename T>
void Graph<T>::clearMapNode(){p_mapNode.clear();}
template<typename T, typename UIdx>
void Graph<T, UIdx>::clearMapNode(){p_mapNode.clear();}
///Clear the list of first Node
template<typename T>
void Graph<T>::clearFirstNode(){p_listFirstNode.clear();}
template<typename T, typename UIdx>
void Graph<T, UIdx>::clearFirstNode(){p_listFirstNode.clear();}
///Clear the list of last Node
template<typename T>
void Graph<T>::clearLastNode(){p_listLastNode.clear();}
template<typename T, typename UIdx>
void Graph<T, UIdx>::clearLastNode(){p_listLastNode.clear();}
//Clear all Node
template<typename T>
void Graph<T>::clearAll(){
template<typename T, typename UIdx>
void Graph<T, UIdx>::clearAll(){
clearFirstNode();
clearLastNode();
clearMapNode();
......@@ -173,16 +205,16 @@ void Graph<T>::clearAll(){
///Remove a Node from the Graph
/** @param index : index of the Node to be removed
*/
template<typename T>
void Graph<T>::removeNode(long index){
Node<T> * indexNode = getNode(index);
template<typename T, typename UIdx>
void Graph<T, UIdx>::removeNode(UIdx index){
Node<T, UIdx> * indexNode = getNode(index);
if(indexNode == NULL){return;} //If the Node does not exist, we stop
//Get the parents of the current Node
ListIndex & listParent = indexNode->getListParent();
std::list<UIdx> & listParent = indexNode->getListParent();
if(listParent.size() != 0lu){
//Tell them they do not have child anymore
for(ListIndex::iterator it(listParent.begin()); it != listParent.end(); ++it){
Node<T> * parentNode = getNode(*it);
for(typename std::list<UIdx>::iterator it(listParent.begin()); it != listParent.end(); ++it){
Node<T, UIdx> * parentNode = getNode(*it);
if(parentNode == NULL){continue;}
parentNode->removeChild(index);
}
......@@ -191,11 +223,11 @@ void Graph<T>::removeNode(long index){
listindex_remove(p_listFirstNode, index);
}
//Get the children of the current Node
ListIndex & listChild = indexNode->getListChild();
std::list<UIdx> & listChild = indexNode->getListChild();
if(listChild.size() != 0lu){
//Tell them they do not have parent anymore
for(ListIndex::iterator it(listChild.begin()); it != listChild.end(); ++it){
Node<T> * childNode = getNode(*it);
for(typename std::list<UIdx>::iterator it(listChild.begin()); it != listChild.end(); ++it){
Node<T, UIdx> * childNode = getNode(*it);
if(childNode == NULL){continue;}
childNode->removeParent(index);
}
......@@ -208,11 +240,11 @@ void Graph<T>::removeNode(long index){
}
///Update the first and last Node of the Graph
template<typename T>
void Graph<T>::updateFirstLastNode(){
template<typename T, typename UIdx>
void Graph<T, UIdx>::updateFirstLastNode(){
clearFirstNode();
clearLastNode();
for(typename std::map<long, Node<T> >::iterator itNode(p_mapNode.begin()); itNode != p_mapNode.end(); ++itNode){
for(typename std::map<UIdx, Node<T, UIdx> >::iterator itNode(p_mapNode.begin()); itNode != p_mapNode.end(); ++itNode){
if(itNode->second.isStart()){ //If the Node does not have any parent, it is a first Node
p_listFirstNode.push_back(itNode->first);
}
......@@ -226,11 +258,11 @@ void Graph<T>::updateFirstLastNode(){
/** @param parent : index of the parent Node
* @param child : index of the child Node
*/
template<typename T>
void Graph<T>::connectNode(long parent, long child){
Node<T> * parentNode = getNode(parent);
template<typename T, typename UIdx>
void Graph<T, UIdx>::connectNode(UIdx parent, UIdx child){
Node<T, UIdx> * parentNode = getNode(parent);
if(parentNode == NULL){return;}
Node<T> * childNode = getNode(child);
Node<T, UIdx> * childNode = getNode(child);
if(childNode == NULL){return;}
parentNode->addChild(child);
childNode->addParent(parent);
......@@ -240,13 +272,13 @@ void Graph<T>::connectNode(long parent, long child){
/** @param parent : index of the parent Node
* @param listChildren : list of the children index
*/
template<typename T>
void Graph<T>::connectNode(long parent, const ListIndex & listChildren){
Node<T> * parentNode = getNode(parent);
template<typename T, typename UIdx>
void Graph<T, UIdx>::connectNode(UIdx parent, const std::list<UIdx> & listChildren){
Node<T, UIdx> * parentNode = getNode(parent);
if(parentNode == NULL){return;}
for(ListIndex::const_iterator it(listChildren.begin()); it != listChildren.end(); ++it){
long child = *it;
Node<T> * childNode = getNode(child);
for(typename std::list<UIdx>::const_iterator it(listChildren.begin()); it != listChildren.end(); ++it){
UIdx child = *it;
Node<T, UIdx> * childNode = getNode(child);
if(childNode == NULL){continue;}
parentNode->addChild(child);
childNode->addParent(parent);
......@@ -257,9 +289,9 @@ void Graph<T>::connectNode(long parent, const ListIndex & listChildren){
/** @param index : index of the node to be used
* @return pointer to this Node or NULL if the Node does not exist
*/
template<typename T>
const Node<T> * Graph<T>::getNode(long index) const{
typename std::map<long, Node<T> >::const_iterator it(p_mapNode.find(index));
template<typename T, typename UIdx>
const Node<T, UIdx> * Graph<T, UIdx>::getNode(UIdx index) const{
typename std::map<UIdx, Node<T, UIdx> >::const_iterator it(p_mapNode.find(index));
if(it != p_mapNode.end()){
return &(it->second);
}else{
......@@ -271,9 +303,9 @@ const Node<T> * Graph<T>::getNode(long index) const{
/** @param index : index of the node to be used
* @return pointer to this Node or NULL if the Node does not exist
*/
template<typename T>
Node<T> * Graph<T>::getNode(long index){
typename std::map<long, Node<T> >::iterator it(p_mapNode.find(index));
template<typename T, typename UIdx>
Node<T, UIdx> * Graph<T, UIdx>::getNode(UIdx index){
typename std::map<UIdx, Node<T, UIdx> >::iterator it(p_mapNode.find(index));
if(it != p_mapNode.end()){
return &(it->second);
}else{
......@@ -285,25 +317,25 @@ Node<T> * Graph<T>::getNode(long index){
/** @param index : index of the node to be searched
* @return true if the Node does exist, false otheriwse
*/
template<typename T>
bool Graph<T>::isNodeExist(long index) const{
typename std::map<long, Node<T> >::iterator it(p_mapNode.find(index));
template<typename T, typename UIdx>
bool Graph<T, UIdx>::isNodeExist(UIdx index) const{
typename std::map<UIdx, Node<T, UIdx> >::iterator it(p_mapNode.find(index));
return it != p_mapNode.end();
}
///Copy function of Graph
/** @param other : class to copy
*/
template<typename T>
void Graph<T>::copyGraph(const Graph<T> & other){
template<typename T, typename UIdx>
void Graph<T, UIdx>::copyGraph(const Graph<T, UIdx> & other){
p_mapNode = other.p_mapNode;
p_listFirstNode = other.p_listFirstNode;
p_listLastNode = other.p_listLastNode;
}
///Initialisation function of the class Graph
template<typename T>
void Graph<T>::initialisationGraph(){
template<typename T, typename UIdx>
void Graph<T, UIdx>::initialisationGraph(){
}
......
......@@ -10,34 +10,36 @@
#include "list_index_utils.h"
///@brief Node of a Graph
template<typename T>
/** T : type of the data to be connected in the graph
* UIdx : type of the index to be used to connect the Node together
*/
template<typename T, typename UIdx>
class Node{
public:
Node(const std::string & name = "");
Node(const T & data, const std::string & name = "");
Node(const Node<T> & other);
Node(const Node<T, UIdx> & other);
virtual ~Node();
Node & operator = (const Node<T> & other);
Node & operator = (const Node<T, UIdx> & other);
void addChild(long child);
void addParent(long parent);
void addChild(UIdx child);
void addParent(UIdx parent);
void removeChild(long child);
void removeParent(long parent);
void removeChild(UIdx child);
void removeParent(UIdx parent);
void setListChild(const ListIndex & listChild);
void setListParent(const ListIndex & listParent);
void setIndex(long index);
void setListChild(const std::list<UIdx> & listChild);
void setListParent(const std::list<UIdx> & listParent);
void setIndex(UIdx index);
void setName(const std::string & name);
void setIsUpdated(bool isUpdated);
void setData(const T & data);
const ListIndex & getListChild() const;
ListIndex & getListChild();
const ListIndex & getListParent() const;
ListIndex & getListParent();
long getIndex() const;
long & getIndex();
const std::list<UIdx> & getListChild() const;
std::list<UIdx> & getListChild();
const std::list<UIdx> & getListParent() const;
std::list<UIdx> & getListParent();
UIdx getIndex() const;
const std::string & getName() const;
std::string & getName();
bool getIsUpdated() const;
......@@ -52,17 +54,17 @@ class Node{
std::string getDotDefinition() const;
protected:
void copyNode(const Node<T> & other);
void copyNode(const Node<T, UIdx> & other);