• No results found

Logikprogrammering del av DD1351 Logik för dataloger

N/A
N/A
Protected

Academic year: 2022

Share "Logikprogrammering del av DD1351 Logik för dataloger"

Copied!
179
0
0

Loading.... (view fulltext now)

Full text

(1)

Material 2020 för

Logikprogrammering

del av DD1351 Logik för dataloger

Thomas Sjöland sjoland@kth.se

SCS, Software and Computer Systems division CS – Computer Science department

EECS - School of Electrical Engineering and Computer Science KTH, The Royal Institute of Technology

(2)

Funktioner och relationer Deklarativ programmering

Bakgrund

(3)

Binär relation

(4)

Funktion

(5)

Om p är en binär relation så kan vi skriva:

(a, b) Î p p(a, b)

relation predikat För relationer med fler argument

(a, b, c, d, e) Î p p(a, b, c, d, e) relation predikat

Relationer

(6)

Om f är en funktion så kan vi skriva:

f(a) = b (a, b) Î f f(a, b)

funktion relation predikat Relationer är mer generella:

inte varje relation är en funktion.

Exempel: ”Fadern till a är b” kan uppfattas:

o som funktion: far(a) = b o som relation: far(a, b)

Däremot är ”b är dotter till a" en relation men inte självklart en funktion!

Funktioner

(7)

• Programmet är en beskrivning av problemdomänen

• Funktionell programmering

• Ocaml, Haskell, Scheme

• Relationell programmering

• Databasspråk (SQL), Logikprogrammering (Prolog)

• Exekveringar resulterar från frågor (queries)

• Exakta ordningen kan ändras (tillåter parallellism)

• Funktionell programmering beräknar ett värde

• Logikprogrammering konstruerar ett eller flera bevis

Deklarativ programmering

(8)

• Predikat beskriver relationer mellan objekt

• Domänen beskrivs som en sammansättning av

predikatlogiska formler i så kallad Horn-klausul form

• Frågor besvaras med en sök-algoritm som kallas resolution

• Exekveringen motsvarar sökningen efter ett bevis

• Resultatet är bindningar för logiska variabler

Logikprogrammering

(9)

• Se kurswebbsidorna: Före kursstart, Kursmaterial

• Kursbok: Learn Prolog Now!

P. Blackburn, J. Bos, och K. Striegnitz

Free online version: www.learnprolognow.org

• SWI-Prolog manual

• Föreläsningsanteckningar

• Prolog-l: *.pl

Delkurslitteratur och -material

(10)

• Logisk versus procedurell läsning

• Kontrollflöde: Unifiering, Backtracking, Snitt, Negation

• Data och rekursion

• Sammansatta data med syntaxstöd: listor

• Sammansatta data, generellt: träd

• Programmeringtekniker med Prolog

• Generera-och-testa

Delkursinnehåll

(11)

Efter godkänd kurs ska studenten kunna:

specificera allmänna egenskaper hos matematisk-datalogiska strukturer och bevisa dessa med hjälp av naturlig deduktion i satslogik och predikatlogik,

specificera induktiva definitioner hos datastrukturer och bevisa dessa med strukturell induktion, specificera och bevisa systemegenskaper med hjälp av temporal logik,

specificera och bevisa programegenskaper med hjälp av Hoarelogik,

tillämpa metoder för automatisk deduktion och utföra enkla bevis med modellprövning,

tillämpa och förklara grundläggande begrepp inom logikprogrammering:

unifiering, backtracking, snitt, negering och olika programmeringstekniker som t.ex. generate-test

i syfte att

behärska de bevistekniker som behövs i kommande kurser i utbildningen.

För högre betyg ska studenten dessutom kunna:

argumentera för korrektheten hos en viss bevisteknik: sundhet och fullständighet, argumentera för bevisteknikers lämplighet till automatisk deduktion: avgörbarhet.

Lärandemål DD1351

(12)

Logik som programmeringsspråk - Prolog Likhet för termer - Unifiering

Definition av relationer Rekursion

Backtracking

DD1351 –

Logikprogrammering

föreläsning 1(4) 9 sep 2020

(13)

Ämnen

• Data och variabler i logikprogram

• Unifiering

• Satser: fakta och regler

• Logisk versus procedurell läsning

• Backtracking

• Rekursion

Läsmaterial

• Boken: kap. 1-3

• Föreläsningsanteckningar

Idag

(14)

Data (objekt) i logikprogram

Program uttrycker sanningar som ett antal predikat (relationer) över en värld av data (objekt)

Konstanter

Individkonstanter Tal

Sammansatta termer, strukturer (normalt finita)

Träd

Specialfall (med syntaxstöd): Listor

(15)

Objekt i logikprogram

Individkonstanter

a ’B’ foo 4711 -37 34.5

Funktorer

strukturnamn för noder i träd

samma syntax som icke-numeriska individkonstanter

Syntaxexampel. en struktur (ett träd):

term(a,b,-4711,other(b,a))

(16)

Logiska variabler - Syntax

