/** Dijkstra Algorithm for searching of the shortest path between words $first and $finish * https://en.wikipedia.org/wiki/Dijkstra's_algorithm * * Gets shortest paths from a word with ID $first to $finish, * writes shortest path (distance and path) to arrays while $finish is not marked. * * @param int $first a first word in a shortest path * @param int $finish a last word in a shortest path */ public static function DijkstraAlgorithmByArray($first, $finish) { global $LINK_DB; if ($first == $finish) { return array(0, array($first)); } $vertex_arr = PWRelatedWords::getAllRelatedWords(); // list of unvisited vertexes generated from list of vertexes having an edge if (!in_array($first, $vertex_arr)) { return array(0, NULL); } // search vertexes is not connected with any edge $infinity = 1000000; foreach ($vertex_arr as $v) { $unvisited[$v] = $infinity; } $unvisited[$first] = 0; $edge_table = PWRelatedWords::getTableName(); // table of related words (words and distance between them) $prev_arr = array(); // list of next-to-last for path from first to last vertexes $prev_arr[$first] = NULL; $prev = $first; $path_len = 0; // $dist_arr = array(); // <key>,<value>: list of distances <value> from $first to <key> // $dist_arr[$first] =0; $success = 0; // the condition of finding the shortest path in the given vertex ($finish) //print "<PRE>"; $count = 0; //print $first; //return; while (!$success && sizeof($unvisited) && $path_len < $infinity) { // until all vertixes will not be visited // && $count<10 print "<p>" . $count . ": " . sizeof($unvisited); //.".-----------------------------</p>"; //print_r($finish_arr); //print_r($len_arr); $query = "SELECT * FROM {$edge_table} WHERE lemma_id1='{$prev}' or lemma_id2='{$prev}'"; // search nearest vertexes to $prev (НЕТ необходимости сортировать, так как неважно в какой последовательности ставятся метки) $res_neib = $LINK_DB->query_e($query, "Query failed in file <b>" . __FILE__ . "</b>, string <b>" . __LINE__ . "</b>"); while ($row_neib = $res_neib->fetch_object()) { if ($row_neib->lemma_id1 == $prev) { $last = $row_neib->lemma_id2; } else { $last = $row_neib->lemma_id1; } $new_path_len = $path_len + $row_neib->weight; // path length from $prev to $last (neighbour of $prev via semantic relations) // if (!isset($dist_arr[$last]) || $dist_arr[$last]>$new_path_len) { // this is new path from $first to $last OR if (isset($unvisited[$last]) && $unvisited[$last] > $new_path_len) { // this is new path from $first to $last OR // already (one) path from $first to $last does exist, but the new path is shorter // $dist_arr[$last] = $unvisited[$last] = $new_path_len; $prev_arr[$last] = $prev; } } $count++; $path_len = min(array_values($unvisited)); // choose minimal distance of path from first to any unvisited vertex $prev = array_search($path_len, $unvisited); // choose unvisited vertex with minimal distance print " = " . $path_len; unset($unvisited[$prev]); // mark this vertes as visited, delete it from unvisited list if ($prev == $finish) { // the shortest path in $finish are found!! $success = 1; continue; } } print "<p>{$count} iterations"; if ($success) { // $path = array($finish); $prev = $prev_arr[$finish]; while ($prev != NULL) { array_unshift($path, $prev); $prev = $prev_arr[$prev]; } return array($path_len, $path); } else { return array(NULL, NULL); } // any path from $first to $finish are not found }