Completed
Push — master ( d67164...411d0d )
by Pierre
03:21
created

Floydwarshall   A

Complexity

Total Complexity 17

Size/Duplication

Total Lines 131
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 38
c 1
b 0
f 0
dl 0
loc 131
ccs 35
cts 35
cp 1
rs 10
wmc 17

6 Methods

Rating   Name   Duplication   Size   Complexity  
A populate() 0 15 6
A process() 0 15 5
A reset() 0 6 1
A __construct() 0 7 3
A getDistances() 0 3 1
A getPrecedence() 0 3 1
1
<?php
2
3
namespace App\Component\Math\Graph\Path;
4
5
/**
6
 * Weighted graph path finder using Floydwarshall method
7
 * @author Pierre Fromager <[email protected]>
8
 */
9
class Floydwarshall
10
{
11
12
    const INFINITE = 66666;
13
14
    /**
15
     * Distances array
16
     * @var array
17
     */
18
    protected $dist;
19
20
    /**
21
     * Precedence matrix
22
     * @var array
23
     */
24
    protected $pred;
25
26
    /**
27
     * Weights array
28
     * @var array
29
     */
30
    protected $weights;
31
32
    /**
33
     * Number of nodes
34
     * @var integer
35
     */
36
    protected $nodeCount;
37
38
    /**
39
     * Node names list
40
     * @var array
41
     */
42
    protected $nodenames;
43
44
    /**
45
     * Temporary table for various stuff.
46
     * @var array
47
     */
48
    protected $tmp;
49
50
    /**
51
     * instanciate
52
     * @param array $graph Graph matrice.
53
     * @param array $nodenames Node names as an array.
54
     */
55 5
    public function __construct(array $graph, array $nodenames = [])
56
    {
57 5
        $this->reset();
58 5
        $this->weights = $graph;
59 5
        $this->nodeCount = count($this->weights);
60 5
        if (!empty($nodenames) && $this->nodeCount == count($nodenames)) {
61 5
            $this->nodenames = $nodenames;
62
        }
63
    }
64
65
    /**
66
     * reset
67
     *
68
     * @return Floydwarshall
69
     */
70 1
    protected function reset(): Floydwarshall
71
    {
72 1
        $this->tmp = [];
73 1
        $this->dist = [[]];
74 1
        $this->pred = [[]];
75 1
        return $this;
76
    }
77
78
    /**
79
     * populate then calculate distance and precedence
80
     */
81 3
    public function process(): Floydwarshall
82
    {
83 3
        $this->populate();
84 3
        for ($k = 0; $k < $this->nodeCount; $k++) {
85 3
            for ($i = 0; $i < $this->nodeCount; $i++) {
86 3
                for ($j = 0; $j < $this->nodeCount; $j++) {
87 3
                    $nextDist = $this->dist[$i][$k] + $this->dist[$k][$j];
88 3
                    if ($this->dist[$i][$j] > $nextDist) {
89 3
                        $this->dist[$i][$j] = $nextDist;
90 3
                        $this->pred[$i][$j] = $this->pred[$k][$j];
91
                    }
92
                }
93
            }
94
        }
95 3
        return $this;
96
    }
97
98
    /**
99
     * populate graph nodes to
100
     * set distances matrix from weights
101
     * and set matrix precedences
102
     *
103
     * @return Floydwarshall
104
     */
105 2
    protected function populate(): Floydwarshall
106
    {
107 2
        for ($i = 0; $i < $this->nodeCount; $i++) {
108 2
            for ($j = 0; $j < $this->nodeCount; $j++) {
109 2
                if ($i == $j) {
110 2
                    $this->dist[$i][$j] = 0;
111 2
                } elseif (isset($this->weights[$i][$j]) && $this->weights[$i][$j] > 0) {
112 2
                    $this->dist[$i][$j] = $this->weights[$i][$j];
113
                } else {
114 2
                    $this->dist[$i][$j] = self::INFINITE;
115
                }
116 2
                $this->pred[$i][$j] = $i;
117
            }
118
        }
119 2
        return $this;
120
    }
121
122
    /**
123
     * return distance matrix
124
     *
125
     * @return array
126
     */
127 1
    public function getDistances(): array
128
    {
129 1
        return $this->dist;
130
    }
131
132
    /**
133
     * return precedence matrix
134
     *
135
     * @return array
136
     */
137 1
    public function getPrecedence(): array
138
    {
139 1
        return $this->pred;
140
    }
141
}
142