Deklarative Programmierung

Werbung
Was bisher geschah
Funktionale Programmierung (Haskell):
I
Algebraische Datentypen
I
strukturelle Induktion
I
Rekursionsschemata
I
Funktionen höherer Ordnung (z.B. map, fold, filter)
I
Lazy evaluation
I
Monaden (z.B. Maybe, List, IO)
I
Parser-Monade (Parsec)
184
Funktionale und logische Programmierung
I
funktionale Programmierung:
LISP (John McCarthy, 1957)
benutzerdefinierte Funktionen,
definiert durch Gleichungen (Ersetzungsregeln)
Rechnen = Normalform bestimmen
Methode: Termersetzung
I
logische Programmierung:
Prolog (Alain Colmerauer, 1972)
benutzerdefinierte Relationen (Prädikate),
definiert durch Schlussregeln (Implikationen).
Rechnen = Schlussfolgerung (Widerspruch) ableiten
Methode: prädikatenlogische Resolution
185
Wiederholung: Prolog-Syntax
Regel (Klausel) a :- a1, ..., am.
Bedeutung in Prädikatenlogik (der ersten Stufe)
(∀X1 · · · ∀Xn ((a1 ∧ · · · ∧ am ) → a)
wobei X1 , . . . Xn alle in a, a1 , . . . , an
vorkommenden Variablen sind.
Rumpf a1 ∧ . . . ∧ am , Kopf a
Fakt Atom a. (positives Literal, Regel ohne Rumpf)
Bedeutung in Prädikatenlogik (der ersten Stufe):
∀X1 · · · ∀Xn a, wobei X1 , . . . Xn alle in a
vorkommenden Variablen sind.
Zielklausel (Query, Anfrage) ?- a1, ..., an.
Bedeutung in Prädikatenlogik (der ersten Stufe):
(∀X1 · · · ∀Xn (a1 ∧ · · · ∧ am )
wobei X1 , . . . Xn alle in a1 , . . . , am vorkommenden
Variablen sind.
Variablennamen beginnen mit Großbuchstaben,
Funktions- und Relationssymbole mit Kleinbuchstaben
186
Wiederholung: Prolog-Programme
Programm P (Wissensbasis):
endliche Menge von Fakten und Regeln,
repräsentiert eine prädikatenlogische
Formelmenge Φ,
(repräsentiert
eine prädikatenlogische Formel
V
ϕ = ψ∈Φ ψ)
Beispiel: Programm P
liest(paul,krimi).
liest(bob,zeitung).
liest(tina,arztroman).
mag(tina,X) :- liest(X,krimi).
repräsentiert die Formelmenge
Φ = {l(p, k ), l(b, z), l(t, a), ∀x(l(x, k ) → m(t, x))}
187
Wiederholung: Prolog-Anfragen
Zielklausel Atom
repräsentiert eine prädikatenlogische Formel ψ
Beispiel: ?- mag (tina,X).
repräsentiert die Formel ψ = mag(tina, X )
188
Wiederholung: Prolog-Auswertung
Ausgewertet werden Paare (Φ, ψ) aus
I
Programm Φ
I
Zielklausel ψ
(prädikatenlogische Darstellung von Programm und Anfrage)
Antwort: Substitution θ mit Φ |= θ(ψ)
(Prolog-Ausgabe: Grundinstanzen θ(ψ) der Zielklausel ψ)
189
Prolog: Bestimmung der Antworten
I
durch Lösung der Aufgabe:
Für welche Substitutionen θ gilt Φ |= θ(ψ)?
I
durch Lösung der äquivalenten Aufgabe:
Für welche Substitutionen θ ist die Formelmenge
Φ ∪ ¬θ(ψ) unerfüllbar?
I
durch Lösung der äquivalenten Aufgabe:
Für welche Substitutionen θ gilt Φ ∪ ¬θ(ψ) |= f ?
I
durch Bestimmung der Substitutionen θ, für die f aus
Φ ∪ ¬θ(ψ) syntaktisch herleitbar ist.
I
durch prädikatenlogische Resolution mit festgelegter
Auswertungsreihenfolge (SLD-Resolution)
190
Beispiel für Prolog-Auswertung
Programm P:
p(a,b).
p(b,c).
p(c,d).
e(X,Y) :- p(X,Y).
e(X,Y) :- p(X,Z), e(Z,Y).
Zielklausel e(X , d)
Prädikatenlogische Bedeutung:
I
Programm P:
p(a, b), p(b, c), p(c, d), ∀X ∀Y (p(X , Y ) → e(X , Y )),
Φ=
∀X ∀Y ∀Z (p(X , Z ) ∧ e(Z , Y ) → e(X , Y ))
I
Zielklausel ψ = e(X , d)
I
negierte Zielklausel ¬ψ = ¬e(X , d)
I
Problem


 ¬e(X , d), p(a, b), p(b, c), p(c, d),

∀X ∀Y (p(X , Y ) → e(X , Y )),
{¬ψ} ∪ Φ =


∀X ∀Y ∀Z (p(X , Z ) ∧ e(Z , Y ) → e(X , Y ))
191
Datentypen für Prolog-Interpreter in Haskell
I
Funktions- und Prädikatsymbole Identifier (String)
I
Variablen Identifier (String)
I
Terme Term (Baum)
I
Atome (Identifier, [Term])
I
Regelrümpfe Body ([Atom])
I
Regeln (Atom, Body)
Fakten (Atom, [])
I
Anfragen (Regeln mit leerem Kopf) Body
I
Programme [Regel]
I
Substitutionen Map s Term
192
Datentypen in Haskell
data Term = App String [ Term ]
| Var String
data Atom = Atom String [ Term ]
data Body = Body [Atom]
data Rule = Fact Atom
| Rule Atom Body
data Query = Query Body
data PQProg = PQ [Rule] Query
Parser dafür im voriger Vorlesung
(ähnlich in PParse.hs und Program.hs)
193
Wiederholung Unifikation
Substitution: partielle Funktion θ : X → Term(Σ, X ), wobei
keine Variable x, für welche θ(x) definiert ist, für
ein y ∈ X in θ(y ) vorkommt,
Notation: [x 7→ t1 , y 7→ t2 , . . .]
Unifikator der Terme (Atome, Literale) s und t:
Substitution θ mit θ(s) = θ(t)
mgu(s, t) allgemeinster Unifikator der Terme (Atome,
Literale) s und t:
Unifikator θ für s und t, so dass zu jedem
Unifikator σ für s und t eine Substitution ρ für s
und t existiert, so dass gilt:
σ(s) = ρ(θ(s))
(analog ggT zweier natürlicher Zahlen)
194
Beispiele
I
s = f (x, g(y )), t = f (g(z), z)
Substitution σ(x) = g(g(f (a, a))), σ(y ) = f (a, a)),
σ(z) = g(f (a, a)) ist Unifikator
Substitution σ(x) = g(g(y )), σ(z) = g(y ) ist allgemeinster
Unifikator
I
p(x), p(f (y ))
Substitution σ(x) = f (f (a)), σ(y ) = f (a) ist Unifikator
Substitution σ(x) = f (y ), σ(y ) = y ist allgemeinster
Unifikator
I
p(f (a), g(x)), p(f (z), s(f (z)))
195
Substitutionen in Haskell
Datentyp:
type Substitution = Map Identifier Term
Anwendung auf Term:
apply :: Substitution -> Term -> Term
apply sub t = case t of
Var v -> case M.lookup v sub of
Just t’ -> t’
Nothing -> t
App f xs -> App f $ map ( apply sub ) xs
Nacheinanderausführung:
times
times
[
,
,
]
:: Substitution -> Substitution -> Substitution
s t = M.unions
chained s t
s ‘without‘ M.keysSet t
t ‘without‘ M.keysSet s
(in Substitution.hs)
196
Wiederholung Unifikationsalgorithmus
zur Bestimmung des mgu (sofern dieser existiert)
Eingabe: Terme (Atome, Literale) s, t
Ausgabe: (unifizierbar, mgu(s, t)), falls mgu(s, t) existiert,
sonst nicht unifizierbar
Algorithmus (rekursiv) : unifiziere(s, t)
BF1 falls s, t Konstanten:
falls s = t: (unifizierbar, mgu(s, t) = []),
sonst nicht unifizierbar
BF2 falls s Variable, t Konstante:
[s 7→ t] in θ einfügen und auf alle rechten Seiten in θ
anwenden
BF3 falls s Variable, t = f (t1 , . . . , tn ):
falls s nicht in t vorkommt: mgu(s, t) = [s 7→ t],
sonst nicht unifizierbar
RF falls s = g(s1 , . . . , sm ), t = f (t1 , . . . , tn ):
falls m 6= n oder f 6= g: nicht unifizierbar
sonst θ = unifiziere(s1 , t1 ), . . . , unifiziere(sn , tn )
197
Beispiele
allgemeinste Unifikatoren von
1. P(a, x), P(y , y )
2. P(g(x), z), P(g(y ), g(z))
3. P(g(x), y ), P(y , h(x))
4. P(y , f (a, z)), P(b, f (a, b))
5. P(y , f (x, y )), P(b, f (a, y ))
6. P(y , f (x, x)), P(b, f (a, y ))
198
Unifikation in Haskell
mgu :: Term -> Term -> Maybe Substitution
mgu s t | s == t = return $ M.empty
mgu ( Var v ) t = do
guard $ not $ S.member v $ variables t
return $ M.fromList [ (v, t) ]
mgu t ( Var v ) = mgu ( Var v ) t
mgu ( App f xs ) ( App g ys ) = do
guard $ f == g
mgu_for_list xs ys
mgu_for_list [] [] = return M.empty
mgu_for_list (x:xs) (y:ys) = do
sub1 <- mgu_for_list xs ys
sub2 <- mgu ( apply sub1 x ) ( apply sub1 y )
return $ times sub1 sub2
(in Unify.hs)
199
Wiederholung: aussagenlogische Resolution
Φ |= ψ
gdw. leere Klausel (f) aus Φ ∪ {¬ψ} durch Resolution
ableitbar
Wiederholte Anwendung der Resolutionsregel
{ψ ∨ p, ¬p ∨ η} |= ψ ∨ η
Beispiele:
I
(¬p ∧ ¬q ∧ r ) ∨ (¬p ∧ ¬r ) ∨ (q ∧ r ) ∨ p allgemeingültig
I
{a ∨ b ∨ c, (a ∨ b) → d, ¬c ∧ e} |= d ∧ e
200
Grundresolution
Idee: implizite Übersetzung in Aussagenlogik
I
Instanziierung aller Regeln.
I
Grundterme als Aussagenvariablen
I
Herbrand-Struktur.
Unerfüllbarkeitstest durch aussagenlogische Resolution
201
Prädikatenlogische Resolution
Berechnung einer prädikatenlogischen Resolvente der
0 :
Klauseln l1 ∨ . . . ∨ ln } und l10 ∨ . . . ∨ lm
I
Variablenumbenennung (Klauseln haben keine
gemeinsamen Variablen)
I
Bestimmung eines allgemeinsten Unifikators σ für ein Paar
von Literalen li und ¬lj0
I
Resolvente: σ(l1 ) ∨ . . . ∨ σ(li−1 )∨)σ(li+1 ) ∨ . . . ∨ σ(ln ) ∨
0 ) ∨ σ(l 0 ) ∨ . . . ∨ σ(l 0 )
σ(l10 ) ∨ . . . ∨ σ(lj−1
m
j+1
202
Beispiel
Klauselmenge
Φ = {P(x, b) ∨ P(a, y ) ∨ Q(x, f (y )), ¬P(z, w), ¬Q(w, z)}
Resolution:
positive Literale P(x, b), P(a, y )
negatives Literal ¬P(z, w)
Substitution σ = [x 7→ a, y 7→ b, z 7→ a, w 7→ b]
Resolvente Q(a, f (b)) ∨ ¬Q(b, a)
203
SLD-Resolution
für Mengen von Hornklauseln
Auswahl der angewendeten Regeln in einer festen Reihenfolge:
I
erste anwendbare Regel im Programm,
I
in jedem Schritt entsteht eine Hornklausel
I
neu erzeugte Regel sofort angewenden
I
zuerst das erste Rumpf-Literal resolvieren
I
Auswahl nur für dessen Resolutions-Partner (Suchbaum,
meist Tiefensuche)
(immer Substitution β mitführen)
204
Suche in Haskell
Modellierung von Suche / Nichtdeterminismus in Haskell:
Listen-Monade
Liste von Resultaten, wie z.B. bei Berechnung aller
Permutationen einer Liste
import Data.List
perm :: Eq a => [a] -> [[a]]
perm [] = [[]]
perm xs = do
x <- xs
ys <- perm (delete x xs)
return $ (x : ys)
205
Prolog-Interpreter
query :: [ P.Clause ] -> Int -> Terms
-> [ (Substitution, Int) ]
query cs u0 [] = do return ( M.empty, u0 )
query cs u0 (t : ts) =
query_apply cs ( single cs u0 t ) ts
Nichtdeterminismus / Suche nach anwendbarer Regel:
single :: [ P.Clause ] -> Int -> Term
-> [ (Substitution, Int) ]
single cs u0 t = do
c0 <- cs
let c = rename u0 c0
ufs = do
sub <- maybeToList $ mgu t $ P.head c
return ( sub, u0 + 1 )
( sub, u1) <- query_apply cs ufs $ P.body c
let vs = S.unions $ map variables
$ P.head c : P.body c
return ( cleanup vs sub, u1 )
(in Eval.hs)
206
Ideales und Reales Prolog
wie hier definiert (ideal):
I
Semantik ist deklarativ
I
Reihenfolge der Regeln im Programm und Atome in
Regel-Rumpf beeinflusst Effizienz, aber nicht Korrektheit
reales Prolog:
I cut (!) zum Abschneiden der Suche
I
I
green cut: beeinflusst Effizienz
red cut: ändert Semantik
merke: cut ≈ goto, grün/ rot schwer zu unterscheiden
I
Regeln mit Nebenwirkungen (u. a. für Ein/Ausgabe)
für beides: keine einfache denotationale Semantik
207
Herunterladen