//---------------------------------------------------------------------------------------------------------------------- // // C_DirectedGraph : algorithms on ordered graphs // // This file is part of libpm library // // Copyright (C) 2013, ..., 2013 Pierre Molinaro. // // e-mail : pierre@pcmolinaro.name // // This library 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 2 of the License, or (at your option) // any later version. // // This program is distributed in the hope it will be useful, but WITHOUT ANY WARRANTY; without even the implied // warranty of MERCHANDIBILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for // more details. // //---------------------------------------------------------------------------------------------------------------------- #include "utilities/C_DirectedGraph.h" //---------------------------------------------------------------------------------------------------------------------- C_DirectedGraph::C_DirectedGraph (void) : mNodes (), mEdges (), mReverseEdges () { } //---------------------------------------------------------------------------------------------------------------------- C_DirectedGraph C_DirectedGraph::reversedGraph (void) const { C_DirectedGraph result ; result.mNodes = mNodes ; result.mEdges = mReverseEdges ; result.mReverseEdges = mEdges ; #ifndef DO_NOT_GENERATE_CHECKINGS result.checkGraph (HERE) ; #endif return result ; } //---------------------------------------------------------------------------------------------------------------------- void C_DirectedGraph::addNode (const uint32_t inNodeIndex) { mNodes.add (inNodeIndex) ; while (((int32_t) inNodeIndex) >= mEdges.count ()) { mEdges.appendObject (C_UIntSet ()) ; mReverseEdges.appendObject (C_UIntSet ()) ; } #ifndef DO_NOT_GENERATE_CHECKINGS checkGraph (HERE) ; #endif } //---------------------------------------------------------------------------------------------------------------------- void C_DirectedGraph::addNodes (const C_UIntSet inNodes) { mNodes |= inNodes ; const uint32_t lastPlusOne = mNodes.firstValueNotIsSet () ; while (lastPlusOne > (uint32_t) mEdges.count ()) { mEdges.appendObject (C_UIntSet ()) ; mReverseEdges.appendObject (C_UIntSet ()) ; } #ifndef DO_NOT_GENERATE_CHECKINGS checkGraph (HERE) ; #endif } //---------------------------------------------------------------------------------------------------------------------- void C_DirectedGraph::removeNode (const uint32_t inNodeIndex) { if (inNodeIndex < (uint32_t) mEdges.count ()) { mNodes.remove (inNodeIndex) ; const C_UIntSet targetSet = mEdges ((int32_t) inNodeIndex COMMA_HERE) ; TC_UniqueArray targetList ; targetSet.getValueArray (targetList) ; for (int32_t i=0 ; i & outNodes) const { mNodes.getBoolValueArray (outNodes) ; } //---------------------------------------------------------------------------------------------------------------------- void C_DirectedGraph::getNodeValueArray (TC_UniqueArray & outNodes) const { mNodes.getValueArray (outNodes) ; } //---------------------------------------------------------------------------------------------------------------------- bool C_DirectedGraph::isNodeDefined (const uint32_t inNodeIndex) const { return mNodes.contains (inNodeIndex) ; } //---------------------------------------------------------------------------------------------------------------------- uint32_t C_DirectedGraph::nodeCount (void) const { return mNodes.count () ; } //---------------------------------------------------------------------------------------------------------------------- uint32_t C_DirectedGraph::edgeCount (void) const { uint32_t result = 0 ; for (int32_t i=0 ; i & inNodeNameArray) const { C_String s = "digraph G {\n" ; for (int32_t i=0 ; i targetList ; targetSet.getValueArray (targetList) ; for (int32_t j=0 ; j " << inNodeNameArray (int32_t (targetIndex) COMMA_HERE).utf8RepresentationEnclosedWithin ('"') << " ;\n" ; } } } s << "}\n" ; return s ; } //---------------------------------------------------------------------------------------------------------------------- #ifndef DO_NOT_GENERATE_CHECKINGS void C_DirectedGraph::checkGraph (LOCATION_ARGS) const { MF_AssertThere (mEdges.count () == mReverseEdges.count (), "mEdges.count () %lld != mReverseEdges.count () %lld", mEdges.count (), mReverseEdges.count ()) ; MF_AssertThere (mNodes.firstValueNotIsSet () == (uint32_t) (mEdges.count ()), "mNodes.firstValueNotIsSet () %lld != mEdges.count () %lld", mNodes.firstValueNotIsSet (), mEdges.count ()) ; //--- for (uint32_t i=0 ; i<(uint32_t) mEdges.count () ; i++) { TC_UniqueArray targetList ; mEdges ((int32_t) i COMMA_HERE).getValueArray (targetList) ; for (int32_t j=0 ; j sourceList ; mReverseEdges ((int32_t) i COMMA_HERE).getValueArray (sourceList) ; for (int32_t j=0 ; j & outEdges) const { outEdges.setCountToZero () ; for (int32_t i=0 ; i targetList ; mEdges (i COMMA_HERE).getValueArray (targetList) ; for (int32_t j=0 ; j & outNodes) const { outNodes.setCountToZero () ; for (uint32_t i=0 ; i<(uint32_t) mReverseEdges.count () ; i++) { if (isNodeDefined (i) && mReverseEdges ((int32_t) i COMMA_HERE).isEmpty ()) { outNodes.appendObject (i) ; } } } //---------------------------------------------------------------------------------------------------------------------- void C_DirectedGraph::getNodesWithNoSuccessor (TC_UniqueArray & outNodes) const { outNodes.setCountToZero () ; for (uint32_t i=0 ; i<(uint32_t) mEdges.count () ; i++) { if (isNodeDefined (i) && mEdges ((int32_t) i COMMA_HERE).isEmpty ()) { outNodes.appendObject (i) ; } } } //---------------------------------------------------------------------------------------------------------------------- void C_DirectedGraph::getNodesInvolvedInCircularities (TC_UniqueArray & outNodes) const { outNodes.setCountToZero () ; //--- Get working copies TC_UniqueArray nodes ; getNodeBoolArray (nodes) ; TC_UniqueArray successorCount ; TC_UniqueArray predecessorCount ; for (int32_t i=0 ; i s ; mEdges (i COMMA_HERE).getValueArray (s) ; for (int32_t j=0 ; j & inNodeNames, #endif const C_UIntSet & inNodesToExclude) const { TC_UniqueArray nodeBoolArray ; mNodes.getBoolValueArray (nodeBoolArray) ; C_DirectedGraph result ; { C_UIntSet nodeSet = inStartNodes ; nodeSet -= inNodesToExclude ; result.addNodes (nodeSet) ; } #ifdef USE_NODE_NAMES_WITH_SUBGRAPH_COMPUTATION { TC_UniqueArray sourceNodeArray ; result.getNodeValueArray (sourceNodeArray) ; printf ("START NODES (%d):\n", sourceNodeArray.count ()) ; for (int32_t i=0 ; i sourceNodeArray ; result.getNodeValueArray (sourceNodeArray) ; #ifdef USE_NODE_NAMES_WITH_SUBGRAPH_COMPUTATION printf ("********************* NODE COUNT %d\n", sourceNodeArray.count ()) ; #endif for (int32_t i=0 ; i targetNodeArray ; s.getValueArray (targetNodeArray) ; for (int32_t j=0 ; j sourceNodeArray ; nodeSet.getValueArray (sourceNodeArray) ; for (int32_t i=0 ; i s ; mEdges (i COMMA_HERE).getValueArray (s) ; for (int32_t j=0 ; j %d\n", i, s (j COMMA_HERE)) ; } } } } //---------------------------------------------------------------------------------------------------------------------- void C_DirectedGraph::topologicalSort (TC_UniqueArray & outSortedNodes, TC_UniqueArray & outUnsortedNodes) const { outSortedNodes.setCountToZero () ; outUnsortedNodes.setCountToZero () ; //--- Get working copies TC_UniqueArray nodes ; getNodeBoolArray (nodes) ; TC_UniqueArray dependencyCount (mReverseEdges.count (), 0 COMMA_HERE) ; for (int32_t i=0 ; i s ; mReverseEdges (i COMMA_HERE).getValueArray (s) ; for (int32_t j=0 ; j s ; while (loop) { loop = false ; for (int32_t i=0 ; i & outSortedNodes, TC_UniqueArray & outUnsortedNodes) const { outSortedNodes.setCountToZero () ; outUnsortedNodes.setCountToZero () ; //--- Get working copies TC_UniqueArray nodes ; getNodeBoolArray (nodes) ; TC_UniqueArray dependencyCount (mReverseEdges.count (), 0 COMMA_HERE) ; for (int32_t i=0 ; i s ; mReverseEdges (i COMMA_HERE).getValueArray (s) ; for (int32_t j=0 ; j workingArray ; TC_UniqueArray s ; bool loop = true ; while (loop) { //--- Find a node without any dependence for (int32_t i=0 ; (i 0 ; if (loop) { const uint32_t node = workingArray.lastObject (HERE) ; workingArray.removeLastObject (HERE) ; outSortedNodes.appendObject (node) ; mReverseEdges ((int32_t) node COMMA_HERE).getValueArray (s) ; for (int32_t j=0 ; j & outDominators COMMA_LOCATION_ARGS) const { outDominators.setCountToZero () ; //--- Enter initial dominators TC_UniqueArray startNodeFlag ; for (int32_t i=0 ; i startNodeArray ; getNodesWithNoPredecessor (startNodeArray) ; MF_AssertThere (startNodeArray.count () == 1, "startNodeArray.count () == %lld != 1", startNodeArray.count (), 0) ; for (int32_t i=0 ; i s ; mReverseEdges (node COMMA_HERE).getValueArray (s) ; for (int32_t j=0 ; j dominators ; getDominators (dominators COMMA_THERE) ; for (int32_t node=0 ; node s ; mEdges (node COMMA_HERE).getValueArray (s) ; for (int32_t i=0 ; i %u\n", node, s (i COMMA_HERE)) ; } } } } #ifndef DO_NOT_GENERATE_CHECKINGS checkGraph (HERE) ; #endif } //---------------------------------------------------------------------------------------------------------------------- // // E X A M P L E // //---------------------------------------------------------------------------------------------------------------------- void C_DirectedGraph::example (void) { C_DirectedGraph g ; /* g.addEdge (1, 2) ; g.addEdge (1, 3) ; g.addEdge (2, 3) ; g.addEdge (3, 4) ; g.addEdge (4, 6) ; g.addEdge (6, 4) ; g.addEdge (10, 4) ; g.addEdge (10, 9) ; g.addEdge (6, 9) ; g.addEdge (100, 0) ; g.addEdge (100, 1) ; g.addEdge (100, 10) ; */ g.addEdge (17, 33) ; g.addEdge (17, 35) ; g.addEdge (17, 36) ; g.addEdge (33, 37) ; g.addEdge (37, 39) ; g.addEdge (36, 35) ; g.addEdge (37, 40) ; g.addEdge (40, 35) ; g.addEdge (39, 35) ; g.addEdge (40, 42) ; g.addEdge (42, 35) ; g.addEdge (35, 45) ; g.addEdge (35, 46) ; g.addEdge (45, 47) ; g.addEdge (45, 48) ; g.addEdge (46, 51) ; g.addEdge (46, 52) ; g.addEdge (51, 54) ; g.addEdge (51, 47) ; g.addEdge (52, 57) ; g.addEdge (52, 58) ; g.addEdge (54, 47) ; g.addEdge (57, 47) ; g.addEdge (57, 60) ; g.addEdge (58, 63) ; g.addEdge (58, 64) ; g.addEdge (60, 47) ; g.addEdge (63, 47) ; g.addEdge (63, 66) ; g.addEdge (64, 69) ; g.addEdge (64, 70) ; g.addEdge (66, 47) ; g.addEdge (69, 47) ; g.addEdge (69, 72) ; g.addEdge (70, 47) ; g.addEdge (70, 75) ; g.addEdge (72, 47) ; g.addEdge (75, 47) ; g.addEdge (75, 78) ; g.addEdge (78, 47) ; g.addEdge (78, 47) ; //--- Print printf ("--- Graph\n") ; g.print () ; printf ("--- Nodes with no predecessor:") ; TC_UniqueArray nodes ; g.getNodesWithNoPredecessor (nodes) ; for (int32_t i=0 ; i dominators ; g.getDominators (dominators COMMA_HERE) ; printf ("--- Dominators:\n") ; for (int32_t i=0 ; i sortedNodes ; TC_UniqueArray unsortedNodes ; g.topologicalSort (sortedNodes, unsortedNodes) ; printf (" Sorted nodes:") ; for (int32_t i=0 ; i theNodes ; g.getNodeValueArray (theNodes) ; loop = theNodes.count () > 0 ; if (loop) { g.removeNode (theNodes (theNodes.count () / 2 COMMA_HERE)) ; } } } //----------------------------------------------------------------------------------------------------------------------