Completed
Push — master ( b63e19...94a408 )
by Ventaquil
03:47
created

Dijkstra   A

Complexity

Total Complexity 32

Size/Duplication

Total Lines 133
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 1

Importance

Changes 6
Bugs 0 Features 0
Metric Value
wmc 32
c 6
b 0
f 0
lcom 1
cbo 1
dl 0
loc 133
rs 9.6

6 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 6 2
A setRelations() 0 13 4
A generate() 0 20 2
A distances() 0 5 1
D validate() 0 27 10
C dist() 0 51 13
1
<?php
2
namespace Algorithms;
3
4
class Dijkstra
5
{
6
    protected $points;
7
    protected $relations;
8
9
    public function __construct($relations = NULL)
10
    {
11
        if (!empty($relations)) {
12
            $this->setRelations($relations);
13
        }
14
    }
15
16
    public function setRelations($relations)
17
    {
18
        if (self::validate($relations)) {
19
            $this->relations = $relations;
20
        } else {
21
            if (is_callable($relations) && ($relations instanceof \Closure)) {
22
                $creator = new GraphTools\Creator;
23
                call_user_func($relations, $creator);
24
25
                $this->relations = $creator->createConnections();
26
            }
27
        }
28
    }
29
30
    public function generate()
31
    {
32
        $result = []; # Prepare results array
33
34
        # Analyze all relations
35
            foreach ($this->relations as $point => $relation) {
36
                # Prepare $points array by isset source point
37
                    $this->points = [
38
                        $point => [
39
                            0,
40
                            '',
41
                        ],
42
                    ];
43
44
                $this->dist($point, $point);
45
                $result[$point] = $this->points; # Copy $points content to results array
46
            }
47
48
        return $result;
49
    }
50
51
    private function dist($source, $point, &$visited = [])
52
    {
53
        $visited[$point] = TRUE; # Set current point as visited
54
55
        # Prepare help variables
56
            $min_ptr = -1;
57
            $min = 0;
58
59
        # Analyzes point neighborhood
60
            foreach ($this->relations[$point] as $relation) {
61
                if ($relation[0] != $source) { # If current point is different than source
62
                    if (empty($visited[$relation[0]])) { # If current point is not visited
63
                        if ($min_ptr == -1) { # When minimal point is not finded
64
                            $min_ptr = $relation[0];
65
                            $min = $relation[1];
66
                        } else {
67
                            if ($min > $relation[1]) {
68
                                $min_ptr = $relation[0];
69
                                $min = $relation[1];
70
                            }
71
                        }
72
                    }
73
74
                    # Change the shortest way to current point
75
                        if (isset($this->points[$point][0])) {
76
                            $first_field = $this->points[$point][0];
77
                        } else {
78
                            $first_field = 0;
79
                        }
80
81
                        if (empty($this->points[$relation[0]])) {
82
                            $this->points[$relation[0]] = [
83
                                $first_field + $relation[1],
84
                                ((empty($this->points[$point][1])) ? $point : $this->points[$point][1]) . ':' . $relation[0],
85
                            ];
86
                        } else {
87
                            if ($this->points[$relation[0]][0] > ($this->points[$point][0] + $relation[1])) {
88
                                $this->points[$relation[0]] = [
89
                                    ((isset($this->points[$point][0])) ? $this->points[$point][0] : 0) + $relation[1],
90
                                    ((empty($this->points[$point][1])) ? NULL : $this->points[$point][1] . ':') . $relation[0],
91
                                ];
92
                            }
93
                        }
94
                }
95
            }
96
97
        # If isset unvisited point with minimal way go for it
98
            if ($min_ptr != -1) {
99
                $this->dist($source, $min_ptr, $visited);
100
            }
101
    }
102
103
    public function distances($point)
104
    {
105
        $this->dist($point, $point);
106
        return $this->points;
107
    }
108
109
    private static function validate($relations_array)
110
    {
111
        if (is_array($relations_array)) {
112
            $return = TRUE;
113
            foreach ($relations_array as $relations) {
114
                if (is_array($relations)) {
115
                    foreach ($relations as $relation) {
116
                        if (!(is_array($relation) && (count($relation) == 2) && isset($relation[0]) && isset($relation[1]))) {
117
                            $return = FALSE;
118
                            break;
119
                        }
120
                    }
121
122
                    if ($return === FALSE) {
123
                        break;
124
                    }
125
                } else {
126
                    $return = FALSE;
127
                    break;
128
                }
129
            }
130
131
            return $return;
132
        } else {
133
            return FALSE;
134
        }
135
    }
136
}
137