Logikprogrammering 23/10 Binära träd In- och uthantering David Hjelm.

Slides:



Advertisements
Liknande presentationer
Det första du bör göra är att rita horisonten
Advertisements

PowerPoint av Bendik S. Søvegjarto Koncept, text och regler av Skage Hansen.
Talföljder formler och summor
F3 Matematikrep Summatecknet Potensräkning Logaritmer Kombinatorik.
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:
Institutionen för matematik, KTH Mats Boij 5B1118 Diskret matematik 5 november B1118 Diskret matematik Tredje föreläsningen - Kombinatorik.
Logikprogrammering Ons, 25/9
Predicting protein folding pathways.  Mohammed J. Zaki, Vinay Nadimpally, Deb Bardhan and Chris Bystroff  Artikel i Bioinformatics 2004.
Binära Sökträd, kapitel 19
ABC EFG IJK Markera noden som besökt. Grannar = {E, F, B} E ej besökt, rekursivt anrop. depthFirst(A) * Djupet först i en oriktad graf.
Introduktion Logikprogrammering HT-02 Staffan Larsson.
Växjö 21 april -04Språk & logik: Kontextfria grammatiker1 DAB760: Språk och logik 21/4: Kontextfria 10-12grammatiker Leif Grönqvist
Föreläsning 10 Länkade lista Stack och Kö Att arbeta med listor
Datastrukturer och algoritmer
© Anders Broberg, Ulrika Hägglund, Lena Kallin Westin, 2003 Föreläsning 7 Träd.
© Patrick Blackburn, Johan Bos & Kristina Striegnitz FL 7: Cut och negation (kap. 10) Teori –Förklarar hur man kontrollerar Prologs backtracking-beteende.
Träd och tillämpningar Data Structures & Problem Solving using Java -- Kapitel 19, 12.
© 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 3: rekursion Teori –Introducera rekursiva definitioner i Prolog –Fyra exempel –Visa att.
XSLT – en introduktion Digitalisering av kulturarvet.
PROCESSPROGRAMMERING
Föreläsning 4 Kö Implementerad med array Implementerad med länkad lista Djup kontra bredd Bredden först mha kö.
XSLT – en introduktion Elektronisk publicering.
1 Träd nr 11 Binära träd ordnade, traversering, sökning.
1.Välj en nod vilken som helst och markera den som öppen. Låt den bli rot. A R B F C D E G
Grundämne byggnad.
Namnrum, räckvidd och rekursion Linda Mannila
© Anders Broberg, Ulrika Hägglund, Lena Kallin Westin, 2003 Föreläsning 11 Trie, Sökning och Sökträd.
Logikprogrammering 21/10 Binära träd
Föreläsning 5 Arrayer & ArrayList Hur man använder API:n
Datastrukturer och algoritmer
TILLÄMPAD DATALOGI (TILDA) Övning 3
Logik med tillämpningar
Logikprogrammering 16/ : operatorer Staffan Larsson.
Labgrupper: 2 pers/grupp fr o m lab 2 schema ENKÄT.
© Anders Broberg, Ulrika Hägglund, Lena Kallin Westin, 2003 Föreläsning 12 Sökning och Sökträd.
Länkade listor Binära träd
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.
Träd -Allmänt om träd -Binärt träd -Filkomprimering med Huffman träd
Föreläsning 13 Logik med tillämpningar Innehåll u Aritmetik i Prolog u Rekursiva och iterativa program u Typpredikat u Metalogiska predikat.
© Anders Broberg, Lena Kallin Westin, 2007 Datastrukturer och algoritmer Föreläsning 12.
Karl-Henrik Hagdahl, 11 november Repetition Logikprogrammering: måndag 11 november 2002.
För utveckling av verksamhet, produkter och livskvalitet. Algoritmer och datastrukturer - En annan sort tänkande, rekursiva metoder -Datastrukturen träd,
ITM1 Kapitel 8 Datastrukturer Grundläggande datavetenskap, 4p Utgående från boken Computer Science av: J. Glenn Brookshear.
© Anders Broberg, Ulrika Hägglund, Lena Kallin Westin, 2003 Föreläsning 9 Grafalgoritmer.
Föreläsning 16 Logik med tillämpningar Innehåll u Information kring kursvärdering och tentagenomgång u Genomgång av övningstenta 2.
1 Objektorienterad programmering för ingenjörer, VT04 Kort repetition av C-programmering och nyttiga verktyg. Tomas Larsson B439.
© Anders Broberg, Ulrika Hägglund, Lena Kallin Westin, 2003 Datastrukturer och algoritmer Föreläsning 13 Sortering.
Logik med tillämpningar
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.
Föreläsning2 Operativsystem.
© Anders Broberg, Lena Kallin Westin, 2007 Datastrukturer och algoritmer Föreläsning 14.
För utveckling av verksamhet, produkter och livskvalitet. Algoritmer och Datastrukturer -- Kap 21,14 Prioritets Köer (Priority Queues ), Graph.
© Anders Broberg, Ulrika Hägglund, Lena Kallin Westin, 2003 Datastrukturer och algoritmer Föreläsning 14.
Logikprogrammering ons 4/9 Rebecca Jonson.
För utveckling av verksamhet, produkter och livskvalitet. Algoritmer och datastrukturer Sökning, Symbol tabeller Binära sökträd.
För utveckling av verksamhet, produkter och livskvalitet. Algoritmer och datastructurer - En annan sort tänkande, rekursiva metoder -Datastrukturen träd.
A R B F C D E G Välj en nod vilken som helst och markera den som öppen. Låt den bli rot.
På den här bilden, marken (vattnet) stannar där linjen är
Indexberäkning Svarsalternativ Poäng per alternativ Antal svar
Tala om tal.
Filosofisk logik Kapitel 15
© Anders Broberg, Ulrika Hägglund, Lena Kallin Westin, 2003
Multiplikation Problemlösningar.
Presentationens avskrift:

