© Patrick Blackburn, Johan Bos & Kristina Striegnitz FL 4: Listor (kap. 4 & 6) Teori –Introducera listor, en viktig rekursiv datastruktur som ofta används.

Slides:



Advertisements
Liknande presentationer
F. Drewes, Inst. f. datavetenskap1 Föreläsning 13: Resolution •Resolution i satslogiken •Resolution i predikatlogiken.
Advertisements

Talföljder formler och summor
Andragradsfunktioner & Andragradsekvationer
Interface.  Interface är en datatyp och har alltså egen syntax och en hel del egna regler för vad arv från interface innebär.  Interface är renodlad.
En genomgång av spelet: Dubbelkrig-Grön
MaB: Ekvationssystem Allmänt
void hittaMax(int tal[], int antal, int *pmax) { int i; ??=tal[0]; for(i=1;i??) ??=tal[i]; } int main() { int v[]={1,2,3,4,2}; int.
hej och välkomna EKVATIONER Ta reda på det okända talet.
1 Listor En sekvens värden av samma typ Nr 5. 2 Listor Sekvens av värden, element Variabelt antal Alla med samma typ Bara första elementet direkt åtkomligt.
1 Logikprogrammering ons 11/9 David Hjelm. 2 Repetition Listor är sammansatta termer. De består av en ordnad mängd element. Elementen i en lista kan vara.
2D1311 Programmeringsteknik med PBL
Prolog, Mån 16/9 Rebecca Jonson.
Logikprogrammering, Mån 23/9 Rebecca Jonson. Repetition P :- Q, R. Deklarativ syn: –P är sann om Q och R är sanna. –Av Q och R följer P Procedurell syn:
Algoritmer och data strukturer -Länkade listor
Nya typer Konstruerare, selektorer och predikat Rekursiva datatyper
PowerPoint av Bendik S. Søvegjarto Koncept, text och regler av Skage Hansen.
Logikprogrammering Ons, 25/9
Föreläsning 7 Analys av algoritmer T(n) och ordo
© Anders Broberg, Ulrika Hägglund, Lena Kallin Westin, 2003 Datastrukturer och algoritmer Föreläsning 4.
Tentamensdags och lab 3…. Större program delas normalt upp i flera filer/moduler vilket har flera fördelar:  Programmets logiska struktur när man klumpar.
Algoritmer och datastrukturer
Föreläsning 6 Länkade lista Komplexitet Linjärsökning & binärsökning
Grundläggande programmering
Föreläsning 2 Datalogi för E1 2D1343
Föreläsning 10 Länkade lista Stack och Kö Att arbeta med listor
© Patrick Blackburn, Johan Bos & Kristina Striegnitz FL 7: Cut och negation (kap. 10) Teori –Förklarar hur man kontrollerar Prologs backtracking-beteende.
© Patrick Blackburn, Johan Bos & Kristina Striegnitz FL 5: Aritmetik Teori –Introducerar Prologs inbyggda operationer för aritmetik –Tillämpar dessa på.
© Patrick Blackburn, Johan Bos & Kristina Striegnitz Föreläsning 2 Teori –Unifiering –Unifiering i Prolog –Sökning efter bevis Övningar –Ett lite större.
© Patrick Blackburn, Johan Bos & Kristina Striegnitz Föreläsning 3: rekursion Teori –Introducera rekursiva definitioner i Prolog –Fyra exempel –Visa att.
© Patrick Blackburn, Johan Bos & Kristina Striegnitz FL 6: Definite Clause Grammars (kap. 7) Teori –Introducerar kontextfria grammatikor och några besläktade.
Sid period2CD5250 OOP med C++ Mats Medin MDH/IDT Objektbaserad programmering –Grundläggande om klasser och objekt – (Arv får vänta)  Iden med klasser.
Programmering B PHP Lektion 2
Tentamensdags och lab 3…. Större program delas normalt upp i flera filer/moduler vilket har flera fördelar:  Programmets logiska struktur när man klumpar.
Jonny Karlsson INTRODUKTION TILL PROGRAMMERING Föreläsning 6 ( ) INNEHÅLL: -Mera om tabeller.
Pekare och speciell programstruktur i inbyggda system
Pathfinding. –Vad är det? –Sökning från A till B.
Pointers. int a=5; int f(int b) { a--; b++; return b; } int main() { int a=3; printf("%d,",f(a)); printf("%d",a); return 0; }
Programmering B PHP Lektion 2
Logikprogrammering och Prolog
Föreläsning 4 Kö Implementerad med array Implementerad med länkad lista Djup kontra bredd Bredden först mha kö.
Listor En lista är en föränderlig ordnad samling objekt.
Känna till och ha provat metoder och verktyg för processledning
PROCESSPROGRAMMERING Föreläsning ‏ Innehåll: Högnivå objekt för trådprogrammering: - Trådgrupper (”Thread pools”)‏ - Exekverare (Executor.
Grundläggande programmering
Jonny Karlsson INTRODUKTION TILL PROGRAMMERING Föreläsning 8 ( ) INNEHÅLL:Klasser: -Konstruktorer -Klassvariabler -Instansmetoder -Privata.
1 Föreläsning 6 Programmeringsteknik och Matlab 2D1312/2D1305 Metoder & parametrar Array API och klassen ArrayList.
Namnrum, räckvidd och rekursion Linda Mannila
Logikprogrammering 21/10 Binära träd
1 Programmera med strängar nr 9 Tal till sträng Sträng till tal Grep Sträng till lista av ord.
Kenneth Wilhelmsson 1 Logikprogrammering 10 P Onsdag 20 november 2002.
Läsbar prolog CM 8.1. allmäna principer correctness user-friendliness efficiency readability modifiability robustness documentation.
Logikprogrammering 16/ : operatorer Staffan Larsson.
Labgrupper: 2 pers/grupp fr o m lab 2 schema ENKÄT.
© Patrick Blackburn, Johan Bos & Kristina Striegnitz Logikprogrammering –Undervisningsmaterialet NYTT för 2013: –Learn Prolog Now! –SWI Prolog-tolk, startas.
Föreläsning 4 Listor, tupler, och for-loopar. Listor En lista är en föränderlig ordnad samling objekt. Listor skapas med hakparenteser. lista = [12,13,14,15]
Aritmetik 3.4 M 8.2 E 2.2. dagens föreläsning operatorer för aritmetik tillämpningar.
1 Mönstermatchning och rekursion Nr 4. 2 Förenklad notation val fnname = fn name => expression Förenklas till fun fnname name = expression Exempel fun.
F. Drewes, Inst. f. datavetenskap1 Föreläsning 9: Implementering av underprogram Aktiveringsposter Exekveringsstacken Implementera dynamisk räckvidd.
Föreläsning 13 Logik med tillämpningar Innehåll u Aritmetik i Prolog u Rekursiva och iterativa program u Typpredikat u Metalogiska predikat.
Karl-Henrik Hagdahl, 11 november Repetition Logikprogrammering: måndag 11 november 2002.
ITM1 Kapitel 8 Datastrukturer Grundläggande datavetenskap, 4p Utgående från boken Computer Science av: J. Glenn Brookshear.
Föreläsning 16 Logik med tillämpningar Innehåll u Information kring kursvärdering och tentagenomgång u Genomgång av övningstenta 2.
© Anders Broberg, Ulrika Hägglund, Lena Kallin Westin, 2003 Datastrukturer och algoritmer Föreläsning 13 Sortering.
Pontus Johansson 1 grammatiker 21.1 G 1 (BBS 7)
Föreläsning 14 Logik med tillämpningar Innehåll u Cuts och negation u Input/output u Extralogiska predikat u Interaktiva program, failure-drivna.
Procedurellt potpurri Dagens samtalsämnen –Klipp (Cut) –If-then-else –fail/0 –repeat/0 Att läsa –The Art of Prolog, kapitel 11 –Relevant avsnitt i Learn.
Logikprogrammering ons 4/9 Rebecca Jonson.
Lennart Edblom, Frank Drewes, Inst. f. datavetenskap 1 Föreläsning 13: Resolution Resolution i satslogiken Resolution i predikatlogiken.
Algoritmer och datastrukturer Föreläsning 8 Tidskomplexitet (Weiss kap
Föreläsning 8: Exempel och problemlösning
Presentationens avskrift:

© Patrick Blackburn, Johan Bos & Kristina Striegnitz FL 4: Listor (kap. 4 & 6) Teori –Introducera listor, en viktig rekursiv datastruktur som ofta används inom Prolog-programmering –Definiera predikatet member/2, ett basverktyg för listhantering –Illustrera idén om hur man bearbetar listorna rekursivt.

© Patrick Blackburn, Johan Bos & Kristina Striegnitz Listor En lista är en ändlig sekvens av element Exempel på listor i Prolog: [mia, vincent, jules, yolanda] [mia, robber(honeybunny), X, 2, mia] [ ] [mia, [vincent, jules], [butch, friend(butch)]] [[ ], dead(z), [2, [b,c]], [ ], Z, [2, [b,c]]]

© Patrick Blackburn, Johan Bos & Kristina Striegnitz Viktigt om listor Listelementen innesluts i hakparenteser Längden av en lista är antalet element i den Alla sorter av Prolog-termer kan utgöra listelement, också i en och samma lista! Det finns en speciell lista: tomma listan [ ]

© Patrick Blackburn, Johan Bos & Kristina Striegnitz Head och Tail En icke-tom lista kan tänkas bestå av två delar –listhuvud (head) –svansen (tail) Huvudet är listans första element Svansen är resten av listan –Svansen är det som återstår när vi avlägsnar det första elementet –Svansen av en lista är alltid en lista

© Patrick Blackburn, Johan Bos & Kristina Striegnitz Head och Tail exempel 1 [mia, vincent, jules, yolanda] Head: Tail:

© Patrick Blackburn, Johan Bos & Kristina Striegnitz Head och Tail exempel 1 [mia, vincent, jules, yolanda] Head: mia Tail:

© Patrick Blackburn, Johan Bos & Kristina Striegnitz Head och Tail exempel 1 [mia, vincent, jules, yolanda] Head: mia Tail: [vincent, jules, yolanda]

© Patrick Blackburn, Johan Bos & Kristina Striegnitz Head och Tail exempel 2 [[ ], dead(z), [2, [b,c]], [ ], Z, [2, [b,c]]] Head: Tail:

© Patrick Blackburn, Johan Bos & Kristina Striegnitz Head och Tail exempel 2 [[ ], dead(z), [2, [b,c]], [ ], Z, [2, [b,c]]] Head: [ ] Tail:

© Patrick Blackburn, Johan Bos & Kristina Striegnitz Head och Tail exempel 2 [[ ], dead(z), [2, [b,c]], [ ], Z, [2, [b,c]]] Head: [ ] Tail: [dead(z), [2, [b,c]], [ ], Z, [2, [b,c]]]

© Patrick Blackburn, Johan Bos & Kristina Striegnitz Head och Tail exempel 3 [dead(z)] Head: Tail:

© Patrick Blackburn, Johan Bos & Kristina Striegnitz Head och Tail exempel 3 [dead(z)] Head: dead(z) Tail:

© Patrick Blackburn, Johan Bos & Kristina Striegnitz Head och Tail exempel 3 [dead(z)] Head: dead(z) Tail: [ ]

© Patrick Blackburn, Johan Bos & Kristina Striegnitz Head och tail av tom lista Den tomma listan har varken huvud eller svans För Prolog är [ ] en speciell, enkel lista utan struktur Den tomma listan spelar en viktig roll för rekursiva predikat för listhantering i Prolog

© Patrick Blackburn, Johan Bos & Kristina Striegnitz Inbyggd operator | Prolog har en speciell inbyggd operator | som kan användas för att dekonstruera en lista i head och tail. |-operatorn är ett centralt verktyg när det gäller att skriva kod för listmanipulering

© Patrick Blackburn, Johan Bos & Kristina Striegnitz Inbyggd operator | ?- [Head|Tail] = [mia, vincent, jules, yolanda]. Head = mia Tail = [vincent,jules,yolanda] yes ?-

© Patrick Blackburn, Johan Bos & Kristina Striegnitz Inbyggd operator | ?- [X|Y] = [mia, vincent, jules, yolanda]. X = mia Y = [vincent,jules,yolanda] yes ?-

© Patrick Blackburn, Johan Bos & Kristina Striegnitz Inbyggd operator | ?- [X|Y] = [ ]. no ?-

© Patrick Blackburn, Johan Bos & Kristina Striegnitz Inbyggd operator | ?- [X,Y|Tail] = [[ ], dead(z), [2, [b,c]], [], Z, [2, [b,c]]]. X = [ ] Y = dead(z) Z = _4543 Tail = [[2, [b,c]], [ ], Z, [2, [b,c]]] yes ?-

© Patrick Blackburn, Johan Bos & Kristina Striegnitz Anonym variabel Anta att vi är intresserade av listans andra och fjärde element ?- [X1,X2,X3,X4|Tail] = [mia, vincent, marsellus, jody, yolanda]. X1 = mia X2 = vincent X3 = marsellus X4 = jody Tail = [yolanda] yes ?-

© Patrick Blackburn, Johan Bos & Kristina Striegnitz Anonyma variabler Det finns ett enklare sätt att få bara den information vi är intresserade av: ?- [ _,X2, _,X4|_ ] = [mia, vincent, marsellus, jody, yolanda]. X2 = vincent X4 = jody yes ?- Understrecket är den anonyma variabeln

© Patrick Blackburn, Johan Bos & Kristina Striegnitz Den anonyma variabeln Används när du behöver en variabel, men är inte intresserad av vad den instantieras till Varje instans av den anonyma variabeln är oberoende, dvs de kan instantieras till olika termer i samma mönster

© Patrick Blackburn, Johan Bos & Kristina Striegnitz Member En av de mest grundläggande saker när det gäller listhantering är att veta om ett element är medlem i en lista eller ej Så nu gäller det att skriva ett predikat som, givet en term X och en lista L, berättar ifall X hör till L Detta predikat brukar kallas för member/2

© Patrick Blackburn, Johan Bos & Kristina Striegnitz member/2 member(X,[X|T]). member(X,[H|T]):- member(X,T). ?-

© Patrick Blackburn, Johan Bos & Kristina Striegnitz member/2 member(X,[X|T]). member(X,[H|T]):- member(X,T). ?- member(yolanda,[yolanda,trudy,vincent,jules]).

© Patrick Blackburn, Johan Bos & Kristina Striegnitz member/2 member(X,[X|T]). member(X,[H|T]):- member(X,T). ?- member(yolanda,[yolanda,trudy,vincent,jules]). yes ?-

© Patrick Blackburn, Johan Bos & Kristina Striegnitz member/2 member(X,[X|T]). member(X,[H|T]):- member(X,T). ?- member(vincent,[yolanda,trudy,vincent,jules]).

© Patrick Blackburn, Johan Bos & Kristina Striegnitz member/2 member(X,[X|T]). member(X,[H|T]):- member(X,T). ?- member(vincent,[yolanda,trudy,vincent,jules]). yes ?-

© Patrick Blackburn, Johan Bos & Kristina Striegnitz member/2 member(X,[X|T]). member(X,[H|T]):- member(X,T). ?- member(zed,[yolanda,trudy,vincent,jules]).

© Patrick Blackburn, Johan Bos & Kristina Striegnitz member/2 member(X,[X|T]). member(X,[H|T]):- member(X,T). ?- member(zed,[yolanda,trudy,vincent,jules]). no ?-

© Patrick Blackburn, Johan Bos & Kristina Striegnitz member/2 member(X,[X|T]). member(X,[H|T]):- member(X,T). ?- member(X,[yolanda,trudy,vincent,jules]).

© Patrick Blackburn, Johan Bos & Kristina Striegnitz member/2 member(X,[X|T]). member(X,[H|T]):- member(X,T). ?- member(X,[yolanda,trudy,vincent,jules]). X = yolanda; X = trudy; X = vincent; X = jules; no

© Patrick Blackburn, Johan Bos & Kristina Striegnitz Att omskriva member/2 member(X,[X|_]). member(X,[_|T]):- member(X,T).

© Patrick Blackburn, Johan Bos & Kristina Striegnitz Att bearbeta listorna rekursivt Predikatet member/2 jobbar genom att rekursivt arbeta längs listan –Det gör något med listhuvudet och sedan –... gör det samma sak rekursivt med svansen Den här tekniken är central för Prolog och därför är den viktig att behärska

© Patrick Blackburn, Johan Bos & Kristina Striegnitz Exempel: a2b/2 Predikatet a2b/2 tar två listor som argument och lyckas –om det första argumentet är en lista av a:n, och –det andra argumentet är en lika lång lista av b:n ?- a2b([a,a,a,a],[b,b,b,b]). yes ?- a2b([a,a,a,a],[b,b,b]). no ?- a2b([a,c,a,a],[b,b,b,t]). no

© Patrick Blackburn, Johan Bos & Kristina Striegnitz Definiera a2b/2: steg 1 Ofta är det bästa sättet att lösa dylika problem att tänka på det enklaste fallet Här innebär detta den tomma listan a2b([],[]).

© Patrick Blackburn, Johan Bos & Kristina Striegnitz Definiera a2b/2: steg 2 Nu gäller det att tänka rekursivt! När borde a2b/2 bestämma att två icke- tomma listor är en lista av a:n och en lista av b:n av exakt samma längd? a2b([],[]). a2b([a|L1],[b|L2]):- a2b(L1,L2).

© Patrick Blackburn, Johan Bos & Kristina Striegnitz Testa a2b/2 a2b([],[]). a2b([a|L1],[b|L2]):- a2b(L1,L2). ?- a2b([a,a,a],[b,b,b]). yes ?-

© Patrick Blackburn, Johan Bos & Kristina Striegnitz Testa a2b/2 a2b([],[]). a2b([a|L1],[b|L2]):- a2b(L1,L2). ?- a2b([a,a,a,a],[b,b,b]). no ?-

© Patrick Blackburn, Johan Bos & Kristina Striegnitz Testa a2b/2 a2b([],[]). a2b([a|L1],[b|L2]):- a2b(L1,L2). ?- a2b([a,t,a,a],[b,b,b,c]). no ?-

© Patrick Blackburn, Johan Bos & Kristina Striegnitz Studera a2b/2 vidare... a2b([],[]). a2b([a|L1],[b|L2]):- a2b(L1,L2). ?- a2b([a,a,a,a,a], X). X = [b,b,b,b,b] yes ?-

© Patrick Blackburn, Johan Bos & Kristina Striegnitz Studera a2b/2 vidare... a2b([],[]). a2b([a|L1],[b|L2]):- a2b(L1,L2). ?- a2b(X,[b,b,b,b,b,b,b]). X = [a,a,a,a,a,a,a] yes ?-

© Patrick Blackburn, Johan Bos & Kristina Striegnitz Denna FL hittills... Vi har introducerat listor och rekursiva predikat som bearbetar listor Denna typ av programmering är fundamental för Prolog De flesta predikat du kommer att skriva när du jobbar med Prolog kommer att vara varianter av dessa predikat

© Patrick Blackburn, Johan Bos & Kristina Striegnitz FL fortsätter: mera listor Teori –Definiera append/3, ett predikat för att sammanfoga två listor, och visa vad som kan göras med det –Diskutera två sätt att reversera en lista Ett naivt sätt mha append/3 Ett mera effektivt sätt mha ackumulatorer

© Patrick Blackburn, Johan Bos & Kristina Striegnitz Append Nu gäller det att definiera det viktiga predikatet append/3 vars argument är alla listor Deklarativt gäller append(L1,L2,L3) om listan L3 är resultatet av att sammanfoga listorna L1 och L2 ?- append([a,b,c,d],[3,4,5],[a,b,c,d,3,4,5]). yes ?- append([a,b,c],[3,4,5],[a,b,c,d,3,4,5]). no

© Patrick Blackburn, Johan Bos & Kristina Striegnitz Append proceduralt sett Från ett proceduralt perspektiv är den mest självklara användningen av append/3 att sammanfoga två listor Vi kan göra detta enkelt genom att använda en variabel som tredje argument ?- append([a,b,c,d],[1,2,3,4,5], X). X=[a,b,c,d,1,2,3,4,5] yes ?- Kom ihåg att elementen INTE behöver ha samma datatyp!

© Patrick Blackburn, Johan Bos & Kristina Striegnitz Definition av append/3 Rekursiv definition –Basfallet: att sammanfoga den tomma listan till vilken lista som helst producerar samma lista –Det rekursiva steget säger att när man sammanfogar en icke-tom lista [H|T] med en lista L, blir resultatet en lista med huvudet H och resultatet av att sammanfoga T med L append([], L, L). append([H|L1], L2, [H|L3]):- append(L1, L2, L3).

© Patrick Blackburn, Johan Bos & Kristina Striegnitz Hur append/3 fungerar Två sätt att ta reda på detta: –Använd trace/0 på några exempel –Rita sökträdet! ?- append([a,b,c],[1,2,3], R).

© Patrick Blackburn, Johan Bos & Kristina Striegnitz Exemplet med sökträd ?- append([a,b,c],[1,2,3], R). append([], L, L). append([H|L1], L2, [H|L3]):- append(L1, L2, L3).

© Patrick Blackburn, Johan Bos & Kristina Striegnitz Exemplet med sökträd ?- append([a,b,c],[1,2,3], R). / \ append([], L, L). append([H|L1], L2, [H|L3]):- append(L1, L2, L3).

© Patrick Blackburn, Johan Bos & Kristina Striegnitz Exemplet med sökträd ?- append([a,b,c],[1,2,3], R). / \ † R = [a|L0] ?- append([b,c],[1,2,3],L0) append([], L, L). append([H|L1], L2, [H|L3]):- append(L1, L2, L3).

© Patrick Blackburn, Johan Bos & Kristina Striegnitz Exemplet med sökträd ?- append([a,b,c],[1,2,3], R). / \ † R = [a|L0] ?- append([b,c],[1,2,3],L0) / \ append([], L, L). append([H|L1], L2, [H|L3]):- append(L1, L2, L3).

© Patrick Blackburn, Johan Bos & Kristina Striegnitz Exemplet med sökträd ?- append([a,b,c],[1,2,3], R). / \ † R = [a|L0] ?- append([b,c],[1,2,3],L0) / \ † L0=[b|L1] ?- append([c],[1,2,3],L1) append([], L, L). append([H|L1], L2, [H|L3]):- append(L1, L2, L3).

© Patrick Blackburn, Johan Bos & Kristina Striegnitz Exemplet med sökträd ?- append([a,b,c],[1,2,3], R). / \ † R = [a|L0] ?- append([b,c],[1,2,3],L0) / \ † L0=[b|L1] ?- append([c],[1,2,3],L1) / \ append([], L, L). append([H|L1], L2, [H|L3]):- append(L1, L2, L3).

© Patrick Blackburn, Johan Bos & Kristina Striegnitz Exemplet med sökträd ?- append([a,b,c],[1,2,3], R). / \ † R = [a|L0] ?- append([b,c],[1,2,3],L0) / \ † L0=[b|L1] ?- append([c],[1,2,3],L1) / \ † L1=[c|L2] ?- append([],[1,2,3],L2) append([], L, L). append([H|L1], L2, [H|L3]):- append(L1, L2, L3).

© Patrick Blackburn, Johan Bos & Kristina Striegnitz Exemplet med sökträd ?- append([a,b,c],[1,2,3], R). / \ † R = [a|L0] ?- append([b,c],[1,2,3],L0) / \ † L0=[b|L1] ?- append([c],[1,2,3],L1) / \ † L1=[c|L2] ?- append([],[1,2,3],L2) / \ append([], L, L). append([H|L1], L2, [H|L3]):- append(L1, L2, L3).

© Patrick Blackburn, Johan Bos & Kristina Striegnitz Exemplet med sökträd ?- append([a,b,c],[1,2,3], R). / \ † R = [a|L0] ?- append([b,c],[1,2,3],L0) / \ † L0=[b|L1] ?- append([c],[1,2,3],L1) / \ † L1=[c|L2] ?- append([],[1,2,3],L2) / \ L2=[1,2,3] † append([], L, L). append([H|L1], L2, [H|L3]):- append(L1, L2, L3). R1 matchar nu vårt mönster,så vi når basfallet. R2 gäller ej längre.

© Patrick Blackburn, Johan Bos & Kristina Striegnitz Exemplet med sökträd ?- append([a,b,c],[1,2,3], R). / \ † R = [a|L0] ?- append([b,c],[1,2,3],L0) / \ † L0=[b|L1] ?- append([c],[1,2,3],L1) / \ † L1=[c|L2] ?- append([],[1,2,3],L2) / \ L2=[1,2,3] † L2=[1,2,3] L1=[c|L2]=[c,1,2,3] L0=[b|L1]=[b,c,1,2,3] R=[a|L0]=[a,b,c,1,2,3] append([], L, L). append([H|L1], L2, [H|L3]):- append(L1, L2, L3).

© Patrick Blackburn, Johan Bos & Kristina Striegnitz Exemplet med sökträd ?- append([a,b,c],[1,2,3], R). / \ † R = [a|L0] ?- append([b,c],[1,2,3],L0) / \ † L0=[b|L1] ?- append([c],[1,2,3], [c|1,2,3]) / \ † L1=[c|1,2,3] ?- append([],[1,2,3], [1,2,3]) / \ L2=[1,2,3] † L2=[1,2,3] L1=[c|L2]=[c,1,2,3] L0=[b|L1]=[b,c,1,2,3] R=[a|L0]=[a,b,c,1,2,3] append([], L, L). append([H|L1], L2, [H|L3]):- append(L1, L2, L3).

© Patrick Blackburn, Johan Bos & Kristina Striegnitz Exemplet med sökträd ?- append([a,b,c],[1,2,3], R). / \ † R = [a|L0] ?- append([b,c],[1,2,3], [b|c,1,2,3]) / \ † L0=[b|c,1,2,3] ?- append([c],[1,2,3], [c|1,2,3]) / \ † L1=[c|1,2,3] ?- append([],[1,2,3], [1,2,3]) / \ L2=[1,2,3] † L2=[1,2,3] L1=[c|L2]=[c,1,2,3] L0=[b|L1]=[b,c,1,2,3] R=[a|L0]=[a,b,c,1,2,3] append([], L, L). append([H|L1], L2, [H|L3]):- append(L1, L2, L3).

© Patrick Blackburn, Johan Bos & Kristina Striegnitz Exemplet med sökträd ?- append([a,b,c],[1,2,3], [a,b,c,1,2,3] ). / \ † R = [a|b,c,1,2,3] ?- append([b,c],[1,2,3], [b,c,1,2,3]) / \ † L0=[b|c,1,2,3] ?- append([c],[1,2,3], [c|1,2,3]) / \ † L1=[c|1,2,3] ?- append([],[1,2,3], [1,2,3]) / \ L2=[1,2,3] † L2=[1,2,3] L1=[c|L2]=[c,1,2,3] L0=[b|L1]=[b,c,1,2,3] R=[a|L0]=[a,b,c,1,2,3] append([], L, L). append([H|L1], L2, [H|L3]):- append(L1, L2, L3).

© Patrick Blackburn, Johan Bos & Kristina Striegnitz Att använda append/3 Nu när vi vet hur append/3 fungerar ska vi se på några tillämpningar Att dela en lista: ?- append(X,Y, [a,b,c,d]). X=[ ] Y=[a,b,c,d]; X=[a] Y=[b,c,d]; X=[a,b] Y=[c,d]; X=[a,b,c] Y=[d]; X=[a,b,c,d] Y=[ ]; no

© Patrick Blackburn, Johan Bos & Kristina Striegnitz Prefix och suffix Vi kan också använda append/3 för att definiera andra nyttiga predikat Ett bra exempel är att hitta prefixen (dellistor i början) och suffixen (dellistor i slutet) av en lista

© Patrick Blackburn, Johan Bos & Kristina Striegnitz Definition av prefix/2 En lista P är ett prefix av någon lista L när det existerar någon sådan lista att L utgör resultatet av att sammanfoga P med denna lista. Vi använder oss av den anonyma variabeln eftersom vi inte bryr oss om den andra listan prefix(P,L):- append(P,_,L).

© Patrick Blackburn, Johan Bos & Kristina Striegnitz Att använda prefix/2 prefix(P,L):- append(P,_,L). ?- prefix(X, [a,b,c,d]). X=[ ]; X=[a]; X=[a,b]; X=[a,b,c]; X=[a,b,c,d]; no

© Patrick Blackburn, Johan Bos & Kristina Striegnitz Definition av suffix/2 En lista S är ett suffix av någon lista L när det existerar någon sådan lista att L utgör resultatet av att sammanfoga denna lista med S. Vi använder oss igen av den anonyma variabeln, eftersom vi inte bryr oss om denna andra lista. suffix(S,L):- append(_,S,L).

© Patrick Blackburn, Johan Bos & Kristina Striegnitz Att använda suffix/2 suffix(S,L):- append(_,S,L). ?- suffix(X, [a,b,c,d]). X=[a,b,c,d]; X=[b,c,d]; X=[c,d]; X=[d]; X=[]; no

© Patrick Blackburn, Johan Bos & Kristina Striegnitz Definition av sublist/2 Nu är det enkelt att skriva ett predikat som hittar dellistorna av en lista Dellistorna av en lista L är helt enkelt prefixen av suffixen av L sublist(Sub,List):- suffix(Suffix,List), prefix(Sub,Suffix). Alternativt: suffixen av prefixen av L

Testkörning... © Patrick Blackburn, Johan Bos & Kristina Striegnitz ?- listing. prefix(A, B) :- append(A, _, B). sublist(B, A) :- suffix(C, A), prefix(B, C). suffix(A, B) :- append(_, A, B). true. prefixen av suffixen av lista A...

Testkörning... © Patrick Blackburn, Johan Bos & Kristina Striegnitz ?- sublist(Sub, [a,b,c,d,e]). Sub = [] ; Sub = [a] ; Sub = [a, b] ; Sub = [a, b, c] ; Sub = [a, b, c, d] ; Sub = [a, b, c, d, e] ; Sub = [] ; Sub = [b] ; Sub = [b, c] ; Sub = [b, c, d] ; Sub = [b, c, d, e] ; Sub = [] ; Sub = [c] ; Sub = [c, d] ; Sub = [c, d, e] ; Sub = [] ; Sub = [d] ; Sub = [d, e] ; Sub = [] ; Sub = [e] ; Sub = [] ; false. prefixen av suffixen av lista A... suffix [a,b,c,d,e] suffix [b,c,d,e] suffix [c,d,e] suffix [d,e] suffix [e] suffix []

Testkörning... © Patrick Blackburn, Johan Bos & Kristina Striegnitz ?- listing. prefix(A, B) :- append(A, _, B). sublist(B, A) :- prefix(C, A), suffix(B, C). suffix(A, B) :- append(_, A, B). true. suffixen av prefixen av lista A...

Testkörning... © Patrick Blackburn, Johan Bos & Kristina Striegnitz ?- sublist(Sub, [a,b,c,d,e]). Sub = [] ; Sub = [a] ; Sub = [] ; Sub = [a, b] ; Sub = [b] ; Sub = [] ; Sub = [a, b, c] ; Sub = [b, c] ; Sub = [c] ; Sub = [] ; Sub = [a, b, c, d] ; Sub = [b, c, d] ; Sub = [c, d] ; Sub = [d] ; Sub = [] ; Sub = [a, b, c, d, e] ; Sub = [b, c, d, e] ; Sub = [c, d, e] ; Sub = [d, e] ; Sub = [e] ; Sub = [] ; false. prefix [a,b,c,d,e] prefix [a,b,c,d] prefix [a,b,c] prefix [a,b] prefix [a] prefix [] suffixen av prefixen av lista A...

© Patrick Blackburn, Johan Bos & Kristina Striegnitz append/3 och effektivitet Predikatet append/3 är nyttigt, och det är viktigt att känna till hur det ska användas Det är lika viktigt att veta att append/3 kan leda till mycket ineffektiva program Varför? –Att sammanfoga en lista görs inte som en enda handling... –... utan genom att traversera längs den ena listan

© Patrick Blackburn, Johan Bos & Kristina Striegnitz Fråga Vi skulle vilja sammanfoga två listor mha append/3 –List 1: [a,b,c,d,e,f,g,h,i] –List 2: [j,k,l] Resultatet borde vara en lista med alla elementen från List 1 och List 2, men elementens ordning spelar ingen roll Vilketdera av de följande målen är det mest effektiva sättet att sammafoga listorna? ?- append([a,b,c,d,e,f,g,h,i],[j,k,l],R). ?- append([j,k,l],[a,b,c,d,e,f,g,h,i],R). append([], L, L). append([H|L1], L2, [H|L3]):- append(L1, L2, L3).

© Patrick Blackburn, Johan Bos & Kristina Striegnitz Svaret Se hur append/3 är definierat Det jobbar längs det första argumentet och rör egentligen inte alls den andra listan Detta innebär att det lönar sig att anropa det med den kortare listan som första argument Naturligtvis vet man inte alltid vilkendera listan som är kortare, och man kan bara göra detta när elementens ordning i resultatlistan inte spelar någon roll. Men om denna princip går att tillämpa, blir programmet mera effektivt append([], L, L). append([H|L1], L2, [H|L3]):- append(L1, L2, L3).

© Patrick Blackburn, Johan Bos & Kristina Striegnitz Att reversera en lista Vi ska exemplifiera problemet med append/3 genom att använda det för att reversera en lista Vi ska alltså definiera ett predikat som omvandlar listan [a,b,c,d,e] till lista [e,d,c,b,a] Detta kan vara ett nyttigt verktyg att ha, eftersom Prolog endast erbjuder lätt access till listans första element

© Patrick Blackburn, Johan Bos & Kristina Striegnitz Naiv reverse Rekursiv definition 1.Om vi reverserar den tomma listan, får vi den tomma listan 2.Om vi reverserar listan [H|T], får vi den lista som är reversen av T sammanfogad med lista [H] För att se att denna definition är korrekt, betrakta listan [a,b,c,d]. –Om vi reverserar svansen av denna lista, får vi[d,c,b]. –Att sammanfoga denna med [a] ger [d,c,b,a]

© Patrick Blackburn, Johan Bos & Kristina Striegnitz Naiv reverse i Prolog Den här definitionen är korrekt, men den innebär en massa arbete! Största delen av tiden går åt att utföra appends Men det finns ett bättre sätt … naiveReverse([],[]). naiveReverse([H|T],R):- naiveReverse(T,RT), append(RT,[H],R).

© Patrick Blackburn, Johan Bos & Kristina Striegnitz Reverse mha en ackumulator Det bättre sättet använder en ackumulator Ackumulatorn kommer att vara en lista som är tom när vi börjar reversera Vi tar helt enkelt huvudet av listan vi vill reversera och sätter det som huvud till ackumulatorn (sista element i vår lista blir först i ackumulatorn) Vi fortsätter tills vi når [ ]. Vid detta skede kommer ackumulatorn att innehålla reversen av vår lista

© Patrick Blackburn, Johan Bos & Kristina Striegnitz Reverse mha en ackumulator accReverse([ ],L,L). accReverse([H|T],Acc,Rev):- accReverse(T,[H|Acc],Rev).

© Patrick Blackburn, Johan Bos & Kristina Striegnitz Reverse mha en ackumulator accReverse([ ],L,L). accReverse([H|T],Acc,Rev):- accReverse(T,[H|Acc],Rev). accReverse gäller mellan lista [H|T], Acc och Rev om accReverse gäller mellan T, [H|Acc] och Rev

© Patrick Blackburn, Johan Bos & Kristina Striegnitz Reverse mha en ackumulator accReverse([ ],L,L). accReverse([H|T],Acc,Rev):- accReverse(T,[H|Acc],Rev). accReverse([1,2,3,4], [], R) :- accReverse([2,3,4], [1|[]], R) accReverse([2,3,4], [1], R) :- accReverse([3,4], [2|1], R) accReverse([3,4], [2,1], R) :- accReverse([4], [3|2,1], R) accReverse([4], [3,2,1], R) :- accReverse([], [4|3,2,1], R) accReverse([], [4,3,2,1], R) basfallet!

© Patrick Blackburn, Johan Bos & Kristina Striegnitz Att tillägga ett “wrapper”- predikat accReverse([ ],L,L). accReverse([H|T],Acc,Rev):- accReverse(T,[H|Acc],Rev). reverse(L1,L2):- accReverse(L1,[ ],L2). Gömmer det ackumulativa hjälp- predikatet

© Patrick Blackburn, Johan Bos & Kristina Striegnitz Så här fungerar ackumulatorn List: [a,b,c,d]Ackumulator: []

© Patrick Blackburn, Johan Bos & Kristina Striegnitz Så här fungerar ackumulatorn List: [a,b,c,d] List: [b,c,d] Ackumulator: [] Ackumulator: [a]

© Patrick Blackburn, Johan Bos & Kristina Striegnitz Så här fungerar ackumulatorn List: [a,b,c,d] List: [b,c,d] List: [c,d] Ackumulator: [] Ackumulator: [a] Ackumulator: [b,a]

© Patrick Blackburn, Johan Bos & Kristina Striegnitz Så här fungerar ackumulatorn List: [a,b,c,d] List: [b,c,d] List: [c,d] List: [d] Ackumulator: [] Ackumulator: [a] Ackumulator: [b,a] Ackumulator: [c,b,a]

© Patrick Blackburn, Johan Bos & Kristina Striegnitz Så här fungerar ackumulatorn List: [a,b,c,d] List: [b,c,d] List: [c,d] List: [d] List: [] Ackumulator: [] Ackumulator: [a] Ackumulator: [b,a] Ackumulator: [c,b,a] Ackumulator: [d,c,b,a]

Listor i användning © Patrick Blackburn, Johan Bos & Kristina Striegnitz Problemlösning i Prolog! Farmaren, vargen, geten och kålhuvudet

Materialet från George F. Luger & William A. Stubblefield: Artificial Intelligence: Structures and Strategies for Complex Problem Solving © Patrick Blackburn, Johan Bos & Kristina Striegnitz

Farmaren, vargen, geten och kålhuvudet Farmaren, hans varg, get och ett kålhuvud ska över en flod med en robåt. Båten kan bära farmaren och en annan. Bara farmaren kan ro. Om vargen lämnas ensam (utan den övervakande farmaren) med geten, äter vargen upp geten. Om geten lämnas ensam (utan den övervakande farmaren) med kålhuvudet, äter geten upp kålhuvudet. Hur ska alla komma oskadda över floden? © Patrick Blackburn, Johan Bos & Kristina Striegnitz

Farmaren, vargen, geten och kålhuvudet Modellera tillstånd: En fyrtupel state(farmer, wolf, goat, cabbage) ska representera deltagarna. Vi antar att floden ska korsas från väst (w) till öst (e) (eller tvärtom). Då visar vi var alla deltagarna befinner sig med fyrtupeln ovan, ex. state(w, w, w, w). © Patrick Blackburn, Johan Bos & Kristina Striegnitz farmer wolf goat cabbage

Modellera tillstånd © Patrick Blackburn, Johan Bos & Kristina Striegnitz Startläget är state(w, w, w, w). Slutläget ska vara state(e, e, e, e). Hur kommer vi från startläget till slutläget?

Modellera tillstånd © Patrick Blackburn, Johan Bos & Kristina Striegnitz state(farmer, wolf, goat, cabbage) Startläget är state(w, w, w, w). Slutläget ska vara state(e, e, e, e). För att tillståndet state ska ändras, ska farmaren byta sida från w till e eller tvärtom. Utöver farmarens byte får högst en annan byta sida (bara farmaren kan ro!). Förbjudna states: state(w, e, e, _) (Vargen och geten tillsammans utan farmaren) state(e, w, w, _) (Vargen och geten tillsammans utan farmaren) state(w, _, e, e) (Geten och kålhuvudet tillsammans utan farmaren) state(e, _, w, w) (Geten och kålhuvudet tillsammans utan farmaren)

Modellera förflyttning © Patrick Blackburn, Johan Bos & Kristina Striegnitz state(farmer, wolf, goat, cabbage) opp(e, w). opp(w, e). unsafe(state(X, Y, Y, C) :- opp(X, Y). unsafe(state(X, W, Y, Y) :- opp(X, Y). move(state(X,X,G,C), state(Y,Y,G,C)) :- opp(X,Y), not(unsafe(state(Y,Y,G,C))), writelist(['try farmer takes wolf',Y,Y,G,C]).

Modellera förflyttning © Patrick Blackburn, Johan Bos & Kristina Striegnitz state(farmer, wolf, goat, cabbage) move(state(X,W,X,C), state(Y,W,Y,C)) :- opp(X,Y), not(unsafe(state(Y,W,Y,C))), writelist(['try farmer takes goat',Y,W,Y,C]). move(state(X,W,G,X), state(Y,W,G,Y)) :- opp(X,Y), not(unsafe(state(Y,W,G,Y))), writelist(['try farmer takes cabbage',Y,W,G,Y]).

Modellera förflyttning © Patrick Blackburn, Johan Bos & Kristina Striegnitz state(farmer, wolf, goat, cabbage) move(state(X,W,G,C), state(Y,W,G,C)) :- opp(X,Y), not(unsafe(state(Y,W,G,C))), writelist(['try farmer takes self',Y,W,G,C]). move(state(F,W,G,C), state(F,W,G,C)) :- writelist([' BACKTRACK from:',F,W,G,C]), fail. Vi registrerar en dead end

Modellera förflyttning © Patrick Blackburn, Johan Bos & Kristina Striegnitz state(farmer, wolf, goat, cabbage) writelist([]) :- nl. writelist([H|T]) :- print(H), tab(1), /* "tab(n)" skips n spaces. */ writelist(T).

Modellera förflyttning © Patrick Blackburn, Johan Bos & Kristina Striegnitz state(farmer, wolf, goat, cabbage) Hur hindra farmaren från att ro fram och tillbaka utan att han kommer närmare sitt mål? Samma problem som loopar i en graf! Vi måste hålla reda på de tillstånd där vi redan varit. För detta ändamål måste vi ha en stack.

Modellera förflyttning © Patrick Blackburn, Johan Bos & Kristina Striegnitz state(farmer, wolf, goat, cabbage) ~/prolog]$ more adt.pl /* ADT by Luger & Stubblefield */ member(X, [X|_]). member(X, [_|T]) :- member(X, T). empty_stack([]). member_stack(E, S) :- member(E, S). % tests if an element is a member % of the stack

Modellera förflyttning © Patrick Blackburn, Johan Bos & Kristina Striegnitz state(farmer, wolf, goat, cabbage) stack(E, S, [E|S]). % push: ?- stack(a, [b, c, d], S). % S = [a, b, c, d]. % pop: stack(Top, Rest, [a, b, c]). % Top = a, Rest = [b, c]. % peek at the top element: % ?- stack(Top, _, [a, b, c]). % Top = a

Modellera förflyttning © Patrick Blackburn, Johan Bos & Kristina Striegnitz state(farmer, wolf, goat, cabbage) reverse_print_stack(S) :- empty_stack(S). reverse_print_stack(S) :- stack(E, Rest, S), reverse_print_stack(Rest), write(E), nl. Tillstånden lagras på stacken. Genom att printa stackinnehållet i motsatt ordning får vi den rätta sekvensen som farmaren ska följa.

Modellera förflyttning © Patrick Blackburn, Johan Bos & Kristina Striegnitz state(farmer, wolf, goat, cabbage) path(Goal, Goal, Been_stack) :- write('Solution Path Is:' ), nl, reverse_print_stack(Been_stack). path(State, Goal, Been_stack) :- move(State, Next_state), not(member_stack(Next_state, Been_stack)), stack(Next_state, Been_stack, New_been_stack), path(Next_state, Goal, New_been_stack), !. Been_stack håller reda på tillstånd där vi redan varit push Existerar stigen? cut!

Modellera förflyttning © Patrick Blackburn, Johan Bos & Kristina Striegnitz state(farmer, wolf, goat, cabbage) path(Goal, Goal, Been_stack) :- write('Solution Path Is:' ), nl, reverse_print_stack(Been_stack). path(State, Goal, Been_stack) :- move(State, Next_state), not(member_stack(Next_state, Been_stack)), stack(Next_state, Been_stack, New_been_stack), path(Next_state, Goal, New_been_stack), !. cut! cut gör att vi inte söker efter alter- nativa bevis

Modellera förflyttning © Patrick Blackburn, Johan Bos & Kristina Striegnitz state(farmer, wolf, goat, cabbage) go(Start, Goal) :- empty_stack(Empty_been_stack), stack(Start, Empty_been_stack, Been_stack), path(Start, Goal, Been_stack). / * Run this code by giving PROLOG a "go" goal. * For example, to find a path from the west bank to the east bank, * give PROLOG the query: * * go(state(w,w,w,w), state(e,e,e,e)). */

Körning © Patrick Blackburn, Johan Bos & Kristina Striegnitz ?- go(state(w,w,w,w), state(e,e,e,e)). try farmer takes goat e w e w % från w w w w try farmer takes goat w w w w % misslyckas, pröva try farmer takes self w w e w % detta från e w e w try farmer takes wolf e e e w % från föreg. try farmer takes wolf w w e w % från föreg. try farmer takes goat w e w w % från e e e w try farmer takes goat e e e w % från föreg. try farmer takes cabbage e e w e % från w e w w try farmer takes wolf w w w e % från föreg. try farmer takes wolf e e w e % från föreg. try farmer takes goat e w e e % från w w w e try farmer takes goat w w w e % från föreg. try farmer takes cabbage w w e w % från e w e e BACKTRACK from: e w e e % dead end BACKTRACK from: w w w e % dead end

Körning © Patrick Blackburn, Johan Bos & Kristina Striegnitz try farmer takes cabbage w e w w % från e e w e try farmer takes self w e w e % från e e w e try farmer takes goat e e e e % från föreg. Solution Path Is: state(w,w,w,w) % start state(e,w,e,w) % farmaren tar geten... state(w,w,e,w) %... och ror ensam tillbaka state(e,e,e,w) % farmaren tar vargen... state(w,e,w,w) %... och ror tillbaka med geten state(e,e,w,e) % farmaren tar kålhuvudet... state(w,e,w,e) %... och ror ensam tillbaka state(e,e,e,e) % farmaren hämtar geten. true. % Alla har korsat floden.

Tillståndsgrafen... © Patrick Blackburn, Johan Bos & Kristina Striegnitz (w w w w) (e w e w) (w w e w) (e e e w) (w e w w) (e e w e) (w w w e) (e w e e) (w w e w) (w e w w) (w e w e) (e e e e)

© Patrick Blackburn, Johan Bos & Kristina Striegnitz Nästa FL: aritmetik i Prolog