Syntax: börjar med stor bokstav (eller '_’) X Y Z Foo _Bar _

Variabler kan finnas överallt där konstanter eller strukturer förekommer.

Motsvarar termer, logiska objekt

"anonym variabel" eller "void” _

(17)

foo(X,Y,Z)

matchar termer med funktorn foo och argumenten termer som matchar X, Y, Z.

foo(T,a,T)

matchar termer med funktorn foo och argument som matchar T, a, och en term som matchar

samma T i position 3 bar(_,_,_)

matchar varje term med funktorn bar och tre argument, inte nödvändigtvis samma

Logiska variabler - Syntax

(18)

Termer

Givet en mängd variabler V, en mängd konstanter C,

och en mängd funktionssymboler F t är en term omm

t Î V eller t Î C

eller t = f(t

1

,…t

n

) där f Î F och t

i

är en term

(19)

Två termer kan unifieras om det finns en substitution (med termer) för variablerna i termerna, så att båda termerna blir syntaktiskt identiska.

Exempel:

• X och agnes unifierar med substitutionen X = agnes

• far(X, petter) och far(agnes, petter) unifierar med substitutionen X = agnes

• far(agnes, Y) och far(agnes, petter) unifierar med substitutionen Y = petter

• far(X, petter) och far(agnes, Y) unifierar med substitutionen X = agnes, Y = petter

• Kan far(X, petter) och far(agnes, X) unifiera?

Term-unifiering

(20)

X=t(V1, f(3,g(4, V2)), V3), Y=t(h(V2), f(3,g(4, 5)), V1), X=Y

--- [unifiering]

X=t(h(5), f(3,g(4, 5)), h(5)) Y=t(h(5), f(3,g(4, 5)), h(5)) V1=h(5)

V2=5 V3=h(5)

Unifiera nästlade termer

(21)

Predikatlogikens syntax har såväl

predikatsymboler som funktionssymboler, tagna från olika syntaktiska mängder.

I Prolog däremot finns det ingen syntaktisk

skillnad mellan dem, och båda representeras som atomer.

Det är kontexten som bestämmer hur symbolerna tolkas.

Prolog-termer

(22)

I satsen:

a(b, c(X)).

är a en 2-ställig predikatsymbol, c en 1-ställig funktionssymbol,

b en konstant (dvs en 0-ställig funktionssymbol), och X en variabel.

OBS Funktionssymboler evalueras inte.

Prolog-termer

(23)

Relationer kan deklareras explicit, varje tupel för sig själv (uppfattas som en

konjunktion av klausuler).

Sådana definitioner kallas för fakta:

far(agnes, petter).

far(per, petter).

far(anton, per).

mor(agnes, annika).

mor(per, annika).

mor(kia, agnes).

mor(anton, agnes).

Prologsatser: fakta

(24)

Nu när vi har skapat en relationell databas, vill vi kunna ställa frågor (queries) till den.

?- far(agnes, per).

?- far(anton, per).

?- far(monika, per).

Notera att Prolog inte vet vad vi menar med alla symboler. Systemet resonerar helt symboliskt, utan tolkning!

Prolog vet inte om far(a, b) betyder ”far till a är b", eller ”a är far till b", eller t.o.m. att ”himlen har färgen a och det är b stycken moln på den".

Frågeformler, queries

(25)

Vi kan också ställa frågor som involverar variabler:

?- far(agnes, X).

Vem är far till agnes?

Eller, kan du hitta ett X som gör frågan sann?

?- far(X, petter).

Vems far är petter?

Flera svar möjliga!

Fås ett i taget med ”n” eller ";"

?- far(X, Y).

Frågor med variabler

(26)

Relationer definieras med regler:

farmor(X, Y) :- far(X, Z), mor(Z, Y).

Läs: X farmor är Y

om far till X är (någon) Z och mor till Z är Y.

Vi kan observera att:

Ø":-" läses som "om", dvs implikation ”<-" i omvänd riktning

Ø"," här läses som "och", dvs konjunktion "^"

Øvariablerna är (implicit) universellt kvantifierade Sådana formler (satser) kallas för Horn-klausuler

Prologsatser: regler

kon jun ktio n

(27)

OBS att

far(anton, per).

kan skrivas

far(anton, per) :- true.

eller

far(X, Y) :- X= anton, Y= per.

så vi behöver bara en form av sats för definitioner Head :- Body

Prologsatser: regler

(28)

Disjunktiva regler kan anges som separata klausuler:

foralder(X, Y) :- far(X, Y).

foralder(X, Y) :- mor(X, Y).

eller ekvivalent som

foralder(X, Y) :- far(X, Y) ; mor(X, Y).

Läs:

en förälder till X är Y

om far till X är Y eller mor till X är Y.

Följer logiska ekvivalensen:

p v q -> r ó (p -> r ) ^ (q -> r )

Prologsatser: regler

disj unk tion

(29)

• Problemdomän beskrivs med relationer

• Fakta och regler

• Data som termer

Prolog söker svar på frågor om domänen

Den deklarativa aspekten

(30)

• Unifiering för att göra termer lika

• Sökning med backtracking

• Typisk programstruktur: generera-och-testa

• Snitt

• Att ta bort oönskade beräkningssteg eller svar

Prolog söker svar genom att bygga ett enkelt logiskt bevis för ett påstående med användning av programmets satser.

Den procedurella aspekten

kontrollflödet

(31)

Logisk läsning

Ø som en predikatlogisk formel, deklarativt

Procedurell läsning

Ø proceduren som Prolog följer för att hitta ett bevis Ø Prolog läser klausulerna uppifrån och ned, och

kroppens literaler från vänster till höger

Ø Prolog försöker instansiera variablerna med termer så att målet blir sant: unifiering

Ø om detta misslyckas går Prolog till föregående literal inom klausulens kropp om en sådan finns, och annars till nästa klausul i programmet: backtracking

Logisk versus procedurell läsning

(32)

Bevisteori:

Exekvering är att söka efter ett bevis eller misslyckande. Detta genererar ett eller-träd

begränsningar på variablernas värden visas som bindningar hos

variablerna

(33)

Sökträd och bevisträd

bevis

Sökträd Bevisträd

lösning

(34)

Hur Prolog exekverar

En fråga ?- p(Args).

bevisas med resolution

- leta efter alla klausuler som definierar p

- välj den första, spara de kvarvarande som alternativ

- matcha argumenten Args med termerna i klausulens huvud, skapa nödvändiga variabel- bindningar med unifiering

- om unifieringen misslyckas, prova nästa alternativa klausul

- bevisa annars målen i kroppen från vänster till

höger; om detta misslyckas, prova alternativ klausul

- om alla bevis är klara, presentera bindningarna,

annars är resultatet ” no ” eller ” fail ”.

(35)

Mål: farmor(anton, X).

Skapar regelinstans:

farmor(X1, Y1) :- far(X1, Z1), mor(Z1, Y1).

unifierar X1=anton, Y1=X

Delmål: far(anton, Z1).

unifierar Z1=per

Delmål: mor(per, X).

unifierar X=annika

Svar: X=annika

Kontrollflödet i Prolog: Exempel 1

(36)

Ø Mål: foralder(kia, X).

Ø Skapar regelinstans:

foralder(X1, Y1) :- far(X1, Y1).

unifierar X1=kia, Y1=X Ø Delmål: far(kia, X).

Kan inte unifieras. Backtrackar till nästa regel.

Ø Skapar regelinstans:

foralder(X2, Y2) :- mor(X2, Y2).

unifierar X2=kia, Y2=X

Ø Delmål: mor(kia, X).

unifierar X=agnes

Ø Svar: X=agnes

Kontrollflödet i Prolog: Exempel 2

(37)

Regler kan vara rekursiva, dvs referera till sig själv:

forfader(X, Y) :- foralder(X, Y).

forfader(X, Y) :- foralder(X, Z), forfader(Z, Y).

Betrakta frågan:

?- forfader(kia, X).

Vad blir kontrollflödet till första svaret?

Och till andra svaret? (';' leder till backtracking!)

Vad skulle hända om vi vänder om ordningen på de två reglerna?

Och på de två konjunkterna i andra regeln?

Rekursion

(38)

För att få en bättre förståelse av

kontrollflödet i Prolog och trace-funktionen, läs också om lådmodellen: se handouts.

Kontrollflödet i Prolog: Lådmodellen

(39)

Likhet = betyder ”unifierbara”, inte "samma värde"!

Speciella predikatet is utvärderar andra termen och unifierar med första. Obs: andra termen måste vara tillräckligt instansierad!

X is Expression

Dubbelsidig utvärdering och jämförelse: =:=.

Aritmetiska operatorer: +, -, *, /, //, mod, etc.

Olikheter: <, >, =<, >=, etc.

T.ex. X<35, X>=13. ” X finns i intervallet [13..35[”

Aritmetik i Prolog

(40)

Två nödvändiga predikat:

Øread(t): läs en term fram till nästa punkt och unifiera den med termen t;

Øwrite(t): skriv ut termen t till terminalen.

Vad händer vid frågan:

?- read(X+Y), write(Y-3).

I/O i Prolog

(41)

Syntaktiskt stöd

Med op/3 kan egenskaper (prioritet, prefix, infix, postfix, associativitet) hos operatorer defineras och därefter

användas. (see manualen för detaljer)

Predikat som definieras av användaren skrivs med samma syntax som datastrukturer, till exempel

:- op(950, xfy, [in]).

foo(Y) :- X in Y, baz(Y in U,Z).

(42)

Material 2020 för

Logikprogrammering

del av DD1351 Logik för dataloger

Thomas Sjöland sjoland@kth.se

SCS, Software and Computer Systems division CS – Computer Science department

EECS - School of Electrical Engineering and Computer Science KTH, The Royal Institute of Technology

(43)

Lite om databasoperationer Induktiv definition av data:

Sammansatta termer

Listor (inbyggt syntaxstöd)

DD1351 –

Logikprogrammering

föreläsning 2(4) 14 sep 2020

(44)

Listor

• Strukturell induktion över listor

• Kontrollflöde

• Generera och testa

• Strängar

Läsmaterial

• Boken: kap. 4, 6

• Prolog-l: list.pl

• Handouts: Föreläsningsanteckningar

Idag

(45)

LP och relationsdatabaser

Union:

r_union_s(X1,…,Xn) :- r(X1,…,Xn).

r_union_s(X1,…,Xn) :- s(X1,…,Xn).

Cartesian product:

r_X_s(X1,…,Xn,Y1,…,Ym) :- r(X1,…,Xn), s(Y1,…,Ym).

Projection:

r1(X1,X3) :- r(X1,X2,X3).

(46)

LP och relationsdatabaser

Selection:

r1(X1,X2,X3) :- r(X1,X2,X3), X2\=X3.

Natural join:

r_join_s(X1,…,Xn, X, Y1,…,Ym) :- r(X1,…,Xn, X), s(X,Y1,…,Ym).

Intersection:

r_meets_s(X1,…,Xn) :-

r(X1,…,Xn), s(X1,…,Xn).

(47)

LP och databaser, sammanfattning

LP kan användas som ett uniformt språk för att representera databaser, t.ex. datastrukturer and frågor kan skrivas med ett språk

LP utvidgar traditionella databaser genom att

det har rekursiva regler och strukturerad data

(48)

Exempel: strukturerad data

Använd sammansatta termer för beskrivning av personer.

parent(erik, jonas).

parent(erik, eva).

parent(lena, jonas).

male(person(erik,50,180cm)).

male(person(jonas,25,_)).

father(Dad,Child) :- Dad = person(DadName,_,_),

Child = person(ChildName,_,_), parent(DadName, ChildName), male(Dad).

?-father(person(_,50,_), person(X,_,_)).

X=jonas (lösning #2: X = eva)

Fråga: Hur fungerar unifieringsalgoritmen här? Beskriv kontrollflödet!

(49)

%Kommentarkonvention

% +X betyder X är avsedd som ”input”

% -X betyder X är avsedd som ”output”

% ?X betyder X kan var input eller output

%

% foo(+X,?Y,-Z)

%

% OBS en term kan vara partiellt instantierad, samtidigt ”input” och ”output”

Konventioner om input och output

(50)

Att konstruera rekursiva definitioner

Tänk på deklarativa meningen hos den rekursiva relationen (en datatypsdefinition)

Skriv ner rekursiva klausuler och basklausul(er) Ladda in i prologsystemets interpretator

Kör enkla exempel - testa olika mål Kontrollera vad som händer

- Får du det resultat du väntar dig?

(51)

Att konstruera rekursiva definitioner

Typiska fel:

Saknat eller felaktigt definierat basfall Fel i datastrukturernas representation Fel ställighet (arity) hos strukturer

Fel ställighet (arity) hos predikat (relationer) Sammanblandning av ett element och en lista Permuterade argument

Felstavningar. Stora och små bokstäver

Samma variabler används för olika saker

(52)

Naturliga tal

Unär syntax

Till exempel,

0 - betyder noll

s(0) - betyder ett

s(…s(s(0))…) ... - betyder talet n

Att definiera de naturliga talen

natural_number(0).

natural_number(s(X)) :-

natural_number(X).

(53)

Naturliga tal

plus

plus(0, X, X) :- natural_number(X).

plus(s(X), Y, s(Z)) :- plus(X, Y, Z).

?- plus(s(0),0,s(0)). – kontrollerar om 1+0=1 Yes.

?- plus(X,s(0),s(s(0))). - kontrollerar om X+1=2, (beräkna X=2-1) X=s(0).

?- plus(X, Y, s(s(0))). - kontrollerar om X+Y=2, (t.ex. generera alla par av naturliga tal, vilkas summa är två)

X=0, Y=s(s(0));

X=s(0), Y=s(0);

X=s(s(0)), Y=0.

(54)

Naturliga tal

Mindre än eller lika

le(0, X) :- natural_number(X).

le(s(X), s(Z)) :- le(X, Z).

multiplikation

times(0, X, 0) :- natural_number(X).

times(s(X), Y, Z) :-

plus(Y, Z1, Z), times(X, Y, Z1).

Kontrollera hur substitutionerna I unifieringen fungerar!

(55)

Binära träd

tree(5,tree(8,void,void),tree(9,void,tree(3,void,void)))

8

5

3 9

void void void

void void

(56)

Binära träd (mera tydligt)

tree(5,tree(8,void,void),tree(9,void,tree(3,void,void)))

tree

tree

tree tree

void void void

void void

5

3

8 9

(57)

Binära träd

Syntax (inte inbyggt, du definierar dina egna sammansatta termer)

Till exempel,

void - betyder tomma trädet

tree(Element, Left, Right)

- betyder ett träd, där Element är roten och Left, Right är delträd tree(5,tree(8,void,void),tree(9,void,tree(3,void,void)))

Att definiera ett träd

binary_tree(void).

binary_tree(tree(Element, Left, Right)) :-

binary_tree(Left), binary_tree(Right).

(58)

Binära träd

medlemskap

tree_member(X,tree(X,_,_)).

tree_member(X,tree(Y,Left ,_)):- tree_member(X,Left).

tree_member(X,tree(Y,_,Right)):- tree_member(X,Right).

OBS: X kan vara samma term som Y I klausulerna 2 och 3!

(59)

Binära träd– mirror/2

Att spegla ett träd

mirror(void,void).

mirror(tree(Y,L1,R1),tree(Y,R2,L2)):- mirror(L1,L2),

mirror(R1,R2).

3 1

4 2

void void void

void void

3

1

4 2

void void void

void void

(60)

Listor

'.'(Head,Tail) cons cell

Head är ett element, Tail är en lista) [] tomma listan

Föredragen syntax (oftast): [Head|Tail]

enklare syntax

[a|[]] = [a] [a|[b|[c|[]]]] = [a,b,c]

. . . -

.

.

a b c

[]

[]

a

b

c

(61)

Listor

Syntax

[Head|Tail] eller '.'(Head,Tail) cons-cell Head är ett element, Tail är en lista

[] tomma listan

definiera en lista

list([]). - definera basen

list([X|Xs]) :- list(Xs). - definera rekursionen

(62)

Listor

Att kontrollera medlemskap

member(X, [X|Xs]).

member(X, [Y|Ys]) :- member(X, Ys).

?- member(a, [b,c,a,d]). - att kontrollera medlemskap

?- member(X, [b,c,a,d]). - hitta ett element i en lista

?- member(b, Z). - generera en lista som innehåller b

(63)

Rekursiv aritmetik

Jämför dessa två definitioner och förklara skillnaden:

sum([],0).

sum([H|T],S) :- sum(T,V), S is H+V.

sum0([],0).

sum0([H|T],S) :- sum0(T,V), S=H+V.

(64)

Listorna utgör en oändlig mängd av Prolog-termer.

Induktiv definition:

en lista är antingen tom [], eller en konstruktion [H|T]

av ett element H ("huvud") och en lista T ("svans").

OBS kom ihåg även denna konvention!

’.’(H,T)= [H|T]

Listor

(65)

Definition i Backus-Naur Form (BNF):

<Lst> ::= [] | [<El>|<Lst>]

där <El> är vilken som helst Prolog-term.

Därmed matchar varje lista l antingen []

eller [H|T] , och vi kan använda detta för att ta isär (destruera) listor för att definiera predikat över listor med strukturell

induktion.

Listor

(66)

Notationskonvention:

Vi skriver

[a, b, c]

istället för

[a | [b | [c | []]]],

detta gör också Prologs "pretty-print".

OBS även denna konvention!

’.’(H,T)= [H|T]

Listor

(67)

Strukturell induktion är en princip att garantera ”well- definedness”.

För induktivt definierade datatyper kan vi använda oss av strukturell induktion för att definiera predikat över dem.

Konkret, för listor:

• för tomma listan [], definiera predikatet icke-rekursivt;

• för sammansatta listan [H|T] , definiera predikatet med användning av samma predikat, men bara över svansen T.

Om man följer principen garanterar man att predikatet blir

"väldefinierat" över alla listor.

Läs också texten: "The Principle of Structural Induction" !

Strukturell induktion över listor

(68)

is_list([]).

is_list([ _ | T]) :-

is_list(T).

first_element([ E | _],E).

last_element([E],E).

last_element([ _ | T],E) :- last_element(T,E).

OBS syntaxstöd: [A] = ’.’(A,[]) = [A|[]]

Predikat över listor

(69)

Längden på en lista L är antalet element N i listan.

Definition med strukturell induktion:

• längden på tomma listan [] är 0;

• längden på sammansatta listan [H | T] är längden på svansen T plus 1.

Låt oss använda detta för att implementera listLength(L, N).

Längden på en lista

(70)

I Prolog:

listLength([], 0).

listLength([ _ | T], N) :- listLength(T, NT), N is NT + 1.

Notera att vi använder operatorn "is" istället för "=". Varför?

Notera också hur vi använder mönster-matchning i första argumentet för att åstadkomma datatyp-destruktionen som är

nödvändig för strukturella induktionen.

Kan vi vända på ordningen på de två konjunkterna?

Finns även inbyggd som length(L, N).

listLength(L, N)

(71)

Mål: listLength([a, b], N).

skapar en instans av andra regeln:

listLength([A1 | T1], N1) :- listLength(T1, NT1), N1 is NT1 + 1.

unifierar A1=a, T1=[b], N1=N

• Delmål: listLength([b], NT1).

• skapar instans av andra regeln:

• listLength([A2 | T2], N2) :- listLength(T2, NT2), N2 is NT2 + 1.

• unifierar A2=b, T2=[], N2=NT1

• Delmål : listLength([], NT2).

• matchar första regeln, unifierar NT2=0

• Delmål : NT1 is 0 + 1.

• evaluerar 0+1 till 1, unifierar NT1=1

• Delmål : N is 1 + 1.

• evaluerar 1+1 till 2, unifierar N=2 Svar: N=2

Kontrollflödet vid listLength([a, b], N).

(72)

Från KS:en HT15:

Fråga: listLength(L, 2).

- misslyckas med första regeln, därför att 0 och 2 inte kan unifieras - skapar instans av andra regeln

listLength([A1|T1], N1) :-

listLength(T1, NT1), N1 is NT1+1.

unifierar: L=[A1|T1], N1=2 -- listLength(T1, NT1).

--- lyckas med första regeln unifierar: T1=[], NT1=0 -- 2 is 0+1.

--- evaluerar 0+1 till 1

--- misslyckas, därför att 2 och 1 inte kan unifieras --- backtrackar

….. (forts på nästa bild)

Kontrollflödet vid listLength(L, 2).

(73)

Från KS:en HT15:

….

(Forts från föregående bild) -- listLength(T1, NT1).

--- skapar instans av andra regeln:

listLength([A2|T2], N2) :- listLength(T2, NT2), N2 is NT2+1.

unifierar: T1=[A2|T2], N2=NT1 ---- listLength(T2, NT2)

--- lyckas med första regeln unifierar: T2=[], NT2=0 ---- NT1 is 0+1

--- evaluerar 0+1 till 1 --- unifierar: NT1=1 -- 2 is 1+1

--- evaluerar 1+1 till 2

--- lyckas, därför att 2 kan unifieras med 2

Svar: L=[A1|[A2|[]]] som presenteras som L=[A1, A2]

Kontrollflödet vid listLength(L, 2).

(forts)

(74)

Medlemstest som ska vara sant om och bara om X finns i listan L.

in(H, [H | _]).

in(X, [_ | T]) :- in(X, T).

Strukturella induktionen är över listan L (dvs andra argumentet).

in(X, []) är alltid falskt: ingen regel för tom lista!

Finns även inbyggd som member(X, L).

Medlemskap i en lista: in(X, L)

(75)

• Mål: in(2, L), in(1, L).

• Delmål: in(2, L).

• skapar instans av första regeln:

in(H1, [H1 | A1]).

unifierar H1=2, L=[2 | A1]

• Delmål : in(1, [2 | A1]).

• skapar instans av första regeln:

in(H2, [H2 | A2]).

misslyckas med unifieringen (varför?)

• skapar instans av andra regeln:

in(X1, [A3 | T1]) :- in(X1, T1).

unifierar X1=1, A3=2, T1=A1

• Delmål : in(1, A1).

• skapar instans av första regeln:

in(H3, [H3 | A4]).

unifierar H3=1, A1=[1 | A4]

• Svar: L =[2, 1 | A4] Finns det fler svar? Hur hittas L=[1, 2] ?

Kontrollflödet vid in(2, L), in(1, L).

(76)

Ska vara sant om Z är konkateneringen av listan X med listan Y.

append([], Y, Y).

append([HX | TX], Y, [HX | TZ]) :- append(TX, Y, TZ).

Strukturella induktionen är över listan X (dvs första argumentet).

(Finns inbyggd i många prologsystem.)

Sätta samman listor: append(X, Y, Z)

(77)

Listor

Konkatenering av två listor

append([], Xs, Xs).

append([X|Xs], Y, [X|Zs]) :- append(Xs, Y, Zs).

?- append([a,b], [c,d], X). - sammansättning av två listor

. .

a b

[]

. .

c d

[]

. .

a b

. .

c d

X= []

(78)

Listor

“differens” mellan två listor

append([], Xs, Xs).

append([X|Xs], Y, [X|Zs]) :- append(Xs, Y, Zs).

?- append(Xs, [c,d], [a,b,c,d]).

- finner “differensen” mellan listor

. .

a b

[]

. .

c d

[]

. .

a b

. .

c d

[]

Xs=

(79)

Listor

Att dela upp en lista i två delar (1)

append([], Xs, Xs).

append([X|Xs], Y, [X|Zs]) :- append(Xs, Y, Zs).

?- append(Xs, Ys, [a,b,c,d]).

. .

a b

[]

. .

c d

[]

. .

a b

. .

c d

[]

Xs= Ys=

(80)

Listor

Att dela upp en lista i två delar (2)

append([], Xs, Xs).

append([X|Xs], Y, [X|Zs]) :- append(Xs, Y, Zs).

?- append(Xs, Ys, [a,b,c,d]).

. .

a b

[]

. .

c d

[]

. .

a b

. .

c d

[]

Xs= Ys=

(81)

Listor

Att dela upp en lista i två delar (3)

append([], Xs, Xs).

append([X|Xs], Y, [X|Zs]) :- append(Xs, Y, Zs).

?- append(Xs, Ys, [a,b,c,d]).

. .

a b

[]

. .

c d

[]

. .

a b

. .

c d

[]

Xs= Ys=

(82)

Listor

Att dela upp en lista i två delar (4)

append([], Xs, Xs).

append([X|Xs], Y, [X|Zs]) :- append(Xs, Y, Zs).

?- append(Xs, Ys, [a,b,c,d]).

. .

a b

. .

c d

[]

. .

a b

. .

c d

[]

Xs= [] Ys=

(83)

Listor

Att dela upp en lista i två delar (5)

append([], Xs, Xs).

append([X|Xs], Y, [X|Zs]) :- append(Xs, Y, Zs).

?- append(Xs, Ys, [a,b,c,d]).

. .

a b

. .

c d

[]

. .

a b

. .

c d

[]

Xs= Ys= []

(84)

Listor

Att vända på en lista

reverse([], []).

reverse([H|T],R) :- reverse(T,S), append(S,[H],R).

?- reverse([a,b,c,d],R). - ger R=[d,c,b,a]

. .

a b

. .

c d

[]

. .

d c

. .

b a

R= []

(85)

Ska vara sant om listan NL är listan L med elementet X tillagt i slutet.

appendEl(X, [], [X]).

appendEl(X, [H | T], [H | Y]) :- appendEl(X, T, Y).

Strukturella induktionen är över listan L (dvs andra argumentet).

Lägg till ett element: appendEl(X, L, NL)

(86)

Ska vara sant om Y är omvända listan X.

rev([], []).

rev([H | T], Y) :-

rev(T, RT),

appendEl(H, RT, Y).

Finns även inbyggd som reverse(X, Y).

Listomvändning: rev(X, Y)

(87)

Ackumulerande parametrar

Reversering av listor

a) naive reverse (använder append i varje rekursionssteg) reverse([], []).

reverse([X|Xs], Ys) :-

reverse(Xs, Zs), append(Zs, [X], Ys).

b) reverse med ackumulator (argument 2 i hjälppredikatet) reverse(Xs, Ys) :-

reverse(Xs, [], Ys).

reverse([], Acc, Acc).

reverse([X|Xs], Acc, Ys) :-

reverse(Xs, [X|Acc], Ys).

Varför är denna teknik viktig?

Tänk på hur många steg som blir resultatet för långa listor!

(88)

Strängar

• Är symbolsekvenser.

• Representeras i Prolog internt som listor av heltal. Varje tal representerar därmed en

symbol (ASCII-koden).

• Inbyggda predikatet atom_codes(X, Y) är sant när Y är strängen (dvs heltalslistan) som motsvarar atomen X.

Strängar

(89)

Det finns många sätt att sortera listor.

Här ska vi implementera

permutationssortering, som illustration

av hur vi kan använda backtracking som en styrka för att realisera en

programmeringsteknik som kallas för generera och testa.

Listsortering

(90)

Denna programmeringsteknik använder sig av

backtracking för att successivt generera en möjlig lösning, testa om den uppfyller villkoren för att vara en korrekt

lösning, sedan backtracka och generera en möjlig lösning till, testa den, osv.

Generella strukturen ser ut så här:

problem(Problem, Solution) :-

generate(Problem, Solution), test(Solution).

För effektivitet behöver man ofta ”väva in” test i generatorn.

Generera och testa

(91)

Vi utgår från den matematiska definitionen av sortering: att sortera en lista kan definieras som att skapa (dvs beräkna) en sorterad permutation av ursprungliga listan:

permSort(X, Y) :-

permutation(X, Y), \\ generera permutation sorted(Y). \\ testa om sorterad

Programmet använder (inbyggda) predikatet

permutation(X, Y) för att generera en permutation av listan X, som sedan testas med predikatet sorted(Y)

huruvida den är sorterad eller inte.

Listsortering: permSort(+X, ?Y)

(92)

Ska vara sant om Y är en permutation av X.

Strukturella induktionen är på första listan X.

Vi utgår från följande logiska karakterisering av permutation:

Y är en permutation av X om huvudet på X (E) finns i Y, och om E tagits bort från Y, den resulterade listan är en permutation av svansen på X.

permutation([], []).

permutation([E | X], Y) :- permutation(X, Y1),

append(Y2, Y3, Y1), % används för att dela upp Y1 append(Y2, [E | Y3], Y).

Del 1: permutation(+X, ?Y)

(93)

Definieras här bara för listor av tal!

sorted([]).

sorted([X]).

sorted([X, Y | L]) :-

X =< Y,

sorted([Y | L]).

Del 2: sorted(X)

(94)

permutation(Xs, [Z|Zs]) :- select(Z, Xs, Ys), permutation(Ys, Zs).

permutation([], []).

select(X, [X|Xs], Xs).

select(X, [Y|Ys], [Y|Zs]) :- select(X, Ys, Zs).

Mer elegant permute

(95)

Material 2020 för

Logikprogrammering

del av DD1351 Logik för dataloger

Thomas Sjöland sjoland@kth.se

SCS, Software and Computer Systems division CS – Computer Science department

EECS - School of Electrical Engineering and Computer Science KTH, The Royal Institute of Technology

(96)

Definitioner över träd (sammansatta termer)

DD1351 –

Logikprogrammering

föreläsning 3(4) 16 sep 2020

(97)

Summera tal i en lista Summera tal i ett träd Definitioner över träd Binära träd utan data Binära träd med data

ØProblemdomänbeskrivning

Läsmaterial

ØProlog-l: tree.pl

ØHandouts: Föreläsningsanteckningar

Idag

(98)

Summera talen i en lista

Example

Definiera ett predikat som summerar talen i en lista.

a) rekursion

