0% found this document useful (0 votes)
88 views19 pages

tddd08 Tut1

The document provides instructions for completing Prolog labs, including registering for labs, reading lab instructions, modifying emacs configuration, using the Prolog system, submitting labs before the deadline, and Prolog syntax. It discusses constants, variables, facts, rules, queries, arithmetic, recursion, useful built-in predicates, negation, data types, debugging, and tips for using Prolog.

Uploaded by

pelleplutt1337
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
88 views19 pages

tddd08 Tut1

The document provides instructions for completing Prolog labs, including registering for labs, reading lab instructions, modifying emacs configuration, using the Prolog system, submitting labs before the deadline, and Prolog syntax. It discusses constants, variables, facts, rules, queries, arithmetic, recursion, useful built-in predicates, negation, data types, debugging, and tips for using Prolog.

Uploaded by

pelleplutt1337
Copyright
© Attribution Non-Commercial (BY-NC)
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 19

Before you can start Register yourself in Webreg to participate in the labs. Deadline 4th november.

. Read the lab instructions. Add module file (use module [init]add prog/sicstus). Modify your .emacs (see course page). Using the system Separate code (filename.pl) and query (*prolog*) buffers: all facts and rules in the file-buffer Just open or create filename.pl to enter prolog mode automatically. Save file and press C-c C-b to consult buffer and create the query window. Quit command: halt.. Strict deadline 17 Dec. for labs (if you miss it, you have to wait for the next re-examination) the labs should be completed, ie graded and reported in webreg that date so hand them in so I have time to grade them during the workday!

Prolog syntax

Constants: lower case first letter (a, anna, aX)

Variables: upper case first letter (X, Xs) Special ignored variables: _ as first letter Comments: % Single line comment
/* Block comment */

Facts
mother(anna, bob). anna is mother of bob. likes(_, icecream). Everybody likes icecream.

Ends with a period. A rule


grandparent(X,Z) :parent(X,Y), parent(Y,Z). X is a grandparent to Z if there is some Y such that X is a parent of Y

and Y is a parent of Z. sub-goals are separated by commas. And more, Lists, data structures. We'll get back to them later.

Querying Prolog A query (goal):


| ?- grandparent(X, julia). no

(written in *prolog* buffer) Queries can contain multiple simultanious subgoals separated by commas:
| ?- grandparent(X, jonatan), grandparent(X, skorpan). X = astrid

Prolog answers with either a satisfying binding, yes or no. If you want more answers, type ; and prolog will back-track and give another solution if it can find one.

A simple example Contents of .pl file:


mother(anna,bertil). father(adam,bertil). father(arne,beata). mother(beata,christina). father(bertil,cecilia). parent(X,Y) :- mother(X,Y). parent(X,Y) :- father(X,Y). grandfather(X,Y) :father(X,Z), parent(Z,Y).

Queries (goals)
| ?- mother(anna,bertil). yes | ?- parent(X,bertil). X = anna ? ; X = adam ? ; no | ?- grandfather(X,Y). X = adam, Y = cecilia ? ; X = arne, Y = christina ? ; no

Example, a boolean circuit.

Contents of .pl file:


and(0,0,0). and(0,1,0). and(1,0,0). and(1,1,1). or(0,0,0). or(0,1,1). or(1,0,1). or(1,1,1). not(0,1). not(1,0). nand(X,Y,Out) :and(X,Y,OutAnd), not(OutAnd,Out). circuit(X1, X2, X3, X4, Out) :and(X1, X2, Y1), not(X3, Y2), or(Y2, X4, Y3), not(Y3, Y4), or(Y1, Y4, Out).

Example, boolean circuits, cont. Queries


?- circuit(0, 1, 0, 1, Out). Out = 0 ? yes ?- circuit(X1, X2, X3, X4, 1). X1 = 0, X2 = 0, X3 = 1, X4 = 0 ? ; X1 = 0, X2 = 1, X3 = 1, X4 = 0 ? yes | ?- circuit(1,X,Y,Z,0). X = 0, Y = 0, Z = 0 ? ; X = 0, Y = 0, Z = 1 ? ; X = 0, Y = 1, Z = 1 ? ; no

(Fill in the blanks computation)

Lists [X,2,c] is a (linked) list with three elements. [] is the empty list.

[X|Xs] is a list where the first element is X and the tail of the list is the list Xs. [1,2,3] is just syntactic sugar for [1|[2|[3|[]]]], which is the real

form. These forms can be combined: [X,Y,Z|Rest]

Similar to lists in Lisp, Haskell or O'Caml. Prolog


[] [1,2,3] [X|Xs]

Lisp
() (1 2 3) (X . Xs)

