390 likes | 634 Views
labgrupper: 2 pers/grupp fr o m lab 2 schema ENKÄT. varför logikprogrammering?. Staffan Larsson logikprogrammering 14/10 2002. Programmeringsspråk. Procedurella/imperativa språk. Man beskriver hur problemet ska lösas. Exempel: basic, pascal, c, c++, java, ada, python, perl, ...
E N D
labgrupper: 2 pers/grupp fr o m lab 2 • schema • ENKÄT
varför logikprogrammering? Staffan Larsson logikprogrammering 14/10 2002
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
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 lista ackumulator [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/10 2002
att läsa • Bratko: • 2.1-2.2, 7.2-7.3, • 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: 123.43 eller -3.14. • 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
exempel • 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, forts. • 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, 7734378), 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: • någon är en oinstansierad variabel • den kommer att instansieras till den andra termen. • båda är atomer som är lika. • båda är tal som är lika. • 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
diverse predikat för termer • 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, 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 = [_|_]
sammansättning och isärplockning av termer • 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))