sumlist([], 0).

sumlist([I|Is], Sum) :-

sumlist(Is, Sum1), Sum is Sum1 + I.

b) iteration (med ackumulator)

sumlist(List, Sum) :- sumlist(List, 0, Sum).

sumlist([], Sum, Sum).

sumlist([I|Is], Sum1, Sum) :- Sum2 is Sum1 + I,

sumlist(Is, Sum2, Sum).

Hur mycket minne behövs?

(99)

Algoritmer över träd

Definiera ett predikat för att beräkna summan av talen i ett träd Här är en rättfram lösning:

sumtree(void,0).

sumtree(tree(E,L,R),S) :- sumtree(L,S1),

sumtree(R,S2),

S is E+S1+S2.

3

1

4 2

void void void

void void

(100)

Algoritmer över träd

Definiera ett predikat för att beräkna summan av element i ett träd - Gå igenom trädet till exempel vänster-till-höger

- För varje nod: lägg till talet till en ackumulator - Presentera slutvärdet som resultatet!

Here is the efficient solution:

sumtree(T,S) :-

sumtree(T,0,A), S is A.

sumtree(void,A,A).

sumtree(tree(E,L,R),A,S) :- sumtree(L,E+A,S1),

sumtree(R,S1,S).

3 1

4 2

void void void

