Principles of Programming Languages - Defaultppl172/wiki.files/class/presentations/... ·...

Post on 05-Feb-2018

216 views 0 download

transcript

Collaboration and ManagementDana Fisman

1

Principles ofProgrammingLanguages

Lesson 22 – An Introduction to Logic Programming –Logic Programming (“Pure Prolog”)

www.cs.bgu.ac.il/~ppl172

Review of Last Lecture

RelationalLogic

Programming

Logic Programming

Prolog

How does it look like?

What is the meaning?

What is the execution alg?

Operational Semantics for LP

Interpreter of LP uses two main procedures:

o Answer-query(P,Q) aka ProofTree(P,Q)

Builds a proof tree for Q wrt. P

returns a substitution s to the variables of Q showing Q holds (or true if there are no variables)

or fail if no substitution will make the formula true (or false if there are no variables)

o Unify(A,B)

returns a substitution s such that s = mgu(A,B)

or Fail if A and B cannot be unified

Unify

Goal of Unify(A,B): find the most general unifier.

Example:

Unify( p(X,3,X,W), p(Y,Z,4,W) ) ==> {X=4, Y=4, Z=3}

Indeed:

p(X, 3, X, W)◦{X=4, Y=4, Z=3} = p(4, 3, 4, W)

p(Y, Z, 4, W)◦{X=4, Y=4, Z=3} = p(4, 3, 4, W)

Disagreement Set

The disagreement set of two atomic formulas A and B is the set of left most symbols on which the formulas disagree.

Examples:

d-s(p(X,3,X,W), p(Y,Z,4,W)) = {X,Y}.

d-s(p(5,3,X,W), p(5,3,4,W)) = {X,4}.

Unify - A unification algorithmSignature: unify(A, B)Type: [atomic-formula * atomic-formula -> a substitution or FAIL]Postcondition: result = mgu(A, B) if A and B are unifiable or FAIL, otherwise

unify(A, B) return unify_h(A, B, {})

unify_h(A, B, s)

if A’s top pred is different than A’s top pred (in name or arity) return FAIL

Let A’ = A sLet B’ = B s if A’ = B’

return selse

let D = disagreement-set(A’, B’)if D = {X, t} /* X is a variable; t is a term */

let s’ = s {X = t}unify_h(A’, B’, s’)

elsereturn FAIL

Unify - example

unify[ p(X, 3, X, W), p(Y, Y, Z, Z) ] ==>

unify_h[p(X, 3, X, W), p(Y, Y, Z, Z), {} ] ==>

D = {X, Y}

unify_h[p(Y, 3, Y, W), p(Y, Y, Z, Z), {X = Y} ] ==>

D = {Y, 3}

unify_h[p(3, 3, 3, W), p(3, 3, Z, Z), {X = 3, Y= 3} ] ==>

D = {Z, 3}

unify_h[p(3, 3, 3, W), p(3, 3, 3, 3), {X = 3, Y= 3, Z = 3} ] ==>

D = {W, 3}

unify_h[p(3, 3, 3, 3), p(3, 3, 3, 3), {X = 3, Y= 3, Z:= 3, W = 3} ] ==>

{X = 3, Y = 3, Z = 3, W = 3}

answer-query: an interpretation algorithm for LP

Input:

A query Q ?- Q1, ..., Qn. Each component is called goal

A program P , with numbered rules

A goal selection policy Gsel

A rule selection policy Rsel

Output:

A set of (possibly partial) substitutions for variables of Q.

Operational Semantics for LPMethod: Build a node N for the given query Q

From current node N:

If it is a success leaf (N = true),

o extract answer and return it

o Backtrack to obtain more answers

If it is a failure leaf (N =false)

o Backtrack

If it is not a leaf node and N = (G1,…,Gn)

o select a goal Gi and

o select a rule H :- B1, …, Bk

If H can be unified with Gi unifier Substhen create a new node N’ = (G1,…Gi-1, B1, …, Bk , Gi+1,…Gn) Subs

Otherwise, create a new node N’ = false.

o Make N’ the current node.

Input: a program P and a query Q

Output: partial subs to query variables (or true/false)

Applying Answer-Query parent(abraham, isaac). %p1parent(isaac, jacob). %p2parent(sarah, isaac). %p3parent(jacob, joseph). %p4

