$candidata) if ($richiesta == $candidata) $corrente[$j+1] = $precedente[$j]+1; else $corrente[$j+1] = max($precedente[$j+1],$corrente[$j]); $precedente = $corrente; } $match = $precedente[count($candidate)]; return ["sequenza"=>$sequenza, "occorrenze"=>(int)$occorrenze, "richieste"=>count($richieste), "match"=>$match, "mancanti"=>count($richieste)-$match, "totali"=>count($candidate), "distanza"=>count($candidate)-$match]; } /* * Ordinamento provvisorio: e' il solo pezzo da sostituire quando * avremo una formula migliore. Non costituisce ancora il modello. */ function confronta_euristiche($a, $b) { if ($a["match"] != $b["match"]) return $b["match"] <=> $a["match"]; if ($a["mancanti"] != $b["mancanti"]) return $a["mancanti"] <=> $b["mancanti"]; if ($a["occorrenze"] != $b["occorrenze"]) return $b["occorrenze"] <=> $a["occorrenze"]; if ($a["distanza"] != $b["distanza"]) return $a["distanza"] <=> $b["distanza"]; return strcmp($a["sequenza"], $b["sequenza"]); } function classifica($pattern) { global $db, $tabella; $result = mysqli_query($db, "SELECT sequenza, occorrenze FROM $tabella"); $classifica = []; while ($row = mysqli_fetch_assoc($result)) $classifica[] = misura($pattern, $row["sequenza"], $row["occorrenze"]); usort($classifica, "confronta_euristiche"); return $classifica; } function search($pattern) { $classifica = classifica($pattern); return $classifica[0] ?? null; } /* * Prima versione volutamente stupida. * * infer() riceve direttamente il pattern rilassato. * Non decide ancora DA SOLA quali parole trasformare * in wildcard. */ function infer($pattern) { return search($pattern); } function learn_file($nome_file, $limite=0) { $testo = file_get_contents($nome_file); if ($testo === false) die("Impossibile leggere $nome_file\n"); $testo = str_replace("_", "", $testo); $frasi = preg_split('/(?<=[.!?])\s+(?=[\p{Lu}—])/u', trim($testo)); $imparate = 0; foreach ($frasi as $frase) { if (normalizza($frase) == "") continue; learn($frase); $imparate++; if ($limite && $imparate >= $limite) break; } return $imparate; } if (PHP_SAPI == "cli" && isset($argv[1])) { if ($argv[1] == "learn-file" && isset($argv[2])) { $limite = isset($argv[3]) ? (int)$argv[3] : 0; echo "Frasi imparate: ".learn_file($argv[2], $limite)."\n"; exit; } if ($argv[1] == "query" && isset($argv[2])) { $r = infer(implode(" ", array_slice($argv,2))); echo $r ? $r["sequenza"]."\t".$r["occorrenze"]."\n" : "boh\n"; exit; } if ($argv[1] == "rank" && isset($argv[2])) { $limite = 10; $pattern = implode(" ", array_slice($argv,2)); foreach (array_slice(classifica($pattern),0,$limite) as $n => $r) echo ($n+1).". match={$r["match"]}/{$r["richieste"]} mancanti={$r["mancanti"]} distanza={$r["distanza"]} occ={$r["occorrenze"]} | {$r["sequenza"]}\n"; exit; } die("Uso: php LLMA-euristica.php learn-file file [numero_frasi] | query pattern | rank pattern\n"); } /* ------------------------------------------------------- MINI ESPERIMENTO ------------------------------------------------------- */ for ($i=0; $i<6; $i++) learn("il gatto mangia la carne"); for ($i=0; $i<2; $i++) learn("il cane mangia l'osso"); learn("lo sparviero mangia carogne"); learn("lo sparviero mangia carne di cavallo se gliela tiri"); function prova($pattern) { $r = infer($pattern); echo "\n"; echo "QUERY : $pattern\n"; if ($r) { echo "MATCH : " . $r["sequenza"] . "\n"; echo "COUNT : " . $r["occorrenze"] . "\n"; } else echo "MATCH : boh\n"; } prova("lo * mangia *"); prova("* * mangia *"); prova("il * mangia *"); ?>