void void

(101)

Definiera ett predikat för att platta ut en nästlad lista!

- T. ex. flatten([a,[b,c],d],L) skall generera listan L=[a,b,c,d]

- Tips: Kan du använda en ackumulator?

Nästlade listor

. .

a

.

d

[]

.

b

.

c

[]

.

a

.

d

[]

.

b

.

c

(102)

Definiera ett predikat för att slå samman en lista av listor!

- T.ex. listan [[1,2],[3],[4,5],[6,7,8]]

- skall generera listan [1,2,3,4,5,6,7,8]

Frågan: Hur effektivt kan du göra detta predikat?

Att lägga samman många listor

(103)

Binära träd utan data utgör en oändlig mängd av Prolog-termer:

Ett binärt träd utan data är antingen ett löv, leaf, eller ett sammansatt träd, branch(t1, t2) , som består av ett vänster delträd t1 och ett höger

delträd t2.

Induktiv definition (BNF)

<Tree> ::= leaf | branch(<Tree>, <Tree>) där leaf och branch kallas för konstruktorer.

Därmed matchar varje binärt träd utan data t antingen leaf eller branch(TL, TR).

Exempel på (stängda) träd-termer: leaf, branch(leaf, leaf), branch(leaf, branch(leaf, leaf)).

Träd-termer kan också innehålla variabler: branch(X, leaf).