Haskell
[] [1,2,3] (x:xs)

Using Lists Code


% member(X, L): Does the list L contain X? member(X, [X|_]). member(X, [_|L]) :- member(X, L).

Queries
| ?- member(X, [1,2,3]). X = 1 ? ; X = 2 ? ; X = 3 ? ; no | ?- member(a, L). L = [a|_A] ? ;

Note: list with at least one element (_A is a list).


L = [_A,a|_B] ? yes

L has at least two elements (_A is an item, _B is a list).


| ?- member(a,X), member(b,X). %X contains both a and b. X = [a,b|_A] ? ; X = [a,_A,b|_B] ? ; X = [a,_A,_B,b|_C] ? ; X = [a,_A,_B,_C,b|_D] ? yes

Not a very good enumeration. Prolog is not magic. Code


samelength([],[]). samelength([X|Xs], [Y|Ys]) :samelength(Xs, Ys).

Query
| ?- samelength(A,[1,2,3,4]). A = [_A,_B,_C,_D] ?

(=) != (=:=) != is

Equality sign always means unification, never anything else!


X = Y + Z: Unifies X with +(Y,Z) without performing any

calculation (for example, 6 = 5 + 1 fails). We can do things like ?- X+1 = (7+Y)+Y. X = 7+1, Y = 1 Arithmetics X is E: Calculate expression E, then unify. X is 5+1 results in
X = 6; X is Y+Z requires that Y and Z are numbers (or

expressions containing numbers, for example Y = 2 * 3). E1 < E2, E1 =< E2, E1 >= E2, E1 > E2: Compare expressions. (Note that =< is used instead of <=) E1 =:= E2: Expressions E1 and E2 have the same value 2 * 3 = 3 * 2 false, 2 * 3 =:= 3 * 2 true.

All the usual arithmetic operations exist,


+, -, *, **, mod, abs, round, floor, sin, cos, exp...

We wont need much math in this course though.

Example: Arithmetic Code


% fac(N, F) % F is the factorial of N. That is, F = N! fac(0, 1). fac(N, F) :N > 0, M is N-1, fac(M, G), F is G*N.

Queries
| ?- fac(3, F). F = 6 ? yes | ?- fac(N, 6). {INSTANTIATION ERROR: _51>0 - arg 1}

Be careful when you use arithmetics, most predicates no longer work both ways!

Recursion example: Order matters Code (Same parent relation as in example 1)


% ancestor1(X, Y) % X is an ancestor of Y ancestor1(X, Y) :- parent(X, Y). ancestor1(X, Y) :parent(X, Z), ancestor1(Z, Y). % ancestor2(X, Y) % X is an ancestor of Y ancestor2(X, Y) :- parent(X, Y). ancestor2(X, Y) :ancestor2(X, Z), parent(Z, Y).

Queries
| ?- ancestor1(X, cecilia). X = bertil ? ; X = anna ? ; X = adam ? ; no | ?- ancestor2(X, cecilia). X = bertil ? ; X = anna ? ; X = adam ? ; (*Infinite loop!*)

Example 6: Useful builtins length(L, N): L is a list with length N. setof(X, p(X), Set) Set (sorted list) of all results to query p(X). bagof(X, p(X), Bag) Bag of all results to query p(X). Example code:
| ?- setof(X, member(X, [b, a, c, a]), Set). Set = [a,b,c] ? yes

The set is a sorted list with unique members.


| ?- bagof(X, member(X, [b,a,c,a]), Bag). Bag = [b,a,c,a] ? yes

The bag contains all answers in the order they are found.

Negation
\+ p(X, Y): p(X, Y) has no solutions | ?- parent(anna, adam). no | ?- \+ parent(anna, adam). yes | ?- \+ parent(anna, X). no | ?- \+ parent(X, X). true ? ; yes \+ (X = Y) is written X \= Y: X, Y cannot be equal

Negation is covered in more detail in Ulfs lectures. Can be tricky, be careful.

Example: Data types Code


birthday(anna, date(feb, 20)). birthday(arne, date(jun, 15)). birthday(beata, date(feb, 10)). birthday(bertil, date(oct, 20)).

birthday is a predicate. date is a functor. Queries


| ?- birthday(anna, X). X = date(feb, 20) ? yes Is anyone born in februari? | ?- birthday(X, date(feb, Y)). X = anna, Y = 20 ? ; X = beata, Y = 10 ? ; no Does two persons have the same birtday? | ?- birthday(X, Date), birthday(Y, Date), X\=Y. no

Created on the fly, no type declaration needed.

More data type usage Define the tree type:


