© Patrick Blackburn, Johan Bos & Kristina Striegnitz Föreläsning 3: rekursion Teori –Introducera rekursiva definitioner i Prolog –Fyra exempel –Visa att det kan finnas diskrepanser mellan Prolog-programmets deklarativa och procedurala betydelse!
© Patrick Blackburn, Johan Bos & Kristina Striegnitz Rekursiva definitioner Prolog-predikat kan definieras rekursivt Ett predikat är rekursivt definierat om en eller flera regler i dess definition refererar till detta predikat.
© Patrick Blackburn, Johan Bos & Kristina Striegnitz Exempel 1: Eating isDigesting(X,Y):- justAte(X,Y). isDigesting(X,Y):- justAte(X,Z), isDigesting(Z,Y). justAte(mosquito,blood(john)). justAte(frog,mosquito). justAte(stork,frog). ?-
© Patrick Blackburn, Johan Bos & Kristina Striegnitz En bild av läget... X Y justAte isDigesting ✚
© Patrick Blackburn, Johan Bos & Kristina Striegnitz En bild av läget... X Y justAte isDigesting X Z justAte isDigesting Y ✚ myggan som drack Johns blod
© Patrick Blackburn, Johan Bos & Kristina Striegnitz Exempel 1: Eating isDigesting(X,Y):- justAte(X,Y). isDigesting(X,Y):- justAte(X,Z), isDigesting(Z,Y). justAte(mosquito,blood(john)). justAte(frog,mosquito). justAte(stork,frog). ?- isDigesting(stork,mosquito).
© Patrick Blackburn, Johan Bos & Kristina Striegnitz En annan rekursiv definition p:- p. ?-
© Patrick Blackburn, Johan Bos & Kristina Striegnitz En annan rekursiv definition p:- p. ?- p.
© Patrick Blackburn, Johan Bos & Kristina Striegnitz En annan rekursiv definition p:- p. ?- p. ERROR: out of memory
© Patrick Blackburn, Johan Bos & Kristina Striegnitz Exempel 2: descendant child(bridget,caroline). child(caroline,donna). descend(X,Y):- child(X,Y). descend(X,Y):- child(X,Z), child(Z,Y). Tolkning av child(X, Y): “X has_child Y”
© Patrick Blackburn, Johan Bos & Kristina Striegnitz Exempel 2: Descendant child(bridget,caroline). child(caroline,donna). descend(X,Y):- child(X,Y). descend(X,Y):- child(X,Z), child(Z,Y). Tolkning av descend(X, Y): “Y descends from X”
© Patrick Blackburn, Johan Bos & Kristina Striegnitz Exempel 2: Descendant child(anna,bridget). child(bridget,caroline). child(caroline,donna). child(donna,emily). descend(X,Y):- child(X,Y). descend(X,Y):- child(X,Z), child(Z,Y). anna bridget caroline donna emily
© Patrick Blackburn, Johan Bos & Kristina Striegnitz Exempel 2: Descendant child(anna,bridget). child(bridget,caroline). child(caroline,donna). child(donna,emily). descend(X,Y):- child(X,Y). descend(X,Y):- child(X,Z), child(Z,Y). ?- descend(anna,donna). no ?- anna bridget caroline donna emily
© Patrick Blackburn, Johan Bos & Kristina Striegnitz Exempel 2: Descendant child(anna,bridget). child(bridget,caroline). child(caroline,donna). child(donna,emily). descend(X,Y):- child(X,Y). descend(X,Y):- child(X,Z), child(Z,Y). descend(X,Y):- child(X,Z), child(Z,U), child(U,Y). ?- anna (X) bridget (Z) caroline (U) donna (Y) emily
© Patrick Blackburn, Johan Bos & Kristina Striegnitz Exempel 2: Descendant child(anna,bridget). child(bridget,caroline). child(caroline,donna). child(donna,emily). descend(X,Y):- child(X,Y). descend(X,Y):- child(X,Z), descend(Z,Y). ?- anna bridget caroline donna emily
© Patrick Blackburn, Johan Bos & Kristina Striegnitz Exempel 2: Descendant child(anna,bridget). child(bridget,caroline). child(caroline,donna). child(donna,emily). descend(X,Y):- child(X,Y). descend(X,Y):- child(X,Z), descend(Z,Y). ?- descend(anna,donna). anna bridget caroline donna emily
© Patrick Blackburn, Johan Bos & Kristina Striegnitz Sökträd Rita sökträdet för ?- descend(anna,donna). anna bridget caroline donna emily child(anna,bridget). child(bridget,caroline). child(caroline,donna). child(donna,emily). descend(X,Y):- child(X,Y). descend(X,Y):- child(X,Z), descend(Z,Y).
Sökträd © Patrick Blackburn, Johan Bos & Kristina Striegnitz descend(anna, donna)? child(anna, donna)? child(anna,_G395), descend(_G395, donna)? r1r2 Fchild(anna, bridget) descend(bridget, donna)? child(bridget, donna)? r1 F child(bridget,_G395), descend(_G395, donna)? r2
Sökträd © Patrick Blackburn, Johan Bos & Kristina Striegnitz r1r2 child(bridget,_G395), descend(_G395, donna)? child(bridget, caroline)descend(caroline, donna)? child(caroline, donna)?child(caroline,_G395), descend(_G395, donna)? r1r2 Glöm inte att prolog söker alla sätten att bevisa målet! true
Sökträd © Patrick Blackburn, Johan Bos & Kristina Striegnitz r1 r2 child(caroline,_G395), descend(_G395, donna)? r1r2 child(caroline, donna)descend(donna, donna)? child(donna, donna)? F child(emily,_G395), descend(_G395, donna)? child(donna, emily)descend(emily, donna)? r1r2 child(emily, donna)? F r1 child(donna,_G395), descend(_G395, donna)? r2 F
Trace descend(anna, donna). © Patrick Blackburn, Johan Bos & Kristina Striegnitz trace] ?- descend(anna, donna). Call: (6) descend(anna, donna) ? creep Call: (7) child(anna, donna) ? creep Fail: (7) child(anna, donna) ? creep Redo: (6) descend(anna, donna) ? creep Call: (7) child(anna, _G415) ? creep Exit: (7) child(anna, bridget) ? creep Call: (7) descend(bridget, donna) ? creep Call: (8) child(bridget, donna) ? creep Fail: (8) child(bridget, donna) ? creep Redo: (7) descend(bridget, donna) ? creep Call: (8) child(bridget, _G415) ? creep Exit: (8) child(bridget, caroline) ? creep Call: (8) descend(caroline, donna) ? creep Call: (9) child(caroline, donna) ? creep Exit: (9) child(caroline, donna) ? creep Exit: (8) descend(caroline, donna) ? creep Exit: (7) descend(bridget, donna) ? creep Exit: (6) descend(anna, donna) ? creep true ;
Trace descend(anna, donna). © Patrick Blackburn, Johan Bos & Kristina Striegnitz Redo: (8) descend(caroline, donna) ? creep Call: (9) child(caroline, _G415) ? creep Exit: (9) child(caroline, donna) ? creep Call: (9) descend(donna, donna) ? creep Call: (10) child(donna, donna) ? creep Fail: (10) child(donna, donna) ? creep Redo: (9) descend(donna, donna) ? creep Call: (10) child(donna, _G415) ? creep Exit: (10) child(donna, emily) ? creep Call: (10) descend(emily, donna) ? creep Call: (11) child(emily, donna) ? creep Fail: (11) child(emily, donna) ? creep Redo: (10) descend(emily, donna) ? creep Call: (11) child(emily, _G415) ? creep Fail: (11) child(emily, _G415) ? creep Fail: (10) descend(emily, donna) ? creep Fail: (9) descend(donna, donna) ? creep Fail: (8) descend(caroline, donna) ? creep Fail: (7) descend(bridget, donna) ? creep Fail: (6) descend(anna, donna) ? creep false. Kunde inte bevisas på ett annat sätt.
© Patrick Blackburn, Johan Bos & Kristina Striegnitz Exempel 3: Successor Anta att vi använder följande sätt att skriva nummer: 1. 0 är ett nummer. 2. Om X är ett nummer, så är även succ(X).
© Patrick Blackburn, Johan Bos & Kristina Striegnitz Exempel 3: Successor numeral(0). numeral(succ(X)):- numeral(X).
© Patrick Blackburn, Johan Bos & Kristina Striegnitz Exempel 3: Successor numeral(0). numeral(succ(X)):- numeral(X). ?- numeral(succ(succ(succ(0)))). yes ?-
© Patrick Blackburn, Johan Bos & Kristina Striegnitz Exempel 3: Successor numeral(0). numeral(succ(X)):- numeral(X). ?- numeral(X).
© Patrick Blackburn, Johan Bos & Kristina Striegnitz Exempel 3: Successor numeral(0). numeral(succ(X)):- numeral(X). ?- numeral(X). X=0; X=succ(0); X=succ(succ(0)); X=succ(succ(succ(0))); X=succ(succ(succ(succ(0))))
© Patrick Blackburn, Johan Bos & Kristina Striegnitz Exempel 4: Addition ?- add(succ(succ(0)),succ(succ(succ(0))), Result). Result=succ(succ(succ(succ(succ(0))))) yes
© Patrick Blackburn, Johan Bos & Kristina Striegnitz Exempel 4: Addition add(0,X,X). %% base clause ?- add(succ(succ(0)),succ(succ(succ(0))), Result). Result=succ(succ(succ(succ(succ(0))))) yes
© Patrick Blackburn, Johan Bos & Kristina Striegnitz Exempel 4: Addition add(0,X,X). %% base clause add(succ(X),Y,succ(Z)):- %% recursive clause add(X,Y,Z). ?- add(succ(succ(0)),succ(succ(succ(0))), Result). Result=succ(succ(succ(succ(succ(0))))) yes succ(X) + Y blir succ(Z) om X + Y är Z.
© Patrick Blackburn, Johan Bos & Kristina Striegnitz Sökträd Rita sökträdet för add(succ(succ(0)), succ(succ(succ(0))), R).
© Patrick Blackburn, Johan Bos & Kristina Striegnitz Sökträd add(succ(succ(0)), succ(succ(succ(0))), R). add(0,X,X). add(succ(X),Y,succ(Z)):- add(X,Y,Z). add((succ(0), succ(succ(succ(0))), R1). add(0, succ(succ(succ(0))), R2). R = succ(R1) R1 = succ(R2) basfall: R2 = succ(succ(succ(0)))
© Patrick Blackburn, Johan Bos & Kristina Striegnitz Sökträd add(succ(succ(0)), succ(succ(succ(0))), R). add(0,X,X). add(succ(X),Y,succ(Z)):- add(X,Y,Z). add((succ(0), succ(succ(succ(0))), R1). add(0, succ(succ(succ(0))), R2). R = succ(R1) R1 = succ(R2) basfall: R2 = succ(succ(succ(0))) R1 = succ (succ(succ(succ(0)))) R = succ (succ(succ(succ(succ(0)))))
Trace... © Patrick Blackburn, Johan Bos & Kristina Striegnitz [trace] ?- add(succ(succ(0)), succ(succ(succ(0))), Z). Call: (6) add(succ(succ(0)), succ(succ(succ(0))), _G348) ? creep Call: (7) add(succ(0), succ(succ(succ(0))), _G424) ? creep Call: (8) add(0, succ(succ(succ(0))), _G426) ? creep Exit: (8) add(0, succ(succ(succ(0))), succ(succ(succ(0)))) ? creep Exit: (7) add(succ(0), succ(succ(succ(0))), succ(succ(succ(succ(0))))) ? creep Exit: (6) add(succ(succ(0)), succ(succ(succ(0))), succ(succ(succ(succ(succ(0)))))) ? creep Z = succ(succ(succ(succ(succ(0))))).
© Patrick Blackburn, Johan Bos & Kristina Striegnitz Prolog och logik Prolog var det första rimliga försöket att skapa ett språk för logikprogrammering –Programmeraren ger en deklarativ specifikation av problemet, mha logikens språk –Programmeraren borde inte behöva berätta för datorn vad den ska göra –För att få information ger programmeraren helt enkelt en förfrågning
© Patrick Blackburn, Johan Bos & Kristina Striegnitz Prolog och logic Prolog innebär flera viktiga steg i denna riktning, men trots allt är Prolog inte ett fullständigt logikprogrammeringsspråk! Prolog har ett specifikt sätt att besvara förfrågningar: –Sök kunskapsbasen uppifrån ner –Processera satserna från vänster till höger –“Backtracka” för att ersätta dåliga val eller för att söka efter flera svar/bevis.
© Patrick Blackburn, Johan Bos & Kristina Striegnitz descend1.pl child(anna,bridget). child(bridget,caroline). child(caroline,donna). child(donna,emily). descend(X,Y):- child(X,Y). descend(X,Y):- child(X,Z), descend(Z,Y). ?- descend(A,B). A=anna B=bridget
© Patrick Blackburn, Johan Bos & Kristina Striegnitz descend2.pl child(anna,bridget). child(bridget,caroline). child(caroline,donna). child(donna,emily). descend(X,Y):- child(X,Z), descend(Z,Y). descend(X,Y):- child(X,Y). ?- descend(A,B). A=anna B=emily
© Patrick Blackburn, Johan Bos & Kristina Striegnitz descend2.pl child(anna,bridget). child(bridget,caroline). child(caroline,donna). child(donna,emily). descend(X,Y):- child(X,Z), descend(Z,Y). descend(X,Y):- child(X,Y). ?- descend(A,B). A=anna B=emily Ordningen där svaren ges ändras.
© Patrick Blackburn, Johan Bos & Kristina Striegnitz descend2.pl child(anna,bridget). child(bridget,caroline). child(caroline,donna). child(donna,emily). descend(X,Y):- child(X,Z), descend(Z,Y). descend(X,Y):- child(X,Y). ?- descend(A,B). A=anna B=emily Att ändra ordningen i vilken reglerna ges brukar inte annars ändra på programmets beteende.
© Patrick Blackburn, Johan Bos & Kristina Striegnitz descend3.pl child(anna,bridget). child(bridget,caroline). child(caroline,donna). child(donna,emily). descend(X,Y):- descend(Z,Y), child(X,Z). descend(X,Y):- child(X,Y). ?- descend(A,B). ERROR: OUT OF LOCAL STACK Vi har ändrat på ordningen av delmålen INNE i en regel
© Patrick Blackburn, Johan Bos & Kristina Striegnitz descend3.pl child(anna,bridget). child(bridget,caroline). child(caroline,donna). child(donna,emily). descend(X,Y):- descend(Z,Y), child(X,Z). descend(X,Y):- child(X,Y). ?- descend(A,B). ERROR: OUT OF LOCAL STACK Det första delmålet är rekursivt => evig rekursion!!
descend3.pl © Patrick Blackburn, Johan Bos & Kristina Striegnitz descend(anna, donna) descend(X,Y):- descend(Z,Y), child(X,Z) descend(W4, donna) child(anna, W1) descend(W2, donna) descend(W3, donna) descend(W1, donna)... En vänster- rekursiv regel
© Patrick Blackburn, Johan Bos & Kristina Striegnitz descend4.pl child(anna,bridget). child(bridget,caroline). child(caroline,donna). child(donna,emily). descend(X,Y):- child(X,Y). descend(X,Y):- descend(Z,Y), child(X,Z). ?- descend(A,B). Vissa svar hittas, andra leder till evig rekursion
Övning Utgå från följande kunskapsbas: © Patrick Blackburn, Johan Bos & Kristina Striegnitz mother_of(alli, carl). mother_of(lena, anna). mother_of(lena, kajsa). mother_of(lena, ellen). mother_of(lena, olle). mother_of(ulla, janne). mother_of(ulla, brita). mother_of(eva, lisa). mother_of(eva, petter). father_of(carl, erik). father_of(carl, lena). father_of(erik, stig). father_of(erik, lars). father_of(stig, janne). father_of(stig, brita). father_of(lars, lisa). father_of(lars, petter).
Övning Skriv reglerna (predikaten) för: –paternal_grandfather_of(X,Y) –maternal_grandfather_of(X,Y) –paternal_grandmother_of(X,Y) –maternal_grandmother_of(X,Y) –full_siblings(X, Y) –half_siblings(X,Y) © Patrick Blackburn, Johan Bos & Kristina Striegnitz
Sammandrag Idag har vi sett på rekursiva predikat Vi har också diskuterat skillnaden mellan ett Prolog-programs deklarativa och procedurala betydelse. Vi har identifierat några av Prologs svagheter som ett logikprogrammeringsspråk.
© Patrick Blackburn, Johan Bos & Kristina Striegnitz Nästa FL... Introducerar listorna i Prolog –Viktig rekursiv datastruktur i Prolog- programmering –Definierar predikatet member/2, ett grundläggande Prolog-verktyg för listhantering –Diskuterar hur man rekursivt bearbetar listorna –Extra: prolog i problemlösning Läckert !