Binära träd utan data

(104)

För att definiera ett predikat över binära träd utan data:

§ för löven leaf, definiera predikatet utan rekursion;

§ för sammansatta träden branch(TL, TR), definiera predikatet med användning av samma predikat över delträden TL och TR.

Då blir predikatet väldefinierat för alla binära träd utan data.

Strukturell induktion

(105)

Höjden på ett träd t är längden (antalet bågar) av längsta stigen från roten till något löv.

Definition med strukturell induktion?

§ höjden på ett löv leaf är 0;

§ höjden på ett sammansatt träd

branch(TL, TR) är maximum av

höjderna på delträden TL och TR plus 1.

Höjden på ett träd

(106)

max(X, Y, X) :- Y<X.

max(X, Y, Y) :- X=<Y.

height(leaf, 0).

height(branch(TL, TR), N) :- height(TL, NL),

height(TR, NR), max(NL, NR, M), N is M+1.

Höjden på ett träd: height(T, N)

(107)

Ett träd är komplett om det har alla sina löv på samma höjd.

Definition med strukturell induktion?

balanced(leaf).

balanced(branch(TL, TR)) :- balanced(TL),

balanced(TR), height(TL, N), height(TR, N).

Kompletta träd: balanced(T)

(108)

Ett binärt träd med data är antingen ett löv leaf(d) med en data-term d, eller ett sammansatt träd branch(d, t1, t2)