Logikprogrammering 23/10 Binära träd In- och uthantering David Hjelm

Binära träd

Binära träd repetition Binära träd är antingen tomma eller så består de av två delträd samt en rot. Vi noterar dem så här: –Det tomma trädet: nil. –Annars: t(V,R,H) där V är vänster delträd, H är höger delträd och R är roten, som innehåller elementet för just den noden. V och H är binära träd eva / \ pär ada / \ * * * *

Binära träd repetition Ett ordnat binärt träd (binary dictionary) är antingen: –Det tomma trädet nil eller –Ett träd t(V,R,H) där alla noderna i V är mindre än R, alla noderna i H är större än R och delträden V och R är ordnade my / \ anna * / \ * eva / \ * *

Binära träd repetition Ett balanserat binärt träd är antingen: –Det tomma trädet nil eller –Ett träd t(V,R,H) där delträden V och H är balanserade samt om V och H har nästan lika många element. Med ’nästan lika många’ menas här att det kan få finnas ett mer element i det ena delträdet än det andra men inte fler eva / \ anna my / \ / \ * * * åsa / \ * *

Binära träd repetition | ?- Tree = t(T1,linda,T2),T1=t(T3,eva,T4),T3=t(T5,anna,T6), T5=nil,T6=nil,T4=nil,T2=t(T7,nadja,T8),T7=t(T9,my,T10),T9=nil, T10=nil,T8=nil. T1 = t(t(nil,anna,nil),eva,nil), T2 = t(t(nil,my,nil),nadja,nil), T3 = t(nil,anna,nil), T4 = nil, T5 = nil, T6 = nil, T7 = t(nil,my,nil), T8 = nil, T9 = nil, T10 = nil, Tree = t(t(t(nil,anna,nil),eva,nil),linda,t(t(nil,my,nil), nadja,nil)) ? linda / \ evanadja / \ / \ anna * my * / \ / \ * * * *

Binära träd - size/2 Vi vill beräkna antalet element i ett binärt träd. För att göra detta definierar vi predikatet size/2.där första argumentet är ett binärt träd och andra argumentet är storleken. Eftersom binära träd är rekursiva datastrukturer måste vi skriva ett rekursivt predikat. Basfall: storleken på ett tomt träd är 0. Rekursionsfall: storleken på ett sammansatt träd är summan av storleken på de båda delträden + 1.

