270 likes | 530 Views
Programming Language Theory Logic Programming. Leif Grönqvist The national Graduate School of Language Technology (GSLT) MSI. Contents. Leif’s three parts of the course: Functional programming Logic programming Similar ways of thinking, but different from the imperative way
E N D
Programming Language TheoryLogic Programming Leif Grönqvist The national Graduate School of Language Technology (GSLT) MSI Logic Programming
Contents Leif’s three parts of the course: • Functional programming • Logic programming Similar ways of thinking, but different from the imperative way • Formal semantics Logic Programming
Logic Programming • Based on logic (surprise!) • First order predicate calculus (predikatlogik) • Statements and rules are stored in the prolog database, for example: • 0 is even • Växjö is bigger than Göteborg • if A is bigger than B then B is smaller than A • If n is even then n+1 is odd Logic Programming
Predicate calculus • The examples above can be written in first order predicate calculus: • even (0) • bigger (Växjö, Göteborg) • bigger (A, B) smaller (B, A) • n: even (n) odd (n+1) • The numbers and cities are constants, sometimes called atoms • “even”, “odd”, “smaller”, and “bigger” are predicates • A, B and n are variables (may be free or bound) • “” is a connective (others are “and”, “or”, and “not”) • “” is a quantifier Logic Programming
Prolog • In prolog they may be written as: even (0). bigger (växjö, göteborg). smaller (A, B) :- bigger (B, A). odd (N) :- even (M), M is N+1. • Atoms start with a lowercase and variables with an uppercase letter • Atoms starting with an uppercase letter has to be written like ‘Eva’ • With the facts read into the prolog system we may ask queries Logic Programming
Horn Clauses • A statement in the form: a1 and a2 and … and an b Is a so called Horn Clause • b is called the head • a1, a2, …, an is the body • A rule with an empty body is a fact (an axiom) • Axioms are statements that are assumed to be true • Theorems are proved from axioms (and theorems) Logic Programming
An example • Let’s look at the Euclidian algorithm to compute the greatest common divisor gcd u 0 = u gcd u v = gcd v (v `mod` u) • Translating to first-order predicate calculus: u: gcd(u,0,u). u: v: w: not zero(v) and gcd(v, u mod v, w) gcd(u, v, w). • And as Horn Clauses: gcd(u, 0, u). not zero(v) and gcd(v, u mod v, w) gcd(u, v, w). Logic Programming
A small prolog example • Lets feed this into the prolog database: woman (anna). woman (mia). woman (eva). man (john). man (peter). man (erik). • We now have six facts that are defined as true • The words anna, john, etc. are atoms (not strings, “Anna” is a string) • An atom may be looked up extremely quickly Logic Programming
The example in Sicstus Prolog • Read the file: SICStus 3.8.4 (x86-win32-nt-4): Tue Jun 13 11:31:44 2000 Licensed to ling.gu.se | ?- {source_info} | ?- {consulting c:/documents and settings/leifg/skrivbord/vups/ex1.pl...} {consulted c:/documents and settings/leifg/skrivbord/vups/ex1.pl in module user, 40 msec 864 bytes} • We may ask if facts are true: | ?- man(john). yes | ?- woman(olle). no • Or another kind of query: | ?- woman(X). X = anna ? ; X = mia ? ; X = eva ? ; no | ?- woman(X), man(X). no Answers come one by one, get the next with ; Logic Programming
More facts • Let’s add some more facts, and some rules man(eva). happy(anna). happy(john). tall(erik). loves(john,mia). loves(peter,mia). loves(erik,eva). loves(erik,erik). loves(eva,erik). • And some rules Jealous_at(X,Y) :- loves(X,Z),loves(Y,Z), X\==Y, \+ happy(X). playsAirGuitar(jody). playsAirGuitar(X) :- listensToMusic(X), happy(X). listensToMusic(mia). listensToMusic(X) :- woman(X) ; tall(X), man(X). Logic Programming
The rules • Most of the rules are Horn clauses • listensToMusic(X), true if • Mia listens to music • Or X is a woman • Or X is a tall man • playsAirGuitar(X), true if: • X is judy • Or if X is happy and listens to music • Jealous_at(X,Y), true if: • There is a Z such that both X and Y loves Z • X and Y have to be different • X is not happy • Important note: We define things, the system accepts what we say – even if we are lying in a “real world”! Logic Programming
Try the rules | ?- jealous_at(X,Y). X = peter, Y = john ? ; X = erik, Y = eva ? ; X = eva, Y = erik ? ; no | ?- woman(X),man(X). X = eva ? ; no | ?- listensToMusic(A). A = mia ? ; A = anna ? ; A = mia ? ; A = eva ? ; A = erik ? ; no | ?-playsAirGuitar(X). X = jody ? ; X = anna ? ; no Logic Programming
Lists and recursion • Recursion is an important feature – just as in functional programming • This example checks if two lists are equal :- use_module(library(charsio)). :- use_module(library(lists)). eq([],[]). eq([X|XS], [X|YS]) :- eq(XS, YS). • So eq(A, B) is true if: • If A and B are empty lists, or: • The first element in each list is the same and eq holds for the rest of the lists Logic Programming
Lists and recursion, cont. • The append function (well, predicate) app([], YS, YS). app([X|XS],YS, [X|XYS]) :- app(XS, YS, XYS). • Append has three arguments! • It’s not really a function but a predicate • app(A, B, AB) is true if B appended to the end of A result in AB Logic Programming
Testing the predicates | ?- eq([a,b], [a,b]). yes | ?- eq([a,b], [a,b,c]). no | ?- eq([a,b], A). A = [a,b] ? ; no | ?- eq(A, B). A = [], B = [] ? ; A = [_A], B = [_A] ? ; A = [_A,_B], B = [_A,_B] ? ; A = [_A,_B,_C], B = [_A,_B,_C] ? ; A = [_A,_B,_C,_D], B = [_A,_B,_C,_D] ? A = [_A,_B,_C,_D,_E], B = [_A,_B,_C,_D,_E] ? ; A = [_A,_B,_C,_D,_E,_F], B = [_A,_B,_C,_D,_E,_F] ? yes Logic Programming
Testing the predicates, cont. | ?- app([1], [2], A). A = [1,2] ? ; no | ?- app(A,B,[1]). A = [], B = [1] ? ; A = [1], B = [] ? ; no | ?- app([1], A, [1,2,3]). A = [2,3] ? ; no • We may replace arguments with variables and use predicates as functions in both directions! • Possible queries are for example: • Give me pairs of lists A, B that appended together becomes [1] • Give me the list A that appended to [1] result in [1,2,3] • Give me triples of lists A, B, C such that B appended to A result in C • Check if [3] appended to [1,2] result in [1,2,3] Logic Programming
Evaluation order • Sicstus Prolog is evaluated in depth first order • The trace-functionality shows us how it works: | ?- trace. % The debugger will first creep -- showing everything (trace) yes % trace,source_info | ?- listensToMusic(A). 1 1 Call: listensToMusic(_430) ? ? 1 1 Exit: listensToMusic(mia) ? A = mia ? ; • One solution! Let’s try to find more solutions: 1 1 Redo: listensToMusic(mia) ? 2 2 Call: woman(_430) ? 2 2 Exit: woman(anna) ? Logic Programming
Evaluation order, cont. ? 1 1 Exit: listensToMusic(anna) ? A = anna ? ; 1 1 Redo: listensToMusic(anna) ? 2 2 Redo: woman(anna) ? ? 2 2 Exit: woman(mia) ? ? 1 1 Exit: listensToMusic(mia) ? A = mia ? ; 1 1 Redo: listensToMusic(mia) ? 2 2 Redo: woman(mia) ? 2 2 Exit: woman(eva) ? ? 1 1 Exit: listensToMusic(eva) ? A = eva ? ; 1 1 Redo: listensToMusic(eva) ? 3 2 Call: tall(_430) ? • All female solutions found! Are there any more? Logic Programming
Evaluation order, cont. 3 2 Call: tall(_430) ? 3 2 Exit: tall(erik) ? 4 2 Call: man(erik) ? 4 2 Exit: man(erik) ? 1 1 Exit: listensToMusic(erik) ? A = erik ? ; no • No more solutions • Note that mia listensToMusic because • She is mia • She is female • So she’s listed twice Logic Programming
Evaluation order, cont. • We can see the depth first order and the backtracking • Sicstus evaluates: • Top to bottom • Left to right • Sometimes a breadth first search could give a result where depth first fails • Recall the properties of strict and lazy evaluation in a functional programming language Logic Programming
Unification and types • There are no types in Prolog • But unification could give us similar help • Only objects with the same structure could be unified • Unification tries to make pairs “the same” • Could work if one of the elements is undecided, let’s ask the system to unify: A=2. A = 2 ? | ?- [A,2,3]=[1|B]. A = 1, B = [2,3] ? 1=2 no (A-A)=(B-C). B = A, C = A ? Logic Programming
An example: permutation sort • Is the list sorted? sorted([]). sorted([_]). sorted([X,Y|Z]):- X=<Y, sorted([Y|Z]). • Y is a sorted permutation of X permsort(X,Y):- perm(X,Y), sorted(Y). • Will it work? Complexity? • We will now define a sort predicate: • is the second list a permutation of the first? perm([],[]). perm([X|Y],Z) :- perm(Y,W), insert(X,W,Z). • Y is inserted somewhere in XZ to form XYZ insert(Y,XZ,XYZ) :- append(X,Z,XZ), append(X,[Y|Z],XYZ). Logic Programming
Problems with logic programming • No real negation • P is False if it’s not provable • Works fine in many cases: | ?- \+ man(anna). yes | ?- \+ man(john). no • But! Shouldn’t this work? | ?- \+ X=0. no | ?- \+ man(X). no • We would expect for example 1 and anna • What about this one? | ?- \+ man(leif) ? Logic Programming
More problems: cut • The cut (!) is used to cut branches in the search tree • If we pass a cut we may not backtrack • This makes prolog effective • BUT! The nice logic definitions are not as easy to understand any more… • We can use cut to express: D = if A then B else C • This is how to do i: D :- A, !, B. D :- C. • The more intuitive: D :- A, B. D :- \+A, B. • Executes A twice Logic Programming
Other problems in the book • Some logical statements are not possible to express in Horn clauses: • p(a) and (x: not(p(x)) • Control of execution order • In some cases we know the best way to calculate something, but in logic programming we are not able to specify the order things are done Logic Programming