med

en data-term d, ett vänster delträd t1, och ett höger delträd t2.

Induktiv definition (BNF)

<Tree> ::= leaf(<Data>) |

branch (<Data>, <Tree>, <Tree> ) Därmed matchar varje binärt träd med data antingen leaf(D) eller branch(D, TL, TR).

Exempel:

branch(-3,branch(4,leaf(8),leaf(-2)),leaf(7))

Binära träd med data

(109)

Som member(X, L), fast för träd med data.

Definition med strukturell induktion

lookup(D, leaf(D)).

lookup(D, branch(D, _, _)).

lookup(D, branch(_, TL, _)) :- lookup(D, TL).

lookup(D, branch(_, _, TR)) :- lookup(D, TR).

Medlemskap i ett träd: lookup(D, T)

(110)

Beräknar summan av alla tal i trädet (antar att allt data är tal).

Definition med strukturell induktion

treesum(leaf(N), N).

treesum(branch(N, TL, TR), N1) :- treesum(TL, NL),

treesum(TR, NR), N1 is NL+NR+N.

Summering i ett träd: treesum(T, N)

(111)

Operationer

ØAtt lägga till ett element.

ØAtt ta bort ett element.

Problematiskt för binära träd!

Ofullständiga binära träd (utan data)

Øidé: tillåt också tomma träd. (skrivs nil) ØBNF-definition:

<Tree> ::= nil | leaf | branch(<Tree>, <Tree> ) Ø exempel: branch(leaf, branch(nil, leaf))

Strukturella operationer på träd

(112)

Datatypen hierarkiska mjukvarusystem kan definieras induktivt med två regler: ett mjukvarusystem är antingen en funktion (som i språket C), eller en modul bestående av mjukvarusystem.

1. Föreslå ett sätt att representera mjukvarusystem som Prolog- termer, där funktionerna representeras som atomer med samma namn som funktionen, t.ex. main, min, max.

2. Ge två exempel på termer som representerar mjukvarusystem med flera nästlade nivåer.

3. För din representation av datatypen mjukvarusystem, skriv ett predikat funcsMVS(S, FL) som är sant om och bara om FL är en lista som innehaller namnen pa alla funktioner i det hierarkiska mjukvarusystemet S (med möjlig upprepning).

Problemdomänbeskrivning:

Hierarkiska mjukvarusystem

(113)

1. Sammansättningar går enklast att representera som listor.

En möjlig BNF-grammatik vore:

<MVS> ::= func(<Name>) | mod(<MVSList>)

<MVSList> ::= [] | [<MVS>|<MVSList>]

2. Exempel-termer:

Ø func(foo)

Ø mod([func(main),

mod([func(min), func(max), func(avg)])])

Hierarkiska mjukvarusystem: Prolog-termer

(114)

3. Om vi följer strukturella induktionsprincipen för

ömsesidigt rekursiva datatyper (se texten "The Principle of Structural Induction"), så får vi:

funcsMVS(func(N), [N]).

funcsMVS(mod(SL), FL) :-

funcsMVSList(SL, FL).

funcsMVSList([], []).

