ALGORITMA FLOYD WARSHALL PENCARIAN RUTE TERDEKAT DENGAN PHP
Mekanisme algoritma Floyd Warshall Langkah awal yang harus dilakukan untuk menentukan shortest path dengan menggunakan algoritma Floyd Warshal adalah : merepresentasikan suatu graph sebagai suatu matriks bobot. Dimana bobot untuk masing-masing edge adalah: wij = 0 jika i = j, = w(i,j) jika i ≠ j dan (i,j) Є E = ∞ jika i ≠ j dan (i,j) not(E) Format output berupa matrix n x n berjarak D = [dij] dimana dij adalah jarak dari vertex i ke j.
Langkah Kedua yaitu: melakukan dekomposisi Floyd Warshall. Urutannya adalah sebagai berikut: dij(k) merupakan panjang dari shortest path dari i ke j sehingga semua vertex intermediate yang terdapat pada path (jika ada) terkumpul pada (1, 2, … , k}. dij(0) dikumpulkan pada wij, dimana berarti kondisi tidak ada vertex intermediate D(k) menjadi matrix n x n [dij(k)] Tentukan dij(n) sebagai jarak dari i ke j. Jadi, yang dilakukan selanjutnya adalah menghitung D(n) -> D(n) beranggotakan elemen-elemen dij(n) Hitung D(k) untuk k = 0, 1, …, n.
Langkah Ketiga Yaitu menentukan struktur shortest path. Dalam hal ini, harus dilakukan dua pengamatan terlebih dahulu sebelum melangkah lebih jauh, yaitu: Sebuah shortest path tidak memuat vertex yang sama sebanyak 2 kali. Sebuah path yang memuat vertex 2 kali merupakan merupakan cycle. Untuk sebuah shortest path dari i ke j dengan beberapa vertex intermediate pada path dipilih dari kumpulan {1, 2, …, k), dengan 2 kemungkinan: (k – 1) 1) k bukan vertex pada path, path terpendek mempunyai panjang dij (k –
(k – 1) 1) (k – 1) 1) k adalah vertex pada path, path terpendek mempunyai panjang dik (k – + dkj(k –
Setelah melakukan pengamatan di atas, kemudian dilakukan penentuan shortest path dari i ke j yang memuat vertex k. Shortest path tersebut memuat sebuah subpath dari i ke k dan sebuah subpath dari k ke j.
Setiap subpath hanya dapat memuat vertex intermediate pada {1, …, k -1} dan sedapat mungkin (k – 1) 1) (k – 1) 1) haruslah paling pendek, beri nama panjangnya dik (k – dan dkj(k – . Sehingga path mempunyai (k – 1) 1) (k – 1) 1) panjang dik(k – + dkj(k – Dengan menggabungkan dua persamaan tersebut, maka didapat : (k – 1) 1) (k – 1) 1) (k – 1) 1) - dij(k) = min { dij (k – , dik(k – + dkj(k – }
Langkah Keepat yaitu: melakukan iterasi. Dimulai dari iterasi ke-0 sampai dengan n
Perhitungan yang dilakukan adalah: Menentukan D(0) ( iterasi ke-0 )= [wij], merupakan matrix bobot (k – 1) 1) (k – 1) 1) (k – 1) 1) Menentukan D(k) dengan menggunakan dij (k) = min { dij(k – , dik(k – + dkj(k – }, untuk k = 1, …, n.
(k – 1) 1) k bukan vertex pada path, path terpendek mempunyai panjang dij (k –
(k – 1) 1) (k – 1) 1) k adalah vertex pada path, path terpendek mempunyai panjang dik (k – + dkj(k – Dimana n adalah jumlah verteks verteks
Hasil akhir dari algoritma Floyd Warshall adalah matriks untuk iterasi ke-n. Dari matriks ke-n i ni, dapat dilihat shortest path untuk setiap vertek pada suatu graph.
CONTOH PROGRAM FLOYD WARSHALL MENGGUNAKAN PHP DAN GOOGLE MAPS API
Alasan kenapa kenapa saya saya membuat membuat aplikasi aplikasi ini menggunak menggunakan an bahasa bahasa program PHP ialah karena yang pertama basic saya di php dan yang kedua menurut saya aplikasi ini sangat cocok dibuat dengan menggunakan php karena tutorial php sangat-sangat mudah didapat dari tutorial bahasa-bahasa program lainya. Oke kita langsung saja, jika teman-teman ingin belajar bahasa program php temanteman bisa membacanya lewat link-link yang sudah saya kaitkan dibawah: Baca Juga Artikel PENGERTIAN PHP
Contoh yang akan saya berikan disini ialah tentang pencarian lokasi tempat sosial terdekat serta mencari jalur terpendek dari lokasi fasilitas yang didapat. Jadi pada aplikasi yang akan dibuat disini memiliki dua proses yaitu: Pertama kita akan mencari lokasi sosial mana yang paling dekat dari posisi kita sekarang Kedua jika sudah dapat fasilitas sosial yang paling dekat kemudian kita akan mencari jalur-jalur mana saja yang harus kita lewati agar kita mendapat jalur terpendek untuk menuju fasilitas sosial tersebut. Buat database dan beri nama floyd_warshall. Kemudian kita buat tabel-tabel seperti dibawah ini 1. Nama Tabel : tabel_kategori_fasilitas_umum
SQL SKRIP ? 1 2
CREATE TABLE `tabel_kategori_fasilitas_umum` ( `kode_kategori_fasilitas_umum` varchar(20) NOT NULL,
3
`nama_kategori_fasilitas_umum` varchar(40) DEFAULT NULL,
4
`gambar` varchar(200) DEFAULT NULL,
5
PRIMARY KEY (`kode_kategori_fasilitas_umum`)
6
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
Skript diatas adalah untuk membuat tabel tabel_kategori_fasilitas_umumyang nantinya akan digunakan untuk menampung data kategori fasilitas umum Misalnya : kita akan menambah fasilitas seperti : Rumah sakit, Masjid, Mushallah Dll 2. Nama Tabel : tabel_lokasi_fasilitas SQL SKRIP ? 1
CREATE TABLE `tabel_lokasi_fasilitas` ( 2
`id` int(11) NOT NULL AUTO_INCREMENT, 3 4
`nama` varchar(255) NOT NULL, `lat` varchar(12) NOT NULL,
5
`lon` varchar(12) NOT NULL,
6
`kode_kategori_fasilitas_umum` varchar(20) NOT NULL,
7
`alamat` varchar(50) NOT NULL DEFAULT 'alamat',
8 9
`deskripsi` varchar(100) NOT NULL DEFAULT 'deskripsi', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=28 DEFAULT CHARSET=latin1;
10
Skript diatas adalah untuk membuat tabel tabel_lokasi_fasilitas yang nantinya akan digunakan untuk menampung data fasilitas umum. tabel ini berelasi dengan tabel kategori fasilitas umum karena ditabel inilah nantinya sebuah fasilitas umum dipecah akan masuk kekategori fasilitas apa seperti yang sudah saya sebutkan diatas.
3. Nama Tabel : tabel_node_lokasi
SQL SKRIP ? 1
CREATE TABLE `tabel_node_lokasi` ( 2 3
`id` int(20) NOT NULL AUTO_INCREMENT, `id_lokasi` varchar(10) DEFAULT NULL,
4
`nama_jalan` varchar(200) DEFAULT NULL,
5
`latitude` varchar(100) DEFAULT NULL,
6
`longtitude` varchar(100) DEFAULT NULL,
7 8
PRIMARY KEY (`id`) ) ENGINE=MyISAM AUTO_INCREMENT=12 DEFAULT CHARSET=latin1;
Skript diatas adalah untuk membuat tabel tabel_node_lokasi yang nantinya akan digunakan untuk menampung data node-node yang terdapat pada setiap fasilitas umum. Jadi node-node ini ialah jalur-jalur mana saja yang dapat dilalui untuk menuju suatu fasilitas umum, jalur-jalur inilah yang harus dikumpulkan semua. Selanjutnya jika sudah selesai membuat tabel-tabel yang diperlukan kemudian sekarang kita masuk ketahap skrip php. Disini saya menggunakan sebuah class FloydWarshall yang dibuat oleh anne Mikkonen, class ini dibuat pada tahun 2011, class FloydWarshall ini telah banyak digunakan pengembang untuk mencari rute terdekat, dan hasilnyapun sangat akurat tanpa ada bug segikitpun.
Copy dan pasti skript dibawah kemudian simpan dan beri nama fw.class.php PHP SCRIPT ? 1 2 3 4
FloydWarshall Janne Mikkonen
$Date: 2011/06/13 05:10:48 $
5
* @version
$Revision: 1.1 $
* @license
GNU General Public License, version 2
6 7
href="http://www.opensource.org/licenses/GPL-2.0 href="http://www.opensource.org/licenses/GPL-2.0" " rel="nofollow">http
8
://www.opensource
9
.org/licenses
10 /GPL-2. 11 12
0 **/
13
error_reporting(E_STRICT); 14
define('INFINITE', pow(2, (20 * 8 - 2)-1)); 15 16
class FloydWarshall { 17 18 19
/** * Distances array
20
* @var
21
*/
22 23
array
private $dist = array(array()); /** * Predecessor array
24
* @var 25 26
array
*/ private $pred = array(array());
27
/**
28
* Weights array
29
* @var
30 31
array
*/ private $weights; /**
32
* Number of nodes 33 34
* @var
integer
*/
35
private $nodes;
36
/**
37
* Node names array
38 39
* @var
array
*/ private $nodenames;
40
/** 41 42
* Temporary table for various stuff. * @var
array
43
*/
44
private $tmp = array();
45 46 47 48
/** * Constructor * @param
array $graph Graph matrice.
* @param
array $nodenames Node names as an array.
49
*/ 50
public function __construct($graph, $nodenames='') { 51 52
$this->weights = $graph;
53
$this->nodes
= count($this->weights);
54
if ( ! empty($nodenames) && $this->nodes == count($nodenames) ) { $this->nodenames = $nodenames;
55
}
56
$this->__floydwarshall(); 57 58
} 59 60 61
/** * The actual PHP implementation of Floyd-Warshall algorithm.
62
* @return
63
*/
64
private function __floydwarshall () {
void
65 66 67
// Initialization for ( $i = 0; $i < $this->nodes; $i++ ) { for ( $j = 0; $j < $this->nodes; $j++ ) {
68
if ( $i == $j ) { 69
$this->dist[$i][$j] = 0;
70
} else if ( $this->weights[$i][$j] > 0 ) {
71
$this->dist[$i][$j] = $this->weights[$i][$j]; } else {
72
$this->dist[$i][$j] = INFINITE;
73
}
74
$this->pred[$i][$j] = $i;
75
} 76
} 77 78
// Algorithm
79 80 81 82 83 84 85
for ( $k = 0; $k < $this->nodes; $k++ ) { for ( $i = 0; $i < $this->nodes; $i++ ) { for ( $j = 0; $j < $this->nodes; $j++ ) { if ($this->dist[$i][$j] > ($this->dist[$i][$k] + $this->dist[$k][$j] $this->dist[$i][$j] = $this->dist[$i][$k] + $this->dist[$k][$j] $this->pred[$i][$j] = $this->pred[$k][$j];
//echo "
".$this->pred[$k][$j];
86
}
87
}
88
}
89
} 90 91
} 92 93 94
/** * Private method to get the path.
95
*
96
* Get graph path from predecessor matrice.
97
* @param
integer $i
* @param
integer $j
98 99
* @return
void
*/ 100
private function __get_path($i, $j) { 101 102
if ( $i != $j ) {
103
$this->__get_path($i, $this->pred[$i][$j]);
104
}
105
array_push($this->tmp, $j);
106
}
107 108 109
/** * Public function to access get path information. *
110 111 112
* @param
ingeger $i Starting node.
* @param
integer $j End node.
* @return
array Return array of nodes.
113
*/
114
public function get_path($i, $j) { $this->__get_path($i, $j);
115
return $this->tmp;
116 117 118
}
119
/**
120
* Print nodes from a and b.
121 122
* @param
ingeger $i Starting node.
* @param
integer $j End node.
* @return
void
123
*/ 124
public function print_path($i, $j) {
125 126
if ( $i != $j ) {
127
$this->print_path($i, $this->pred[$i][$j]); }
128 129
if (! empty($this->nodenames) ) {
130
print($this->nodenames[$j]) . ' ';
131
} else {
132
print($j) . ' '; 133
} 134 135
}
136 137
/**
138
* Get total cost (distance) between point a to b.
139
*
140
* @param
integer $i
* @param
ingeger $j
141 142
* @return
array Returns an array of costs.
*/ 143
public function get_distance($i, $j) { 144 145
return $this->dist[$i][$j]; }
146 147
/************************************************************
148
***
DEBUG FUNCTIONS
***
149
***
- print_graph
***
***
- print_dist
***
***
- print_pred
***
150 151
152
*************************************************************/
153 154 155 156
/** * Print out the original Graph matrice. * @return
void
*/ 157
public function print_graph () { 158 159 160 161
//if ( empty($_SERVER['argv']) ) { echo '
Graph';
162
echo '';
163
if (! empty($this->nodenames) ) { echo '';
164
echo '';
165
for ($n = 0; $n < $this->nodes; $n++) {
166
echo ''; 167
} 168 169 170
} echo ''; for ($i = 0; $i < $this->nodes; $i++) {
171
echo '';
172
if (! empty($this->nodenames) ) { echo '';
173
}
174
for ($j = 0; $j < $this->nodes; $j++) { 175
echo ''; 176
}
177
echo '';
178
}
179
echo '
| <
180 181 182
$this->nodenames[$n] . '
' $this->nodenames[$i] . ' | ' .
183
$this->weights[$i][$j] . ' |
'; 184
// } else {
185 186
//}
187 188
}
189 190
/** * Print out distances matrice.
191
* @return 192 193
void
*/ public function print_dist () {
194 195
//if ( empty($_SERVER['argv']) ) {
196
echo '
Distances';
197
echo '';
198
if (! empty($this->nodenames) ) { echo '';
199
echo ''; 200
for ($n = 0; $n < $this->nodes; $n++) { 201
echo '';
202
}
203
}
204
echo '';
205
for ($i = 0; $i < $this->nodes; $i++) { echo '';
206
if (! empty($this->nodenames) ) {
207
echo ''; 208
} 209
for ($j = 0; $j < $this->nodes; $j++) {
210
echo '';
211
}
212
echo '';
213 214 215
} echo '
| < $this->nodenames[$n] . '
'
216
$this->nodenames[$i] . 217
' | ' .
$this->dist[$i][$j] . ' |
';
218
//} else {
219
//
220
echo "cmd line not yet completed!\n";
//}
221 222
} 223 224
/** 225 226
* Print out predecessors matrice. * @return
void
227
*/
228
public function print_pred () {
229 230 231 232
//if ( empty($_SERVER['argv']) ) { echo '
Predecessors'; echo ''; if (! empty($this->nodenames) ) {
233
echo ''; 234
echo '';
235
for ($n = 0; $n < $this->nodes; $n++) {
236
echo ''; }
237 238 239 240
} echo ''; for ($i = 0; $i < $this->nodes; $i++) { echo '';
241
if (! empty($this->nodenames) ) { 242
echo '';
243
}
244
for ($j = 0; $j < $this->nodes; $j++) { echo '';
245
}
246
echo '';
247 248
} echo '
| <
249
$this->nodenames[$n] . 250
'
'
$this->nodenames[$i] .
251
' | ' .
252
$this->pred[$i][$j] . ' |
';
253
// } else {
254
//
echo "cmd line not yet completed!\n";
255
//} 256 257
}
258 259} // End of class 260?>
Kemudian copy dan paste skript dibawah dan simpan dengan nama index.php PHP SKRIP ? 1 2 3
"; $nama_jalan[] = "Start"; $lat[] = $_GET['x'];
4
$long[] = $_GET['y']; 5
echo " | Start"; 6 7
$data = mysql_query("SELECT * from tabel_node_lokasi where id_lokasi='".$idlokasi." while ($d = mysql_fetch_array($data)) {
8
echo " | $d[nama_jalan]";
9
$nama_jalan[] = $d['nama_jalan'];
10
$lat[] = $d['latitude']; $long[] = $d['longtitude'];
11
} 12
$lokasi =mysql_fetch_array(mysql_query("SELECT * from tabel_lokasi_fasilitas where 13
echo " | $lokasi[nama]"; 14 15
$lat[] = $lokasi['lat']; $long[] = $lokasi['lon'];
16
$nama_jalan[] = $lokasi['nama'];
17 18 19 20
$jlhsas = count($nama_jalan)-1; $n = 0; foreach ($nama_jalan as $key1 => $value1) { echo " |
$value1";
21
foreach ($nama_jalan as $key => $value) { 22 23
//include "distans.php"; $nama[$key1][$key] = $value1.'-'.$value;
24 25 26
if ($value == $value1) { $dataf = 0;
27 28
}
29 30
if ($key1>$key) { if ($key == 0 and $key1 == $jlhsas) {
31
$dataf
= "∞";
32
} 33
else{ 34
$asala = $lat[$key].",".$long[$key]; 35
$tujuana =
$lat[$key1].",".$long[$key1];
36 37
include "distans.php";
38
}
39
echo " | ".$dataf;//.' >'.$key.','.$key1;//.'='.$nama[$
40 41 42
} elseif ($key1 == $key) { $dataf=0;
43
echo " | ".$dataf; 44
} 45 46
else{ if ($key1 == 0 and $key == $jlhsas) {
47 48
$dataf }
= "∞";
else{
49 50
$asala = $lat[$key1].",".$long[$key1];
51
$tujuana =
$lat[$key].",".$long[$key];
52
include "distans.php";
53
}
54 55
echo " | ".$dataf;//. ' > '.$key1.','.$key;//.'='.$nama 56
} 57 58
$graph[$key1][] = str_replace(" km", "", str_replace(",", ".", $dataf)); 59
}
60
$nodes[] = $value1;
61
$n++; }
62 63 64
echo " |
"; $jlss = count($nama_jalan)-1; echo "
";
65
include('fw_example.php'); 66
?>
Sekript diatas dibuat untuk membentuk data menjadi array, data ini lah yang nantinya akan diperoses dengan menggunakan fw.class.php yang sudah kita buat diatas. Karena disini saya menggunakan google maps untuk mencari titik kordinat suatu lokasi, maka disini saya tambah satu file untuk mencari jarak antara lokasi satu dengan lokasi yang lainya. Copy dan paste skript dibawah kemudian simpan dengan nama distans.php PHP SKRIP ? 1
2 3
//!empty($_POST['tujuan']) ? urlencode($_POST['tujuan']) : null;
4
$urlApia = "
https://maps.go 6 span>?origins=".$asala."&
7
$resulta = file_get_contents($urlApia);
8 9
$data15 = json_decode($resulta, true);
1 0 1
$dataf=$data15['rows'][0]['elements'][0]['distance']['text'];
1
?> 1 2
Yang terakhir copy dan paste skript dibawah kemudian simpan dengan nama fw_example.php PHP SKRIP ? 1
2 3
include('fw.class.php');
4 5 6
//$graph = array(array(0,5,8,6), //
array(5,0,3,1),
//
array(8,3,0,1),
//
array(6,1,1,0));
//
array(0,0,10,0,0,4),
//
array(0,0,17,20,0,0));
7 8 9 10
//$nodes = array("a", "b", "c", "d");
11 12
$fw = new FloydWarshall($graph, $nodes);
13
//$fw->print_path(0,2);
14
$fw->print_graph();
15
$fw->print_dist(); //$fw->print_pred();
16 17
$sp = $fw->get_path(0,$jlss); 18 19
echo 'Ruter Terdekat Dari Star Ke '.$nodes[$jlss].' Adalah: '; 20
$jl = count($sp);
21
$r=1;
22
foreach ($sp as $value) {
23
echo $nodes[$value];
24
if ($r == $jl) {
25
}
26
else{
27
echo ' => '; 28
} 29
$r++;
30 31
}
32
echo ' | Dengan Jarak Tempu ';
33
$menit = round(($fw->get_distance(0,$jlss)/40)*60,0);
34
print_r($fw->get_distance(0,$jlss)); echo " km yaitu $menit";
35
?>
Skript diatas adalah akhir dari proses, setelah data dibentuk kedalam graph pada file kemudian data dimasukan kedalam class fw.class.phpdan selanjutnya diproses.