male(abraham). %m1male(isaac). %m2male(jacob). %m3male(joseph). %m4

ancestor(A,D) :- parent(A,D). %a1ancestor(A,D) :- parent(A,P), %a2

ancestor(P,D).

anc(isaac,D)

par(isaac, P1),anc(P1,D1)

%a2 {A1=isaac,D1=D}

anc(jacob,D1)true

D=joseph

?- ancestor(isaac,D).

par(isaac, D1)

%p2 {D1=jacob}

%p2 {P1=jacob}

par(jacob, P2),anc(P2,D2)

par(jacob, D2)

true

%p4 {D2=joseph}

anc(joseph,D2)

%p4 {P2=joseph}

par(joseph, P3),anc(P3,D3)

par(joseph, D3)

false

%a1 {A2=jacob, D2=D1}

%a1 {A1=isaac,D1=D}

%a2 {A2=jacob, D2=D1}D=jacob

%a2 {A3=joseph,D3=D2}%a1 {A3=joseph, D3=D2}

false

Applying Answer-Query parent(abraham, isaac). %p1parent(isaac, jacob). %p2parent(sarah, isaac). %p3parent(jacob, joseph). %p4

male(abraham). %m1male(isaac). %m2male(jacob). %m3male(joseph). %m4

ancestor(A,D) :- parent(A,D). %a1ancestor(A,D) :- parent(A,P), %a2

ancestor(P,D).

anc(isaac,D)

anc(P1,D),par(isaac, P1)

%a2 {A1=isaac,D1=D}

?- ancestor(isaac,D).

par(isaac,

abraham)

fail

%a1

anc(P2,D),par(P2, P1),

par(isaac, P1)

%a2 {A2=P2,D2=D}

anc(P3,D),par(P3, P2),par(P2, P1),

par(isaac, P1)

%a2 {A3=P3,D3=D}

%a2%a1

par(P1,D),par(isaac, P1)

%a1 {A2=P1,D2=D}

par(isaac,

issac)

fail

par(isaac,

sarah)

fail

par(isaac,

jacob)

true

Significant kinds of proof trees

Finite success proof tree: A finite tree with a successful path.

Finite failure proof tree: A finite tree with no successful path.

Infinite success proof tree: An infinite tree with a successful path.

Infinite failure proof tree: An infinite tree with no successful path.

Decidability of Relational LP Claim:

Given a program P and a query Q in RLP, the problem