funcsMVSList([S|SL], FL) :-

funcsMVS(S, FL1),

funcsMVSList(SL, FL2), append(FL1, FL2, FL).

Hierarkiska mjukvarusystem: funcsMVS(S, FL)

(115)

Material 2020 för

Logikprogrammering

del av DD1351 Logik för dataloger

Thomas Sjöland sjoland@kth.se

SCS, Software and Computer Systems division CS – Computer Science department

EECS - School of Electrical Engineering and Computer Science KTH, The Royal Institute of Technology

(116)

Begränsa sökningen med snitt (cut) Negation i Prolog

Generera-testa i Prolog Programmeringstekniker

Grafer

Metaprogrammering Prolog i Prolog

DD1351 –

Logikprogrammering

föreläsning 4(4) 22 sep 2020

(117)

Prolog-specifika konstruktioner

ØSnitt

ØNegation

ØKontrollpredikat, metapredikat

Generera och testa Läsmaterial

ØBoken: kap. 5, 9, 10 ØProlog-l: misc.pl

ØHandouts: Föreläsningsanteckningar

Idag

(118)

Innehåll

Snitt (Cut)

exekvering av ett program med cut Att sätta in cut in ditt program:

”gröna" och ”röda" cut

implementation av if-then-else

Negation

grundbegrepp

exekvering av program med negation

implementation av negation i Prolog

(119)

Att kontrollera sökningen

Ibland när en lösning till ett delproblem har hittats, behöver andra lösningar till målet inte testas.

Genom att använda den icke-logiska operationen !, som läses “cut”, tar du bort alternativa grenar till delmål och till klausulen som just nu prövas.

Alternativen på en högre nivå, dvs till klausulen där det nu aktuella målet ingår behålles. Detta kan

minska mängden onödiga utsökningar.

(120)

Snitt (cut)

syntax

!, kan placeras i kroppen I en klausul som ett “mål”

p(X) :- q(X), !, r(X).

effekt

när "!" nås förhindras all backtracking till vänster om “!” i kroppen.

Exekveringen till höger fortsätter som förväntat och kan generera alternativ för senare backtracking.

nya matchningar av huvudet i senare alternativ till klausulen hindras också

Dvs. backtracking hindras en nivå upp i SLD-trädet

(121)

Snitt (cut) gör två operationer

P :- Q, !, R.

P :- ...

Tar bort alternativ till Q som ännu inte har prövats när ! passeras

Tar bort alternativ till P som inte har prövats

när ! passeras

(122)

Snitt skär bort backtrackingen för predikatet i vilkets kropp den förekommer. Kan användas för att förbättra prestandan genom att undvika onödig sökning..

Exempel:

in(H, [H | _]).

in(X, [_ | T]) :- in(X, T).

Hur många svar får vi på frågan:

?- in(2, [1, 2, 3, 1, 2, 3]).

För att eliminera svaren efter det första:

inCut(H, [H | _]) :- !.

inCut(X, [_ | T]) :- inCut(X, T).

Snitt (eng: cut)

(123)

i(1).

i(2).

j(1).

j(2).

j(3).

s(X, Y) :- q(X, Y).

s(0, 0).

q(X, Y) :- i(X), !, j(Y).

q(4, 4).

Vilka blir svaren på frågan?

?- s(X, Y).

Exempel från Learn Prolog Now!

(124)

Betrakta programmet:

max(X, Y, Z) :- X>Y, Z=X.

max(X, Y, Z) :- Z=Y.

Vad blir svaret på:

?- max(4, 3, 3).

Rättad implementation:

maxCut(X, Y, Z) :- X>Y, !, Z=X.

maxCut(X, Y, Z) :- Z=Y.

När behövs snitt?

(125)

Snitt (cut)

exempel: exekverring av ett program med cut

top(X,Y):- p(X,Y).

top(X,X) :- s(X).

p(X,Y) :- true(1), q(X), true(2), r(Y).

p(X,Y) :- s(X), r(Y).

q(a). q(b). r(c). r(d). s(e).

true(X).

?- top(X,Y).

¤ i det givna programmet (sju svar)

¤ när true(1) ersätts av ! (fem svar)

¤ när true(2) ersätts av ! (tre svar) Vad händer om både true(1) och true(2)ersätts av !

(126)

Snitt (cut)

Att sätta in cut i ditt program

För att öka effektiviteten

”gröna" cut:

Ändrar inte semantiken hos ett program (klipper bort endast grenar i ett SLD-träd som misslyckas) eller ger redundanta svar

”röda" cut:

ändrar semantiken hos programmet (klipper bort grenar som ger andra lösningar I SLD-trädet)

Generellt är röda cut uppfattas som skadliga

(127)

Snitt (cut)

”Gröna cut": ett exempel

Givet två sorterade listor med heltal Xs och Ys, konstruera en sorterad lista med heltal Zs, som innehåller element från Xs och Ys.

merge([], Ys, Ys).

merge(Xs, [], Xs).

merge([X|Xs], [Y|Ys], [X|Zs]) :- X < Y, merge(Xs, [Y|Ys], Zs).

merge([X|Xs], [Y|Ys], [X, Y|Zs]) :- X = Y, merge(Xs, Ys, Zs).

merge([X|Xs], [Y|Ys], [Y|Zs]) :- X > Y, merge([X|Xs], Ys, Zs).

(128)

Snitt (cut)

”Gröna cut": ett exempel (forts.)

merge([], Ys, Ys):- !.

merge(Xs, [], Xs):- !.

merge([X|Xs], [Y|Ys], [X|Zs]) :-

X < Y, !, merge(Xs, [Y|Ys], Zs).

merge([X|Xs], [Y|Ys], [X, Y|Zs]) :- X = Y, !, merge(Xs, Ys, Zs).

merge([X|Xs], [Y|Ys], [Y|Zs]) :- X > Y, !, merge([X|Xs], Ys, Zs).

(129)

Snitt (cut)

”Röda cut": ett exempel

Finn minimum av två heltal.

Försök:

minimum(X, Y, X) :- X =< Y, !.

minimum(X, Y, Y).

?- minimum(4,5,Z). - Yes, Z = 4.

?- minimum(5,4,Z). - Yes, Z = 4.

?- minimum(4,5,5). - Yes.

Korrigering:

minimum(X, Y, Z) :- X =< Y, !, Z=X.

minimum(X, Y, Y).

(130)

Snitt (cut)

”Röda cut": ett exempel

Kontrollera medlemskapet i en lista.

member(X, [X|Xs]) :- !.

member(X, [Y|Ys]) :- member(X, Ys).

?- member(a, [b,c,a,d]). - kontrollera medlemskapet,

?- member(X, [b,c,a,d]). OK- tar ut ett element ur en lista, tar bara ut det första elementet

?- member(b, Z). - genererar listor som innehåller b genererar bara en lista

(131)

Snitt (cut)

implementation av if-then-else

P :- Condition, !, TruePart.

P :- ElsePart.

eller med särskild syntax

(Condition -> TruePart; ElsePart) Till exempel,

minimum(X, Y, Z) :- (X =< Y -> Z = X; Z = Y).

