Crash Course in Prolog Peter Funk FUKO HT2001 IDt, Computer Science and Engineering Mälardalen University Västerås, Sweden Peter.Funk@mdh.se Introduktion till PROLOG, dvs. PROgramming in LOGic Prolog-programmen är deklarativa och består av egenskaper, relationer och regler. Lisp and Prolog är de vanligaste programmeringsspråken för symbolisk AI (artificiell intelligens). Mycket bra för utforskning" och "prototyp programmering". Prolog bygger uteslutande på Horn-satser. Horn-satser är en delmängd till första ordningens predikatlogiken. Viktiga begrepp/områden i Prolog Baskunskaper i Prolog: databaser, listor, metalogiska predikat, ackumulatorer, svansrekursion, (DCG), generate-and-test, sökning. Anknytning till andra områden: Databaser, Expertsystem, Formella språk och automata-teori, (Naturlig språkhantering). Att tänka deklarativt. Ett Logikprogram En beskrivning i en vald logik av en verklig eller tänkt värld. Beskrivning av alla för problemet/uppgiften relevanta relationer mellan objekten i världen (personer, tal, listor, träd, ). Logik och Programmering Imperativa programmeringsspråk; - är i stort en abstraktion av turingmaskin (ett program är instruktioner till en turingmaskin). - har en operationell semantik i termer av vad turingmaskinen ska utföra. - är kontextberoende (vilka operationer som gjorts innan). En logik har 4 delar syntax (för logiska formler) semantik (exakt betydelse) uppsättning axiom (tex. tautologier) inferensregler (exv modus ponens) Logiker: Satslogik, predikatlogik, typad logik, temporallogik (händelser, intervaller, ), modallogik (sanlikheter, kanske, sant i alla världar, ) Framtiden? - Programmering närmar sig mänskligt tänkande: deklarativ kunskapsrepresentation, logik och NL (delmängd av ett naturligt språk kan redan idag översättas till logik och logik kan enkelt översättas till naturligt språk). Ökat intresse för temporallogik. -Alla system (program & hårdvara) som är säkerhetskritiska eller säkerhetskänsliga kräver bevis att de är korrekta. - system im flyg, transport, telecom, medicin, mm är inte längre utvecklade gem att väver in kunskapen i kod till en svårförstålig/svårkontrollerbar form (inte många programmerare gillar idag tanken av att den livsuppehållande hjärt/lungmaskin som används för att hålla dem vid liv skulle styrs med ett av dem utvecklat C program). - Prolog utvecklas, den senaste mest lovande utökningen till Prolog är Constraint Logic Programming (CLP). 1
Dagsläge för Logik och Logikprogrammering: Satslogik och predikatlogik används för formell verifiering av säkerhetskritiska system (landningsställ, ställverk/signalering för rälssystem, hårdvara, mm). Används för hårdvarudesign (TTL-logikkretsar, sant=1=5 volt, falskt=0=0 volt), predikatlogik, temporallogik, modallogik, fuzzy logic, mm börjar användas för specifika tillämpningar. Prolog används för att implementera delmängder av logiker (en skräddarsydd delmängd för en vissa tillämpning). Prolog används för prototyper och även större kommersiella system (länkas till.exe och användaren vet ej att systemet är implementerat i Prolog). Första Erlang interpretatorn utvecklades i Prolog. Grafiska paket, snabb exekvering, bra gränssnitt till andra programmeringsspråk (anropbart och kan anropa exv C rutiner). Används im naturligt språk, tolkning, översättning etc. Gränssnitt till webben (exv. LPA-Prolog). Deklarativ beskrivning ~ Imperativ Exempel på deklarativ beskrivning Hitta alla barnbarn till en viss person X. Deklarativ beskrivning Ett barnbarn till X är ett barn till ett av Xs barn. Imperativ beskrivning För att hitta ett barnbarn till X, hitta först ett barn till X. Hitta därefter ett barn till barnet. Imperativ beskrivning II För att hitta ett barnbarn till X, hitta först en förälder till ett barn och kolla därefter om föräldern är ett barn till X. read(person); for i := 1 to maxbarn do if barn[i,1] = person then for j := 1 to maxbarn do if barn[j,1] = barn[i,2] then writeln(barn[j,2]); fi od fi od Logik: " X " Y ($ Z (barn(x, Z) and barn(z, Y)) fi barnbarn(x, Y)). Prolog: barnbarn(x,y) :- barn(x,z), barn(z,y). Deklarativa och imperativa språk Filosofi Program Exempel Fördelar Imperativa språk Användaren talar om hur problemet ska lösas En sekvens av kommandon Basic, C, C++, Ada, Java, Perl, Phyton, Snabba och specialiserade program Deklarativa språk Användaren talar om vad problemet är En mängd påståenden Prolog, ML, Scheme, Gödel, mercury, Oz, (sql), Generella, läsbara och möjlighet till korrekta program Olika språk paradigmer Ett program skrivet I ett imperativa språk är tvingande, dvs en given exekveringsordning. högnivåinstruktioner till en processor. Ett deklarativt program: säger inget om hur det ska exekveras (i Prolog finns några undantag som lagts till av effektivitetsskäl, pure Prolog är ordningsoberoende). har separerat kontroll från programmet, programmeraren behöver inte bry sig om hur programmet exekveras utan beskriver endas problemet och kunskapen om problemet. Bas och ursprung i logik och hur människan resonerar logiskt. Logikens Historik 400 fk De första grunderna läggs av Aristoteles (axiom, premisser, slutsatser Alla valar är däggdjur" osv). 1930 Området stabiliseras [Gödel, Church, Russel, m.fl.]. (Predikatlogik helt kartlagt Church-Turing-satsen => predikatlogik == beräkningsbara funktionerna) 1960 Automatic Theorem Proving & AI. 1965 Resolution och unifiering [Robinson]. Resolution: en effektiv slutsatsdragning men regler måste skrivas på en speciell form. 1972 Den första Prolog-implementationen [Colmerauer]. 1974 Logikprogrammering (SLD-resolution) [Kowalski] (Algoritm = logik + kontroll, låt datorn bestämma hur problemet löses, dvs exekveringsordning). 1977 Negation (SLDNF-resolution) [Clark]. (SLDNF klarar negativa påståenden "En pingvin kan inte flyga"). 1978 Edinburgh Prolog [Warren] (vanligaste syntaxen idag). 1981 Japanerna annserar sitt 5:e-generationsprojekt: robotik, AI, etc, med logikprogrammering ( huvudresultat : ökad användning av datorer i Japan med Kanji, romaji). 1995 Constraint Logic Programming (CLP), Agent Programmering (logiska bubblor), Några viktiga beteckningar (Logik) Predikatnamn är ett samlingsnamn för egenskapsoch relationsnamn. Predikatnamnet åtföljs av argumenten. Ställighet (=aritet) anger antal argument predikatet har. Ställighet = 0: satslogik (inga argument) Ställighet = 1: egenskap Ställighet = 2: relation Argumenten kallas för termer. En term kan vara konstant, variabel eller en struktur (sammansatt term). 2
Testa Prolog Gratis Prolog för utbildning (Windows): http://www.swi.psy.uva.nl/projects/swi-prolog/ Tar lite plats (någon Meg). Många Prolog introduktioner på webben, sök med www.google.com efter Prolog tutorial introduction EGENSKAPER och RELATIONER man(adam). man(kalle). man(lasse). woman(lisa). woman(eva). Därefter kan vi lägga till relationen förälder. parent(adam,peter). % adam är förälder till peter parent(eva,kalle). parent(eva,lisa). parent(lisa,lasse). parent(kalle, knut). Definition av Regler Varje regel har ett huvud (head) namet som definierar relationen. Varje regel har en kropp (body) själva definitionen av relationen. Definition av mor och far följer nedan: OM M är en kvinna och M är förälder till C så är M mor till C: mother(m,c):- woman(m), parent(m,c). OM F är en man och F är förälder till C så är F far till C: father(f,c):- man(f), parent(f,c). :- betyder logisk implikation, men då det inte finns å tangentbordet har prolog valt :-, betyder logiskt och, både man och parent måste vara sant för att father skall vara sant. Interpretatorn Fakta och regler skrivs i fil som har slutar på.pl Kan släppas på prolog ikonen eller ladda in (se manual). Fråga systemet vem som är kvinna. woman(x). X = lisa? ; X = eva? ; Prolog Prompt: Prolog skriver alltid ut?-. Efter prompten ställer du din fråga. ; frågar efter fler lösningar (ger alternativ lösning om det finns). Vi vill bara veta om det finns någon kvinna. woman(_). child(_). whisky(bowmore). region(bowmore, islay). aalder(bowmore, 12). Har vi whisky från Islay och i så fall hur gammal? region(w, islay), aalder(w, A). Prolog bygger på negation as failure, allt som man inte vet är falskt (lite mer om det sedare). A = 12, W = bowmore? ; W instantieras (binds till) bowmore. 3
whisky(bowmore). region(bowmore, islay). aalder(bowmore, 12). Har vi en whisky som är mer än 8 år gammal? whisky(w), aalder(w, A), A>8. A = 12, W = bowmore? ; Strukturer whisky(bowmore). region(bowmore, islay). aalder(bowmore, 12). smak(bowmore,12, smk(torv(my), roekig(me), fyllig(me)). -(5,4) +(1,*(2,3)) 1 + *(2,3) 1 + 2 * 3 smak(w, _, S). S = smak(torv(my), roekig(me), fyllig(me)), W = bowmore? ; smak(w, _, smk(torv(t), _,_)). T = my, W = bowmore? ; Mer REGLER whisky(bowmore). region(bowmore, islay). aalder(bowmore, 12). smak(bowmore,12, smk(torv(my), roekig(me), fyllig(me)). man(peter). % För alla män M och whisky W gäller det att % M gillar W. gillar(m, W) :- man(m), whisky(w). Vad gillar Peter? gillar(peter, X). X = bowmore? ; 4
man(adam). man(kalle). man(lasse). woman(lisa). woman(eva). woman(mia). parent(adam,lasse). % adam är förälder till lasse parent(eva,kalle). parent(eva,lisa). parent(lisa,lasse). parent(kalle,knut). father(f,c):- man(f), parent(f,c). mother(m,c):- woman(m), parent(m,c). Uppgift 1) Lägg till fakta om att kalle har en dotter mia. 2) Skriv en regel som definierar relationen kusin, dvs tar reda på vem mia är kusin med. Överkurs: 3a) skriv en regel som definierar mormor. 3b) Använd den för att visa att eva är lasses mormor. Använd gärna relationen mother/2 (2 betyder att relationen har två argument). Uppgift lösningsidé (finns många lösningar) kusin(k1, K2):- parent(p1, K1), parent(p2, K2), syskon(p1,p2). Test i Prolog?- kusin(x,y). X = lasse Y = knut ; syskon(s1,s2):- parent(x,s1), parent(x,s2), S1 \== S2. % S1 och S2 får inte vara samma person, % man kan ju inte vara syskon med sig själv Listor [ ] : en tom lista [1, 2, abba] : en lista som innehåller 3 element [[11, 12, 13], [21, 22, 23], [31, 32, 33]] : En 3x3 matris (en lista som innehåller 3 listor som...). Listor Huvud på listan, svansen på listan, jämför CAR och CDR i LISP Dessa två listor är identiska! [a,b,c] = [a [b,c]].?- [a,b,c] = [Huvud Svans]. Huvud=a Svans=[b,c] Ger huvud och svans Några enkla predikat: member % Predikatet medlem % X är medlem i listan om den står först i listan medlem(x, [X Rest]). % Annars är X i resten av listan. medlem(x, [F Rest]) :- medlem(x, Rest). ---- medlem(1, [abba, 1, 3]). Kallas svansrekursion om det sista en regel gör är att anropa sig själv. Detta blir lika effektivt som en loop skriven i C om man skulle vara intresserad av exekveringstid. medlem medlem(x, [abba, 1, 3]). X = abba? ; X = 1? ; X = 3? ; 5
medlem(1, [A, B]). A = 1? ; B = 1? ; medlem Luring, A och B är ju variabler och kan i detta exempel vara vad som helst, exempelvis 1. Därmed kan första elementet i listan vara 1 och andra elementet i listan kan även vara 1. first, second, tail % Det första elementet i listan. first(x, [X _]). % Det andra elementet i listan. second(x, [ _,X _ ]). % Resten av listan. tail(r, [ _ R]). Aritmetik och annat +, -, *, /, sin, cos, tan <, >, >=, =<, =:=, =\= (reducerar höger och vänsterleden). is ==, \== (strikt likhet, olikhet) = (unifiering, det vill säga att Prolog försöker binda alla obundna variabler så långt det går. Lyckas det så lyckas unifieringen). 2 =< 4. 2+2 =:= 4. 2+2 =:= 5. 2+2 =\= sin(0), 0 + 0 =:= sin(0). Trace? - trace, X is sin(4/5), X>2. 1 1 Call: _59 is sin(4/5)? <ENTER> 1 1 Exit: 0.71735609 is sin(4/5)? <ENTER> 2 1 Call: 0.71735609 > 2? <ENTER> 2 1 Fail: 0.71735609 > 2? <ENTER> 1 1 Redo: 0.71735609 is sin(4/5)? <ENTER> 1 1 Fail: _59 is sin(4/5)? <ENTER> Redo betyder att Prolog interpretatorn backtrackar (backar ett eller flera steg för att försöker hitta alternativ lösning). A is B. Uttrycket B beräknas och unifieras med variabeln (eller konstanten) A.? - Area is 3.14 * 5 * 5. Area = 78.5? <ENTER>? - 4 is 4.? X is 2 + M. ERROR? M = 2, X is 2 + M. X = 4 För att högertsidan om is ska kunna beräknas får det inte finnas obundna variabler 6
Strikt likhet == V == Q. %variabel V är inte strikt samma som Q % man skulle kunna instantiera V = 1 och Q till 2 om man vill V = 5, Q = 5, V == Q. % nu är båda strikt lika (båda=5). 1+2 == 2+1. % strukturen 1+2 är inte strikt lik 2 + 1 1+2 == 1+2. Unifiering = Två predikat kan unifieras omm de har samma namn de har lika många termer termerna kan unifieras två termer kan unifieras omm den ena är en variabel både är samma konstant både är strukturer... Unifiering fortsätter två strukturer kan unifieras omm de har samma konstruktor (namn) de har samma ställighet argumenten kan unifieras Exampel på unifiering-1 10 = X. X = 10? ; 5 + 5 = 10. xx(left, 123, X) = xx(a,b,b). A = left, B = 123, X = 123? ; Exampel på unifiering-2 E = 1+2. E = 1+2? <ENTER> Yes (E har tilldelats strukturen 1+2 vilket är samma sak som +(1,2) p(p(p(p(0)))) = p(p(x)). X = p(p(0))? ; Exampel på unifiering-3a % predikatet lenght1 length1(0, [ ]). length1(n, [ F R]) :- length1(n2, R), N = N2+1. length1(x, [a,b,c]). X = 1+(1+(1+0))? ; 7
Exampel på unifiering-3b % predikatet lenght1 length1(0, [ ]). length1(n, [ F R]) :- length1(n2, R), N is N2+1. length1(x, [a,b,c]). X = 3? ; Syntax Predikat: mamma, mmm, _1_. Variabler: W, W12, _12 Konstanter: stefan, stefan, Stefan Strukturer: de(de(x,10,nil),12,nil). Listor: [], [1,2, [44, 55], 3], [a, n(1,2,3)] Aritmetik & annat: +, -, *, /, sin, cos, tan, <, >, >=, =<, =:=, =\=, ==, =, is Siffror och tal: 0,, 9, 123.31, 55.2e-3 Closed world assumption (CWA) Exempel: SJ uppger att det dagligen går ett tåg från Linköping till Stockholm kl. 9:22. Dock säger man inte explicit att det inte går ett tåg kl. 9:56 eller 10:24. Eftersom det inte är angivet ett tåg kl. 9:56 går det förmodligen inget tåg då. CWA: Det som inte kan visas är inte sant. Negation as Failure: NF: Det som Prologprogrammet inte kan härleda i ändlig tid är falskt. Hur hittar Prolog alla lösningar Djupet-först sökning med s k backtracking: När en lövd påträffas backar interpretatorn tillbaks till föregående förgrening och provar nästa alternativ. Problem: oändliga subträd oändlig loop. SLD-träd för medlem(x, [a, b, c]). Program: medlem(x, [X _]). medlem(x, [_ T]) :- medlem(x, T). medlem(x, [a, b, c]). medlem(x, [b, c]). X/a medlem(x, [c]). X/b medlem(x, []). X/c dörr(s,a). dörr(a,b). dörr(b,c). dörr(c,d). dörr(d,e). dörr(e,f). Sökning i prolog gå(a,b):-dörr(a,b). %Finns det en dörr mellan A och B så har vi lyckats nå B gå(a,b):-dörr(a,x), gå(x,b). %Finns det en dörr mellan A och X och % man kan gå från X till B så har man lyckats nå B?- gå(s,f). Yes c d e f b a s 8
dörr(s,a). dörr(a,b). dörr(b,c). dörr(c,d). dörr(d,e). dörr(e,b). %nu kan det loopa dörr(e,f). gå(a,b):-dörr(a,b). gå(a,c):-dörr(a,x), gå(x,c).?- gå(s,f). Stack overflow Sökning, ny dörr e-b c d e f gå(a,b, _):-dörr(a,b). gå(a,b,v):-dörr(a,x), \+ medlem(x, V), gå(x,b, [X V]).?- gå(s,f). Yes gå2(a,b,v,p):-dörr(a,b), V = P. gå2(a,b,v,p):-dörr(a,x), \+ medlem(x, V), gå2(x,b, [X V], P).?- gå2(s,f, [], P). P = [a,b,c,d,e,f] b a s Metalogiska predikat Prolog innehåller en uppsättning predikat som inte är strikt predikatlogiska. Man kan även skriva program som ändrar sin egen kod (viktig egenskap im AI). var( X) - misslyckas om X är instansierad. Exempel:? X = Y, var(x).? var(sol). integer( X) - om X är bunden till ett heltal. atomic(x) - om X är bunden till en konstant. Se egen sida. Inlämningsuppgift Bland annat fixa till de konstiga dörrarna som bara släpper igem åt ett håll Detta är vad som behövs för att skriva Prolog program. Resten är övning i att tänka deklarativt och hjärngymnastik om man har fassnat i att tänka imperativt :) SLU T 9