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); | |
| } | |
| } |