"Is Q provable from P ", denoted P ` Q

is decidable.

Proof:

The number of terms (constants/variables) and predicates appearing in P and Q is finite.

Thus, the number of possible atomic formula (i.e. goals appearing in a node of the proof tree) is finite (except for renaming).

Let N(P,Q) be that number.

Then, any path that is longer than N(P,Q) is infinite. QED

Prolog and subsets of interest

RelationalLogic

Programming

DatalogLogic

Programming

Prolog

Modeling SQL in RLP

o RLP naturally represents structured databases (tables with static columns).

o A procedure consisting of facts can represent a table in the database.

o Often databases are access via elementary SQL operations such as:

select, project, union, Cartesian product and join.

Modeling SQL in RLP

Select (rows from table r, fitting some criteria):

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

X2 \= X3.

Project (some columns from table r):

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

Union (unite tables r and s, with identical columns):

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

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

Modeling SQL in RLP

Cartesian product (all combinations of rows from r and s):

r_X_s(X1, ..., Xn, Y1, ..., Ym) :-

r(X1, ..., Xn ),

s(Y1, ..., Ym).

Natural Join (join tables r and s, with mutual column X):

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

r(X1, ..., Xn, X ),

s(X, Y1, ..., Ym).

Prolog and its subsets

RelationalLogic

Programming

Logic Programming

Prolog

Logic Programming

The only difference between RLP and LP is that a

functor symbol is added to the syntax

Functors are used to represent composite data

structures.

course(ppl, time(Sun,14,16), location(35,310)).

course(ppl, time(Mon,14,16), location(32,307)).

course(ppl, Sun, 14, 16, 35, 310).

course(ppl, Mon, 14, 16, 32, 307).

Logic Programming

This addition of functors has significant implication:

• the resulting logic is Turing Complete (recursively

enumerable).

• and thus partially decidable.

• Implementation requires a more complex unification

algorithm.

Logic Programming – Terms Syntax

Terms are now define inductively:

Base

A constant is a term

A variables is a term

Inductive step

If t1, . . . , tn are terms and f is a functor symbol

then f(t1, . . . , tn) is a term.

Atomic formula in FLP - examples

parent(juliet, Child)

course(ppl, time(Mon,14,16), location(32,307)).

member(cube(red(X)), Lst)

ancestor(mary, sister_of(john))

p(f(f(f(g(a,g(b,c))))))Constants: a, b, cFunctors: f,g,p

Functors: cube, red, memberVariables: X, Lst

Constants: ppl, Mon, 14, 16, 32, 307Functors: time, location, course

Constants: john, maryFunctors: sister_of, ancestor

LP – Concrete Syntax Extension

<term> ==> <constant> | <variable> | <composite-term>

<composite-term> ==> <functor> ( (<term> , )* <term> )

<functor> ==> <constant>

LP – Abstract Syntax Extension

<term>:

Kinds: <constant>,<variable>, <composite-term>

<composite-term>:

Components: Functor: <constant>Term: <term>. Amount: >=1. Ordered.

Example – power of functors

To show the power of functors, we will write a small program in pure Prolog that

o defines what are formulas in conjunctive normal form (CNF)

o provides a procedure to transform a formula not in CNF to an equivalent formula in CNF

Credit for the example: Marcin Judinski

PL – CNF Exampleo: ORa: ANDn: NEG

Example: Defining CNF

monomial(X) :- atom(X). monomial(neg(X)) :- atom(X).

disjunction(X) :- monomial(X). disjunction(or(X,Y)) :- disjunction(X), disjunction(Y).

cnf(X) :- disjunction(X). cnf(and(X,Y)) :- disjunction(X), disjunction(Y).cnf(and(X,Y)) :- cnf(X), cnf(Y).

?- atom(foo).

true

?- monomial(bar).

true

?- monomial(neg(bar)).

true

?- monomial(and(bar)).

false

Example: Defining CNF

monomial(X) :- atom(X). monomial(neg(X)) :- atom(X).

disjunction(X) :- monomial(X). disjunction(or(X,Y)) :- disjunction(X), disjunction(Y).

cnf(X) :- disjunction(X). cnf(and(X,Y)) :- disjunction(X), disjunction(Y).cnf(and(X,Y)) :- cnf(X), cnf(Y).

?- disjunction(foo).

true

?- disjunction(or(neg(foo),bar)).

true

?- disjunction(and(neg(foo),bar)).

false

?- disjunction(neg(foo)).

true

Example: Defining CNF

monomial(X) :- atom(X). monomial(neg(X)) :- atom(X).

disjunction(X) :- monomial(X). disjunction(or(X,Y)) :- disjunction(X), disjunction(Y).

cnf(X) :- disjunction(X). cnf(and(X,Y)) :- disjunction(X), disjunction(Y).cnf(and(X,Y)) :- cnf(X), cnf(Y).

?- cnf(and(neg(foo),bar)).

true

?- cnf(or(neg(foo),and(bar,moo))).

false

?- cnf(and(neg(foo),or(bar,moo))).

true

?- cnf(or(neg(foo),bar)).

true

PL – CNF ExampleNow we would like to define a procedure with

input: a boolean formula (using and,or,neg)

output: an equivalent formula in CNF

% Signature: givecnfequiv(boolform)/1% Purpose: Prints a formula cnf that is equivalent % to boolform is in CNF

% Signature: cnfequiv(boolform, cnf)/2 % Purpose: Transforms a boolean formula to an equivalent % one in CNF% Postcondition: cnf is equivalent to boolform in CNF% Precondition: boolform is a boolean formula % and cnf is a variable

This procedure will invoke

Ex. Defining givecnfequiv

givecnfequiv(X) :- cnfequiv(X,Y), write(Y).

cnfequiv(X,Y) :- transform(X,Z), cnfequiv(Z,Y).cnfequiv(X,X).

?- cnfequiv(or(neg(foo),and(bar,moo)) , X).

X = and(or(neg(foo), bar), or(neg(foo), moo))

?- givecnfequiv(or(neg(foo),and(bar,moo))).

and(or(neg(foo), bar), or(neg(foo), moo))true

Ex. Defining transformtransform(neg(neg(X)),X). % eliminate double negation

transform(neg(and(X,Y)), or(neg(X),neg(Y))). % De Morgantransform(neg(or(X,Y)), and(neg(X),neg(Y))). % De Morgan

% distribution transform(or(X,and(Y,Z)), and(or(X,Y),or(X,Z))). transform(or(and(X,Y),Z), and(or(X,Z),or(Y,Z))).

% recursion to transform sub termstransform(or(X1,Y), or(X2,Y)) :- transform(X1,X2). transform(or(X,Y1), or(X,Y2)) :- transform(Y1,Y2).

transform(and(X1,Y), and(X2,Y)) :- transform(X1,X2). transform(and(X,Y1), and(X,Y2)) :- transform(Y1,Y2).

transform(neg(X1),neg(X2)) :- transform(X1,X2).

Ex. Defining transformtransform(neg(neg(X)),X). % eliminate double negation

transform(neg(and(X,Y)), or(neg(X),neg(Y))). % De Morgantransform(neg(or(X,Y)), and(neg(X),neg(Y))). % De Morgan

% distribution transform(or(X,and(Y,Z)), and(or(X,Y),or(X,Z))). transform(or(and(X,Y),Z), and(or(X,Z),or(Y,Z))).

% recursion to transform sub termstransform(or(X1,Y), or(X2,Y)) :- transform(X1,X2). transform(or(X,Y1), or(X,Y2)) :- transform(Y1,Y2).

transform(and(X1,Y), and(X2,Y)) :- transform(X1,X2). transform(and(X,Y1), and(X,Y2)) :- transform(Y1,Y2).

transform(neg(X1),neg(X2)) :- transform(X1,X2).

PL – Operational Semantics

The abstract interpreter AnswerQuery(P,Q) for RLP applies to LP as well.

The only difference is that the unification algorithm has to be extended to handle the richer term structure, which now includes functors that can be nested within other functors.

LP - Unification

- unify(member(X,tree(X,Left,Right)) , member(Y,tree(9,void,tree(3,void,void)))) ==>

{Y=9, X=9, Left=void, Right=tree(3,void,void)}

− unify(t(X, f(a), X), t(g(U), U, W)) ==>

{X=g(f(a)), U=f(a), W=g(f(a))}

− unify(t(X, f(X), X), t(g(U), U, W)) ==>

fails

Unify – in LPSignature: unify(A, B)Type: [atomic-formula * atomic-formula -> a substitution or FAIL]Postcondition: result = mgu(A, B) if A and B are unifiable or FAIL, otherwise

unify(A, B) return unify_h(A, B, {})

unify_h(A, B, s)

if A’s top pred is different than A’s top pred (in name or arity) return FAIL

Let A’ = A sLet B’ = B s if A’ = B’

return selse

let D = disagreement-set(A’, B’)if D = {X, t} and X does not occur in t

let s’ = s {X = t}unify_h(A’, B’, s’)

elsereturn FAIL

The occur check constraint

LP as Programming Language?

Can we call Pure Prolog a programming language?

o It has the required 3:

Syntax, Semantics, Operational semantics

To be called a general purpose programming logic it also has to be Turing Complete.

o We should be able to implement any RE function in it.

Expressivity and Decidability LP

Claim:

LP is Turing-Complete.

Claim:

LP is only partially decidable.

One can write a short LP program that implements a

Turing Machine.

The finiteness algorithm we used for RLP does

no longer hold.

In the presence of functorsthat can be nested within each other,

the number of different atomic formulas is unbounded.

How can this be proven?

Expressivity of Prolog and its subsets

RelationalLogic

Programming

Logic Programming

Prolog

Not Turing Complete

Turing Complete

Turing Complete

Sch

eme

L5

only primitive ops and types

What about our Scheme Subsets?

L3cons

carcdr '() list

L2cond lambda

L1define

L4letrec

Which is the smallest one which is Turing

Complete?

Turing Complete

RelationalLogic

Programming

Logic Programming

Prolog

Not Turing Complete

Turing Complete

Turing Complete

So, why do we need to extend “Pure Prolog”?

Expressivity of Prolog and its subsets

Before we go into “Full Prolog”, let’s try to

implement some of these ourselves.