Code Coverage |
||||||||||
Classes and Traits |
Functions and Methods |
Lines |
||||||||
Total | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
CRAP | |
100.00% |
30 / 30 |
PowerIteration | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
10 | |
100.00% |
30 / 30 |
getEigenVectorSparse($precision = 0.001) | |
100.00% |
1 / 1 |
10 | |
100.00% |
30 / 30 |
<?php | |
/* | |
* Mondrian | |
*/ | |
namespace Trismegiste\Mondrian\Graph; | |
/** | |
* PowerIteration is a the a decorator for Power Iteration algorithm | |
* | |
* In mathematics, the power iteration is an eigenvalue algorithm: given a | |
* matrix A, the algorithm will produce a number λ (the eigenvalue) and a | |
* nonzero vector v (the eigenvector), such that Av = λv. The algorithm is | |
* also known as the Von Mises iteration.[1] | |
* | |
* http://en.wikipedia.org/wiki/Power_iteration | |
* | |
* In general, there will be many different eigenvalues for which an | |
* eigenvector solution exists. However, the additional requirement that all | |
* the entries in the eigenvector be positive implies (by the Perron–Frobenius | |
* theorem) that only the greatest eigenvalue results in the desired centrality | |
* measure.[12] The component of the related eigenvector then gives the | |
* centrality score of the vertex in the network. Power iteration is one of | |
* many eigenvalue algorithms that may be used to find this | |
* dominant eigenvector. | |
* | |
* http://en.wikipedia.org/wiki/Eigenvector_centrality#Eigenvector_centrality | |
* | |
*/ | |
class PowerIteration extends Algorithm | |
{ | |
/** | |
* Return the dominant eigenvector of the adjacency matrix of | |
* this graph | |
* | |
* @param float $precision | |
* @return \SplObjectStorage | |
*/ | |
public function getEigenVectorSparse($precision = 0.001) | |
{ | |
$vertex = $this->getVertexSet(); | |
$dimension = count($vertex); | |
$approx = new \SplObjectStorage(); | |
foreach ($vertex as $v) { | |
$approx[$v] = 1 / sqrt($dimension); | |
} | |
$iter = 0; | |
do { | |
// result = M . approx | |
$result = new \SplObjectStorage(); | |
foreach ($vertex as $v) { | |
$result[$v] = 0; | |
} | |
foreach ($vertex as $v) { | |
foreach ($this->graph->getSuccessor($v) as $succ) { | |
$result[$v] += $approx[$succ]; // very suspicious | |
// what if we invert $v and $succ, isn't the reversed digraph ? | |
} | |
} | |
// calc the norm | |
$sum = 0; | |
foreach ($result as $v) { | |
$sum += $result->getInfo() * $result->getInfo(); | |
} | |
$norm = sqrt($sum); | |
$delta = 0; | |
// normalize | |
foreach ($result as $v) { | |
$newVal = ($norm > 0) ? $result->getInfo() / $norm : 0; | |
$delta += abs($newVal - $approx[$v]); | |
$approx[$v] = $newVal; | |
} | |
$iter++; | |
} while (($delta > $precision) && ($iter < (2 * $dimension))); | |
return array('value' => $norm, 'vector' => $approx); | |
} | |
} |