labgrupper: 2 pers/grupp fr o m lab 2 schema ENKÄT
varför logikprogrammering? Staffan Larsson logikprogrammering 14/
Programmeringsspråk Procedurella/imperativa språk. Man beskriver hur problemet ska lösas. –Exempel: basic, pascal, c, c++, java, ada, python, perl,... Deklarativa språk. Man försöker istället beskriva vad problemet är, och överlämnar åt datorn att bestämma exakt hur. –Funktionella språk. Exempel: lisp, scheme, ml, haskell,... –Logiska språk. Exempel: prolog, mercury, oz, (sql),...
fördelar med logiska språk enkel och överskådlig kod –jämfört med imperativa program –(se exempel) speciellt utformat för –logisk inferens –språkbehandling (t ex DCG) vilket råkar passa särskilt bra för –kognitionsvetenskap –datalingvistik
Prolog i kognitionsvetenskap en central metodik i kognitionsvetenskap: –hitta på en teori om någon kognitiv förmåga (slutsatsdragning, planering, etc) –formalisera teorin i något logiskt ramverk (t ex predikatlogik, modallogik) axiom slutledningsregler Prolog –tillåter program som ligger mycket nära den logiska formaliseringen –gör det enkelt att implementera och testa och experimentera med en sådan teori axiom -> fakta slutledningsregler -> prologregler
Prolog i datalingvistik en central metodik i datalingvistik: –hitta på en teori om någon språklig förmåga (tolkning, parsning, generering, etc.) –formalisera teorin i något logiskt eller grammatiskt ramverk (t ex DCG, predikatlogik) axiom + slutledningsregler; semantisk representation grammatikregler + tolkningsregler Prolog –tillåter program som ligger mycket nära den grammatiska / logiska formaliseringen –gör det enkelt att implementera och testa och experimentera med en sådan teori axiom -> fakta, slutledningsregler -> prologregler grammatikregler -> DCG
repetition: ackumulatorer
iteration & rekursion prolog tillhandahåller inte iteration vi itererar med hjälp av den mer generella rekursionen –men: ett rekursivt program växer linjärt. en iterativ procedur använder en konstant mängd utrymme –oberoende av antal iterationer ett sätt att göra rekursiva procedurer iterativa är att använda ackumulatorer ackumulatorer kan även användas för att öka effektiviteten
3. reverse [a,b,c,d] ska reverseras till [d,c,b,a] två versioner: –naiveRev/2 –accRev/3 (rev/2)
naiveRev basfall: –om vi reverserar [], så får vi tomma listan ([]) rekursiva fallet: –om vi reverserar [H|Tail], så slutar vi med listan vi får av att reversera Tail och sätta ihop den med H.
naiveRev/2 alltså: naiveRev([],[]). naiveRev([H|Tail],R) :- naiveRev(Tail,RevT), append(RevT,[H],R).
trace: naiveRev ?- naiveRev([a,b,c],R). 1 1 Call: naiveRev([a,b,c],_227) ? 2 2 Call: naiveRev([b,c],_699) ? 3 3 Call: naiveRev([c],_1069) ? 4 4 Call: naiveRev([],_1438) ? 4 4 Exit: naiveRev([],[]) ? 5 4 Call: append([],[c],_1069) ? 5 4 Exit: append([],[c],[c]) ? 3 3 Exit: naiveRev([c],[c]) ? 6 3 Call: append([c],[b],_699) ? 7 4 Call: append([],[b],_3515) ? 7 4 Exit: append([],[b],[b]) ? 6 3 Exit: append([c],[b],[c,b]) ? 2 2 Exit: naiveRev([b,c],[c,b]) ? 8 2 Call: append([c,b],[a],_227) ? 9 3 Call: append([b],[a],_5245) ? 10 4 Call: append([],[a],_5609) ? 10 4 Exit: append([],[a],[a]) ? 9 3 Exit: append([b],[a],[b,a]) ? 8 2 Exit: append([c,b],[a],[c,b,a]) ? 1 1 Exit: naiveRev([a,b,c],[c,b,a]) ? R = [c,b,a]
resultat 20 steg i tracen
accRev/3 accRev([H|Tail],A,R) :- accRev(Tail,[H|A],R). accRev([],A,A).
trace: accRev ?- accRev([a,b,c],[],R). 1 1 Call: accRev([a,b,c],[],_491) ? 2 2 Call: accRev([b,c],[a],_491) ? 3 3 Call: accRev([c],[b,a],_491) ? 4 4 Call: accRev([],[c,b,a],_491) ? 4 4 Exit: accRev([],[c,b,a],[c,b,a]) ? 3 3 Exit: accRev([c],[b,a],[c,b,a]) ? 2 2 Exit: accRev([b,c],[a],[c,b,a]) ? 1 1 Exit: accRev([a,b,c],[],[c,b,a]) ? R = [c,b,a]
resultat 8 steg i tracen
accRev listaackumulator [a,b,c][] [b,c][a], dvs: [a|[]] [c][b,a] [][c,b,a] ackumulatorn kopieras sedan till accRev/3 tredje argument –accRev([],A,A). vi effektiviserar alltså bort ’append’
jämförelse naiveRev (3 element):20 instruktioner accRev (3 element): 8 instruktioner naiveRev (8 element):90 instruktioner accRev (8 element):18 instruktioner och som sagt: minnesutrymmet växer linjärt i naiveRev, men är konstant i accRev
termer & unifiering logikprogrammering Staffan Larsson 14/
att läsa Bratko: – , , SICStus-manualen –M4.1, M8.3
Termer Alla objekt i Prolog är termer, t.ex. alla argument till predikat. En term kan vara en av fyra möjliga saker: –Atomer –Tal –Variabler –Sammansatta termer
Termer, forts. Atomer –börjar med liten bokstav och fortsätter med bokstäver/siffror/understreck. –ex: pelle, lisa, en_bil, boeing747. –Dessutom kan man stoppa in nästan vad som helst inuti enkla citationstecken för att få en atom. –ex: 'pelle', 'Lisa', '+' eller '123'.
termer, forts. Tal –består enbart av siffror, och kan föregås av minustecken. –ex: 123, 0 eller -34. –Dessutom kan talet vara ett decimaltal –ex: eller Variabler –börjar med stor bokstav (eller understreck) och fortsätter med bokstäver/siffror/understreck. –ex: Sak, Pelle, CSC455 eller _tjohej.
Sammansatta termer (i kursboken: ”strukturerade objekt”) termer med argument. En sammansatt term består av –ett namn (en atom) –ett antal argument (vilka termer som helst) Namnet på termen kallas funktor antalet argument kallas aritet eller ställighet. Syntax: –Namn(Arg1, Arg2, …, ArgN) –d v s samma som för predikat
databas över föreläsningar som ska hållas på universitetet. –I databasen ska finnas information om vilken kurs föreläsningen går i, vem som är föreläsare, vilken tid föreläsningen ska gå, och i vilken lokal. vi behöver alltså ett predikat enligt följande relationsschema: % föreläsning(?Kurs, ?Föreläsare, ?Tid, ?Lokal) exempel
Men antag nu att –olika institutioner kan ha kurser med samma namn, t.ex. kursen "introduktion" kan finnas både på datavetenskap och på lingvistik. Alltså måste också information om institutionen finnas med i kursinformationen. Dessutom har kurser kurskoder. –Det kan finnas flera föreläsare som heter samma sak, alltså vill vi dessutom ha ett telefonnummer kopplat till personen, samt kunna skilja på för- och efternamn. exempel, forts.
antag vidare att –Tiden ska inte bara specificera ett datum, utan även två klockslag, ett för när det ska börja och ett för när det är slut. –Och såväl datum som klockslag är sammansatt information med dag-månad- år eller timme-minut. –Lokalen måste inte bara specificera ett namn, t.ex. "hörsalen", utan även det hus som lokalen finns i, t.ex. "matematiskt centrum", eller "humanisten".
exempel, forts. Alltså blir alla argumenten sammansatta termer relationsschema % föreläsning(?Kurs, ?Föreläsare, ?Tid, ?Lokal) % där Kurs = kurs(Institution, Kursnamn, Kurskod) % Föreläsare = person(Förnamn, Efternamn, Telefonnummer) % Tid = tid(Datum, StartKlockslag, SlutKlockslag) % där Datum = datum(Dag, Månad, År) % Klockslag = klockslag(Timme, Minut) % Lokal = lokal(Byggnad, Lokalnamn)
exempel, forts. Dagens föreläsning kan då se ut som följer i databasen. föreläsning( kurs(datavetenskap, logikprogrammering, inl070), person(staffan, larsson, ), tid( datum(14,okt,2002), klockslag(13,15), klockslag(15,00)), lokal(matematiskt_centrum, hörsalen) ).
Listor En lista är helt enkelt en sammansatt term –en speciell funktor '.' –två argument det första argumentet är huvudet det andra är svansen varför har man valt ett så dumt namn som '.' ? –det är inte är meningen att man ska använda sig av det sättet att skriva listor. –Så man har infört ett förenklat sätt att skriva listor, med hjälp av hakparenteser [...] som vi är vana vid. exempel: ?- Xs = '.'(a,[b, c]). Xs = [a,b,c]; ?- Xs = '.'(a, '.'(b, '.'('c', []))). Xs = [a,b,c];
Matchning / unifiering likhetstest för sammansatta termer –funktorerna/namnen måste vara lika –de måste ha lika många argument –varje argument måste vara lika.
Alltså, två termer är lika, X=Y, om något av följande gäller: 1.någon är en oinstansierad variabel –den kommer att instansieras till den andra termen. 2.båda är atomer som är lika. 3.båda är tal som är lika. 4.båda är sammansatta termer med likadana funktorer och samma aritet, dessutom är motsvarande argument lika. –exempel: ?- datum(15, X, Y) = datum(Z, okt, 2001). X = okt, Y = 2001, Z = 15 ?- tid(Datum, Tid, Tid) = tid(datum(_,okt,_), klockslag(13,_), klockslag(_,15)) Datum = datum(_, okt, _), Tid = klockslag(13, 15)
Andra jämförelser mellan termer Två termer är identiska om de är instansierade till samma sak, –Identitet testas med == –motsatsen är \== –två variabler som har unifierats är därefter identiska exempel ?- lisa==lisa. yes ?- X==X. yes ?- X==Y. no ?- X=Y, X==Y. yes
För att ta reda på om en variabel är instansierad eller inte så kan man använda predikatet var/1, vilket har som motsats nonvar/1. exempel: –?- var(X). –yes –?- X=3, var(X). –no –?- X=Y, var(X). –yes –?- var([X]). –no diverse predikat för termer
diverse predikat för termer, forts. predikat för att kolla om en term är av en viss sort ?- number(34). yes ?- atom(pelle). yes ?- compound("lisa"). yes ?- ground([X]). no ?- ground([3]). yes
Predikaten arg/3 och functor/3 arg(+ArgNr,+Term,?Arg) –hämtar ett givet argument från en sammansatt term. –exempel: ?- arg(3, datum(15,okt,2001), X). X = 2001 Tänk på att huvudet i en lista är första argumentet, och svansen det andra argumentet. En lista har inte tre argument. –exempel: ?- arg(1, "pelle", X). X = p ?- arg(2, "pelle", X). X = [e,l,l,e] ?- arg(3, "pelle", X). no
arg/3 och functor/3 forts. Observera att termen måste vara sammansatt, och den får inte vara oinstansierad. exempel: ?- arg(1, lisa, X). {TYPE ERROR: arg(1,lisa,X) - arg 2: expected compound, found lisa} ?- arg(1, Lisa, X). {INSTANTIATION ERROR: arg(1,Lisa,X) - arg 2}
arg/3 och functor/3 forts. Predikatet functor/3 kan användas på två sätt –ta reda på namnet och ariteten av en term functor(+Term,?Namn,?Aritet). exempel ?- functor(datum(15,okt,2001), Namn, Aritet). Namn = datum, Aritet = 3 ?- functor("lisa", Namn, Aritet). Namn = '.', Aritet = 2 –skapa en term om man känner till namnet och ariteten functor(?Term,+Namn,+Aritet). exempel ?- functor(Term, datum, 3). Term = datum(_, _, _) ?- functor(Term, '.', 2). Term = [_|_]
Term =.. [Funktor, Arg1, …, ArgN] ?- f(a,b) =.. L L= [f,a,b] ?- T =.. [rectangle, 3, 5]. T= rectangle(3,5) ?- Z =.. [p, X, f(X,Y)]. Z = p(X, f(X, Y)) sammansättning och isärplockning av termer