NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
Packagist · #3634 most downloaded on Packagist
GraPHP is the mathematical graph/network library written in PHP.
Last release 5 years ago
no release in 18 months
Ships unpredictably
gaps range from 2 months to 4.6 years
Nearly every release is documented
notes for 9 of 9 stable releases
Nothing withdrawn
no release was ever pulled
13 years old
9 releases · first in 2013
Feature: Support PHP 8.1 release. ( #208 by @clue )
Feature: Support PHP 8 and PHPUnit 9.3. ( #200 by @SimonFrings )
One column per quarter.
Fix: Deleting vertex with loop edge no longer fails. ( #149 by @tomzx )
Fix: Deleting vertex with loop edge no longer fails.
(#149 by @tomzx)
Fix: Fix returning directed loop edges and adjacent vertices from vertex twice.
(#170 by @clue)
Minor documentation updates and fixes.
(#153 by @marclaporte and #163, #164 and #172 by @clue)
Improve test suite to move tests to Fhaculty\Graph\Tests namespace,
update test suite to support PHPUnit 6 and PHPUnit 5 and
support running on legacy PHP 5.3 through PHP 7.2 and HHVM.
(#148 by @tomzx and #150 and #162 by @clue)
Originally planned to add a new AttributeAware::removeAttribute() method,
but reverted due to BC break. Change will be reconsidered for next major release.
(#138 and #171 by @johnathanmdell and @clue)
BC break: Split off individual components in order to stabilize core graph lib.
Algorithm namespace into separate graphp/algorithms package.Exporter\TrivialGraphFormat into separate graphp/trivial-graph-format package.Loader namespace into separate graphp/plaintext package.Graph and Graph::__toString() (trivial graph format exporter has been split off).src/ and add tests to achieve 100% test coverage.Feature: Add general purpose Attributes.
Graph, Vertex and EdgeBase classes can now benew operator instead of having to useGraph::createVertex() family of methods.Algorithm\Directed::isDirected() to remove its ambiguity| Old name | New name |
|---|---|
Algorithm\Directed::isDirected() |
Algorithm\Directed::hasDirected() |
Algorithm\Directed::hasUndirected() andAlgorithm\Directed::isMixed() in order to complement the renamedAlgorithm\Directed::hasDirected()Walk::factoryCycleFromVertices() no longer tries to auto-completeInvalidArgumentException instead (#87)Walks, i.e. a walk with only a single edge fromAlgorithm\ShortestPath\MooreBellmanFord now also works for unweightedAlgorithm\DetectNegativeCycle didn't workAlgorithm\MinimumCostFlow algorithms now work again. The referencegetVertexFirst(),getVertexSource() and getVertexTarget()| Old name | New name |
|---|---|
Graph::getVertexFirst() |
Graph::getVertices()->getVertexFirst() |
Walk::getVertexSource() |
Walk::getVertices()->getVertexFirst() |
Walk::getVertexTarget() |
Walk::getVertices()->getVertexLast() |
Fix: Throwing an UnexpectedValueException if writing GraphViz Dot script to a temporary file fails and remove its debugging output ( #77 and #78 @Meta
Feature: Add new Set\Vertices and Set\Edges classes that handle common operations on a Set of multiple Vertex and Edge instances respectively.
Set\Vertices and Set\Edges classes that handle commonVertex and Edge instances respectively.| Old name | New name |
|---|---|
Edge\Base::getFirst() |
Set\Edges::getEdgeOrder() |
Edge\Base::getAll() |
Set\Edges::getEdgesOrder() |
Edge\Base::ORDER_* |
Set\Edges::ORDER_* |
| --- | --- |
Vertex::getFirst() |
Set\Vertices::getVertexOrder() |
Vertex::getAll() |
Set\Vertices::getVerticesOrder() |
Vertex::ORDER_ |
Set\Vertices::ORDER_* |
getVertices*() and getEdges*() method now returns a SetSet implements an Iteratorforeach. However, using a SetSet is empty,$set->isEmpty().Vertex::getVertices(), Vertex::getVerticesEdgeTo() andVertex::getVerticesEdgeFrom() now return a Set\Vertices instance thatVertex instances, useVertex::getVertices()->getVerticesDistinct() where applicable.getVerticesId(), usegetVertices()->getIds() instead.Cycle into Walk (#61).| Old name | New name |
|---|---|
Cycle::factoryFromPredecessorMap() |
Walk::factoryCycleFromPredecessorMap() |
Cycle::factoryFromVertices() |
Walk::factoryCycleFromVertices() |
Cycle::factoryFromEdges() |
Walk::factoryCycleFromEdges() |
Graph::isEmpty() because it's not well-defined and mightAlgorithm\Property\GraphProperty::isNull() (old behavior) or (where applicable)Algorithm\Property\GraphProperty::isEdgeless() (#63).Walk::factoryCycleFromPredecessorMap(),Walk::factoryCycleFromVertices(), Walk::factoryCycleFromEdges()) nowWalk instance is actually a valid Cycle,Vertex is the same as the end Vertex (#61)Algorithm\ShortestPath algorithm now consistenly does notAlgorithm\ShortestPath algorithm now consistently throws anOutOfBoundsException for unreachable verticesAlgorithm\Tree\Base::isTree()getNumberOfVertices() andgetNumberOfEdges() (#75 and| Old name | New name |
|---|---|
$set->getNumberOfVertices() |
count($set->getVertices()) |
$set->getNumberOfEdges() |
count($set->getEdges()) |
Set class with Set\DualAggregate interface. ThisAlgorithm\ShortestPath\Base::hasVertex(Vertex $vertex) to check whetherAlgorithm\MinimumSpanningTree\Base::getWeight() to get totalAlgorithm\MinimumSpanningTree algorithm now supportsAlgorithm\MinimumSpanningTree algorithm now throws anUnexpectedValueException for unconnected Graphs (and thus also null Graphs).Walk::factoryFromVertices()Walk::isValid()Algorithm\ShortestPath\MooreBellmanFord::getCycleNegative() from actuallyUnderflowException if no cycle was foundExporter\Image::setFormat() had no effect due to misassignmentBC break: Move algorithm definitions in base classes to separate algorithm classes ( #27 ). The following methods containing algorithms were now moved
| Old name | New name | Related ticket |
|---|---|---|
Set::getWeight() |
Algorithm\Weight::getWeight() |
#33 |
Set::getWeightFlow() |
Algorithm\Weight::getWeightFlow() |
#33 |
Set::getWeightMin() |
Algorithm\Weight::getWeightMin() |
#33 |
Set::isWeighted() |
Algorithm\Weight::isWeighted() |
#33 |
| - | - | - |
Graph::getDegree() |
Algorithm\Degree::getDegree() |
#29 |
Graph::getDegreeMin() |
Algorithm\Degree::getDegreeMin() |
#29 |
Graph::getDegreeMax() |
Algorithm\Degree::getDegreeMax() |
#29 |
Graph::isRegular() |
Algorithm\Degree::isRegular() |
#29 |
Graph::isBalanced() |
Algorithm\Degree::isBalanced() |
#29 |
Vertex::getDegree() |
Algorithm\Degree:getDegreeVertex() |
#49 |
Vertex::getDegreeIn() |
Algorithm\Degree:getDegreeInVertex() |
#49 |
Vertex::getDegreeOut() |
Algorithm\Degree:getDegreeOutVertex() |
#49 |
Vertex::isSink() |
Algorithm\Degree:isVertexSink() |
#49 |
Vertex::isSource() |
Algorithm\Degree:isVertexSource() |
#49 |
Vertex::isIsolated() |
Algorithm\Degree::isVertexIsolated() |
#49 |
| - | - | - |
Set::isDirected() |
Algorithm\Directed::isDirected() |
#34 |
| - | - | - |
Graph::isSymmetric() |
Algorithm\Symmetric::isSymmetric() |
#41 |
| - | - | - |
Graph::isComplete() |
Algorithm\Complete::isComplete() |
#43 |
| - | - | - |
Set::hasFlow() |
Algorithm\Flow::hasFlow() |
#47 |
Graph::getBalance() |
Algorithm\Flow::getBalance() |
#30, #47 |
Graph::isBalancedFlow() |
Algorithm\Flow::isBalancedFlow() |
#30, #47 |
Vertex::getFlow() |
Algorithm\Flow::getFlowVertex() |
#47 |
| - | - | - |
Vertex::isLeaf() |
Algorithm\Tree\Undirected::isVertexLeaf() |
#44 |
| - | - | - |
Set::hasLoop() |
Algorithm\Loop::hasLoop() |
#51 |
Vertex::hasLoop() |
Algorithm\Loop::hasLoopVertex() |
#51 |
| - | - | - |
Set::hasEdgeParallel() |
Algorithm\Parallel::hasEdgeParallel() |
#52 |
Edge\Base::hasEdgeParallel() |
Algorithm\Parallel::hasEdgeParallelEdge() |
#52 |
Edge\Base::getEdgesParallel() |
Algorithm\Parallel::getEdgeParallelEdge() |
#52 |
| - | - | - |
Graph::isEdgeless() |
Algorithm\Property\GraphProperty::isEdgeless() |
#54 |
Graph::isTrivial() |
Algorithm\Property\GraphProperty::isTrivial() |
#54 |
Walk::isCycle() |
Algorithm\Property\WalkProperty::isCycle() |
#54 |
Walk::isPath() |
Algorithm\Property\WalkProperty::isPath() |
#54 |
Walk::hasCycle() |
Algorithm\Property\WalkProperty::hasCycle() |
#54 |
Walk::isLoop() |
Algorithm\Property\WalkProperty::isLoop() |
#54 |
Walk::isDigon() |
Algorithm\Property\WalkProperty::isDigon() |
#54 |
Walk::isTriangle() |
Algorithm\Property\WalkProperty::isTriangle() |
#54 |
Walk::isSimple() |
Algorithm\Property\WalkProperty::isSimple() |
#54 |
Walk::isHamiltonian() |
Algorithm\Property\WalkProperty::isHamiltonian() |
#54 |
Walk::isEulerian() |
Algorithm\Property\WalkProperty::isEulerian() |
#54 |
| Old/removed alias definition | Actual name |
|---|---|
Graph::isConnected() |
Algorithm\ConnectedComponents::isSingle() |
Graph::hasEulerianCycle() |
Algorithm\Eulerian::hasCycle() |
Graph::getNumberOfComponents() |
Algorithm\ConnectedComponents::getNumberOfComponents() |
Graph::getNumberOfGroups() |
Algorithm\Groups::getNumberOfGroups() |
Graph::isBipartit() |
Algorithm\Bipartit::isBipartit() |
Vertex::hasPathTo() |
Algorithm\ShortestPath\BreadthFirst::hasVertex() |
Vertex::hasPathFrom() |
Algorithm\ShortestPath\BreadthFirst::hasVertex() |
Vertex::getVerticesPathTo() |
Algorithm\ShortestPath\BreadthFirst::getVertices() |
Vertex::getVerticesPathFrom() |
Algorithm\ShortestPath\BreadthFirst::getVertices() |
Graph::createVertices() now returns an array of vertices instead of theGraph (#19)Loader\UmlClassDiagram to separate fhaculty/graph-umlAlgorithm\MinimumSpanningTree\PrimWithIfAlgorithm\MinimumSpanningTree\Prim instead)Vertex::createEdgeTo() now returns an instance of typeEdge\Undirected instead of Edge\UndirectedIdEdge\Base::setCapacity() now consistently throws an RangeExceptionInvalidArgumentException if the current flow exceeds the new maximumAlgorithm\Tree namespace with algorithms for undirected and directed,Algorithm\Weight (#33)Algorithm\Degree (#29, #49)Algorithm\Directed (#34)Algorithm\Symmetric (#41)Algorithm\Complete (#43)Algorithm\Flow (#30, #47)Algorithm\Tree (#44)Algorithm\Loop (#51)Algorithm\Parallel (#52)Algorithm\Property (#54)Graph::createVertices() now also accepts an array of vertex IDsAlgorithm\Property\WalkProperty::hasLoop() alias definition forAlgorithm\Property\WalkProperty::isCircuit() definition to distinguishVertex/Edge layout attributesFirst tagged release (See issue #20 for more info on why it starts as v0.5.0)
Your coding agent can read these notes before it upgrades. Set up the MCP server →