Skip to content

Commit dc35774

Browse files
committed
Merge branch 'master' into add-extend
Conflicts: lib/Fhaculty/Graph/Graph.php
2 parents 7791f64 + 23985a2 commit dc35774

20 files changed

Lines changed: 481 additions & 104 deletions

CHANGELOG.md

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,46 @@ you spot any mistakes.
66

77
## 0.8.0 (2013-xx-xx)
88

9+
* BC break: Rename `Algorithm\Directed::isDirected()` to remove its ambiguity
10+
in regards to mixed and/or empty graphs
11+
([#80](https://github.com/clue/graph/issues/80))
12+
13+
| Old name | New name |
14+
|---|---|
15+
| `Algorithm\Directed::isDirected()` | `Algorithm\Directed::hasDirected()` |
16+
17+
* Feature:: Add new `Algorithm\Directed::hasUndirected()` and
18+
`Algorithm\Directed::isMixed()` in order to complement the renamed
19+
`Algorithm\Directed::hasDirected()`
20+
([#80](https://github.com/clue/graph/issues/80))
21+
22+
* BC break: `Walk::factoryCycleFromVertices()` no longer tries to auto-complete
23+
a cycle if the first vertex does not match the last one, but now throws an
24+
`InvalidArgumentException` instead ([#87](https://github.com/clue/graph/issues/87)
25+
26+
* Feature: Support loop `Walk`s, i.e. a walk with only a single edge from
27+
vertex A back to A ([#87](https://github.com/clue/graph/issues/87)
28+
29+
* Fix: Stricter checks for invalid cycles, such as one with an invalid
30+
predecessor-map or no edges at all ([#87](https://github.com/clue/graph/issues/87)
31+
32+
* Fix: The `Algorithm\ShortestPath\MooreBellmanFord` now also works for unweighted
33+
edges. This also fixes an issue where `Algorithm\DetectNegativeCycle` didn't work
34+
for unweighted edges. ([#81](https://github.com/clue/graph/issues/81)
35+
936
* Fix: Throwing an `UnexpectedValueException` if writing GraphViz Dot script
1037
to a temporary file fails and remove its debugging output
1138
([#77](https://github.com/clue/graph/issues/77) and [#78](https://github.com/clue/graph/issues/78) @Metabor)
39+
40+
* BC break: Remove unneeded alias definitions of `getVertexFirst()`,
41+
`getVertexSource()` and `getVertexTarget()`
42+
[#76]https://github.com/clue/graph/issues/76)):
43+
44+
| Old name | New name |
45+
|---|---|
46+
| `Graph::getVertexFirst()` | `Graph::getVertices()->getVertexFirst()` |
47+
| `Walk::getVertexSource()` | `Walk::getVertices()->getVertexFirst()` |
48+
| `Walk::getVertexTarget()` | `Walk::getVertices()->getVertexLast()` |
1249

1350
## 0.7.0 (2013-09-11)
1451

lib/Fhaculty/Graph/Algorithm/ConnectedComponents.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ private function createSearch(Vertex $vertex)
7070
public function isSingle()
7171
{
7272
try {
73-
$vertex = $this->graph->getVertexFirst();
73+
$vertex = $this->graph->getVertices()->getVertexFirst();
7474
}
7575
catch (UnderflowException $e) {
7676
// no first vertex => empty graph => has zero components

lib/Fhaculty/Graph/Algorithm/Degree.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ class Degree extends BaseGraph
3131
public function getDegree()
3232
{
3333
// get initial degree of any start vertex to compare others to
34-
$degree = $this->getDegreeVertex($this->graph->getVertexFirst());
34+
$degree = $this->getDegreeVertex($this->graph->getVertices()->getVertexFirst());
3535

3636
foreach ($this->graph->getVertices() as $vertex) {
3737
/** @var $vertex Vertex */

lib/Fhaculty/Graph/Algorithm/Directed.php

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use Fhaculty\Graph\Algorithm\BaseGraph;
66
use Fhaculty\Graph\Edge\Directed as EdgeDirected;
7+
use Fhaculty\Graph\Edge\Undirected as EdgeUndirected;
78

89
/**
910
* Basic algorithms for working with the undirected or directed Graphs (digraphs) / Walks.
@@ -14,11 +15,14 @@
1415
class Directed extends BaseDual
1516
{
1617
/**
17-
* checks whether the graph has any directed edges (aka digraph)
18+
* checks whether the graph has any directed edges
19+
*
20+
* This method is intentionally not named "isDirected()" (aka digraph),
21+
* because that might be misleading in regards to empty and/or mixed graphs.
1822
*
1923
* @return boolean
2024
*/
21-
public function isDirected()
25+
public function hasDirected()
2226
{
2327
foreach ($this->set->getEdges() as $edge) {
2428
if ($edge instanceof EdgeDirected) {
@@ -28,4 +32,35 @@ public function isDirected()
2832

2933
return false;
3034
}
35+
36+
/**
37+
* checks whether the graph has any undirected edges
38+
*
39+
* This method is intentionally not named "isUndirected()",
40+
* because that might be misleading in regards to empty and/or mixed graphs.
41+
*
42+
* @return boolean
43+
*/
44+
public function hasUndirected()
45+
{
46+
foreach ($this->set->getEdges() as $edge) {
47+
if ($edge instanceof EdgeUndirected) {
48+
return true;
49+
}
50+
}
51+
52+
return false;
53+
}
54+
55+
/**
56+
* checks whether this is a mixed graph (contains both directed and undirected edges)
57+
*
58+
* @return boolean
59+
* @uses self::hasDirected()
60+
* @uses self::hasUndirected()
61+
*/
62+
public function isMixed()
63+
{
64+
return ($this->hasDirected() && $this->hasUndirected());
65+
}
3166
}

lib/Fhaculty/Graph/Algorithm/MaximumMatching/Flow.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ class Flow extends Base
1818
public function getEdges()
1919
{
2020
$alg = new Directed($this->graph);
21-
if ($alg->isDirected()) {
21+
if ($alg->hasDirected()) {
2222
throw new UnexpectedValueException('Input graph contains directed edges');
2323
}
2424

lib/Fhaculty/Graph/Algorithm/ShortestPath/MooreBellmanFord.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ private function bigStep(Edges $edges, array &$totalCostOfCheapestPathTo, array
4343
// New possible costs of this path
4444
$newCost = $totalCostOfCheapestPathTo[$fromVertex->getId()] + $edge->getWeight();
4545
if (is_infinite($newCost)) {
46-
$newCost = $edge->getWeight();
46+
$newCost = $edge->getWeight() + 0;
4747
}
4848

4949
// No path has been found yet

lib/Fhaculty/Graph/Algorithm/TravelingSalesmanProblem/Bruteforce.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,8 @@ public function setUpperLimitMst()
9292

9393
protected function getVertexStart()
9494
{
95-
return $this->graph->getVertexFirst();
95+
// actual start doesn't really matter as we're only considering complete graphs here
96+
return $this->graph->getVertices()->getVertexFirst();
9697
}
9798

9899
protected function getGraph()
@@ -116,8 +117,7 @@ public function getEdges()
116117
// numEdges 3-12 should work
117118

118119
$this->bestWeight = $this->upperLimit;
119-
// actual start doesn't really matter as we're only considering complete graphs here
120-
$this->startVertex = $this->graph->getVertexFirst();
120+
$this->startVertex = $this->getVertexStart();
121121

122122
$result = $this->step($this->startVertex,
123123
0,

lib/Fhaculty/Graph/Algorithm/TravelingSalesmanProblem/MinimumSpanningTree.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ public function __construct(Graph $inputGraph)
2323

2424
protected function getVertexStart()
2525
{
26-
return $this->graph->getVertexFirst();
26+
return $this->graph->getVertices()->getVertexFirst();
2727
}
2828

2929
protected function getGraph()
@@ -43,7 +43,7 @@ public function getEdges()
4343
$minimumSpanningTreeAlgorithm = new MstKruskal($this->graph);
4444
$minimumSpanningTree = $minimumSpanningTreeAlgorithm->createGraph();
4545

46-
$alg = new SearchDepthFirst($minimumSpanningTree->getVertexFirst());
46+
$alg = new SearchDepthFirst($minimumSpanningTree->getVertices()->getVertexFirst());
4747
// Depth first search in minmum spanning tree (for the eulerian path)
4848

4949
$startVertex = NULL;

lib/Fhaculty/Graph/Algorithm/Tree/Undirected.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ class Undirected extends Tree
5050
*
5151
* @return boolean
5252
* @uses Vertices::isEmpty() to skip null Graphs (a Graph with no Vertices is *NOT* a valid tree)
53-
* @uses Graph::getVertexFirst() to get get get random "root" Vertex to start search from
53+
* @uses Vertices::getVertexFirst() to get get get random "root" Vertex to start search from
5454
* @uses self::getVerticesSubtreeRecursive() to count number of vertices connected to root
5555
*/
5656
public function isTree()
@@ -60,7 +60,7 @@ public function isTree()
6060
}
6161

6262
// every vertex can represent a root vertex, so just pick one
63-
$root = $this->graph->getVertexFirst();
63+
$root = $this->graph->getVertices()->getVertexFirst();
6464

6565
$vertices = array();
6666
try {

lib/Fhaculty/Graph/Graph.php

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -324,23 +324,6 @@ public function hasVertex($id)
324324
return $this->vertices->hasVertexId($id);
325325
}
326326

327-
/**
328-
* return first vertex found
329-
*
330-
* some algorithms do not need a particular vertex, but merely a (random)
331-
* starting point. this is a convenience function to just pick the first
332-
* vertex from the list of known vertices.
333-
*
334-
* @return Vertex first vertex found in this graph
335-
* @throws UnderflowException if Graph has no vertices
336-
* @see Vertices::getVertexOrder() if you need to apply ordering first
337-
* @uses Vertices::getVertexFirst()
338-
*/
339-
public function getVertexFirst()
340-
{
341-
return $this->vertices->getVertexFirst();
342-
}
343-
344327
/**
345328
* adds a new Vertex to the Graph (MUST NOT be called manually!)
346329
*

0 commit comments

Comments
 (0)