Weight   A
last analyzed

Complexity

Total Complexity 17

Size/Duplication

Total Lines 159
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 48
c 1
b 0
f 0
dl 0
loc 159
ccs 47
cts 47
cp 1
rs 10
wmc 17

7 Methods

Rating   Name   Duplication   Size   Complexity  
A distance() 0 3 2
A init() 0 12 2
A search() 0 22 6
A processPath() 0 11 2
A min() 0 3 1
A path() 0 8 3
A __construct() 0 3 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace App\Component\Math\Graph\Path;
6
7
/**
8
 * Dijikstra path search for weighted graph
9
 * @author Pierre Fromager <[email protected]>
10
 */
11
class Weight
12
{
13
    const _INF = 99999;
14
15
    /**
16
     * graph
17
     *
18
     * @var array
19
     */
20
    protected $graph;
21
22
    /**
23
     * source
24
     *
25
     * @var String
26
     */
27
    private $src;
28
29
    /**
30
     * destination
31
     *
32
     * @var String
33
     */
34
    private $dst;
35
36
    /**
37
     * path
38
     *
39
     * @var array
40
     */
41
    private $path = [];
42
43
    /**
44
     * the nearest path with its parent and weight
45
     *
46
     * @var array
47
     */
48
    private $s = [];
49
50
    /**
51
     * the left nodes without the nearest path
52
     *
53
     * @var array
54
     */
55
    private $q = [];
56
57
    /**
58
     * __construct
59
     *
60
     * @param array $graph
61
     */
62 4
    public function __construct($graph)
63
    {
64 4
        $this->graph = $graph;
65
    }
66
67
    /**
68
     * path
69
     *
70
     * @param string $src
71
     * @param string $dst
72
     * @return array
73
     */
74 1
    public function path(string $src, string $dst): array
75
    {
76 1
        $this->init($src, $dst);
77 1
        $this->path = [];
78 1
        if (isset($this->graph[$this->src]) && isset($this->graph[$this->dst])) {
79 1
            $this->search()->processPath();
80
        }
81 1
        return $this->path;
82
    }
83
84
    /**
85
     * distance
86
     *
87
     * @return float
88
     */
89 2
    public function distance(): float
90
    {
91 2
        return ($this->path) ? $this->s[$this->dst][1] : 0;
92
    }
93
94
    /**
95
     * start calculating
96
     *
97
     * @return Weight
98
     */
99 1
    protected function search(): Weight
100
    {
101 1
        while (!empty($this->q)) {
102 1
            $min = $this->min();
103 1
            if ($min == $this->dst) {
104 1
                break;
105
            }
106 1
            $keys = array_keys($this->graph[$min]);
107 1
            $kam = count($keys);
108 1
            for ($c = 0; $c < $kam; $c++) {
109 1
                $k = $keys[$c];
110 1
                $v = $this->graph[$min][$k];
111 1
                if (!empty($this->q[$k])) {
112 1
                    if (($checkMin = $this->q[$min] + $v) < $this->q[$k]) {
113 1
                        $this->q[$k] = $checkMin;
114 1
                        $this->s[$k] = [$min, $this->q[$k]];
115
                    }
116
                }
117
            }
118 1
            unset($this->q[$min]);
119
        }
120 1
        return $this;
121
    }
122
123
    /**
124
     * lowest weighted node name
125
     *
126
     * @return string
127
     */
128 1
    protected function min(): string
129
    {
130 1
        return array_search(min($this->q), $this->q);
131
    }
132
133
    /**
134
     * init queue assuming all edges are bi-directional
135
     *
136
     * @param string $src
137
     * @param string $dst
138
     * @return Weight
139
     */
140 1
    protected function init(string $src, string $dst): Weight
141
    {
142 1
        $this->src = $src;
143 1
        $this->dst = $dst;
144 1
        $this->s = [];
145 1
        $this->q = [];
146 1
        $keys = array_keys($this->graph);
147 1
        foreach ($keys as $key) {
148 1
            $this->q[$key] = self::_INF;
149
        }
150 1
        $this->q[$this->src] = 0;
151 1
        return $this;
152
    }
153
154
    /**
155
     * set path
156
     *
157
     * @return Weight
158
     */
159 1
    protected function processPath(): Weight
160
    {
161 1
        $this->path = [];
162 1
        $pos = $this->dst;
163 1
        while ($pos != $this->src) {
164 1
            $this->path[] = $pos;
165 1
            $pos = $this->s[$pos][0];
166
        }
167 1
        $this->path[] = $this->src;
168 1
        $this->path = array_reverse($this->path);
169 1
        return $this;
170
    }
171
}
172