Skip to content

Commit d1a743b

Browse files
committed
Merge remote-tracking branch 'origin/master' into add-vertices-class
2 parents 5a149fb + 5af09b6 commit d1a743b

14 files changed

+1262
-90
lines changed

src/Balance.php

Lines changed: 0 additions & 59 deletions
This file was deleted.

src/Flow.php

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
<?php
2+
3+
namespace Fhaculty\Graph\Algorithm;
4+
5+
use Fhaculty\Graph\Algorithm\BaseGraph;
6+
use Fhaculty\Graph\Edge\Base as Edge;
7+
use Fhaculty\Graph\Edge\Directed as EdgeDirected;
8+
use Fhaculty\Graph\Exception\UnexpectedValueException;
9+
use Fhaculty\Graph\Graph;
10+
use Fhaculty\Graph\Vertex;
11+
12+
/**
13+
* Basic algorithms for working with flow graphs
14+
*
15+
* A flow network (also known as a transportation network) is a directed graph
16+
* where each edge has a capacity and each edge receives a flow.
17+
*
18+
* @link http://en.wikipedia.org/wiki/Flow_network
19+
* @see Algorithm\Balance
20+
*/
21+
class Flow extends BaseSet
22+
{
23+
/**
24+
* check if this graph has any flow set (any edge has a non-NULL flow)
25+
*
26+
* @return boolean
27+
* @uses Edge::getFlow()
28+
*/
29+
public function hasFlow()
30+
{
31+
foreach ($this->set->getEdges() as $edge) {
32+
if ($edge->getFlow() !== NULL) {
33+
return true;
34+
}
35+
}
36+
37+
return false;
38+
}
39+
40+
/**
41+
* Calculates the flow for this Vertex: sum(outflow) - sum(inflow)
42+
*
43+
* Usually, vertices should have a resulting flow of 0: The sum of flows
44+
* entering a vertex must equal the sum of flows leaving a vertex. If the
45+
* resulting flow is < 0, this vertex is considered a sink (i.e. there's
46+
* more flow into this vertex). If the resulting flow is > 0, this vertex
47+
* is considered a "source" (i.e. there's more flow leaving this vertex).
48+
*
49+
* @param Vertex $vertex
50+
* @return float
51+
* @throws UnexpectedValueException if they are undirected edges
52+
* @see Vertex::getBalance()
53+
* @uses Vertex::getEdges()
54+
* @uses Edge::getFlow()
55+
*/
56+
public function getFlowVertex(Vertex $vertex)
57+
{
58+
$sumOfFlow = 0;
59+
60+
foreach ($vertex->getEdges() as $edge) {
61+
if (!($edge instanceof EdgeDirected)) {
62+
throw new UnexpectedValueException("TODO: undirected edges not suported yet");
63+
}
64+
65+
// edge is an outgoing edge of this vertex
66+
if ($edge->hasVertexStart($vertex)) {
67+
// flowing out (flow is "pointing away")
68+
$sumOfFlow += $edge->getFlow();
69+
// this is an ingoing edge
70+
} else {
71+
// flowing in
72+
$sumOfFlow -= $edge->getFlow();
73+
}
74+
}
75+
76+
return $sumOfFlow;
77+
}
78+
79+
public function getBalance()
80+
{
81+
$balance = 0;
82+
// Sum for all vertices of value
83+
foreach ($this->set->getVertices() as $vertex) {
84+
$balance += $vertex->getBalance();
85+
}
86+
87+
return $balance;
88+
}
89+
90+
/**
91+
* check if the current flow is balanced (aka "balanced flow" or "b-flow")
92+
*
93+
* a flow is considered balanced if each edge's current flow does not exceed its
94+
* maximum capacity (which is always guaranteed due to the implementation
95+
* of Edge::setFlow()) and each vertices' flow (i.e. outflow-inflow) equals
96+
* its balance.
97+
*
98+
* checking whether the FLOW is balanced is not to be confused with checking
99+
* whether the GRAPH is balanced (see Graph::isBalanced() instead)
100+
*
101+
* @return boolean
102+
* @see Algorithm\Degree::isBalanced() if you merely want to check indegree=outdegree
103+
* @uses self::getFlowVertex()
104+
* @uses Vertex::getBalance()
105+
*/
106+
public function isBalancedFlow()
107+
{
108+
// no need to check for each edge: flow <= capacity (setters already check that)
109+
// check for each vertex: outflow-inflow = balance
110+
foreach ($this->set->getVertices() as $vertex) {
111+
if ($this->getFlowVertex($vertex) !== $vertex->getBalance()) {
112+
return false;
113+
}
114+
}
115+
116+
return true;
117+
}
118+
}

