prolog - cs.kau.se · prolog summary (1 page) • prolog programs consist of • facts a rule with...
Post on 20-Sep-2020
1 Views
Preview:
TRANSCRIPT
Prolog… the structureRef: Learn Prolog Now! On‐line Prolog Documentation.Blackburn, Bos, Striegnitz.
PrologSummary(1page)• Prolog programs consist of
• Facts a rule with no right hand side (RHS)• Rules LHS :‐ RHS.• Queries fact/rule with value(s) / variable(s)
• Variables• Begin with upper case letters• May be instantiated on the LHS & RHS of rules
• Rules• Composed of sub‐goals (other facts/rules)• May be recursively defined• Result returned in the last variable (or variables)
• Queries• Facts/rules with uninstantiated variables / values
20/04/20
17 22:51
DFR ‐P
rolog Thinking
2
, = and; = or. = end
Lists[ ][ H | T ]
Prolog– important!• Prolog programs consist of
• Facts a rule with no right hand side (RHS)• Rules LHS :‐ RHS.• Queries fact/rule with value(s) / variable(s)
• Examples• bigger(elephant, horse). // fact• is_bigger(X, Y) :‐ bigger(X, Y). // rule – check facts• is_bigger(X, Y) :‐ bigger(X, Z), is_bigger(Z, Y). // rule (1)• is_bigger(elephant, horse). // query• is_bigger(X, Y). // query // (2)
• (1) does there exists X bigger than Z for some Z bigger than Y?• (2) what Xs are bigger than Ys? – for all X and Y
20/04/20
17 22:51
DFR ‐P
rolog Thinking
3
PrologDatabase+Querybigger(elephant, horse).bigger(horse, donkey).bigger(donkey, dog).bigger(donkey, monkey).
is_bigger(X, Y) :‐bigger(X, Y).
is_bigger(X, Y) :‐bigger(X, Z), is_bigger(Z, Y).
bigger(X,Y).X = elephant, Y = horse;X = horse, Y = donkey;X = donkey, Y = dog;X = donkey, Y = monkey.
is_bigger(X,Y).X = elephant, Y = horse;X = horse, Y = donkey;X = donkey, Y = dog;X = donkey, Y = monkey;X = elephant; Y = donkey;X = elephant, Y = dog;X = elephant, Y = monkey;X = horse, Y = dog;X = horse, Y = monkey;false.
20/04/20
17 22:51
DFR ‐P
rolog Thinking
4
Prolog– important!• Prolog variables begin with an upper case letter• Variables are only instantiated within a given fact or rule
• E.g. is_bigger(X, Y) :‐ bigger(X, Z), is_bigger(Z, Y).• X, Y, Z only refer to values within this rule• NOT between rules
• Variables may be instantiated in the LHS & RHS of rules• A Prolog rule is a goal often composed of sub‐goals
• task(A,D) :‐ sub_goal_A(A,B), sub_goal_B(B,C), sub_goal_C(C,D).
• The final variable (or variables) on the LHS is often the result• For sub‐goals this provides the “input” to the next sub‐goal• The RHS of rules are evaluated sequentially• Sub‐goals may (often) be recursive
20/04/20
17 22:51
DFR ‐P
rolog Thinking
5
ReviewofProlog1• What are the main features of Prolog?bigger(elephant, horse). % factsbigger(donkey, monkey).is_bigger(X, Y) :‐ bigger(X, Y). % rulesis_bigger(X, Y) :‐ bigger(X, Z), is_bigger(Z, Y).
• facts + rules = knowledge base• rule = head + body / fact = rule with head only• facts and rules are tested sequentially – if the first fails, the next one is tested
• variable names begin with an upper case letter or _• The last argument in a predicate is often the result
20/04/20
17 22:51
DFR ‐P
rolog Thinking
6
ReviewofProlog1task(A,D) :‐ sub_goal_A(A,B), sub_goal_B(B,C), sub_goal_C(C,D).• name instantiations apply only within one rule• variables are either INSTANTIATED or UNINSTANTIATED• variablesmay be instantiated in the head OR body of a rule
• i.e. information passing can be left to right or right to left!
• lists are either empty [ ] or non‐empty [H|T]• testall :‐ tell('library.out'), showall, told, halt. % I/O?‐ findall(X, is_bigger(X, monkey), L).L = [donkey, elephant, horse]. (sorted)• findall collects information in a list• >prolog % start system• ?‐ [‘abc.pl’]. % load a file (quick version)
20/04/20
17 22:51
DFR ‐P
rolog Thinking
7
ThinkinginProlog• This is not obvious!• Recall in the family program, many of the lists had duplicates• For multiple answers, the ‘;’ had to be used repeatedly• What would be more useful would be a list!• Here is ONE solution (there are no doubt many others)
sbrother(X, Y, [X, Y]) :‐ parent(Z, X), parent(Z, Y), malediff(X, Y).siblings(Q) :‐ findall(Z, sbrother(_,_,Z), L), sort(L,Q).
• How may we reason about this solution?• Where would you begin?
20/04/20
17 22:51
DFR ‐P
rolog Thinking
8
ThinkinginPrologsbrother(X, Y, [X, Y]) :‐ parent(Z, X), parent(Z, Y), malediff(X, Y).siblings(Q) :‐ findall(Z, sbrother(_,_,Z), L), sort(L,Q).
• Work up from the individual predicates• parent(Z, X) is true if Z is a parent of X• malediff(X, Y) is true if X is male and X != Y• sbrother(X, Y, [X, Y]) is true if X and Y have the same parent,
X is male and X is not Ythe 3rd argument gives a list of pairs [X,Y]
• findall(Z, pred(…Z…), L) collects the values of Z in a list L• sort(L, Q) sorts a list L into Q and removes duplicates
Q is a sorted list of pairs [X, Y]• siblings(Q) gives the list Q as a sorted list (no duplicates – set)
20/04/20
17 22:51
DFR ‐P
rolog Thinking
9
ThinkinginPrologpbrother(X, Y) :‐ parent(Z, X), parent(Z, Y), malediff(X, Y).sbrother(X, Y, [X, Y]) :‐ parent(Z, X), parent(Z, Y), malediff(X, Y).
• Note the difference in these 2 definitions• pbrother will simply list each X and Y (using ‘;’)• sbrother will also construct a list containing [X, Y]• This will give [dick, sandra], [paul, lisa], [paul, mary] • sbrother + ‘;’ will still give us too much information hence we can
repackage this using findall/3, as
siblings(Q) :‐ findall(Z, sbrother(_,_,Z), L), sort(L,Q).
• This will give us [ [dick, sandra], [paul, lisa], [paul, mary] ]• How does this work?
20/04/20
17 22:51
DFR ‐P
rolog Thinking
10
ThinkinginPrologpbrother(X, Y) :‐ parent(Z, X), parent(Z, Y), malediff(X, Y).sbrother(X, Y, [X, Y]) :‐ parent(Z, X), parent(Z, Y), malediff(X, Y).
BUT… refactor! Can we say qbrother extends pbrother? OO‐think!
pbrother(X, Y) :‐ parent(Z, X), parent(Z, Y), malediff(X, Y).qbrother(X, Y, [X, Y]) :‐ pbrother(X, Y).
Which is more efficient / readable – then define qsiblings…
qsiblings(Q) :‐ findall(Z, qbrother(_,_,Z), L), sort(L,Q).
20/04/20
17 22:51
DFR ‐P
rolog Thinking
11
ThinkinginPrologIn the library database program we had
listauthor(X) :‐ book(_,author(X),_), display(X).listlastname(X,Y) :‐ book(_,author(X),_), last(X,Y), display(Y).lastnames :‐ findall(Y, listlastname(_,Y), _).
listauthor(X) gives [patrick, henry, winston] for the first booklistlastname(X, Y) gives winston for the first book (in Y)lastnames gives a “list” of the last names
What did we do? Simply insert last(X, Y) in listlastnameThen display the last names.
20/04/20
17 22:51
DFR ‐P
rolog Thinking
12
ThinkinginProlog• What have we done so far?
• Defined facts, rules and queries – Prolog works using relations• Explored Prolog essentially as a DataBase system
• Abstract Programming• Languages such as Prolog and Lisp are more abstract• They often provide abstract data structures + operations e.g. list• You require a knowledge of built‐in predicates e.g. last(X, Y)• You need to learn more about programming paradigms
• Imperative, OO, relational (Prolog), functional (Lisp, Haskell)
• You can then start to combine these ideas in whichever language you are using e.g. a functional style in C (see DSA!)
• Multi‐paradigm programming and languages – e.g. Leda, F#
20/04/20
17 22:51
DFR ‐P
rolog Thinking
13
ThinkinginProlog‐ accumulatorsreverse(Xs, Ys) :‐ reverse(Xs, [ ], Ys).reverse([X|Xs], Acc, Ys) :‐ reverse(Xs, [X|Acc], Ys).reverse([ ], Ys, Ys).
reverse([a,b,c], R).Call: (6) reverse([a,b,c], _G378). reverse/2Call: (7) reverse([a,b,c], [ ], _G378). reverse/3Call: (8) reverse([b,c], [a], _G378). reverse/3Call: (9) reverse([c], [b,a], _G378). reverse/3Call: (10) reverse([ ], [c,b,a], _G378). reverse/3Exit: (10) reverse([ ], [c,b,a], [c,b,a]). reverse/3Exit: (9) reverse([c], [b,a], [c,b,a]). reverse/3Exit: (8) reverse([b,c], [a], [c,b,a]). reverse/3Exit: (7) reverse([a,b,c], [ ], [c,b,a]). reverse/3Exit: (6) reverse([a,b,c], [c,b,a]). reverse/2R = [c,b,a] did you spot the stack?
20/04/20
17 22:51
DFR ‐P
rolog Thinking
14
NB: 2 reversereverse/2reverse/3
ThinkinginProloginsert([], It, [It]). insert([H|T], It, [It, H|T]) :‐ H @> It. insert([H|T], It, [H|NewT]) :‐ H @< It, insert(T, It, NewT).
Very often, the last argument to a predicate is the result.insert can be read as insert(List, Value, NewList)or in English: add a value to a list to produce a new list.Points to note:‐• a Prolog list is often expressed as [H|T] (head/tail)• the empty list is written as [ ]• names are instantiated within a rule on both the left & right• The order of the rules is important – if the first definition failsthen the second is tried and so on…
20/04/20
17 22:51
DFR ‐P
rolog Thinking
15
ThinkinginProlog1. insert([], It, [It]). 2. insert([H|T], It, [It, H|T]) :‐ H @> It. 3. insert([H|T], It, [H|NewT]) :‐ H @< It, insert(T, It, NewT).
1 – the empty case – the result is a list with one element, It
2 – the value is added at the head of the new list
3 – the value is added to the tail of the list – result NewTthe old head is the head of the new list
You have already done this in C (in DSA) – the recursive versionApply this knowledge to understanding the Prolog code
20/04/20
17 22:51
DFR ‐P
rolog Thinking
16
insert([],It, [It]).(1)insert([H|T],It, [It,H|T]) :‐H@>It.(2)insert([H|T],It, [H|NewT]) :‐H@<It,insert(T,It,NewT).(3)
[trace] ?‐ insert([1,2,3], 4, Z).Call: (6) insert([1,2,3], 4, _G379)Call: (7) 1@>4?Fail: (7) 1@>4?Redo: (6) insert([1,2,3], 4, _G379)Call: (7) 1@<4 ?Exit: (7) 1@<4 ?Call: (7) insert([2,3], 4, _G437)Call: (8) 2@>4?Fail: (8) 2@>4?Redo: (7) insert([2,3], 4, _G437)Call: (8) 2@<4 ?Exit: (8) 2@<4 ?
Call: (8) insert([3], 4, _G440)Call: (9) 3@>4?Fail: (9) 3@>4?Redo: (8) insert([3], 4, _G440)Call: (9) 3@<4 ?Exit: (9) 3@<4 ?Call: (9) insert([ ], 4, _G443)Exit: (9) insert([ ], 4, [4])Exit: (8) insert([3], 4, [3,4])Exit: (7) insert([2,3], 4, [2,3,4])Exit: (6) insert([1,2,3], 4, [1,2,3,4])
Z = [1, 2, 3, 4].
20/04/20
17 22:51
DFR ‐P
rolog Thinking
17
ThinkinginProlog(+Haskell+C)insert([], It, [It]). insert([H|T], It, [It, H|T]) :‐ H @> It. insert([H|T], It, [H|NewT]) :‐ H @< It, insert(T, It, NewT).
bAdd v [ ] = v: [ ]bAdd v (x:xs)| v < x = v : (x:xs)| otherwise = x : bAdd v xs
static listref b_add(int v, listref L) {return is_empty(L) ? create_e(v): v < get_value(head(L)) ? cons(create_e(v), L): cons(head(L), b_add(v, tail(L)));
}
20/04/20
17 22:51
DFR ‐P
rolog Thinking
18
ThinkinginProlog(+Haskell+C)insert([], It, [It]). insert([H|T], It, [It, H|T]) :‐ H @> It. insert([H|T], It, [H|NewT]) :‐ H @< It, insert(T, It, NewT).
bAdd v [ ] = v: [ ]bAdd v (x:xs)| v < x = v : (x:xs)| otherwise = x : bAdd v xs
static listref b_add(int v, listref L) {return is_empty(L) ? create_e(v): v < get_value(head(L)) ? cons(create_e(v), L): cons(head(L), b_add(v, tail(L)));
}
20/04/20
17 22:51
DFR ‐P
rolog Thinking
19
Languageoverview:Prolog• How is Prolog structured? Prolog Syntax.
• Terms: Atoms, Numbers, Variables,Complex Terms (Structures)
• Constants: Atoms, Numbers• Simple Terms: Constants, Variables• Character Set: A‐Z, a‐z, 0‐9, symbols (+, ‐, *, …)• Atom: string of characters (including underscore)
sequence of characters in single quotesa string of special characters
• Numbers: integers (real, floating point)
20/04/20
17 22:51
DFR ‐P
rolog Thinking
20
Languageoverview:Prolog• Variables: string of upper/lower case letters, digits
starts with _ or an upper case letter• Complex Term: functor + sequence of arguments (X,Y,…)
the functor (name) must be an atomarity – the number of argumentse.g. last(X, Y) is last/2 where 2 = arityabc/2 and abc/3 are distinct predicatesmay be nested and/or recursive
• Rules: Head :‐ Body.• Body: conjunctions (,) & disjunctions (;) (and/or)• Facts: Head. (rule with empty body)
• Clauses: rules & facts (describe relations)
• Execution: satisfying GOALS
20/04/20
17 22:51
DFR ‐P
rolog Thinking
21
Languageoverview:Prolog• Repetition: recursion• Relations: work in both directions (more later)• Design Patterns: clichés or common solutions• Tail Recursion: often used cliché; optimised in Prolog• Higher‐Order predicate which takes predicates asProgramming: arguments – e.g. findall(X, pred(..X..), L)
• Hashing: often implemented• Modules: not always provided
• Restrictions: CWA – Closed World Assumption• Negation: mortal(Aristotle). false – see CWA
20/04/20
17 22:51
DFR ‐P
rolog Thinking
22
Languageoverview:Prolog• Recursive Definitions (note Tail Recursion)
is_bigger(X, Y) :‐ bigger(X, Y).is_bigger(X, Y) :‐ bigger(X, Z), is_bigger(Z, Y).
• Lists: [a,b,c,d,e], [] (empty list), [H|T] head/tail patternmember(X, [X|_]).member(X, [_|T) :‐ member(X, T)._ is the anonymous variable (“don’t care”)append([], L, L). append([H|T], L2, [H|L3]) :‐ append(T, L2, L3). this predicate requires thinking about! Try it!note how the predicate works in 2 directions
20/04/20
17 22:51
DFR ‐P
rolog Thinking
23
Languageoverview:Prolog• Append example – how does this work?
append([], L, L). append([H|T], L2, [H|L3]) :‐ append(T, L2, L3).
append(L1, L2, L3) is best way to think about this predicatee.g. append([a,b,c], [d,e,f], X) . will give X = [a,b,c,d,e,f].
Note that the second line definition1. Splits L1 into its head and tail components (decomposition)2. Leaves L2 unchanged3. Adds the head of L1 to the List L3 (recomposition)4. The recursive descent passes tail(L1); 5. The recursive ascent adds the ”heads” in reverse
20/04/20
17 22:51
DFR ‐P
rolog Thinking
24
Languageoverview:Prologappend([], L, L). append([H|T], L2, [H|L3]) :‐ append(T, L2 , L3).
1. append([a,b,c], [d,e,f], L3) L1 not []2. append([b,c], [d,e,f], L3) L1 not []3. append([c], [d,e,f], L3) L1 not []4. append([], [d,e,f], L3) L1 is [], L3 = [d,e,f]5. Return ‐ recursive calls!6. append(_, _, c | [d,e,f]) L3 is [c,d,e,f]7. append(_, _, b | [c,d,e,f]) L3 is [b,c,d,e,f]8. append(_, _, a | [b,c,d,e,f]) L3 is [a,b,c,d,e,f]9. Finished!
20/04/20
17 22:51
DFR ‐P
rolog Thinking
25
Languageoverview:PrologRule (1): append( [], L, L). Rule (2): append( [H|T], L2, [H|L3]) :‐ append(T, L2, L3).
trace:‐append([a,b], [c,d], L3).Call: (6) append( [a,b], [c,d], _G382) ; Rule (2)Call: (7) append( [b], [c,d], _G443) ; Rule (2)Call: (8) append( [], [c,d], _G446) ; Rule (1)Exit: (8) append( [], [c,d], [c,d]) ; Rule (1)Exit: (7) append( [b], [c,d], [b,c,d]) ; Rule (2)Exit: (6) append( [a,b], [c,d], [a,b,c,d]) ; Rule (2)L3 = [a,b,c,d].
20/04/20
17 22:51
DFR ‐P
rolog Thinking
26
Languageoverview:PrologRule (1): append([], L, L). Rule (2): append([H|T], L2, [H|L3]) :‐ append(T, L2, L3).
Deconstruction phase ‐ Rule(2) goes from Left to RightRule (2): Call (1) append([ a | b ], [ c, d ], [ a | L3] ) :‐ append( [ b ], [ c, d ], L3).Rule (2): Call (2) append([ b | [ ] ], [ c, d ], [ b | L3] ) :‐ append([ ], [ c , d ], L3).Rule (1): Call (3) append([ ], [c,d], [c,d] ) ‐ i.e. List2 [c,d] is "copied" to L3
Reconstruction phase ‐ Rule(2) goes Right to Lefti.e. L3 is "passed back" to the Left Hand SideRule (1): Exit (3) returns append( [ ], [ c ,d ], [ c ,d ] ) i.e. List2 [c,d] is "copied back" to L3Rule (2): Exit (2) returns append( [ b ], [ c, d ], [ b | [ c, d ] ) i.e. append([ b ], [ c, d ], [ b, c, d ] ) ‐ List [ b, c, d] is "copied back" to L3Rule (2): Exit (1) returns append[ a | b ], [ c ,d ], [ a | [ b, c, d ] ) i.e. append( [ a ,b ], [ c ,d ], [a, b, c, d]) ‐ L3 is List [a, b, c, d]answer L3 is [a, b, c, d]
20/04/20
17 22:51
DFR ‐P
rolog Thinking
27
Languageoverview:Prolog• Some list predicate examples (you would expect these!)• length([a,b,c], X). X = 3.• member(a, [a,b,c]). true.• member(x, [a,b,c]). false.• last([a,b,c], X). X = c.• reverse([a,b,c], X). X = [c,b,a].• select(a, [a,b,c], X). X = [b,c].• append([a,b,c], [d,e,f], X). X = [a,b,c,d,e,f].• append(X, Y, [a,b,c,d]). X = [], Y = [a,b,c,d] ;
X = [a], Y = [b,c,d] ;X = [a,b], Y = [c,d] ;X = [a,b,c], Y = [d] ;X = [a,b,c,d], Y = [] ; false.
20/04/20
17 22:51
DFR ‐P
rolog Thinking
28
Languageoverview:Prolog• Some arithmetic predicate examples
• X is 2 + 2. X is 4.• X is +(2, 2). X is 4.
• Similarly for 2‐2; 2*2; 2/2; mod(7,2); 3+2*4; (3+2)*4; etc.• The usual arithmetic precedence rules apply
• Comparison: X op Y: op: <, =<, =:=, =/=, =>, >
• Notation: Prolog uses 2+2 as well as +(2, 2) • The arithmetic operators are in fact predicates e.g. +/2, +/1
20/04/20
17 22:51
DFR ‐P
rolog Thinking
29
Languageoverview:Prolog• Some predicates for terms• NB: Prolog is a “type‐free” language as such these languages require predicates to test properties of constructs e.g. terms
• is the argument…• atom/1 …an atom?• integer/1 …an integer?• float/1 …a floating point number?• number/1 …a number?• atomic/1 …a constant?• var/1 …an uninstantiated variable?• nonvar/1 …an instantiated variable OR
another term not an uninstantiated variable
20/04/20
17 22:51
DFR ‐P
rolog Thinking
30
Languageoverview:Prolog• More predicates for terms• functor/3 ‐ name and ‐arity of a predicate
?‐ functor(append(L1, L2, X), F, A).F = append.A = 3.
• arg/3 ‐ value of the nth argument?‐ arg(2, append([a,b], [c,d],X), A).A = [c,d].
• ‘=..’/2 ‐ functor + args list?‐ append([a,b], [c,d], X) =.. Z.Z = [append, [a,b],[c,d], X].
20/04/20
17 22:51
DFR ‐P
rolog Thinking
31
Languageoverview:Prolog• Some predicates for strings ( = list of ASCII codes)?‐ atom_codes(donald, X).X = [100, 111, 110, 97, 108, 100].?‐ atom_codes(‘Donald’, X).X = [68, 111, 110, 97, 108, 100].?‐ atom_codes(abc, X), append(X, X, L), atom_codes(N, L).X = [97, 98, 99].L = [97, 98, 99, 97, 98, 99].N = abcabc• Similarly for numbers?‐ number_codes(123, X).X = [49, 50, 51].
20/04/20
17 22:51
DFR ‐P
rolog Thinking
32
Languageoverview:Prolog• Some simple I/O predicates• From the library database example
testall :‐ tell('library.out'), showall, told, halt.• tell change the standard output (screen) to a file• showall process information• told switch the standard output back to the screen
display(X) :‐ tab(3), write(X), nl.• From the lab 2 codesee(File), get0(C), readword(C,W,C1), restsent(W,C1,Ws), seen.
• see(File) switch input to file input• get0(C) read a character from the file• seen switch standard input back to the keyboard
20/04/20
17 22:51
DFR ‐P
rolog Thinking
33
Languageoverview:Prolog• Some simple I/O predicates – display / copy a fileprocess(File) :‐ open(File, read, In),
get_char(In, Char1), process_stream(Char1, In), close(In).
process_stream(end_of_file, _) :‐ !. // cut – stops processprocess_stream(Char, In) :‐ print(Char),
get_char(In, Char2), process_stream(Char2, In).
p1 :‐ process('IOtest.in'). p2 :‐ tell('IOtest.out'), process('IOtest.in'), told.
20/04/20
17 22:51
DFR ‐P
rolog Thinking
34
Languageoverview:Prolog• Some simple I/O predicates – formatting• Ref:‐ SICStus Prolog User's Manual
• format/2 and format/3 provide an interface to the C’s <stdio.h> function printf
• Examples are given in the above reference for those interested
• See / seen & tell / told come from the DEC‐10 Prolog file I/O• Again see the above reference
• The SICStus Prolog User's Manual will also give you an idea of the level of sophistication Prolog has reached
• Link: https://sicstus.sics.se/sicstus/docs/3.7.1/html/sicstus_toc.html
20/04/20
17 22:51
DFR ‐P
rolog Thinking
35
Languageoverview:Prolog• Summary – what to focus on• Thinking in Prolog & writing programs
• Use the built‐in predicates• Write short predicates which may be further combined• Be aware that relations work in 2 directions• Use patterns such as tail recursion & [H|T]• Try to program abstractly – think first what you want to do!
• Learning Prolog• Start with short programs (course/web examples)• Use web sources to find examples e.g. Rosetta Code• Experiment and make mistakes!!!
20/04/20
17 22:51
DFR ‐P
rolog Thinking
36
top related