(132)

Negation: hur man använder och bevisar negativ information?

En negerad fråga 'not_p(x)’ skall lyckas om beviset för

påståendet 'p(x)’ misslyckas och det skall misslyckas om beviset för påståendet 'p(x)’ lyckas.

%not_p(++) (++ står för en grund term) not_p(X) :- p(X), !, false.

not_p(_).

(133)

Antagandet om en sluten värld

Det som är motbevisbart på finit tid är falskt. Om det inte är motbevisbart på finit tid, anses negationen sann

animal(cow).

not_animal(X) :- animal(X), !, false.

not_animal(_).

?- not_animal(X), X=house.

Ett hus är inte ett djur så frågan skall lyckas

Tyvärr misslyckas det. Varför?

(134)

Antagandet om en sluten värld

animal(cow).

not_animal(X) :- animal(X),!, false.

not_animal(_).

not_not_animal(X) :- not_animal(X),!, false.

not_not_animal(_).

?- not_not_animal(X), X=house.

Tyvärr lyckas detta. Varför?

(135)

Negation

foundation(X) :- on(Y, X), on_ground(X).

on_ground(X) :- \+ off_ground(X).

off_ground(X) :- on(X, Y).

above(X, Y) :- on(X, Y).

above(X, Y) :- on(X, Z), above(Z, Y).

on(c, b).

on(b, a).

(136)

Negation

implementation of \+

\+ Goal :- call(Goal), !, fail.

\+ Goal.

example

p(a).

?- p(X). ja, X = a.

?- \+ \+ p(X). sant, X är inte instantierad efteråt

(137)

Betrakta programmet:

snygg(kia).

ej_snygg(X) :- snygg(X), !, fail.

ej_snygg(X).

Vad blir svaren på:

?- ej_snygg(nisse).

?- ej_snygg(kia).

Vad åstadkommer predikatet ej_snygg?

Mera snitt

(138)

Prolog utgår ifrån closed world assumption:

Allt som Prolog inte lyckas bevisa betraktas som falskt!

Negation i Prolog betraktas som bevis-teoretisk negation, och inte som logisk negation.

snygg(kia).

ej_snygg(X) :- \+ snygg(X).

Vad blir svaren på dessa queries?

?- ej_snygg(nisse).

?- ej_snygg(kia).

?- ej_snygg(X).

Negation i Prolog

(139)

Vi implementerade medlemstestet för listor så här:

in(H, [H | _]).

in(X, [_ | T]) :- in(X, T).

Vad blir svaret till:

?- in(X, [1, 2]), \+ in(X, [1,3]).

?- in(X, [1, 2]), \+ in(X, Y).

Beskriv kontrollflödet

(variant på uppgift från omtentan 2016-03-15).

disjoint(X, Y) :- \+ (in(Z, X), in(Z, Y)).

Negation i Prolog

(140)

Vi betraktade redan fail, ett predikat som alltid misslyckas.

Predikatet call(X) betraktar termen som X är unifierad med som ett predikat.

snygg(kia).

not(X) :- call(X), !, fail.

not(X).

Vad blir svaret på denna fråga?

?- not(snygg(nisse)).

Kontrollpredikat

(141)

Funktioner är relationer

Funktioner är deterministiska relationer.

Det finns ett unikt värde i utdatadomänen för varje inputtupel.

En funktion f: Term* -> Term kan till exempel kodas som en relationsdefinition i ett

logikprogram som f(X1,…,Xn,Y) med ett argument med ett unikt värde Y för varje inputtupel X1,…,Xn.

Relationen f/n motsvarande en funktion med n-1 argument är deterministisk. Alla

argument (utom Y som motsvarar

resultatvärdet för funktionen) är fullt

instantierade (grunda) vid anropet.

(142)

Högre ordningens funktioner

Högre ordningens funktioner är inte direkt uttryckbara eftersom funktioner inte är

objekt i den första ordningens logiska modell vi har av ett program.

Man kan dock många gånger koda

programmeringstekniker från funktionell

programmering med en rättfram och effektiv

metod.

(143)

Högre ordningens programmering:

apply

Generell form

apply(foo,X1...Xn) :- foo(X1...Xn).

(144)

Att mappa ett predikat

Predname(In,Out) till varje element i en lista

map_list([X|Xs],Predname,[Y|Ys]) :- apply(Predname,X,Y),

map_list(Xs,Predname,Ys).

map_list([],_,[]).

Högre ordningens programmering:

map

(145)

Predikat för att hitta alla lösningar

Det kan vara meningsfullt att samla alla lösningar till en fråga i en lista.

Prolog stödjer detta genom några ”högre-ordningens" predikat.

father(sven,olle). father(sven,lisa).

father(bengt,lisa). father(bengt,sven).

children(X,Kids) :-

findall(Kid, father(X,Kid),Kids).

Målet

?- children(bengt,Kids).

ger

Kids=[lisa,sven]

(146)

Predikat för att hitta alla lösningar

father(sven,olle). father(sven,lisa).

father(bengt,lisa). father(bengt,sven).

målet

?- findall(F, father(F,Kid),Fathers).

ger

Fathers=[sven,sven,bengt,bengt]

(147)

Predikat för att hitta alla lösningar

Istället för en enda lösning som samla alla fäder till något barn kan vi vara intresserade av en separat lösning för varje barn.

father(sven,olle). father(sven,lisa).

father(bengt,lisa). father(bengt,sven).

?- bagof(F, father(F,Kid),Fathers).

Kid=olle Fathers=[sven]

Kid=lisa Fathers=[sven,bengt]

Kid=sven Fathers=[bengt]

References

Related documents

Militärer och poliser var utposterade runt Tegucigalpas fl ygplats den 5 juli för att hindra Manuel Zelaya från att återvända till Honduras.. Den deporterade presidentens plan

För att möta alla barn och deras behov krävs det som Johansson (2003) menar att förskollärarna är en del av barnets livsvärld och kan sätta sig in hur barnet känner sig i

Ärtor ska djupfrysas in i en fluidbäddfrys. I frysen håller luften så hög hastighet att ärtorna svävar och på så sätt fryses varje ärta individuellt, istället för att de

Sammantaget gjorde undersökningen mig vidare intresserad av barnens upplevelser av demokrati och inflytande i förskolan. Det har satt sig på djupet och jag har

Det övergripande syftet med denna studie är att synliggöra de olika aktörernas uppfattning om förutsättningarna för att kunna leva upp till begreppet ”En skola för alla” i

ordförande i Säveåns vattenråd, miljöskyddschef i Alingsås kommun, administrerar Anten-Mjörnkommittén.. Bild: Stefan Bydén.. Bild: Stefan Bydén.. Bild: Stefan Bydén.. 1) med

Från och med årsredovisningar upprättade för räkenskapsåret 2008 skulle företag kunna tillämpa de nya K2- reglerna, som är ämnade till att förenkla redovisningen för

Syftet med denna rapport är att analysera och matematiskt bevisa ett par befintliga metoder för att lösa polynomekvationer av grad fem eller högre, samt att testa vilken metod som