src/MinimumCostFlow/SuccessiveShortestPath.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
class SuccessiveShortestPath extends Base
2020
{
2121
/**
22-
* @uses Vertex::getFlow()
2322
* @uses Graph::createGraphClone()
2423
* @uses AlgorithmResidualGraph::createGraph()
2524
* @uses AlgorithmSpMooreBellmanFord::getEdgesTo(Vertex $targetVertex)

src/Tree/Base.php

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
<?php
2+
3+
namespace Fhaculty\Graph\Algorithm\Tree;
4+
5+
use Fhaculty\Graph\Algorithm\BaseGraph;
6+
use Fhaculty\Graph\Graph;
7+
use Fhaculty\Graph\Vertex;
8+
use Fhaculty\Graph\Exception\UnderflowException;
9+
use Fhaculty\Graph\Exception\UnexpectedValueException;
10+
use Fhaculty\Graph\Algorithm\Search\StrictDepthFirst;
11+
12+
/**
13+
* Abstract base class for tree algorithms
14+
*
15+
* This abstract base class provides the base interface for working with
16+
* graphs that represent a tree.
17+
*
18+
* A tree is a connected Graph (single component) with no cycles. Every Tree is
19+
* a Graph, but not every Graph is a Tree.
20+
*
21+
* A
22+
* / \
23+
* B C
24+
* / \
25+
* D E
26+
*
27+
* Special cases are undirected trees (like the one pictured above), handled via
28+
* Tree\Undirected and directed, rooted trees (InTree and OutTree), handled via
29+
* Tree\BaseDirected.
30+
*
31+
* @link http://en.wikipedia.org/wiki/Tree_%28graph_theory%29
32+
* @link http://en.wikipedia.org/wiki/Tree_%28data_structure%29
33+
* @see Undirected for an implementation of these algorithms on (undirected) trees
34+
* @see BaseDirected for an abstract implementation of these algorithms on directed, rooted trees
35+
*/
36+
abstract class Base extends BaseGraph
37+
{
38+
/**
39+
* checks whether the given graph is actually a tree
40+
*
41+
* @return boolean
42+
*/
43+
abstract public function isTree();
44+
45+
/**
46+
* checks if the given $vertex is a leaf (outermost vertext)
47+
*
48+
* leaf vertex is also known as leaf node, external node or terminal node
49+
*
50+
* @param Vertex $vertex
51+
* @return boolean
52+
*/
53+
abstract public function isVertexLeaf(Vertex $vertex);
54+
55+
/**
56+
* checks if the given $vertex is an internal vertex (somewhere in the "middle" of the tree)
57+
*
58+
* internal vertex is also known as inner node (inode) or branch node
59+
*
60+
* @param Vertex $vertex
61+
* @return boolean
62+
*/
63+
abstract public function isVertexInternal(Vertex $vertex);
64+
65+
/**
66+
* get array of leaf vertices (outermost vertices with no children)
67+
*
68+
* @return Vertex[]
69+
* @uses Graph::getVertices()
70+
* @uses self::isVertexLeaf()
71+
*/
72+
public function getVerticesLeaf()
73+
{
74+
return array_filter($this->graph->getVertices(), array($this, 'isVertexLeaf'));
75+
}
76+
77+
/**
78+
* get array of internal vertices
79+
*
80+
* @return Vertex[]
81+
* @uses Graph::getVertices()
82+
* @uses self::isVertexInternal()
83+
*/
84+
public function getVerticesInternal()
85+
{
86+
return array_filter($this->graph->getVertices(), array($this, 'isVertexInternal'));
87+
}
88+
}

0 commit comments

Comments
 (0)