| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516 | 
							- /*=========================================================================
 
-   Library:   CTK
 
-  
 
-   Copyright (c) 2010  Kitware Inc.
 
-   Licensed under the Apache License, Version 2.0 (the "License");
 
-   you may not use this file except in compliance with the License.
 
-   You may obtain a copy of the License at
 
-       http://www.commontk.org/LICENSE
 
-   Unless required by applicable law or agreed to in writing, software
 
-   distributed under the License is distributed on an "AS IS" BASIS,
 
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
-   See the License for the specific language governing permissions and
 
-   limitations under the License.
 
-  
 
- =========================================================================*/
 
- // Qt includes
 
- #include <QQueue>
 
- #include <QVarLengthArray>
 
- #include <QDebug>
 
- // CTK includes
 
- #include "ctkDependencyGraph.h"
 
- // STD includes
 
- #include <iostream>
 
- #define MAXV 100
 
- #define MAXDEGREE 50
 
- //----------------------------------------------------------------------------
 
- class ctkDependencyGraph::ctkInternal
 
- {
 
- public:
 
-   ctkInternal(ctkDependencyGraph* p);
 
-   
 
-   /// Compute indegree
 
-   void computeIndegrees(QVarLengthArray<int, MAXV>& computedIndegrees);
 
-   
 
-   /// Traverse tree using Depth-first_search
 
-   void traverseUsingDFS(int v);
 
-   
 
-   /// Called each time an edge is visited
 
-   void processEdge(int from, int to); 
 
-   
 
-   /// Called each time a vertex is processed
 
-   void processVertex(int v);
 
-   /// Retrieve the path between two vertices
 
-   void findPathDFS(int from, int to, QList<int>& path);
 
-   /// Recursive function used by findPaths to retrieve the path between two vertices
 
-   void findPathsRec(int from, int to, QList<int>* path, QList<QList<int>* >& paths);
 
-   
 
-   void setEdge(int vertice, int degree, int value);
 
-   int edge(int vertice, int degree);
 
-   
 
-   /// See http://en.wikipedia.org/wiki/Adjacency_list
 
-   QVarLengthArray<QVarLengthArray<int,MAXDEGREE>*, MAXV+1> Edges;
 
-   QVarLengthArray<int, MAXV+1> Degree;
 
-   int NVertices;
 
-   int NEdges;
 
-   
 
-   /// Structure used by DFS
 
-   /// See http://en.wikipedia.org/wiki/Depth-first_search
 
-   QVarLengthArray<bool, MAXV> Processed;	// processed vertices
 
-   QVarLengthArray<bool, MAXV> Discovered; // discovered vertices
 
-   QVarLengthArray<int, MAXV>  Parent;	    // relation discovered
 
-   
 
-   bool    Abort;	// Flag indicating if traverse should be aborted
 
-   bool    Verbose; 
 
-   bool    CycleDetected; 
 
-   int     CycleOrigin; 
 
-   int     CycleEnd;
 
-   
 
-   QList<int> ListOfEdgeToExclude;
 
-   
 
-   /// Pointer to the public API
 
-   ctkDependencyGraph* P;
 
- };
 
- //----------------------------------------------------------------------------
 
- // ctkInternal methods
 
- //----------------------------------------------------------------------------
 
- ctkDependencyGraph::ctkInternal::ctkInternal(ctkDependencyGraph* p)
 
- {
 
-   Q_ASSERT(p);
 
-   this->P = p;
 
-   this->NVertices = 0; 
 
-   this->NEdges = 0; 
 
-   this->Abort = false;
 
-   this->Verbose = false;
 
-   this->CycleDetected = false;
 
-   this->CycleOrigin = 0;
 
-   this->CycleEnd = 0;
 
- }
 
- //----------------------------------------------------------------------------
 
- void ctkDependencyGraph::ctkInternal::computeIndegrees(QVarLengthArray<int, MAXV>& computedIndegrees)
 
- {
 
- 	for (int i=1; i <= this->NVertices; i++)
 
- 	  {
 
- 	  computedIndegrees[i] = 0;
 
- 	  }
 
- 	for (int i=1; i <= this->NVertices; i++) 
 
- 	  {
 
- 		for (int j=0; j < this->Degree[i]; j++) 
 
- 		  {
 
- 		  computedIndegrees[ this->edge(i,j) ] ++;
 
- 		  }
 
- 		}
 
- }
 
- //----------------------------------------------------------------------------
 
- void ctkDependencyGraph::ctkInternal::traverseUsingDFS(int v)
 
