(S)DT Deel 2 lijsten in Prolog; controle en builtins; programmeertechnieken Prolog
LIJSTEN IN PROLOG (S)DT
3 Prolog termen met speciale syntax Een lege lijst wordt voorgesteld door []. Een niet-lege lijst door het binaire functiesymbool./2 waarbij het eerste argument een element is en het tweede argument de rest van de lijst..(1, []).(2,.(1,[])). 1 []. 1. 2
(S)DT Syntax lijsten.(1, []).(2,.(1,[])) Infix notatie??? Conflict met eindpunt. Syntactische suiker: [1] [2,1] [3,2,1] [3 | [2,1]] [ 3 | [ 2 | [1]]] [X | [2,1]] [X|Y] Verschil met verzamelingen?
(S)DT Listlength(List,Length) De lengte van een lege lijst …. En van een niet lege lijst … listlength([],0). listlength([ _ | Rest ],Len) :- listlength(Rest,LenRest), Len is LenRest + 1. Een lijst bestaande uit juist 3 elementen … Een lijst bestaands uit minstens 3 elementen …
(S)DT From comp.lang.prolog 1. ?- [A,b] = [a,B]. 2. ?- [A,b] = [a|B]. 3. ?- [A|b] = [a|B]. 4. ?- [A|b] = [a,B]. ?- X = [a,b], display(X)..(a,.(b, [])) X = [a, b] ?- X = [a|b], display(X)..(a, b) X = [a|b]
(S)DT Werken met lijsten: concatenatie append([],L,L). append([X | Rest],T,[X | ARest]) :- append(Rest,T,ARest). Queries ?- append([1,2],[a,b],L). ?- append(A,[b],[1,b]). ?- append([X],[Y],[a|Z]). ?- append(A,B,[a,b,c]).
(S)DT Werken met lijsten Een element vooraan/achteraan toevoegen in een lijst … sublist(L1,L2) :- append(A,B,L2), append(_,L1,A). Kun je in het lichaam de 2 literals van plaats wisselen? member(X,[X|_]). member(X,[_|R]) :- member(X,R). Er zijn ruwweg 2 manieren om member/2 op te roepen... Wat met ?- member(3,[a,b]).
(S)DT Werken met lijsten member(X,[X|_]). member(X,[_|R]) :- member(X,R). delete(X,[X|R],R). % andere delete/3 in SWI!!! delete(X,[Y|R],[Y|S]) :- % dit is select/3 in SWI!!! delete(X,R,S). ?- delete(4,[2,3,4,2,3,4],L). ?- delete(4,L,[2,3]).
(S)DT Sorteren(1) sorted([]). sorted([_]). sorted([X,Y|R]) :- X < Y, sorted([Y|R]). psort(L,S) :- permute(L,S), sorted(S). permute([],[]). permute([X|R],P) :- permute(R,RP), delete(X,P,RP). %insert
(S)DT Sorteren(2) qsort([],[]). qsort([Spil|Rest],Sorted) :- split(Spil,Rest,Kleiner,Groter), qsort(Kleiner,KS), qsort(Groter,GS), append(KS,[Spil|Gs],Sorted). split(Spil,[],[],[]). split(Spil,[X|R],Kleiner,Groter) :- Spil > X, Kleiner = [X|RestK], split(Spil,R,RestK,Groter). split(Spil,[X|R],Kleiner,Groter) :- Spil =< X, Groter = [X|RestG], split(Spil,R,Kleiner,RestG).
CONTROLE EN BUILTIN PREDICATEN (S)DT
Controle en andere builtin predicaten Disjunctie If-then-else Cut Niet-logische predicaten Meta-predicaten en meta-vertolker Operatoren Meer details in manual van SWI-Prolog (S)DT
(S)DT Alternatieven: disjunctie split(Spil,[],[],[]). split(Spil,[X|R],Kleiner,Groter) :- ( Spil > X, Kleiner = [X|RestK], split(Spil,R,RestK,Groter) ; Spil =< X, Groter = [X|RestG], split(Spil,R,Kleiner,RestG) ). % ;/2 disjunctie – of %,/2 conjunctie – en Algemene vorm: a :- b,c, (d,e ; f; g,h,i), j,k.
(S)DT Alternatieven: if-then-else split(Spil,[],[],[]). split(Spil,[X|R],Kleiner,Groter) :- ( Spil > X -> Kleiner = [X|RestK], split(Spil,R,RestK,Groter) ; Groter = [X|RestG], split(Spil,R,Kleiner,RestG) ). % ; -> Prolog if-then-else % Indien de conditie verschillende oplossingen % heeft, enkel de eerste
(S)DT Alternatieven: cut split(Spil,[],[],[]). split(Spil,[X|R],Kleiner,Groter) :- Spil > X, !, % cut Kleiner = [X|RestK], split(Spil,R,RestK,Groter). split(Spil,[X|R],Kleiner,Groter) :- % Spil =< X, Groter = [X|RestG], split(Spil,R,Kleiner,RestG). % ! Cut – snede: “snijdt” tussenliggende % (backtracking) alternatieven weg en slaagt % de goto van Prolog
(S)DT Cut a(1). b(f). a(2). b(g). a(3). b(h). c(X,Y) :- a(X), b(Y). ?- c(A,B). ?- b(Z),c(A,B).
(S)DT Cut a(1). b(f). a(2). b(g). a(3). b(h). c(X,Y) :- a(X), !, b(Y). c(X,Y) :- a(X), b(Y). ! verandert de semantiek van je programma – soms – zie split ?- c(A,B). ?- b(Z),c(A,B).
(S)DT Cut Waarom willen we een cut? We willen niet meer backtracken naar een volgende clause van het huidige predicaat: bijvoorbeeld in split/4, ook memberchk/2 membercheck(X,[X|Xs]):- !. membercheck(X,[Y|Xs]):- membercheck(X,Xs).
(S)DT Cut We willen geen alternatieve oplossingen meer voor een oproep van een niet-deterministisch predicaat. …, member(Kand,[1,2,3]), voldoet(Kand, …), !, … Is de plaats van een cut relevant? Dus we plaatsen een cut van zodra we weten dat de volgende clauses niet meer moeten geprobeerd worden. Of juist na een oproep met mogelijks verschillende oplossingen.
(S)DT Niet-logische predicaten I var/1 slaagt als argument nog vrij is atom/1 slaagt als argument gebonden is aan een atoom integer/1 slaagt … aan een integer float/1 slaagt … aan een float compound/1 slaagt … aan een samengestelde term niet-logisch: op geen enkele manier te beschrijven in logica
(S)DT Niet-logische predicaten II functor/3?- functor(foo(a,b,[1]),Name,Arity). Name = foo, Arity = 3 ?- functor(Term,bla,2). Term = bla(_A,_B) arg/3 ?- arg(2,foo(a,b,c),X). X = b =../2?- foo(a,b,[1]) =.. U. U = [foo,a,b,[1]] ?- Term =.. [bla,X,23]. Term= bla(X,23)
Meta-programmatie Een computer programma dat zelf programma’s schrijft en/of manipuleert Reflectie Meta-taal en object-taal Bv een compiler Heel natuurlijk in declaratieve talen: meta-taal = object-taal bv. Lisp, Prolog (S)DT
(S)DT Meta-predicaten: clause/2 ?- clause(append(X,Y,Z),Body). X = [], Z = Y, Body = true ; X = [_A|_B], Z = [_A|_C], Body = append(_B,Y,_C) ?- clause(append([1,2],Y,Z),Body). Z = [1|_A], Body = append([2],Y,_A). % de clause is a :- b,c,d. ?- clause(a,B). B = b,c,d Door backtracking geeft clause/2 alle hoofdingen die unificeren met het 1ste argument, terwijl ook het 2de argument unificeert met het bijhorende lichaam.
(S)DT Een mini-meta-vertolker gebaseerd op clause/2 vertolk((G1,G2)) :- !, vertolk(G1), vertolk(G2). vertolk(true) :- !. vertolk(Head) :- clause(Head,Body), vertolk(Body). Waar zie je unificatie? backtracking? selectie? Voor welke klasse van Prologprogrammas werkt dit? Hoe voeg je builtins toe? disjunctie? if-then-else? Hoe voeg je ! toe? Toepassingen: compilers en vertolkers (taal uitbreidingen/varianten; andere uitvoeringsmechanismen), programma analyse en transformatie, debuggers, profilers, expert systemen (uitleg), …
(S)DT Tellen van het aantal logische inferenties vertolk((G1,G2),Li) :- !, vertolk(G1,Li1), vertolk(G2,Li2), Li is Li1 + Li2. vertolk(true,0) :- !. vertolk(Head,Li) :- clause(Head,Body), vertolk(Body,LiB), Li is LiB + 1. ?- vertolk(append([a,b,c],[],L),Li). L = [a,b,c], Li = 4
(S)DT Operator declaraties voor predicaten en functiesymbolen i.p.v. standaard notatie: operator notatie a+b/c +(a, /(b,c)) X is mod(34,7) is(X,mod(34,7)) X = f(Y)=(X,f(Y)) p(X) :- q(X,Y):-(p(X),q(X,Y)) a :-b,c,d.:-(a,,(b,,(c,d))) Wat zijn Prolog clauses??
(S)DT Operator declaratie :- op(,, ). : geheel getal tussen 1 en als + een hogere precedentie heeft dan /, dan a+b/c a+(b/c) +(a,/(b,c)) haakjes nodig in /(+(a,b),c) (a+b)/c : infix: xfx (niet associatief), xfy (rechts associatief), yfx (links associatief) :- op( 1200, xfx, [ :-, --> ]). :- op( 1000, xfy, [ ',' ]). prefix: fx, fy :- op( 500, fx, [ +, - ]). postfix: xf, yf :- op( 900, fy, \+). : kan 1 enkel atoom zijn of een lijst van atomen.
(S)DT Voorafgedefineerde operatoren 1200xfx --> : fx:- ? fxdynamic 1100 xfy ; | 1050 xfy-> 1000 Xfy, 900fy \+ 700xfx= is =.. = =:= =\= = = 600 xfy : 500yfx fx yfx * / // mod rem 200 xfx **
Builtin predicates ≠ swi-prolog library Builtin predicaten: comparison and unification of terms (=, arithmetic (<, =< =:=, =\=) Ook libraries: the swi-prolog library for Lists met append/3, member/3, select/3, … Verschil: auto-loading: bij gebruik van select/3 -> dan laden builtins kunnen niet geherdefinieerd worden door programmeur (S)DT
Termen vergelijken X=Y X en Y unificeren X==Y X en Y zijn identiek X \== Y X en Y zijn niet identiek X =:= Y X en Y zijn aritmetisch gelijk X=\= Y X en Y zijn aritmetisch niet gelijk X, >=) Y de term X is kleiner dan de term Y (S)DT
?- X == Y. ?- X=Y, X == Y. ?- X = 1+2, Y = 4-1. X = 1+2, Y = 4-1. ?- X = 1+2, Y = 4-1, X == Y. ?- X = 1+2, Y = 4-1, X =:= Y. (S)DT
(S)DT Meta-predicaat: call/1 en \+/1 call/1?- X = (write(ok),nl),call(X). ok X = write(ok),nl %%% q(a,b). apply(F,Args) :- G =.. [F|Args], call(G). ?- ……, Mypred = q,…, apply(Mypred,[Y,Z]). Y = a Z = b %%% negatie in Prolog: we lezen \+ als “not provable” \+(G) :- call(G), !, fail. \+(_). Negation by failure - Closed world assumption ?- \+ member(1,[2,3]).
(S)DT Copieren van termen ?-copy_term([f(9),3.14)],T). T = [f(9),3.14)] ?- copy_term(f(X,X,Y),Z). Z = f(_A,_A,_B) Belangrijk: variabelen worden systematisch NIEUW in de copie Wat is het nut van het copieren van een ground term?
(S)DT Meta-predicaat: findall/3 ?- findall( A-B,append(A,B,[1,2,3]),L). L = [ []-[1,2,3], [1]-[2,3], [1,2]-[3],[1,2,3]-[]] findall/3arg1 = template arg2 = generator arg3 = lijst van copie van de template voor elk slagen van arg2 ?- findall(A,append(A,B,[X,Y,X]),L). L = [ [], [_A], [_B,_C],[_D,_E,_D]]
(S)DT We schrijven nu Gegeven een predicaat ouder/2 Vind de lijst van alle kinderen van een gegeven persoon. Vind de lijst van alle kinderen. Vind de lijst van alle broer-zus (“sibling”) paren.
PROGRAMMEERTECHNIEKEN (S)DT
(S)DT Programmeertechnieken Accumulator Termen met open einde Verschillijsten (difference lists) (Dynamische predicaten) Uitstellen van een doel
(S)DT Een lijst omkeren: naief en slim nrev([],[]). nrev([X|R],Result) :- nrev(R,OmgekR), append(OmgekR,[X],Result). O(n 2 ). historisch belangrijk: LIPS lineaire versie te verkrijgen door transformatie nrev(In,Out) :- srev(In,[],Out). srev([],L,L). srev([X|R],Acc,Out) :- srev(R,[X|Acc],Out).
(S)DT time/1 time(+Goal) Execute Goal just like once/1 (i.e., leaving no choice points), but print used time, number of logical inferences and the average number of lips (logical inferences per second). ?- time((data(List), repeat(1000), nrev(List,_), fail ; true)). % 499,000 inferences, 0.14 CPU in 0.14 seconds (101% CPU, Lips) List = _G177 ;
(S)DT repeat/1 repeat(_N). repeat(N) :- N > 1, N1 is N -1, repeat(N1). data([1,2,…, 29,30]).
(S)DT Append/3 veroorzaakt extra complexiteit qsort([],[]). qsort([Spil|Rest],Sorted) :- split(Spil,Rest,Kleiner,Groter), qsort(Kleiner,KS), qsort(Groter,GS), append(KS,[Spil|Gs],Sorted). %versie met accumulerende parameter qsort(Lijst,Sorted) :- qsort(Lijst,[],Sorted). qsort([],L,L). qsort([Spil|R], Acc, Sorted):- split(Spil,R,Kleiner,Groter), qsort(Groter,Acc,NewAcc), qsort(Kleiner, [Spil|NewAcc], Sorted).
(S)DT Hoe lees je qsort(L,Acc,S) ? en qsort(Lijst,[],Sorted) ? Wat bij oproep ?- qsort([1,3,2,5,4,7,6],X,L). L = [1,2,3,4,5,6,7|X] Lijst met open einde – open ended list – Wat kan je ermee doen? Hou begin en einde bij en … append in constante tijd
(S)DT Difference list - Verschillijst Nieuwe voorstelling van een lijst enkel een nieuwe conventie, geen nieuw soort Prolog term!! Als A en B lijsten zijn en B is een staart van A, dan stelt A-B de (gesloten) lijst voor met de elementen van A totdat B begint: [a,2,c,4,d] – [4,d] voorstelling van [a,2,c] [a,2,c,4,d|Tail] – [4,d|Tail] voorstelling van [a,2,c] [a,2,c |Tail] – Tail voorstelling van [ a,2,c] De laatste voorstelling is de goede als programmeertechniek
(S)DT dl_append/3 A – B C – D [1,2,3|B] – B [a,b|D] – D [1,2,3,a,b|D] – D A – D door unifcatie van B en C dl_append(A-B,C-D,A-D) :- B = C.
(S)DT Werken met difference lists Een element vooraan/achteraan toevoegen Een queue met een difference list q_init(X-X). q_push(X-Y,A,X-Z) :- Y = [A|Z]. q_pop(X-Y,A,Z-Y) :- X = [A|Z]. ?- q_init(Q1), q_push(Q1,a,Q2), q_pop(Q2,X,Q3).
(S)DT dl_qsort waarvoor gebruik je de difference list? Hoe roep je dl_qsort op?? qsort(Lijst, Sorted) :- dl_qsort(Lijst, … … ).
(S)DT Bomen met (veel) open einde(s) Herinner je voeg_toe(El,B1,B2) … Waar nu een open einde? gesorteerde boom: node(Links,I,Rechts) zoek_voegtoe(I,node(_,I,_)) :- !. zoek_voegtoe(I,node(Links,J,Rechts)):- (I > J -> zoek_voegtoe(I,Rechts) ; zoek_voegtoe(I,Links) ). ?- zoek_voegtoe(3,B), zoek_voegtoe(4,B), zoek_voegtoe(2,B).
(S)DT Dynamische predicaten en builtins Normaal is de code – de clauses – voor een predicaat onveranderbaar: predicaten zijn statisch. Met een dynamic declaratie kunnen predicaten veranderbaar worden: in een bestand :- dynamic foo/2. foo(1,a). foo(2,b). Eenmaal geladen, kan foo/2 normaal gebruikt worden, maar ook gewijzigd worden: ?- assertz(foo(3,c)). ?- asserta(foo(4,d)). Voegt het feit foo(3,c) toe als laatste en foo(4,d) als eerste.
(S)DT Dynamisch verwijderen van clauses Ook clauses uitvegen kan ?- retract((foo(3,X) :- B)). Zal door backtracking alle clauses die unificeren met foo(3,X) :- B weghalen uit de database. De interactie tussen code wijzigen, oproepen en backtracken is door ISO vastgelegd, MAAR … niet gebruiken voor practicum of examen!!! ?- assert((foo :- write(ok), retract((foo :-B)), write(B))), foo.
(S)DT Dynamische predicaten: waarom dan? Wijzigen van data Niet als globale veranderlijke Hoe kan je data voorstellen in Prolog? In geval van een grafe? Toevoegen van lemma’s om berekende resultaten bij te houden. De rij van Fibonacci : beginnend met 0 en 1 wordt het volgende element steeds gevonden door optelling van de twee vorige elementen.Fibonacci f 0 = 0, f 1 = 1, f n = f n-1 + f n-2,, voor n = 2, 3,...
(S)DT fib/2 fib(0,0). fib(1,1). fib(N,F):- N > 1, N1 is N- 1, N2 is N1 - 1, fib(N1,F1), fib(N2,F2), F is F1 + F2.
(S)DT Lemma :- dynamic lemma_fib/2. lemma_fib(0,0). lemma_fib(1,1). lfib(N,F) :- lemma_fib(N,F),!. lfib(N,F) :- N > 1, N1 is N - 1, N2 is N1 - 1, lfib(N1,F1), lfib(N2,F2), F is F1 + F2, assert(lemma_fib(N,F)).
(S)DT Uitstellen van de uitvoering van een doel Hoe beïnvloeden we de uitvoering van een predicaat? Builtin voor het uitstellen van een oproep; ?- …, freeze(X,doel(X,[],Y)),… voer doel(X,[],Y) uit zodra X niet meer vrij is wat als X toch gebonden is? ?- freeze(X, X mod 2 =:= 0), X = 3. No
(S)DT Coroutines met freeze/2 psort(L,S):- sorted([_]). permute(L,S), sorted([X,Y|T]):- sorted(S). X < Y, sorted([Y|T]). Eerst de generator Dan de test. Natuurlijk of niet???
(S)DT Coroutines met freeze/2 psort(L,S):- sorted([_]). sorted(S), sorted([X,Y|T]):- permute(L,S). % X < Y later freeze(Y,sorted1(X,Y,T)). delete(X,[X|R],R). sorted1(X,Y,R) :- delete([X,[Y|R],[Y|S]):- X < Y, delete(X,R,S). sorted([Y|R]). permute([],[]). permute(In,[X|Out]) :- ?-psort([2,1,3],L). delete(X,In,NewIn), permute(NewIn,Out).
(S)DT SEND + MORE = MONEY S,M tussen 1 en 9, rest tussen 0 en 9, allemaal verschillende getallen D + E = Y + Overdracht1 Overdracht1 + N + R = E + O2 … Prolog programma Generate and test Generate: member/delete Test: sum(C0,A,B,S,C1). Test zo vlug mogelijk Gebruik freeze
(S)DT sumdigit(C,A,B,S,D):- X is C + A + B, (X S = X, D = 0 ; S is X - 10, D = 1 ). send([S,E,N,D] + [M,O,R,E] = [M,O,N,E,Y]) :- delete(D,[0,1,2,3,4,5,6,7,8,9],LD), delete(E,LD,LE), sumdigit(0,D,E,Y,C1), delete(Y,LE,LY), delete(N,LY,LN), delete(R,LN,LR), sumdigit(C1,N,R,E,C2), delete(O,LR,LO), sumdigit(C2,E,O,N,C3), delete(S,LO,LS), S =\=0, delete(M,LS,_), M =\=0, sumdigit(C3,S,M,O,M).
Studiemateriaal Prolog Slides + online tutorials + boeken in CBA Modeloplossingen van de oefenzittingen en de gequoteerde oefeningen “Coding Guidelines for Prolog” artikel met richtlijnen voor het schrijven van Prolog programma's :sectie 2 (layout), 3(naming conventions) en 5(language idioms) zijn zeker het lezen waard! (S)DT
Steadfast code Steadfastness basically means that you cannot force a predicate down the wrong path by filling in output arguments wrongly. max(X, Y, X) :- X >= Y, !. max(X, Y, Y). ?- max(999999, -1, -1). % max(X,Y,Max) :- X >= Y,!, Max = X. (S)DT
(S)DT Extra slides i.v.m. lijst predicaten Voorbeelden van (schema’s voor) Prolog predicaten Recursieve predicaten op lijsten Als extra voorbeelden nodig zijn … Als test: zoekprobleem oplossen zoals boer staat met wolf – geit – kool op de linkeroever en moet met een boot naar de overkant. Hij kan hoogstens 1 meenemen in de boot. Maar, hij kan de wolf niet alleen bij de geit laten en de geit niet alleen bij de kool….
(S)DT Solve_dfs(Toestand, Hist, Lstap) % Lstap is de lijst van stappen die uitgevoerd moeten worden om vanuit de huidige Toestand een beoogde eindtoestand te bereiken en waarbij Hist de toestanden bevat waarin we al geweest zijn. solve_dfs(T,_,[]) :- einde(T),!. solve_dfs(T1,Hist,[Stap|Lstap]) :- overgang(T1,Stap,T2), geldig(T2), \+ member(T2,Hist), solve_dfs(T2,[T2|Hist], Lstap). test(Lstap) :- begin(T), solve_dfs(T,[T],Lstap).
(S)DT wgk(Boot,Links,Rechts) begin(wgk(links,[g,k,w],[])). einde(wgk(rechts,[],[g,k,w])). overgang(wgk(links,L1,R1),lr(Kand),wgk(rechts,L2,R2)):- delete(Kand,L1,L2), insert(Kand,R1,R2). overgang(wgk(rechts,L1,R1),rl(Kand),wgk(links,L2,R2)):- delete(Kand,R1,R2),insert(Kand,L1,L2). overgang(wgk(B1,L,R),alleen,wgk(B2,L,R)):- andere(B1,B2). andere(links,rechts). andere(rechts,links).
(S)DT geldig(wgk(links,L,R)):- \+ gevaar(R ). geldig(wgk(rechts,L,R)) :- \+ gevaar(L). gevaar(L) :- member(wolf,L), member(geit,L). gevaar(L):- member(geit,L), member(kool,L). insert( Kand,L,Sorted):- sort([Kand|L], Sorted).
Ex-examen: wandeling in tuin Kortste pad waar alle bomen juist 1 keer in voor komen Kan op verschillende manieren opgelost worden Zoeken naar pad, lengte van pad berekenen en dan een kortste pad selecteren terras_tot_boom(b1,4). terras_tot_boom(b2,4)..... boom_tot_boom(b1,b2,4).... (S)DT
Schrijf een predicaat wandeling(P,L) dat het kortste pad P met lengte L berekent zodanig dat enkel de bestaande paden gebruikt worden en dat alle bomen precies 1 keer in het pad voorkomen. Ieder geldig pad begint op het terras en eindigt daar ook. Het volstaat dat dit predicaat slechts een van de mogelijke paden teruggeeft hoewel het in sommige gevallen mogelijk is dat meerdere paden aan de opgelegde voorwaarden voldoen. (S)DT
Versie: select paden(PS) :- bomen(Bomen), findall(L-P,(pad(Bomen,[t],P),lengte(P,0,L)),PS). padensorted(PSS) :- paden(PS), sort(PS,PSS). bomen(L) :- findall(B,terras_tot_boom(B,_),L). pad([],Acc,[t|Acc]) :-!. pad(Bomen, Acc,R) :- select(B,Bomen,NBomen), (pad(NBomen,[B|Acc],R) ; pad(NBomen,[B,t|Acc],R) ). (S)DT
Versie: select lengte([_X],L,L) :- !. lengte([t,B|Rest],L1,L) :- terras_tot_boom(B,LT), L2 is L1 + LT, lengte([B|Rest],L2, L). lengte([B1,B2|Rest],L1,L) :- (boom_tot_boom(B1,B2,LB); boom_tot_boom(B2,B1,LB)) L2 is L1 + LB, lengte([B2|Rest],L2,L). lengte([B,t|Rest],L1,L) :- terras_tot_boom(B,LT), L2 is L1+LT, lengte([t|Rest],L2,L). (S)DT
Versie: alle mogelijke paden wandeling(Pres,Lres) :- bomen(Ball), findall( L-P, rg(t,[],0,Ball,P,L), Lall1), sort(Lall1,Lall), Lall = [ Lres-_ | _], member(Lres-Pres,Lall). % rg(CurrPos, CurrPath, CurrLen, Bomen, ResPath, ResLen) % CurrPath is het pad van de huidige positie CurrPos naar het terras t % CurrLen is de lengte van [CurrPos | CurrPad] % Bomen is de lijst van alle bomen! (S)DT
Versie: alle mogelijke paden rg(P1,Cpath,Clen,Bomen,Rpath, Rlen) :- subset(Bomen,[P1|Cpath]), !, % nog terug naar het terras t reverse([t,P1|Cpath],Rpath), terras_tot_boom(P1,Ledge), Rlen is Clen + Ledge. rg(B1,Cpath,Clen,Bomen,Rpath, Rlen) :- % volgende stap : naar het terras; B1 moet een boom zijn! terras_tot_boom(B1,Ledge), % impliciete vw B1 is boom!!! Clen1 is Ledge + Clen, rg(t,[B1|Cpath], Clen1,Bomen,Rpath, Rlen). rg(P1,Cpath,Clen,Bomen,Rpath, Rlen) :- %naar een verbonden boom b1-b2 of t-b2... (S)DT
Versie: alle mogelijke paden % volgende stap : naar het terras; B1 moet een boom zijn!... rg(P1,Cpath,Clen,Bomen,Rpath, Rlen) :- % naar een verbonden boom b1-b2 of s-b2 (boom_tot_boom(P1,B2,Len) ; boom_tot_boom(B2,P1,Len) ; P1 == t, terras_tot_boom(B2,Len) ), \+ member(B2,Cpath), Clen1 is Len + Clen, rg(B2,[P1|Cpath], Clen1,Bomen, Rpath, Rlen). (S)DT
Water_geven water_geven(Pres, Lres) :- allebomen(Ball), findall(L-P, rg(t,[],0,Ball,P,L),Lall1), sort(Lall1,Lall), filterpaths(Lall,Lres, Pres). filterpaths([Length-Path|Rest],L,P):- ( check_refill(Path,0,_)-> L = Length, P = Path ; filterpaths(Rest,L,P) ). (S)DT
Water_geven % Controleert voor een welbepaald pad of de emmer nooit onder nul gaat. De emmer wordt telkens volledig opnieuw gevuld op het terras t. check_refill([t],_,_). check_refill([P|Ps],EmVoor,_EmNa):- ( P == t -> lemmer(X), EmNa = X, check_refill(Ps,EmNa,_EmNa) ; nodig(P,W), EmNa is EmVoor - W, EmNa >= 0, check_refill(Ps,EmNa,_EmNa) ). (S)DT
Jeopardy Once More before he published “Songs of a Sourdough” lemma(1, "he"). partOfSpeech(1,pronoun). lemma(2, "publish"). partOfSpeech(2,verb). lemma(3, "Songs of a Sourdough"). partOfSpeech(3,noun). subject(2,1). object(2,3). authorOf(Author,Composition) :- createVerb(Verb), subject(Verb,Author), author(Author), object(Verb,Composition), composition(Composition). createVerb(Verb) :- partOfSpeech(Verb,verb), lemma(Verb,VerbLemma), member(VerbLemma, ["write", "publish",...]). Derive new fact: authorof(1,3). (S)DT
Jeopardy In de kennisbank: Songs of a Sourdough by Robert W. Service authorOf(Author,Composition) :- composition(Composition), argument(Composition,Preposition), lemma(Preposition, "by"), objectOfPreposition(Preposition,Author), author(Author). -> Robert W. Service is een mogelijk antwoord! (S)DT