From 70bd7d69a4a490b0da337a0d9d8b57541993fe25 Mon Sep 17 00:00:00 2001 From: Gillu13 Date: Wed, 29 Jan 2020 23:37:57 +0100 Subject: [PATCH 1/2] add isAcyclic function in the GraphProperty class to check wether a graph is a DAG --- src/Property/GraphProperty.php | 43 ++++++++++++++++++++++++++ tests/Property/PropertyGraphTest.php | 46 ++++++++++++++++++++++++++++ 2 files changed, 89 insertions(+) diff --git a/src/Property/GraphProperty.php b/src/Property/GraphProperty.php index d83b7a6..eea099a 100644 --- a/src/Property/GraphProperty.php +++ b/src/Property/GraphProperty.php @@ -48,4 +48,47 @@ public function isTrivial() { return ($this->graph->getEdges()->isEmpty() && \count($this->graph->getVertices()) === 1); } + + /** + * checks whether this graph is acyclic (directed graph with no cycles) + * using the Kahn algorithm + * + * @return boolean + * @link https://en.wikipedia.org/wiki/Directed_acyclic_graph + */ + public function isAcyclic() + { + $vertices = $this->graph->getVertices(); + $nVertices = count($vertices); + $visited = 0; + $inDegree = []; + $stack=[]; + + foreach($vertices as $vert){ + $deg=count($vert->getEdgesIn()); + $inDegree[$vert->getId()]=$deg; + if($deg==0){ + $stack[]=$vert; + } + } + + while(!(empty($stack))){ + $n = array_pop($stack); + $visited++; + foreach($n->getEdgesOut() as $e){ + $m = $e->getVertexEnd(); + $inDegree[$m->getId()]--; + if($inDegree[$m->getId()]==0){ + $stack[]=$m; + } + } + } + + if($visited==$nVertices){ + return true; + } + else{ + return false; + } + } } diff --git a/tests/Property/PropertyGraphTest.php b/tests/Property/PropertyGraphTest.php index 32e0374..66cc3da 100644 --- a/tests/Property/PropertyGraphTest.php +++ b/tests/Property/PropertyGraphTest.php @@ -14,6 +14,7 @@ public function testEmptyIsEdgeless() $this->assertTrue($alg->isNull()); $this->assertTrue($alg->isEdgeless()); $this->assertFalse($alg->isTrivial()); + $this->assertTrue($alg->isAcyclic()); } public function testSingleVertexIsTrivial() @@ -26,5 +27,50 @@ public function testSingleVertexIsTrivial() $this->assertFalse($alg->isNull()); $this->assertTrue($alg->isEdgeless()); $this->assertTrue($alg->isTrivial()); + $this->assertTrue($alg->isAcyclic()); + } + + public function testUndirectedIsAcyclic() + { + $graph = new Graph(); + $graph->createVertex(1)->createEdge($graph->createVertex(2)); + + $alg = new GraphProperty($graph); + + $this->assertFalse($alg->isNull()); + $this->assertFalse($alg->isEdgeless()); + $this->assertFalse($alg->isTrivial()); + $this->assertFalse($alg->isAcyclic()); + } + + public function testGraphSimpleIsAcyclic() + { + $graph = new Graph(); + $graph->createVertex(1)->createEdgeTo($graph->createVertex(2)); + + $alg = new GraphProperty($graph); + + $this->assertFalse($alg->isNull()); + $this->assertFalse($alg->isEdgeless()); + $this->assertFalse($alg->isTrivial()); + $this->assertTrue($alg->isAcyclic()); + } + + public function testGraphWithCycleIsAcyclic() + { + $graph = new Graph(); + $vertexOne = $graph->createVertex(1); + $vertexTwo = $graph->createVertex(2); + $vertexThree = $graph->createVertex(3); + $vertexOne->createEdgeTo($vertexTwo); + $vertexTwo->createEdgeTo($vertexThree); + $vertexThree->createEdgeTo($vertexOne); + + $alg = new GraphProperty($graph); + + $this->assertFalse($alg->isNull()); + $this->assertFalse($alg->isEdgeless()); + $this->assertFalse($alg->isTrivial()); + $this->assertFalse($alg->isAcyclic()); } } From b2fb6a8fa86e0d69badda9dcd0fb5abbc068c3ff Mon Sep 17 00:00:00 2001 From: Gillu13 Date: Fri, 31 Jan 2020 00:16:47 +0100 Subject: [PATCH 2/2] change array GraphProperty/isAcyclic (PHP 5.3 compliance) --- src/Property/GraphProperty.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Property/GraphProperty.php b/src/Property/GraphProperty.php index eea099a..6132433 100644 --- a/src/Property/GraphProperty.php +++ b/src/Property/GraphProperty.php @@ -61,14 +61,14 @@ public function isAcyclic() $vertices = $this->graph->getVertices(); $nVertices = count($vertices); $visited = 0; - $inDegree = []; - $stack=[]; + $inDegree = array(); + $stack = array(); foreach($vertices as $vert){ $deg=count($vert->getEdgesIn()); $inDegree[$vert->getId()]=$deg; if($deg==0){ - $stack[]=$vert; + \array_push($stack,$vert); } } @@ -79,7 +79,7 @@ public function isAcyclic() $m = $e->getVertexEnd(); $inDegree[$m->getId()]--; if($inDegree[$m->getId()]==0){ - $stack[]=$m; + \array_push($stack,$m); } } }