Binära träd - size/2 %basfall size(nil,0). %rekursionfall size(t(V,_,H),Size):- size(V,VSize), size(H,HSize), Size is Vsize + Hsize + 1.

?- size(t(t(nil,anna,nil),eva,t(nil,linda,nil)),Size). 1 1 Call: size(t(t(nil,anna,nil),eva,t(nil,linda,nil)),_337)? 2 2 Call: size(t(nil,anna,nil),_886) ? 3 3 Call: size(nil,_1297) ? 3 3 Exit: size(nil,0) ? 4 3 Call: size(nil,_1291) ? 4 3 Exit: size(nil,0) ? 5 3 Call: _886 is ? 5 3 Exit: 1 is ? 2 2 Exit: size(t(nil,anna,nil),1) ? 6 2 Call: size(t(nil,linda,nil),_880) ? 7 3 Call: size(nil,_4384) ? 7 3 Exit: size(nil,0) ? 8 3 Call: size(nil,_4378) ? 8 3 Exit: size(nil,0) ? 9 3 Call: _880 is ? 9 3 Exit: 1 is ? 6 2 Exit: size(t(nil,linda,nil),1) ? 10 2 Call: _337 is ? 10 2 Exit: 3 is ? 1 1 Exit: size(t(t(nil,anna,nil),eva,t(nil,linda,nil)),3) ? Size = 3 ? yes size/2 trace

Binära träd - depth/2 Det kan även vara intressant att veta ett träds djup. Djupet på ett träd är den längsta möjliga vägen från roten till ett löv. Som löv räknar vi det tomma trädet. Även här definierar vi ett rekursivt predikat. Basfall: djupet på ett tomt träd är 0. Rekursionsfall: djupet på ett sammansatt träd är 1 + djupet på det djupaste av delträden.

Binära träd - depth/2 % djupet på ett tomt träd är 0. depth(nil,0). % djupet på ett sammansatt träd är 1 + djupet på det % djupaste av delträden. depth(t(V,_,H),Depth):- depth(V,VDepth), depth(H,HDepth), Depth is 1 + max(VDepth,HDepth). max -funktorn ingår här i det aritmetiska uttrycket som beräknas av is/2. T.ex. så gäller 3 is max(3,2).

?- depth(t(nil,anna,t(t(nil,eva,nil),lisa,nil)),D). 1 1 Call: depth(t(nil,anna,t(t(nil,eva,nil),lisa,nil)),_331) ? 2 2 Call: depth(nil,_880) ? 2 2 Exit: depth(nil,0) ? 3 2 Call: depth(t(t(nil,eva,nil),lisa,nil),_874) ? 4 3 Call: depth(t(nil,eva,nil),_2035) ? 5 4 Call: depth(nil,_2446) ? 5 4 Exit: depth(nil,0) ? 6 4 Call: depth(nil,_2440) ? 6 4 Exit: depth(nil,0) ? 7 4 Call: _2035 is 1+max(0,0) ? 7 4 Exit: 1 is 1+max(0,0) ? 4 3 Exit: depth(t(nil,eva,nil),1) ? 8 3 Call: depth(nil,_2029) ? 8 3 Exit: depth(nil,0) ? 9 3 Call: _874 is 1+max(1,0) ? 9 3 Exit: 2 is 1+max(1,0) ? 3 2 Exit: depth(t(t(nil,eva,nil),lisa,nil),2) ? 10 2 Call: _331 is 1+max(0,2) ? 10 2 Exit: 3 is 1+max(0,2) ? 1 1 Exit: depth(t(nil,anna,t(t(nil,eva,nil),lisa,nil)),3) ? D = 3 ? yes depth/2 trace