istree(N) :number(N). isTree(tree(L, R)) :isTree(L), isTree(R). %Searching procedure: search(X, X). search(tree(L, _R), X) :search(L, X). search(tree(_L, R), X) :search(R, X).

Queries Possibly unexpected query effects:


| ?- search(tree(tree(1, 2), 3), X). X = tree(tree(1, 2), 3) ? ; X = tree(1, 2) ?; X = 1? | ?- search(T, 1). T = 1 ? ; T = tree(1, _A) ? | ?- tree(T).

In this case we get an infinite loop. number(X) only succeeds if X is instantiated to a number. In our case it is a variable. number does not generate numbers.

Debugging
search(X, X). search(tree(L, _R), X) :search(L, X). search(tree(_L, R), X) :search(R, X). | ?- trace. % The debugger will first creep -- showing everything (trace) yes % trace,source_info | ?- search(tree(tree(1, 2), tree(3, 4)), 3). 1 1 Call: search(tree(tree(1,2),tree(3,4)),3) ? 2 2 Call: search(tree(1,2),3) ? 3 3 Call: search(1,3) ? 3 3 Fail: search(1,3) ? 4 3 Call: search(2,3) ? 4 3 Fail: search(2,3) ? 2 2 Fail: search(tree(1,2),3) ? 5 2 Call: search(tree(3,4),3) ? 6 3 Call: search(3,3) ? 6 3 Exit: search(3,3) ? ? 5 2 Exit: search(tree(3,4),3) ? ? 1 1 Exit: search(tree(tree(1,2),tree(3,4)),3) ? yes % trace,source_info | ?-

Debugging, cont.
search(X, X). search(tree(L, _R), X) :search(L, X). search(tree(_L, R), X) :search(R, X).

An example which fails:


| ?- search(tree(tree(1, 2), tree(3, 4)), 5). 1 1 Call: search(tree(tree(1,2),tree(3,4)),5) ? 2 2 Call: search(tree(1,2),5) ? 3 3 Call: search(1,5) ? 3 3 Fail: search(1,5) ? 4 3 Call: search(2,5) ? 4 3 Fail: search(2,5) ? 2 2 Fail: search(tree(1,2),5) ? 5 2 Call: search(tree(3,4),5) ? 6 3 Call: search(3,5) ? 6 3 Fail: search(3,5) ? 7 3 Call: search(4,5) ? 7 3 Fail: search(4,5) ? 5 2 Fail: search(tree(3,4),5) ? 1 1 Fail: search(tree(tree(1,2),tree(3,4)),5) ? no | ?-

Use trace. to start tracing and notrace. to stop tracing.

Hints and remainders There are no return values! Using the result of a predicate is done by reusing variables:
do_something(Input, Output) :find_thing(Input, Thing), process(Thing, Output).

Not
do_something(Input) :Thing = find_things(Input), process(Thing) Prolog tries to interpret everything as a functor if it's found as an arguement to a predicate. foo(5+6). Foo gets passed the functor 5+6 == +(5,6), not 11.

Recursion, not for-loops. X = Y unifies; X is Y+1 evaluates Y+1. Facts, not functions. Each fact and rule should be literally correct, taken as a statement by itself. Prolog is weakly typed. The query member([1,2,3],1). will just fail and not give any warning. Upper case means variables, lower case for everything else member(X,[x,y,z]) and member(x,[x,y,z]) gives completely different results. The prolog buffer is for queries, not programming. Unlike languages like Python, Perl, Ruby etc, you cannot create new predicates in the prolog buffer, only query the existing set. Use the evaluate region/file/buffer commands in emacs.

More tips and tricks. Let the unification do the work.


reverse1([],[]). reverse1([X],[X]). reverse1(X,Y) :append([Firstx],Tailx,X), append(Starty,[Lasty],Y), Firstx = Lasty, append(Midx,[Lastx],Tailx), append([Firsty], Midy,Starty), Firsty = Lastx, reverse1(Midx,Midy).

vs
reverse2([],[]). reverse2([X],[X]). reverse2([Hx|Tailx],[Hy|Taily]) :append(Midx,[Hy],Tailx), reverse2(Midx,Midy), append(Midy,[Hx],Taily).

(Even better! Use tail-recursion with an accumulator if possible.


reverse3([X|Y],Z,W) :- reverse3(Y,[X|Z],W). reverse3([],X,X).)

Be careful when you reorder clauses It's very easy to forget to change commas and periods. Sicstus allows infinite structures to be created.
| ?- X = [1|X]. X = [1,1,1,1,1,1,1,1,1,1|...] ?

This can be occationally be useful, but it can also be a source of confusing bugs.

You might also like

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy