Proces znajdowania rozwiązań zbioru równań symbolicznych.
Wyrażenie symboliczne = term
Term = atom | zmienna | relacja
Syntaktyczna / semantyczna
Rozwiązaniem problemu unifikacji jest substytucja, czyli mapowanie zmiennych równania do termów.
Formalnie: substytucja to iniekcja σ: V → T pomiedzy pewnym zbiorem zmiennych V a zbiorem termów T
Często używana notacja: { x1 ↦ t1, ..., xk ↦ tk }
Aplikacja substytucji σ = { x1 ↦ t1, ..., xk ↦ tk } do termu t (zapisywane jako tσ) oznacza jednoczesne zastąpienie każdego wystąpienia zmiennej xi w t przez ti.
Powstały w ten sposób term t` nazywamy instancją termu t
Algorytm unfikacji powinien szukać najbardziej ogólnego unifikatora (mgu) tj. substytucji rozwiązującej problem która jest:
- zupełna tj. zawiera wszystkie rozwiązania
- minimalna tj. nie ma reduntantnych elementów
- każde inne rozwiązanie u można przedstawić w postaci tσ ≡ u dla każdego termu t w σ
Problem unifikacji może oczywiście nie mieć rozwiązań, bądź, w ogólności, nie mieć skończonego rozwiązania (!) etc.
Automatyczne wnioskowanie
Systemy regułowe/eksperckie
Programowanie logiczne (Prolog, Miranda)
Inferencja typów
Przepisywanie termów (rachunek lambda, Haskell !)
1. Zmienna wolna (niezunifikowana) unifikuje się z dowolnym termem
2. Dwa atomy unifikują się z sobą jeśli są identyczne
3. Funktory unifikują się z sobą jeśli ich nazwy i krotności są identyczne i parametry są rekurencyjnie unifikowalne
1. Zmienna typu (niezunifikowana) unifikuje się z dowolnym wyrażeniem
2. Dwa typy unifikują się z sobą jeśli są identyczne
3. Konstruktory typu unifikują się z sobą jeśli ich nazwy i krotności są identyczne i typy składowe są rekurencyjnie unifikowalne
fallible(X) :- human(X).
human(socrates).
fallible(socrates)?
System nie musi rozumieć co znaczy 'omylny', 'człowiek' czy 'Sokrates' :-).
G ∪ { t ≐ t } ⇒ G delete
G ∪ { f(s0,...,sk) ≐ f(t0,...,tk) } ⇒ G ∪ { s0 ≐ t0, ..., sk ≐ tk } decompose
G ∪ { f(s0,...,sk) ≐ g(t0,...,tm) } ⇒ ⊥ if f ≠ g or k ≠ m conflict
G ∪ { f(s0,...,sk) ≐ x } ⇒ G ∪ { x ≐ f(s0,...,sk) } swap
G ∪ { x ≐ t } ⇒ G{x↦t} if x ∉ vars(t) and x ∈ vars(G) eliminate
G ∪ { x ≐ f(s0,...,sk) } ⇒ ⊥ if x ∈ vars(f(s0,...,sk)) check
PROLOG = unifikacja + backtracking
Program w Prologu =
fakty - cat(tom).
reguły - Head :- Body
zapytania - ?- cat(tom)
Reguły muszą być w postaci klauzul Horna tj. klauzul (dysjunkcji termów), które zawierają co najwyżej jeden niezanegowany term.
Przykłady: https://en.wikipedia.org/wiki/Horn_clause#Definition
Dlaczego? Spełnialność jest problemem P-zupełnym dla klauzul Horna, w ogólnym przypadku NP-zupełnym (ekwiwalentnym do 3SAT), bez zmniejszenia ekspresywności == uniwersalnej maszynie Turinga
Let's code an Interpreter