Lägga till element i ett ordnat binärt träd Vi har ett ordnat binärt träd och vill lägga till ett nytt element Nytt. Detta är ett enkelt sätt att göra det på: Om trädet är tomt, nil, så skapar vi helt enkelt ett nytt träd t(nil,Nytt,nil). Om trädet är sammansatt, t(V,R,H), finns tre alternativ: –Nytt är mindre än R. I så fall lägger vi till Nytt i V. –Nytt är större än R. I så fall lägger vi till Nytt i H. –Nytt och R är lika. I så fall behöver vi inte lägga till Nytt. För att täcka dessa fall behöver vi alltså fyra klausuler. Vi definierar predikatet add/3 som tar ett binärt träd och ett element och returnerar ett nytt träd som resultat.

Binära träd - add/3 %add(Nytt,Träd,NyttTräd) add(Nytt, nil, t(nil,Nytt,nil)). add(Nytt, t(V,Nytt,H), t(V,Nytt,H)). add(Nytt, t(V,Rot,H), t(NyttV,Rot,H)):- Rot, add(Nytt, V, NyttV). add(Nytt, t(V,Rot,H), t(V,Rot,NyttH)):- Y, add(Nytt, H, NyttH).

?- add(lena,t(nil,eva,t(nil,my,nil)),T). 1 Call: add(lena,t(nil,eva,t(nil,my,nil)),_302) ? 2 Call: ? 2 Fail: ? 2 Call: ? 2 Exit: ? 2 Call: add(lena,t(nil,my,nil),_827) ? 3 Call: ? 3 Exit: ? 3 Call: add(lena,nil,_1990) ? 3 Exit: add(lena,nil,t(nil,lena,nil)) ? 2 Exit: add(lena,t(nil,my,nil),t(t(nil,lena,nil),my,nil)) ? 1 Exit: add(lena,t(nil,eva,t(nil,my,nil)), t(nil,eva,t(t(nil,lena,nil),my,nil))) ? T = t(nil,eva,t(t(nil,lena,nil),my,nil)) ? yes add/3 - trace

Lägga till element i balanserade binära träd Ett problem med det add-predikat vi definierat är att balanserade träd kan bli obalanserade om vi stoppar in nya element. Om man till exempel stoppar in elementen i ordning händer detta: ?- add(anna,nil,T1),add(eva,T1,T2),add(lisa,T2,T3). T1 = t(nil,anna,nil), T2 = t(nil,anna,t(nil,eva,nil)), T3 = t(nil,anna,t(nil,eva,t(nil,lisa,nil)))

Lägga till element i balanserade binära träd Det finns sätt att återbalansera träd efter att man har stoppat in element och det finns specialträd som alltid är balanserade (se kap 10 i boken). Ingår inte i denna kurs. Bra informell metod är att stoppa in elementen i oordning.

Ta bort element från ordnade binära träd Det är svårare att ta bort element än att lägga till dem. Antag att det är roten i trädet som ska bort. I så fall finns det två delträd nedanför elementet, som måste kombineras till ett nytt träd. Antag att elementet som ska bort är R, roten i trädet t(V,R,H ). Då är resultatet ett träd med elementen i V och H, och dessutom ska det vara ordnat. Leta upp ett passande element E i något av delträden, antingen det största elementet i V eller det minsta elementet i H, ta bort E från delträdet och stoppa in E istället för R. Står närmare beskrivet på sid. 209ff i kursboken.

Ta bort element från balanserade träd Problemet med att ta bort element är detsamma som med att lägga till element - trädet kan bli obalanserat. Det finns naturligtvis mer sofistikerade sätt att ta bort element från träd. Ingår inte heller i kursen.

In- och uthantering

Det finns i Prolog predikat för att skriva till skärmen och till filer samt läsa från skärmen och från filer. Förutom att läsa och skriva tecken kan man läsa och skriva termer. Det är ju precis det som interpretatorn gör när man ställer en fråga till systemet. SICStusmanualen tar upp en mängd olika predikat för in- och uthantering. Vissa av dessa gäller bara för SICStus Prolog. Idag ska vi främst ta upp write/1, read/1, put_char/1 och get_char/1. De tillhör alla ISO- standarden.