- {
 
-   // allow for search termination
 
- 	if (this->Abort)
 
- 	  {
 
- 	  return;
 
- 	  }
 
- 	this->Discovered[v] = true;
 
- 	this->processVertex(v);
 
-   int y; // successor vertex
 
- 	for (int i=0; i<this->Degree[v]; i++)
 
- 	  {
 
- 		y = this->edge(v, i);
 
- 		if (this->P->shouldExcludeEdge(this->edge(v, i)) == false)
 
- 		  {
 
- 			if (this->Discovered[y] == false)
 
- 			  {
 
- 				this->Parent[y] = v;
 
- 				this->traverseUsingDFS(y);
 
- 			  } 
 
- 			else 
 
- 			  {
 
- 				if (this->Processed[y] == false)
 
- 				  {
 
- 					this->processEdge(v,y);
 
- 					}
 
- 			  }
 
- 		  }
 
- 		if (this->Abort)
 
- 		  {
 
- 		  return;
 
- 		  }
 
- 	}
 
- 	this->Processed[v] = true;
 
- }
 
- //----------------------------------------------------------------------------
 
- void ctkDependencyGraph::ctkInternal::processEdge(int from, int to)
 
- {
 
-   if (this->Parent[from] != to)
 
-     {
 
-     this->CycleDetected = true;
 
-     this->CycleOrigin = to; 
 
-     this->CycleEnd = from;
 
-     if (this->Verbose)
 
-       {
 
-       QList<int> path;
 
-       this->findPathDFS(from, to, path);
 
-       qWarning() << "Cycle detected from " << to << " to " << from;
 
-       qWarning() << " " << path;
 
-       path.clear();
 
-       this->findPathDFS(to, from, path);
 
-       qWarning() << " " << path;
 
-       }
 
-     this->Abort = true;
 
-     }
 
- }
 
- //----------------------------------------------------------------------------
 
- void ctkDependencyGraph::ctkInternal::processVertex(int v)
 
- {
 
- 	if (this->Verbose)
 
- 	  {
 
- 	  qDebug() << "processed vertex " << v;
 
- 	  }
 
- }
 
- //----------------------------------------------------------------------------
 
- void ctkDependencyGraph::ctkInternal::setEdge(int vertice, int degree, int value)
 
- {
 
-   Q_ASSERT(vertice <= this->NVertices);
 
-   Q_ASSERT(degree < MAXDEGREE);
 
-   (*this->Edges[vertice])[degree] = value; 
 
- }
 
- //----------------------------------------------------------------------------
 
- int ctkDependencyGraph::ctkInternal::edge(int vertice, int degree)
 
- {
 
-   Q_ASSERT(vertice <= this->NVertices);
 
-   Q_ASSERT(degree < MAXDEGREE);
 
-   return (*this->Edges[vertice])[degree];
 
- }
 
- //----------------------------------------------------------------------------
 
- void ctkDependencyGraph::ctkInternal::findPathDFS(int from, int to, QList<int>& path)
 
- {
 
-   if ((from == to) || (to == -1))
 
-     {
 
-     path << from;
 
-     }
 
-   else 
 
-     {
 
-     this->findPathDFS(from, this->Parent[to], path);
 
-     path << to;
 
-     }
 
- }
 
- //----------------------------------------------------------------------------
 
- void ctkDependencyGraph::ctkInternal::findPathsRec(
 
-   int from, int to, QList<int>* path, QList<QList<int>* >& paths)
 
- {
 
-   if (from == to)
 
-     {
 
-     return;
 
-     }
 
-   
 
-   QList<int> branch(*path);
 
-   int child = from;
 
-   for (int j=0; j < this->Degree[child]; j++)
 
-     {
 
-     if (j == 0)
 
-       {
 
-       int parent = this->edge(child, j);
 
-       *path << parent;
 
-       this->findPathsRec(parent, to, path, paths);
 
-       }
 
-     else
 
-       {
 
-       int parent = this->edge(child, j);
 
-       // Copy path and add it to the list
 
-       QList<int>* pathCopy = new QList<int>(branch);
 
-       paths << pathCopy;
 
-       *pathCopy << parent;
 
-       this->findPathsRec(parent, to, pathCopy, paths);
 
-       }
 
-     }
 
- }
 
-     
 
- //----------------------------------------------------------------------------
 
- // ctkDependencyGraph methods
 
- //----------------------------------------------------------------------------
 
- ctkDependencyGraph::ctkDependencyGraph(int nvertices)
 
