public static function DijkstraAlgorithmByDB($first, $finish) { global $LINK_DB; if ($first == $finish) { return array(0, array($first)); } $edge_table = PWRelatedWords::getTableName(); // table of related words (words and distance between them) $path_table = PWShortPath::getTableName(); // table of shortest paths (first, last, next-to-last vertexes, length of path) //print "$first, $finish"; $query = "SELECT lemma_id1 FROM {$edge_table} WHERE lemma_id1='{$first}' or lemma_id2='{$first}' LIMIT 1"; // check if any edge with $first exists $res_exist = $LINK_DB->query_e($query, "Query failed in file <b>" . __FILE__ . "</b>, string <b>" . __LINE__ . "</b>"); if ($LINK_DB->query_count($res_exist) == 0) { return array(0, NULL); } $query = "SELECT lemma_id1 FROM {$edge_table} WHERE lemma_id1='{$finish}' or lemma_id2='{$finish}' LIMIT 1"; // check if any edge with $finish exists $res_exist = $LINK_DB->query_e($query, "Query failed in file <b>" . __FILE__ . "</b>, string <b>" . __LINE__ . "</b>"); if ($LINK_DB->query_count($res_exist) == 0) { return array(0, NULL); } $success = 0; // the condition of finding the shortest path in the given vertex ($finish) $count_row = 1; $query = "UPDATE {$path_table} SET mark=0 where lemma_id_1=" . $first; // mark all vertexes as unvisited (if already any paths in DB exists) // $query = "DELETE FROM $path_table where lemma_id_1=".$first; // mark all vertexes as unvisited (if already any paths in DB exists) $LINK_DB->query_e($query, "Query failed in file <b>" . __FILE__ . "</b>, string <b>" . __LINE__ . "</b>"); $prev = $first; $path_len = 0; //print "<PRE>"; $count = 0; //print $first; //return; while (!$success && $count_row) { // until all vertixes will not be visited $count++; // && $count<3 print "<p>" . $count . ": " . $count_row . ".-----------------------------</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) $query = "SELECT path_len,mark FROM {$path_table} WHERE lemma_id_1='{$first}' and lemma_id_n='{$last}'"; // recounted only unvisited vertexes //print "<P>$query"; $res_path = $LINK_DB->query_e($query, "Query failed in file <b>" . __FILE__ . "</b>, string <b>" . __LINE__ . "</b>"); if ($LINK_DB->query_count($res_path) == 0) { // 1. this is new path from $start to $finish which is absent in table pw_short_path_LANG_CODE $query = "INSERT INTO {$path_table} (`lemma_id_1`, `lemma_id_n`, `path_len`, `lemma_id_prev_n`, mark) VALUES ({$first}, {$last}, {$new_path_len}, {$prev}, 0)"; //print "<P>$query"; $LINK_DB->query_e($query, "Query failed in file <b>" . __FILE__ . "</b>, string <b>" . __LINE__ . "</b>"); } else { // 2. already (one) path from $start to $finish does exist, then update (length and previous word) only if length of new path is shorter $row_path = $res_path->fetch_object(); if ($row_path->mark == 0 && $new_path_len < $row_path->path_len) { $query = "UPDATE {$path_table} SET path_len={$new_path_len}, lemma_id_prev_n={$prev} WHERE lemma_id_1={$first} and lemma_id_n={$last}"; //print "<P>$query"; $LINK_DB->query_e($query, "Query failed in file <b>" . __FILE__ . "</b>, string <b>" . __LINE__ . "</b>"); } } } $query = "SELECT path_len, lemma_id_n FROM {$path_table} WHERE lemma_id_1='{$first}' and mark=0 order by path_len"; // choose minimal distance of path from first to any unvisited vertex $res_min = $LINK_DB->query_e($query, "Query failed in file <b>" . __FILE__ . "</b>, string <b>" . __LINE__ . "</b>"); $count_row = $LINK_DB->query_count($res_min); if (!$count_row) { // all paths from start are marked as visited $path_len = 0; } else { // choose vertex with minimal distance $row_min = $res_min->fetch_object(); // get only one row - minimal path length $path_len = $row_min->path_len; // choose minimal distance of path from first to any unvisited vertex $prev = $row_min->lemma_id_n; // choose unvisited vertex with minimal distance } //print "<p>prev:$prev, path_len:".$path_len; $query = "UPDATE {$path_table} SET mark=1 where lemma_id_1={$first} and lemma_id_n={$prev}"; // mark vertex $prev as unvisited //print "<P>$query"; $LINK_DB->query_e($query, "Query failed in file <b>" . __FILE__ . "</b>, string <b>" . __LINE__ . "</b>"); if ($prev == $finish) { // the shortest path in $finish are found!! $success = 1; } } print "<p>{$count} iterations"; if ($success) { // $path = array($finish); $prev = $finish; while ($prev != start) { $query = "SELECT lemma_id_prev_n FROM {$path_table} WHERE lemma_id_1='{$first}' and lemma_id_n='{$prev}' order by path_len LIMIT 1"; // choose minimal distance of path from first to any unvisited vertex $res = $LINK_DB->query_e($query, "Query failed in file <b>" . __FILE__ . "</b>, string <b>" . __LINE__ . "</b>"); $row = $res->fetch_object(); $prev = $row->lemma_id_prev_n; array_unshift($path, $prev); } return array($path_len, $path); } else { return array(NULL, NULL); } // any path from $first to $finish are not found }
public static function setLangCode($lang_code) { self::$lang_code = $lang_code; self::$table_name = 'pw_short_path_' . $lang_code; }
// PhpMorphy include "phpmorphy.inc.php"; //include_once(SITE_ROOT."phpmorphy/src/common.php"); foreach ($_REQUEST as $var => $value) { /* TODO!!! check vars */ ${$var} = $value; } /******************************* * Init constants and variables *******************************/ define('NAME_DB', 'ruwik'); $config['hostname'] = 'localhost'; $config['dbname'] = NAME_DB; $config['user_login'] = '******'; $config['user_password'] = '******'; $config['admin_login'] = '******'; $config['admin_password'] = ''; ## DB connection ## mysql>GRANT SELECT ON %.* TO pw_user@'%' identified by ''; ## mysql>GRANT SELECT, INSERT, UPDATE, CREATE, DROP, INDEX ON %.* TO pw_admin@'%' identified by ''; ## mysql>FLUSH PRIVILEGES; ## $LINK_DB = new DB($config['hostname'], $config['user_login'], $config['user_password'], $config['dbname']); define('LangCode', 'ru'); PWLemma::setLangCode(LangCode); PWRelatedWords::setLangCode(LangCode); PWShortPath::setLangCode(LangCode); // из-за этого слетают стили //include_once(LIB_DIR."multi/".LangCode."/WMeaning.php");