Uthantering - write/1 Predikatet write/1 skriver ut en term på skärmen: ?- write(ellen). ellen yes Argumentet till write/1 kan vara vilken term som helst. Variabler blir dock inte så snyggt eftersom de direkt döps om internt av prolog: ?- write(term(a,[b,c],D)). term(a,[b,c],_239) true ? yes

Uthantering - write/1,nl/0 Predikatet nl/0 skriver ut en radmatning. Det går också att använda write('\n'). ?- write(a),nl,write(b),write(’\n’),write(c). a b c yes

Uthantering - write/1,nl/0 För att skriva ut mellanslag och stora bokstäver måste man använda ’’ ?- write('A B C'). A B C yes ?- write('et'),nl,write(' tu'),nl,write(' Brute'). et tu Brute yes

Inhantering - read/1 Predikatet read/1 läser in en prologterm från tangentbordet. Argumentet till read/1 är en variabel som instantieras till det man matar in. Det man skriver in måste vara en korrekt prologterm, och måste avslutas med punkt. Annars blir det syntaxfel. Skriver man in något med stor bokstav (utan citationstecken) tolkas det som en variabel. | ?- read(X). |: sover(lisa). X = sover(lisa) ? yes

Inhantering - read/1 Man kan även läsa in tal och strängar. | ?- read(X),read(Y). |: 1. |: "ett". X = 1, Y = [e,t,t] ? yes

Inhantering - read/1 Man kan även använda operatorer: ?- read(X). |: 1*2+3. X = 1*2+3 ? yes Skriver man en variabel så tolkas den som en ny okänd variabel: | ?- read(X). |: ETT:2:TRE. X = _A:2:_B ? yes

Uthantering - put_char/1 Predikatet put_char/1 skriver ut ett tecken i taget: ?- put_char(e),put_char(v),put_char(a),put_char('\n'). eva yes put_char/1 kan inte skriva ut något annat än tecken: | ?- put_char(A). {INSTANTIATION ERROR: put_char(_144) - arg 1} | ?- put_char(2). {TYPE ERROR: put_char(2) - arg 1: expected character, found 2}

Inhantering - get_char/1 put_char/1 är inte så användbart, man kan ju alltid använda write/1 istället. Dess motsvarighet get_char/1 är däremot väldigt användbar. Med get_char/1 kan man läsa in (nästan) vad som helst tecken för tecken. ?- get_char(C). |: a C = a ? Här kan vi dessutom använda stora bokstäver och siffror, men de kommer alltid bli tecken i Prolog: ?- get_char(C1),get_char(C2). |: A2 C1 = 'A', C2 = '2' ? yes

Backtracking i in- och uthantering Backtracking fungerar inte för in-/uthanteringspredikaten. Anledningen till det är att Prolog interagerar med operativsystemet i övrigt som inte har en aning om vad backtracking innebär. read/1, write/1, get_char/1 och put_char/1 utförs alltid, oberoende huruvida frågan lyckas eller ej: ?- Term = lisa, write(Term), Term = pelle. lisa no Om vi hade bytt plats på write(Term) och Term = pelle i frågan ovan så hade inget skrivits ut.

Inhantering - get_line/1 Vi vill läsa in en hel rad till en sträng. För att göra detta definierar vi predikatet get_char/1 som anropar get_char/1 tills ’\n’ har lästs. get_line(Str) :- get_char(X), ( X = ’\n' -> Str = [] ; Str = [X|Rest], get_line(Rest) ). OBS!!! OBS!!!: Vi får bara anropa get_char/1 en gång per tecken. Därför kan vi inte dela upp get_line/1 på två klausuler - ett basfall och ett rekursionsfall.

Inhantering - get_line/1 ?- get_line(Str). |: En rad med tecken. Str = ['E',n,' ',r,a,d,' ',m,e,d,' ',t,e,c,k,e,n,'.'] ? yes ?- get_line(Str1),get_line(Str2). |: en rad |: en annan rad Str1 = [e,n,' ',r,a,d], Str2 = [e,n,' ',a,n,n,a,n,' ',r,a,d] ? yes

Det var allt!