- {
 
-   this->Internal = new ctkInternal(this);
 
-   
 
-   this->Internal->NVertices = nvertices; 
 
-   
 
-   // Resize internal array
 
-   this->Internal->Processed.resize(nvertices + 1);
 
-   this->Internal->Discovered.resize(nvertices + 1);
 
-   this->Internal->Parent.resize(nvertices + 1);
 
-   this->Internal->Edges.resize(nvertices + 1);
 
-   this->Internal->Degree.resize(nvertices + 1);
 
-   for (int i=1; i <= nvertices; i++)
 
-     {
 
-     this->Internal->Degree[i] = 0;
 
-     }
 
-     
 
-   // initialize Edge adjacency list
 
-   for (int i=0; i <= nvertices; i++)
 
-     {
 
-     this->Internal->Edges[i] = new QVarLengthArray<int, MAXDEGREE>();
 
-     this->Internal->Edges[i]->resize(MAXDEGREE);
 
-     }
 
-     
 
-   // initialize search
 
-   for (int i=1; i <= nvertices; i++)
 
-     {
 
-     this->Internal->Processed[i] = false;
 
-     this->Internal->Discovered[i] = false;
 
-     this->Internal->Parent[i] = -1;
 
-     }
 
- }
 
- //----------------------------------------------------------------------------
 
- ctkDependencyGraph::~ctkDependencyGraph()
 
- {
 
-   // Clean memory
 
-   for (int i=0; i <= this->Internal->NVertices; i++)
 
-     {
 
-     delete this->Internal->Edges[i];
 
-     }
 
-     
 
-   delete this->Internal; 
 
- }
 
- //----------------------------------------------------------------------------
 
- void ctkDependencyGraph::printAdditionalInfo()
 
- {
 
-   qDebug() << "ctkDependencyGraph (" << this << ")" << endl
 
-            << " NVertices:" << this->numberOfVertices() << endl
 
-            << " NEdges:" << this->numberOfEdges() << endl
 
-            << " Abort:" << this->Internal->Abort;
 
-            
 
-   qDebug() << " [Processed]";
 
-   for(int i=1; i < this->Internal->Processed.size(); i++)
 
-     {
 
-     qDebug() << i << "->" << this->Internal->Processed[i];
 
-     }
 
-   qDebug() << " [Discovered]";
 
-   for(int i=1; i < this->Internal->Discovered.size(); i++)
 
-     {
 
-     qDebug() << i << "->" << this->Internal->Discovered[i];
 
-     }
 
-   qDebug() << " [Parent]";
 
-   for(int i=1; i < this->Internal->Parent.size(); i++)
 
-     {
 
-     qDebug() << i << "->" << this->Internal->Parent[i];
 
-     }
 
-   qDebug() << " [Graph]"; 
 
-   this->printGraph();
 
- }
 
- //----------------------------------------------------------------------------
 
- void ctkDependencyGraph::printGraph()
 
- {
 
-   for(int i=1; i <= this->Internal->NVertices; i++)
 
-     {
 
-     std::cout << i << ":";
 
-     for (int j=0; j < this->Internal->Degree[i]; j++)
 
-       {
 
-       std::cout << " " << this->Internal->edge(i, j);
 
-       }
 
-     std::cout << std::endl;
 
-     }
 
- }
 
- //----------------------------------------------------------------------------
 
- int ctkDependencyGraph::numberOfVertices()
 
- {
 
-   return this->Internal->NVertices;
 
- }
 
- //----------------------------------------------------------------------------
 
- int ctkDependencyGraph::numberOfEdges()
 
- {
 
-   return this->Internal->NEdges;
 
- }
 
- //----------------------------------------------------------------------------
 
- void ctkDependencyGraph::setVerbose(bool verbose)
 
- {
 
-   this->Internal->Verbose = verbose;
 
- }
 
- //----------------------------------------------------------------------------
 
- void ctkDependencyGraph::setEdgeListToExclude(const QList<int>& list)
 
- {
 
-   this->Internal->ListOfEdgeToExclude = list;
 
- }
 
- //----------------------------------------------------------------------------
 
- bool ctkDependencyGraph::shouldExcludeEdge(int edge)
 
- {
 
-   return this->Internal->ListOfEdgeToExclude.contains(edge);
 
- }
 
- //----------------------------------------------------------------------------
 
- bool ctkDependencyGraph::checkForCycle()
 
