| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750 | /*=========================================================================  Library:   CTK  Copyright (c) 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.apache.org/licenses/LICENSE-2.0.txt  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.=========================================================================*/// CTK includes#include "ctkDependencyGraph.h"// STD includes#include <iostream>#include <sstream>#include <algorithm>#include <vector>#include <set>#include <map>#include <list>#include <queue>#include <cassert>#define MAXV 100#define MAXDEGREE 200//----------------------------------------------------------------------------class ctkDependencyGraphPrivate{public:  ctkDependencyGraph* const q_ptr;  ctkDependencyGraphPrivate(ctkDependencyGraph& p);  ~ctkDependencyGraphPrivate();    /// Compute outdegree  void computeOutdegrees(std::vector<int>& computedOutdegrees);    /// 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, std::list<int>& path);  /// Recursive function used by findPaths to retrieve the path between two vertices  void findPathsRec(int from, int to, std::list<int>* path, std::list<std::list<int>* >& paths);    void setEdge(int vertice, int degree, int value);  int edge(int vertice, int degree)const;  void verticesWithIndegree(int indegree, std::list<int>& list);  int subgraphSize(int rootId);  void subgraphSizeRec(int rootId, std::set<int>& uniqueVertices);  void subgraphInsert(ctkDependencyGraph& subgraph, int rootId,                      std::map<int,int>& subgraphIdToGlobal, std::map<int,int>& globalIdToSubgraph);  int getOrGenerateSubgraphId(std::map<int, int>& subgraphIdToGlobal,                      std::map<int, int>& globalIdToSubgraph,                      int globalId);  /// See http://en.wikipedia.org/wiki/Adjacency_list  std::vector<std::vector<int>* > Edges;  std::vector<int> OutDegree;  std::vector<int> InDegree;  int NVertices;  int NEdges;    /// Structure used by DFS  /// See http://en.wikipedia.org/wiki/Depth-first_search  std::vector<bool> Processed;	// processed vertices  std::vector<bool> Discovered; // discovered vertices  std::vector<int>  Parent;	    // relation discovered    bool    Abort;	// Flag indicating if traverse should be aborted  bool    Verbose;   bool    CycleDetected;   int     CycleOrigin;   int     CycleEnd;    std::list<int> ListOfEdgeToExclude;};//----------------------------------------------------------------------------// Returns a space separated string of T.template<class T>std::string listToString(const std::list<T>& list){  std::stringstream outputString;  typename std::list<T>::const_iterator iter;  for (iter = list.begin(); iter != list.end(); iter++)    {    outputString << *iter << " ";    }  return outputString.str();}//----------------------------------------------------------------------------// Returns true if the map contains the key and false otherwise.template<class T1, class T2>bool mapContainsKey(const std::map<T1, T2>& map, const T1& key){  bool result = false;  if (map.find(key) != map.end())    {    result = true;    }  return result;}//----------------------------------------------------------------------------// Returns true if the list contains the value and false otherwise.template<class T>bool listContainsValue(const std::list<T>& list, const T& value){  bool result = false;  typename std::list<T>::const_iterator iter;  for (iter = list.begin(); iter != list.end(); iter++)    {    if ((*iter) == value)      {      result = true;      break;      }    }  return result;}//----------------------------------------------------------------------------// ctkInternal methods//----------------------------------------------------------------------------ctkDependencyGraphPrivate::ctkDependencyGraphPrivate(ctkDependencyGraph& object)  :q_ptr(&object){  this->NVertices = 0;   this->NEdges = 0;   this->Abort = false;  this->Verbose = false;  this->CycleDetected = false;  this->CycleOrigin = 0;  this->CycleEnd = 0;}ctkDependencyGraphPrivate::~ctkDependencyGraphPrivate(){  std::vector<std::vector<int>* >::iterator edgesIterator;  for (edgesIterator = this->Edges.begin(); edgesIterator != this->Edges.end(); edgesIterator++)    {    if (*edgesIterator != NULL)      {      delete *edgesIterator;      }    }}//----------------------------------------------------------------------------void ctkDependencyGraphPrivate::computeOutdegrees(std::vector<int>& computedOutdegrees){	for (int i=1; i <= this->NVertices; i++)	  {    computedOutdegrees[i] = 0;	  }	for (int i=1; i <= this->NVertices; i++) 	  {    for (int j=0; j < this->OutDegree[i]; j++)		  {      computedOutdegrees[ this->edge(i,j) ] ++;		  }		}}//----------------------------------------------------------------------------void ctkDependencyGraphPrivate::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->OutDegree[v]; i++)	  {		y = this->edge(v, i);		if (q_ptr->shouldExcludeEdge(this->edge(v, i)) == false)		  {      this->Parent[y] = v;			if (this->Discovered[y] == false)			  {				this->traverseUsingDFS(y);			  } 			else 			  {				if (this->Processed[y] == false)				  {					this->processEdge(v,y);					}			  }		  }		if (this->Abort)		  {		  return;		  }	}	this->Processed[v] = true;}//----------------------------------------------------------------------------void ctkDependencyGraphPrivate::processEdge(int from, int to){  if (this->Discovered[to] == true)    {    this->CycleDetected = true;    this->CycleOrigin = to;     this->CycleEnd = from;    if (this->Verbose)      {      std::list<int> path;      this->findPathDFS(from, to, path);      std::cerr << "ERROR: Cycle detected from " << to << " to " << from << std::endl;      std::cerr << " " << listToString<int>(path) << std::endl;      path.clear();      this->findPathDFS(to, from, path);      std::cerr << " " << listToString<int>(path) << std::endl;      }    this->Abort = true;    }}//----------------------------------------------------------------------------void ctkDependencyGraphPrivate::processVertex(int v){	if (this->Verbose)	  {	  std::cout << "processed vertex " << v << std::endl;	  }}//----------------------------------------------------------------------------void ctkDependencyGraphPrivate::setEdge(int vertice, int degree, int value){  assert(vertice <= this->NVertices);  assert(degree < MAXDEGREE);  (*this->Edges[vertice])[degree] = value; }//----------------------------------------------------------------------------int ctkDependencyGraphPrivate::edge(int vertice, int degree)const{  assert(vertice <= this->NVertices);  assert(degree < MAXDEGREE);  return (*this->Edges[vertice])[degree];}//----------------------------------------------------------------------------void ctkDependencyGraphPrivate::findPathDFS(int from, int to, std::list<int>& path){  if ((from == to) || (to == -1))    {    path.push_back(from);    }  else     {    this->findPathDFS(from, this->Parent[to], path);    path.push_back(to);    }}//----------------------------------------------------------------------------void ctkDependencyGraphPrivate::findPathsRec(  int from, int to, std::list<int>* path, std::list<std::list<int>* >& paths){  if (from == to)    {    return;    }    std::list<int> branch;  branch = *path;  int child = from;  for (int j=0; j < this->OutDegree[child]; j++)    {    if (j == 0)      {      int parent = this->edge(child, j);      (*path).push_back(parent);      this->findPathsRec(parent, to, path, paths);      }    else      {      int parent = this->edge(child, j);      // Copy path and add it to the list      std::list<int>* pathCopy = new std::list<int>();      *pathCopy = branch;      paths.push_back(pathCopy);      (*pathCopy).push_back(parent);      this->findPathsRec(parent, to, pathCopy, paths);      }    }}//----------------------------------------------------------------------------void ctkDependencyGraphPrivate::verticesWithIndegree(int indegree, std::list<int>& list){  assert(indegree >= 0);  for (int i=1; i <= this->NVertices; i++)    {    if (this->InDegree[i] == indegree)      {      list.push_back(i);      }    }}//----------------------------------------------------------------------------void ctkDependencyGraphPrivate::subgraphSizeRec(int rootId, std::set<int>& uniqueVertices){  assert(rootId > 0);  for (int i = 0; i < this->OutDegree[rootId]; ++i)    {    int child = this->edge(rootId, i);    uniqueVertices.insert(child);    subgraphSizeRec(child, uniqueVertices);    }}//----------------------------------------------------------------------------int ctkDependencyGraphPrivate::subgraphSize(int rootId){  assert(rootId > 0);  std::set<int> vertices;  vertices.insert(rootId);  this->subgraphSizeRec(rootId, vertices);  return static_cast<int>(vertices.size());}void ctkDependencyGraphPrivate::subgraphInsert(    ctkDependencyGraph& subgraph, int rootId,    std::map<int,int>& subgraphIdToGlobal, std::map<int,int>& globalIdToSubgraph){  int from = this->getOrGenerateSubgraphId(subgraphIdToGlobal, globalIdToSubgraph, rootId);  for (int i = 0; i < this->OutDegree[rootId]; ++i)  {    int childId = this->edge(rootId, i);    int to = this->getOrGenerateSubgraphId(subgraphIdToGlobal, globalIdToSubgraph,                                           childId);    subgraph.insertEdge(from, to);    this->subgraphInsert(subgraph, childId, subgraphIdToGlobal, globalIdToSubgraph);  }}//----------------------------------------------------------------------------int ctkDependencyGraphPrivate::getOrGenerateSubgraphId(    std::map<int, int>& subgraphIdToGlobal,    std::map<int, int>& globalIdToSubgraph,    int globalId){  // If needed, generate vertex id  int subgraphId = -1;  if (!mapContainsKey<int, int>(globalIdToSubgraph,globalId))    {    subgraphId = static_cast<int>(globalIdToSubgraph.size()) + 1;    globalIdToSubgraph[globalId] = subgraphId;    subgraphIdToGlobal[subgraphId] = globalId;    }  else    {    subgraphId = globalIdToSubgraph[globalId];    }  return subgraphId;}//----------------------------------------------------------------------------// ctkDependencyGraph methods//----------------------------------------------------------------------------ctkDependencyGraph::ctkDependencyGraph(int nvertices)  :d_ptr(new ctkDependencyGraphPrivate(*this)){  d_ptr->NVertices = nvertices;    // Resize internal array  d_ptr->Processed.resize(nvertices + 1);  d_ptr->Discovered.resize(nvertices + 1);  d_ptr->Parent.resize(nvertices + 1);  d_ptr->Edges.resize(nvertices + 1);  d_ptr->OutDegree.resize(nvertices + 1);  d_ptr->InDegree.resize(nvertices + 1);  for (int i=1; i <= nvertices; i++)    {    d_ptr->OutDegree[i] = 0;    d_ptr->InDegree[i] = 0;    }      // initialize Edge adjacency list  for (int i=0; i <= nvertices; i++)    {    d_ptr->Edges[i] = new std::vector<int>();    d_ptr->Edges[i]->resize(MAXDEGREE);    }      // initialize search  for (int i=1; i <= nvertices; i++)    {    d_ptr->Processed[i] = false;    d_ptr->Discovered[i] = false;    d_ptr->Parent[i] = -1;    }}//----------------------------------------------------------------------------ctkDependencyGraph::~ctkDependencyGraph(){  if (d_ptr != NULL)    {    delete d_ptr;    }}//----------------------------------------------------------------------------void ctkDependencyGraph::printAdditionalInfo()const{  std::cout << "ctkDependencyGraph (" << this << ")" << std::endl            << " NVertices:" << this->numberOfVertices() << std::endl            << " NEdges:" << this->numberOfEdges() << std::endl            << " Abort:" << d_ptr->Abort << std::endl;  std::cout << " [Processed]" << std::endl;  for(unsigned int i=1; i < d_ptr->Processed.size(); i++)    {    std::cout << i << "->" << d_ptr->Processed[i] << std::endl;    }  std::cout << " [Discovered]" << std::endl;  for(unsigned int i=1; i < d_ptr->Discovered.size(); i++)    {    std::cout << i << "->" << d_ptr->Discovered[i] << std::endl;    }  std::cout << " [Parent]" << std::endl;  for(unsigned int i=1; i < d_ptr->Parent.size(); i++)    {    std::cout << i << "->" << d_ptr->Parent[i] << std::endl;    }  std::cout << " [Graph]" << std::endl;  this->printGraph();}//----------------------------------------------------------------------------void ctkDependencyGraph::printGraph()const{  for(int i=1; i <= d_ptr->NVertices; i++)    {    std::cout << i << ":";    for (int j=0; j < d_ptr->OutDegree[i]; j++)      {      std::cout << " " << d_ptr->edge(i, j);      }    std::cout << std::endl;    }}//----------------------------------------------------------------------------int ctkDependencyGraph::numberOfVertices()const{  return d_ptr->NVertices;}//----------------------------------------------------------------------------int ctkDependencyGraph::numberOfEdges()const{  return d_ptr->NEdges;}//----------------------------------------------------------------------------void ctkDependencyGraph::setVerbose(bool verbose){  d_ptr->Verbose = verbose;}//----------------------------------------------------------------------------void ctkDependencyGraph::setEdgeListToExclude(const std::list<int>& list){  d_ptr->ListOfEdgeToExclude = list;}//----------------------------------------------------------------------------bool ctkDependencyGraph::shouldExcludeEdge(int edge)const{  return listContainsValue(d_ptr->ListOfEdgeToExclude, edge);}//----------------------------------------------------------------------------bool ctkDependencyGraph::checkForCycle(){  if (d_ptr->NEdges > 0)    {    // Store unprocessed vertex ids    std::list<int> uncheckedVertices;    for (int i = 1; i <= d_ptr->NVertices; ++i)      {        uncheckedVertices.push_back(i);      }    // Start the cycle detection on the source vertices    std::list<int> sources;    this->sourceVertices(sources);    std::list<int>::const_iterator sourcesIterator;    for (sourcesIterator = sources.begin(); sourcesIterator != sources.end(); sourcesIterator++)      {      d_ptr->traverseUsingDFS(*sourcesIterator);      if (this->cycleDetected()) return true;      for (unsigned int i=0; i < d_ptr->Processed.size(); i++)        {          if (d_ptr->Processed[i] == true)            {            uncheckedVertices.remove(i);            }          d_ptr->Discovered[i] = false;          d_ptr->Processed[i] = false;        }      }    // If a component does not have a source vertex,    // i.e. it is a cycle a -> b -> a, check all non    // processed vertices.    while (!uncheckedVertices.empty())      {      d_ptr->traverseUsingDFS((*uncheckedVertices.rbegin()));      if (this->cycleDetected()) return true;      for (unsigned int i=0; i < d_ptr->Processed.size(); i++)        {          if (d_ptr->Processed[i] == true)            {            uncheckedVertices.remove(i);            }          d_ptr->Discovered[i] = false;          d_ptr->Processed[i] = false;        }      }    }  return this->cycleDetected();}//----------------------------------------------------------------------------bool ctkDependencyGraph::cycleDetected()const{  return d_ptr->CycleDetected;}//----------------------------------------------------------------------------int ctkDependencyGraph::cycleOrigin()const{  return d_ptr->CycleOrigin;}//----------------------------------------------------------------------------int ctkDependencyGraph::cycleEnd()const{  return d_ptr->CycleEnd;}//----------------------------------------------------------------------------void ctkDependencyGraph::insertEdge(int from, int to){  assert(from > 0 && from <= d_ptr->NVertices);  assert(to > 0 && to <= d_ptr->NVertices);    // resize if needed  size_t capacity = d_ptr->Edges[from]->capacity();  if (d_ptr->OutDegree[from] > static_cast<int>(capacity))    {    d_ptr->Edges[from]->resize(capacity + capacity * 0.3);    }  d_ptr->setEdge(from, d_ptr->OutDegree[from], to);  d_ptr->OutDegree[from]++;  d_ptr->InDegree[to]++;  d_ptr->NEdges++;}//----------------------------------------------------------------------------void ctkDependencyGraph::findPaths(int from, int to, std::list<std::list<int>* >& paths){  std::list<int>* path = new std::list<int>;  (*path).push_back(from);  (paths).push_back(path);  d_ptr->findPathsRec(from, to, path, paths);  // Remove lists not ending with the requested element  std::list<std::list<int>* >::iterator pathsIterator;  pathsIterator = paths.begin();  while (paths.size() > 0 && pathsIterator != paths.end())    {    std::list<int>* pathToCheck = (*pathsIterator);    assert(pathToCheck);    if (*(pathToCheck->rbegin()) != to)      {      pathsIterator = paths.erase(pathsIterator);      }    else      {      pathsIterator++;      }    }}//----------------------------------------------------------------------------void ctkDependencyGraph::findPath(int from, int to, std::list<int>& path){  std::list<std::list<int>* > paths;  this->findPaths(from, to, paths);  if (!paths.empty())    {    std::list<int>::iterator pathIterator;    for (pathIterator = (*(paths.begin()))->begin(); pathIterator != (*(paths.begin()))->end(); pathIterator++)      {      path.push_back(*pathIterator);      }    }  std::list<std::list<int>* >::iterator pathsIterator;  for(pathsIterator = paths.begin(); pathsIterator != paths.end(); pathsIterator++)  {    if (*pathsIterator != NULL)    {      delete *pathsIterator;    }  }}//----------------------------------------------------------------------------bool ctkDependencyGraph::topologicalSort(std::list<int>& sorted, int rootId){  if (rootId > 0)    {    ctkDependencyGraph subgraph(d_ptr->subgraphSize(rootId));    std::map<int,int> subgraphIdToGlobal;    std::map<int,int> globalIdToSubgraph;    d_ptr->subgraphInsert(subgraph, rootId, subgraphIdToGlobal, globalIdToSubgraph);    std::list<int> subgraphSorted;    bool result = subgraph.topologicalSort(subgraphSorted);    std::list<int>::const_iterator subgraphSortedIterator;    for (subgraphSortedIterator = subgraphSorted.begin(); subgraphSortedIterator != subgraphSorted.end(); subgraphSortedIterator++)      {      sorted.push_back(subgraphIdToGlobal[*subgraphSortedIterator]);      }    return result;    }  std::vector<int> outdegree; // outdegree of each vertex  outdegree.resize(MAXV);  std::queue<int> zeroout;	  // vertices of outdegree 0	int x, y;			        // current and next vertex    outdegree.resize(d_ptr->NVertices + 1);		// resize if needed	if (d_ptr->NVertices > MAXV)	  {    outdegree.resize(d_ptr->NVertices);	  }	d_ptr->computeOutdegrees(outdegree);		for (int i=1; i <= d_ptr->NVertices; i++)	  {    if (outdegree[i] == 0)		  {      zeroout.push(i);		  }		}	int j=0;  while (zeroout.empty() == false)	  {		j = j+1;    x = zeroout.front();    zeroout.pop();		sorted.push_back(x);    for (int i=0; i < d_ptr->OutDegree[x]; i++)		  {			y = d_ptr->edge(x, i);      outdegree[y] --;      if (outdegree[y] == 0)			  {        zeroout.push(y);			  }		  }	  }	if (j != d_ptr->NVertices)	  {		return false;		}		  return true;}//----------------------------------------------------------------------------void ctkDependencyGraph::sourceVertices(std::list<int>& sources){  d_ptr->verticesWithIndegree(0, sources);}
 |