diff --git a/src/Set/Edges.php b/src/Set/Edges.php index dd90ac0a..37ba8dc5 100644 --- a/src/Set/Edges.php +++ b/src/Set/Edges.php @@ -3,7 +3,6 @@ namespace Graphp\Graph\Set; use Graphp\Graph\Edge; -use Graphp\Graph\Exception\InvalidArgumentException; use Graphp\Graph\Exception\OutOfBoundsException; use Graphp\Graph\Exception\UnderflowException; @@ -18,38 +17,6 @@ */ class Edges implements \Countable, \IteratorAggregate, EdgesAggregate { - /** - * order by edge weight - * - * @var int - * @see Edge::getWeight() - */ - const ORDER_WEIGHT = 1; - - /** - * order by edge capacity - * - * @var int - * @see Edge::getCapacity() - */ - const ORDER_CAPACITY = 2; - - /** - * order by remaining capacity on edge (maximum capacity - current flow) - * - * @var int - * @see Edge::getCapacityRemaining() - */ - const ORDER_CAPACITY_REMAINING = 3; - - /** - * order by edge flow - * - * @var int - * @see Edge::getFlow() - */ - const ORDER_FLOW = 4; - protected $edges = array(); /** @@ -237,10 +204,9 @@ public function getEdgesMatch($callbackCheck) * * Edge index positions will be left unchanged. * - * @param string|int $orderBy criterium to sort by. see edge attribute names or self::ORDER_WEIGHT, etc. - * @param bool $desc whether to return biggest first (true) instead of smallest first (default:false) - * @return Edges a new Edges set ordered by the given $orderBy criterium - * @throws InvalidArgumentException if criterium is unknown + * @param string|callable(Edge):number $orderBy criterium to sort by. see edge attribute names or custom callable + * @param bool $desc whether to return biggest first (true) instead of smallest first (default:false) + * @return Edges a new Edges set ordered by the given $orderBy criterium */ public function getEdgesOrder($orderBy, $desc = false) { @@ -291,11 +257,10 @@ public function getEdgesShuffled() /** * get first edge ordered by given criterium $orderBy * - * @param string|int $orderBy criterium to sort by. see edge attribute names or self::ORDER_WEIGHT, etc. - * @param bool $desc whether to return biggest (true) instead of smallest (default:false) + * @param string|callable(Edge):number $orderBy criterium to sort by. see edge attribute names or custom callable + * @param bool $desc whether to return biggest (true) instead of smallest (default:false) * @return Edge - * @throws InvalidArgumentException if criterium is unknown - * @throws UnderflowException if no edges exist + * @throws UnderflowException if no edges exist */ public function getEdgeOrder($orderBy, $desc=false) { @@ -431,17 +396,14 @@ public function getIterator() /** * call given $callback on each Edge and sum their results * - * @param callable $callback + * @param string|callable(Edge):number $callback callback to sum by. See edge attribute names or custom callback * @return number - * @throws InvalidArgumentException for invalid callbacks * @uses self::getCallback() */ public function getSumCallback($callback) { $callback = $this->getCallback($callback); - // return array_sum(array_map($callback, $this->edges)); - $sum = 0; foreach ($this->edges as $edge) { $sum += $callback($edge); @@ -464,9 +426,8 @@ private function getEdgeMatchOrNull($callbackCheck) /** * get callback/Closure to be called on Edge instances for given callback identifier * - * @param callable|string|int $callback - * @throws InvalidArgumentException - * @return callable + * @param string|callable(Edge):number $callback + * @return callable(Edge):number */ private function getCallback($callback) { @@ -479,27 +440,9 @@ private function getCallback($callback) return $callback; } - if (is_string($callback)) { - return function (Edge $edge) use ($callback) { - return $edge->getAttribute($callback); - }; - } - - static $methods = array( - self::ORDER_WEIGHT => 'getWeight', - self::ORDER_CAPACITY => 'getCapacity', - self::ORDER_CAPACITY_REMAINING => 'getCapacityRemaining', - self::ORDER_FLOW => 'getFlow' - ); - - if (!is_int($callback) || !isset($methods[$callback])) { - throw new InvalidArgumentException('Invalid callback given'); - } - - $method = $methods[$callback]; - - return function (Edge $edge) use ($method) { - return $edge->$method(); + return function (Edge $edge) use ($callback) { + return $edge->getAttribute($callback); }; + } } diff --git a/src/Set/Vertices.php b/src/Set/Vertices.php index 3e1a583b..bc40c9de 100644 --- a/src/Set/Vertices.php +++ b/src/Set/Vertices.php @@ -3,7 +3,6 @@ namespace Graphp\Graph\Set; use Graphp\Graph\Vertex; -use Graphp\Graph\Exception\InvalidArgumentException; use Graphp\Graph\Exception\OutOfBoundsException; use Graphp\Graph\Exception\UnderflowException; @@ -18,22 +17,6 @@ */ class Vertices implements \Countable, \IteratorAggregate, VerticesAggregate { - /** - * order by vertex ID - * - * @var int - * @see Vertex::getId() - */ - const ORDER_ID = 1; - - /** - * order by vertex group - * - * @var int - * @see Vertex::getGroup() - */ - const ORDER_GROUP = 6; - protected $vertices = array(); /** @@ -241,10 +224,9 @@ public function getVerticesMatch($callbackCheck) * Vertex index positions will be left unchanged, so if you call this method * on a VerticesMap, it will also return a VerticesMap. * - * @param string|int $orderBy criterium to sort by. see vertex attribute names or Vertex::ORDER_ID, etc. - * @param bool $desc whether to return biggest first (true) instead of smallest first (default:false) - * @return Vertices a new Vertices set ordered by the given $orderBy criterium - * @throws InvalidArgumentException if criterium is unknown + * @param string|callable(Vertex):number $orderBy criterium to sort by. see vertex attribute names or custom callback + * @param bool $desc whether to return biggest first (true) instead of smallest first (default:false) + * @return Vertices a new Vertices set ordered by the given $orderBy criterium * @see self::getVertexOrder() */ public function getVerticesOrder($orderBy, $desc = false) @@ -329,11 +311,10 @@ public function getVerticesIntersection($otherVertices) /** * get first vertex (optionally ordered by given criterium $by) from given array of vertices * - * @param string|int $orderBy criterium to sort by. see vertex attribute names or Vertex::ORDER_ID, etc. - * @param bool $desc whether to return biggest (true) instead of smallest (default:false) + * @param string|callable(Vertex):number $orderBy criterium to sort by. see vertex attribute names custom callback + * @param bool $desc whether to return biggest (true) instead of smallest (default:false) * @return Vertex - * @throws InvalidArgumentException if criterium is unknown - * @throws UnderflowException if no vertices exist + * @throws UnderflowException if no vertices exist * @see self::getVerticesOrder() */ public function getVertexOrder($orderBy, $desc=false) @@ -470,17 +451,14 @@ public function getIterator() /** * call given $callback on each Vertex and sum their results * - * @param callable $callback + * @param string|callable(Vertex):number $callback callback to sum by. See vertex attribute names or custom callback * @return number - * @throws InvalidArgumentException for invalid callbacks * @uses self::getCallback() */ public function getSumCallback($callback) { $callback = $this->getCallback($callback); - // return array_sum(array_map($callback, $this->vertices)); - $sum = 0; foreach ($this->vertices as $vertex) { $sum += $callback($vertex); @@ -510,9 +488,8 @@ private function getVertexMatchOrNull($callbackCheck) /** * get callback/Closure to be called on Vertex instances for given callback identifier * - * @param callable|string|int $callback - * @throws InvalidArgumentException - * @return callable + * @param string|callable(Vertex):number $callback + * @return callable(Vertex):number */ private function getCallback($callback) { @@ -525,25 +502,8 @@ private function getCallback($callback) return $callback; } - if (is_string($callback)) { - return function (Vertex $vertex) use ($callback) { - return $vertex->getAttribute($callback); - }; - } - - static $methods = array( - self::ORDER_ID => 'getId', - self::ORDER_GROUP => 'getGroup' - ); - - if (!is_int($callback) || !isset($methods[$callback])) { - throw new InvalidArgumentException('Invalid callback given'); - } - - $method = $methods[$callback]; - - return function (Vertex $vertex) use ($method) { - return $vertex->$method(); + return function (Vertex $vertex) use ($callback) { + return $vertex->getAttribute($callback); }; } } diff --git a/src/Walk.php b/src/Walk.php index e29d19f1..4a21746d 100644 --- a/src/Walk.php +++ b/src/Walk.php @@ -42,11 +42,11 @@ public static function factoryFromEdges($edges, Vertex $startVertex) /** * create new walk instance between given set of Vertices / array of Vertex instances * - * @param Vertices|Vertex[] $vertices - * @param null|string|null $orderBy - * @param bool $desc + * @param Vertices|Vertex[] $vertices + * @param null|string|callable(Edge):number $orderBy + * @param bool $desc * @return Walk - * @throws UnderflowException if no vertices were given + * @throws UnderflowException if no vertices were given * @see Edges::getEdgeOrder() for parameters $by and $desc */ public static function factoryFromVertices($vertices, $orderBy = null, $desc = false) @@ -76,10 +76,10 @@ public static function factoryFromVertices($vertices, $orderBy = null, $desc = f /** * create new cycle instance from given predecessor map * - * @param Vertex[] $predecessors map of vid => predecessor vertex instance - * @param Vertex $vertex start vertex to search predecessors from - * @param null|string|int $orderBy - * @param bool $desc + * @param Vertex[] $predecessors map of vid => predecessor vertex instance + * @param Vertex $vertex start vertex to search predecessors from + * @param null|string|callable(Edge):number $orderBy + * @param bool $desc * @return Walk * @throws UnderflowException * @see Edges::getEdgeOrder() for parameters $by and $desc @@ -127,11 +127,11 @@ public static function factoryCycleFromPredecessorMap(array $predecessors, Verte /** * create new cycle instance with edges between given vertices * - * @param Vertex[]|Vertices $vertices - * @param null|string|int $orderBy - * @param bool $desc + * @param Vertex[]|Vertices $vertices + * @param null|string|callable(Edge):number $orderBy + * @param bool $desc * @return Walk - * @throws UnderflowException if no vertices were given + * @throws UnderflowException if no vertices were given * @see Edges::getEdgeOrder() for parameters $by and $desc * @uses self::factoryFromVertices() */ diff --git a/tests/Set/BaseVerticesTest.php b/tests/Set/BaseVerticesTest.php index 3130cfd2..4525eb00 100644 --- a/tests/Set/BaseVerticesTest.php +++ b/tests/Set/BaseVerticesTest.php @@ -40,7 +40,9 @@ public function testEmpty() $this->assertEquals(array(), $vertices->getVector()); $this->assertTrue($vertices->isEmpty()); $this->assertTrue($vertices->getVertices()->isEmpty()); - $this->assertTrue($vertices->getVerticesOrder(Vertices::ORDER_ID)->isEmpty()); + $this->assertTrue($vertices->getVerticesOrder(function (Vertex $vertex) { + return $vertex->getId(); + })->isEmpty()); $this->assertTrue($vertices->getVerticesOrder('id')->isEmpty()); $this->assertTrue($vertices->getVerticesDistinct()->isEmpty()); $this->assertTrue($vertices->getVerticesMatch(function() { })->isEmpty()); @@ -90,7 +92,7 @@ public function testEmptyDoesNotHaveRandom(Vertices $vertices) */ public function testEmptyDoesNotHaveOrdered(Vertices $vertices) { - $vertices->getVertexOrder(Vertices::ORDER_ID); + $vertices->getVertexOrder('group'); } public function testTwo() @@ -227,14 +229,18 @@ public function testOrderByGroup() $biggest = $graph->createVertex()->setGroup(200); $vertices = $graph->getVertices(); - $verticesOrdered = $vertices->getVerticesOrder(Vertices::ORDER_GROUP); + $verticesOrdered = $vertices->getVerticesOrder(function (Vertex $vertex) { + return $vertex->getGroup(); + }); $this->assertInstanceOf('Graphp\Graph\Set\Vertices', $verticesOrdered); $this->assertEquals(1, $verticesOrdered->getVertexFirst()->getGroup()); $this->assertEquals(200, $verticesOrdered->getVertexLast()->getGroup()); $this->assertSame($biggest, $verticesOrdered->getVertexLast()); - $this->assertSame($biggest, $vertices->getVertexOrder(Vertices::ORDER_GROUP, true)); + $this->assertSame($biggest, $vertices->getVertexOrder(function (Vertex $vertex) { + return $vertex->getGroup(); + }, true)); $sumgroups = function(Vertex $vertex) { return $vertex->getGroup(); diff --git a/tests/Set/EdgesTest.php b/tests/Set/EdgesTest.php index 65e90506..c4f03b5d 100644 --- a/tests/Set/EdgesTest.php +++ b/tests/Set/EdgesTest.php @@ -12,7 +12,7 @@ class EdgesTest extends TestCase /** * * @param array $edges - * @return Edges; + * @return Edges */ protected function createEdges(array $edges) { @@ -43,7 +43,9 @@ public function testEmpty() $this->assertEquals(array(), $edges->getVector()); $this->assertTrue($edges->isEmpty()); $this->assertTrue($edges->getEdges()->isEmpty()); - $this->assertTrue($edges->getEdgesOrder(Edges::ORDER_WEIGHT)->isEmpty()); + $this->assertTrue($edges->getEdgesOrder(function (Edge $edge) { + return $edge->getWeight(); + })->isEmpty()); $this->assertTrue($edges->getEdgesOrder('weight')->isEmpty()); $this->assertTrue($edges->getEdgesDistinct()->isEmpty()); $this->assertTrue($edges->getEdgesMatch(function() { })->isEmpty()); @@ -92,7 +94,7 @@ public function testEmptyDoesNotHaveRandom(Edges $edges) */ public function testEmptyDoesNotHaveOrdered(Edges $edges) { - $edges->getEdgeOrder(Edges::ORDER_WEIGHT); + $edges->getEdgeOrder('weight'); } public function testTwo() @@ -244,31 +246,6 @@ public function returnFalse(Edge $edge) return false; } - /** - * @expectedException InvalidArgumentException - */ - public function testGetEdgeOrderInvalidSortBy() - { - // 1 -> 1 - $graph = new Graph(); - $v1 = $graph->createVertex(1); - $graph->createEdgeDirected($v1, $v1); - - $edges = $graph->getEdges(); - - $edges->getEdgeOrder(-2); - } - - /** - * @expectedException InvalidArgumentException - */ - public function testGetEdgesOrderInvalidSortBy() - { - $edges = $this->createEdges(array()); - - $edges->getEdgesOrder(-2); - } - public function testOrderByGroup() { $graph = new Graph(); @@ -283,14 +260,18 @@ public function testOrderByGroup() $biggest = $graph->createEdgeUndirected($v1, $v2)->setWeight(200); $edges = $graph->getEdges(); - $edgesOrdered = $edges->getEdgesOrder(Edges::ORDER_WEIGHT); + $edgesOrdered = $edges->getEdgesOrder(function (Edge $edge) { + return $edge->getWeight(); + }); $this->assertInstanceOf('Graphp\Graph\Set\Edges', $edgesOrdered); $this->assertEquals(1, $edgesOrdered->getEdgeFirst()->getWeight()); $this->assertEquals(200, $edgesOrdered->getEdgeLast()->getWeight()); $this->assertSame($biggest, $edgesOrdered->getEdgeLast()); - $this->assertSame($biggest, $edges->getEdgeOrder(Edges::ORDER_WEIGHT, true)); + $this->assertSame($biggest, $edges->getEdgeOrder(function (Edge $edge) { + return $edge->getWeight(); + }, true)); $sumweights = function(Edge $edge) { return $edge->getWeight(); diff --git a/tests/Set/VerticesTest.php b/tests/Set/VerticesTest.php index ccca740b..21e5c047 100644 --- a/tests/Set/VerticesTest.php +++ b/tests/Set/VerticesTest.php @@ -20,29 +20,6 @@ public function testFactoryEmptyArray() $this->assertTrue($vertices->isEmpty()); } - /** - * @expectedException InvalidArgumentException - */ - public function testGetVertexOrderInvalidSortBy() - { - $graph = new Graph(); - $graph->createVertex(1); - - $vertices = $graph->getVertices(); - - $vertices->getVertexOrder(-1); - } - - /** - * @expectedException InvalidArgumentException - */ - public function testGetVicesOrderInvalidSortBy() - { - $vertices = $this->createVertices(array()); - - $vertices->getVerticesOrder(-1); - } - public function testDuplicates() { $graph = new Graph(); diff --git a/tests/WalkTest.php b/tests/WalkTest.php index 5035451f..50a8436f 100644 --- a/tests/WalkTest.php +++ b/tests/WalkTest.php @@ -3,8 +3,7 @@ namespace Graphp\Graph\Tests; use Graphp\Graph\Graph; -use Graphp\Graph\Set\Edges; -use Graphp\Graph\Vertex; +use Graphp\Graph\Edge; use Graphp\Graph\Walk; class WalkTest extends TestCase @@ -252,7 +251,9 @@ public function testFactoryFromVertices() $walk = Walk::factoryFromVertices(array($v1, $v2)); // edge with weight 10 - $walk = Walk::factoryFromVertices(array($v1, $v2), Edges::ORDER_WEIGHT); + $walk = Walk::factoryFromVertices(array($v1, $v2), function (Edge $edge) { + return $edge->getWeight(); + }); $this->assertSame($e1, $walk->getEdges()->getEdgeFirst()); // edge with weight 10 @@ -260,7 +261,9 @@ public function testFactoryFromVertices() $this->assertSame($e1, $walk->getEdges()->getEdgeFirst()); // edge with weight 20 - $walk = Walk::factoryFromVertices(array($v1, $v2), Edges::ORDER_WEIGHT, true); + $walk = Walk::factoryFromVertices(array($v1, $v2), function (Edge $edge) { + return $edge->getWeight(); + }, true); $this->assertSame($e2, $walk->getEdges()->getEdgeFirst()); // edge with weight 20