- {
 
-   if (this->Internal->NEdges > 0)
 
-     {
 
-     // get a valid vertice Id
 
-     int verticeId = 1;
 
-     this->Internal->traverseUsingDFS(verticeId);
 
-     }
 
-   return this->cycleDetected();
 
- }
 
- //----------------------------------------------------------------------------
 
- bool ctkDependencyGraph::cycleDetected()
 
- {
 
-   return this->Internal->CycleDetected;
 
- }
 
- //----------------------------------------------------------------------------
 
- int ctkDependencyGraph::cycleOrigin()
 
- {
 
-   return this->Internal->CycleOrigin;
 
- }
 
- //----------------------------------------------------------------------------
 
- int ctkDependencyGraph::cycleEnd()
 
- {
 
-   return this->Internal->CycleEnd;
 
- }
 
- //----------------------------------------------------------------------------
 
- void ctkDependencyGraph::insertEdge(int from, int to)
 
- {
 
-   Q_ASSERT(from > 0 && from <= this->Internal->NVertices);
 
-   Q_ASSERT(to > 0 && to <= this->Internal->NVertices);
 
-   
 
-   // resize if needed
 
-   int capacity = this->Internal->Edges[from]->capacity(); 
 
-   if (this->Internal->Degree[from] > capacity)
 
-     {
 
-     this->Internal->Edges[from]->resize(capacity + capacity * 0.3);
 
-     }
 
-   this->Internal->setEdge(from, this->Internal->Degree[from], to);
 
-   this->Internal->Degree[from]++;
 
-   this->Internal->NEdges++;
 
- }
 
- //----------------------------------------------------------------------------
 
- void ctkDependencyGraph::findPaths(int from, int to, QList<QList<int>* >& paths)
 
- {
 
-   QList<int>* path = new QList<int>;
 
-   *path << from; 
 
-   paths << path;
 
-   this->Internal->findPathsRec(from, to, path, paths);
 
-   QList<int> pathToRemove;
 
-   // Remove list no ending with the requested element
 
-   int i = 0; 
 
-   while (!paths.isEmpty() && i < paths.size())
 
-     {
 
-     QList<int>* p = paths[i];
 
-     Q_ASSERT(p);
 
-     if (p->last() != to)
 
-       {
 
-       paths.removeAt(i);
 
-       delete p; 
 
-       }
 
-     else
 
-       {
 
-       i++;
 
-       }
 
-     }
 
- }
 
- //----------------------------------------------------------------------------
 
- void ctkDependencyGraph::findPath(int from, int to, QList<int>& path)
 
- {
 
-   int child = from;
 
-   int parent = this->Internal->edge(child, 0);
 
-   path << child; 
 
-   while (parent > 0)
 
-     {
 
-     path << parent;
 
-     if (parent == to)
 
-       {
 
-       break;
 
-       }
 
-     child = parent;
 
-     parent = this->Internal->edge(child, 0);
 
-     }
 
- }
 
- //----------------------------------------------------------------------------
 
- bool ctkDependencyGraph::topologicalSort(QList<int>& sorted)
 
- {
 
- 	QVarLengthArray<int, MAXV> indegree; // indegree of each vertex
 
- 	QQueue<int> zeroin;	  // vertices of indegree 0
 
- 	int x, y;			        // current and next vertex
 
-   
 
-   indegree.resize(this->Internal->NVertices + 1);
 
- 	
 
- 	// resize if needed
 
- 	if (this->Internal->NVertices > MAXV)
 
- 	  {
 
- 	  indegree.resize(this->Internal->NVertices);
 
- 	  }
 
- 	this->Internal->computeIndegrees(indegree);
 
- 	
 
- 	for (int i=1; i <= this->Internal->NVertices; i++)
 
- 	  {
 
- 		if (indegree[i] == 0) 
 
- 		  {
 
- 		  zeroin.enqueue(i);
 
- 		  }
 
- 		}
 
- 	int j=0;
 
- 	while (zeroin.empty() == false) 
 
- 	  {
 
- 		j = j+1;
 
- 		x = zeroin.dequeue();
 
- 		sorted << x;
 
- 		for (int i=0; i < this->Internal->Degree[x]; i++)
 
- 		  {
 
- 			y = this->Internal->edge(x, i);
 
- 			indegree[y] --;
 
- 			if (indegree[y] == 0)
 
- 			  {
 
- 			  zeroin.enqueue(y);
 
- 			  }
 
- 		  }
 
- 	  }
 
- 	if (j != this->Internal->NVertices)
 
- 	  {
 
- 		return false;
 
- 		}
 
- 		
 
-   return true;
 
- }
 
 
  |