You are on page 1of 74

Logic

and
Logic Programming
Propositions &Sentences
• A proposition is a declarative sentence.
• e.g. Woff is a dog.
• e.g. Jim is the husband of Mary.
• A proposition is represented by a logical symbol.
• P: Woff is a dog.
• R: Jim is the husband of Mary.
• Sentences: True and False are both logical constants.
• Logical constants are sentences.
• e.g. True is a propositional logic sentence.
• Logical symbols are sentences.
• e.g. P is a propositional logic sentence.
Formal Grammar
• Sentence ::= AtomicSentence |
ComplexSentence
• AtomicSentence ::= True | False | P | Q |

• ComplexSentence ::= (Sentence) |
Sentence Connective Sentence | ØSentence
• Connective ::= Ù | Ú | Þ | Û
Horn Clauses
• A Horn Clause is a sentence in the
following form

• P1 Ù P2 Ù … Ù Pn Þ Q

• Prolog only works with logical sentences


which are Horn Clauses
First Order Predicate Logic

• Allows the following to be modeled


• objects
• properties of objects
• relations among the objects
• Like propositional logic, FOL has
sentences
• Additionally it has terms which allow the
representation of objects
Terms
• A term is a logical expression which refers
to an object. (Russel, 188)
• Elements of a term
• Constant Symbols - A, B, John
• Predicate Symbols - refer to a relation
• Function Symbols - refer to a relation
which is a function
Sentences
• Atomic Sentences - state a fact
• e.g. company(gordon).
• e.g. location(gordon,usa)
• Complex Sentences - formed from:
• atomic sentences\
• logical connectives
• quantifiers
Quantifiers
• Universal Quantifier (")
• "x is read “For all x …”
• All cats are mammals.
• "x (Cat(x) Þ Mammal(x))
• Extensile Quantifier ($)
• $x is read “There exists an x ..”
• Spot has a sister who is a cat.
• $x ( Sister(x,Spot) Ù Cat(x))
Other Paradigms :
Logic Programming refers loosely to

• The use of facts and rules to represent information.


• The use of deduction to answer queries.

An Example of a rule is
overlap(X, Y) :- member(M, X), member(M, Y)
Here lists X and Y overlap if there is some member M
that is a member of both X and Y.
In order to deduce this we need Prolog to answer
queries.
How Prolog came into Existence ?
• The concept of logic programming is linked historically to
Prolog (Programming Logic).
• Prolog was first applied to natural language Processing.
Later it has been used for specifying algorithms, searching
databases, writing compilers. It can do all applications for
which Lisp might be used.
• Prolog is effective for applications involving pattern
matching, backtrack searching or incomplete information.
• In short, labor in Logic Programming is denoted by

algorithm = logic + control


We supply logic part, Prog. Lang supplies control part .
Prolog has various dialects, Here we will talk about Edinburgh
Prolog.
Control In Edinburgh Prolog proceeds from left to right.
The rule: P if Q1 and Q2 and …. And Qk. K>= 0 can be read as
to deduce P, deduce Q1, deduce Q2 …. Deduce Qk

Computing with Relations :


• Logic Programming deals with relations rather than
functions. It is based on the premise that programming with
relations is more flexible than with functions.
• Prolog deals with lists.Lists are written between brackets [
and ] , so [ ] is an empty list. [b,c] is a list with two symbols b
and c. here b is head and c is tail.
Relations :
• Relation append is a set of tuples of the form (X, Y, Z) where
Z consists of elements of X followed by elements of Y.
• Relations are specified by rules written in pseudo code as P if
Q1 and Q2 and …. And Qk. K>= 0. Such rules are called as Horn
clauses.
• A fact is a special case of rule, in which k = 0 and P holds
without any conditions, written simply as P
Rules
append( x, y, z) ----> append x and y to get z.
append( [ ], y, y ) ----> append [ ] and y to get y.
Queries : Logic Prog. is driven by queries about relations.
Horn clauses cannot represent negative information, Hence
queries are answered as yes / fail rather than yes / no answers.

?- append( [a, b], [c, d], [a,b,c,d] ) ----> Yes


?- append( [a, b], [c,d], Z ) ----> Yes when Z = [a, b, c, d]
?- append( [a, b],Y, [a, b, c, d]) ----> Yes when Y = [c, d]
?- append( X, [c, d], [a, b, c, d]) ----> Yes when X = [a, b]
?- append( X, [d, c], [a, b, c, d]) ----> Fail

Informally, Relations has no sense of direction, no prejudice


who is computed from whom. Relations treat arguments and
results uniformly.
Introduction To Prolog :
• Facts, rules and queries are specified using terms.

Facts, rules, queries TERMS

number : 0 , 1972 Simple Compound


Term Term
variable : X, Source
atom(subterms)
atom : lisp, algol60

link(bcpl, c)
Introduction to Prolog

• Prolog is a logic programming language


• Prolog is based upon First Order Logic
(FOL)
• A Prolog program consists of a Knowledge
Base composed of:
• facts
• rules
• All facts and rules must be expressed as
Horn Clauses
Syntax Rules

• Predicates (functors) must start with lower-


case letter.
• Constants begin with a lower-case letter
or number.
• Variables begin with an upper-case letter
or an (_).
• All sentences (clauses) must end with a
period.
Clauses& Facts

• All clauses have a head and a body.


• head :- body.
• The symbol :- is read if
• A fact is stated as a functor using constants.
• e.g. dog(woff).
• A fact has only a head
• A fact may be a functor without an argument list.
• A single constant.
• e.g. woff.
Rules

• A rule has both head and body


• dog(X) :- barks(X), wags_tail(X)
• head is: dog(X)
• body is: barks(X), wags_tail(X)
• FOL form: if body then head
• "X (barks(X) Ù wags_tain(X) Þ
dog(X))
A Prolog Program

• Knowledge Base
• dog(X) :- barks(X),
wags_tail(X)barks(woff)barks(spot)wags_tail(
woff)
• Queries
• ?- dog(woff) => yes
• ?- dog(spot) => no
• Means no more matches found.
Using Variables

• Knowledge Base
• dog(X) :- barks(X),
wags_tail(X)barks(woff)barks(spot)wags_ta
il(woff)
• Query
• ?- dog(Y) => Y = woff
Prolog’s Search Algorithm
• Prolog uses a goal directed search of the KB
• Depth first search is used
• Query clauses are used as goals and
searched left to right
• KB clauses are searched in the order they
occur in the KB
• Goals are matched to the head of clauses
• Terms must unify based upon variable
substitution before they match
Unification

• Idea substitute terms for variables so that


facts that match a predicate with a variable
can be found.
• A substitution is a function from
variables to terms.
• {V -> [a,b], Y-> [a,b,c]} is a substitution.
• Y {V -> [a,b], Y-> [a,b,c]} = [a,b,c]
Facts and Rules in file links :
link(fortran, algol60)
link(algol60, cpl)
link(cpl, bcpl)
link(bcpl, c)
link(c, c++)
link(algol60, simula67)
link(simula67, c++)
link(simula67, smalltalk80)
Queries are also called goals.
?- link(cpl, bcpl) , link(bcpl, c) -----> yes
?- link(algol60, L) and link(L, M)?
A solution to query is a binding of variable to makes the query
true. A query with solution is satisfiable. The system responds
to a satisfiable query.
L = cpl , M = bcpl ;
L = simula67 , M = c++ ;
L = simula67 , M = smalltalk80 ;

Universal Facts and Rules :


A rule <term> :- <term>1, <term>2, ……<term>k

head conditions
A fact is a special case of a rule. A fact has no head and
conditions.
path(L, L) ---> fact . We take a path of zero links to be from L
to itself.
Path(L, M) :- link(L, X), path(X, M)
A path from L to M begins with a link to some X and
continues along the path from X to M.
Unification : Deduction in Prolog is based on concept of
unification.
?- f(X, b) = f(a, Y)
Here, f(a, b) is an instance of f(X, b) because it is obtained by
substituting subterm ‘a’ for variable X in f(X, b). Similarly
f(a, b) is an instance of f(a, Y) because it is obtained by
replacing subterm ‘b’ for variable Y in f(a, Y)
X=a Y=b
For Example, g(a,a) is an instance of g(x,x) .
However, g(a,b) is not an instance of g(x,x) because we cannot
substitute ‘a’ for one occurrence of x and ‘b’ for another
occurrence of x.

Arithmetic
• X = 2+3 ---> simply binds variable X to term 2+3
• X is 2+3 ---> The Infix operator evaluates expression and
binds 5 to X.
?- X is 2+3 , X = 5
yes
?- X is 2+3 , X = 2+3
no
fails because 2+3 does not unify with 5. Term 2+3 is the
application of operator + to the arguments 2 and 3, whereas 5
is simply the integer 5. Hence, 2+3 does not unify with 5.
Data Structures In Prolog
Prolog supports several notations for writing Lisp-like lists.
They sweeten the syntax without adding any new capabilities.
Lists in Prolog :
• The simplest way to write a list is to enumerate its elements
• The list containing three atoms a, b and c is written as [a,b,c]
• Empty List is written as [ ]
• Unification can be used to extract the components of a list.
for example :
?- [H | T] = [a,b,c] ---> H = a , T = [b, c] .
• In Prolog any tree can be written as term, any term can be
written as tree.
Example : Term node (K, S, T) can be represented as tree.
K

S T

• Let atom empty represent binary search tree (K, S, T) with an


integer value K at the root, left subtree S, and right subtree T.

Terms for representing Binary trees


leaf

nonleaf(leaf, leaf)
nonleaf(nonleaf(leaf,leaf),nonleaf(leaf,leaf)

Member(k, node(k, _, _ ) represent a binary search tree with k


at the root and some unnamed left and right subtrees.
Beyond trees, variables in Prolog allow terms to represent data
structures with sharing. Terms can also represent graphs with
cycles.
5.4 Programming Techniques

How does Prolog process queries ?

-by backtracking and unification

backtracking - find solution if exist


unification - place holder variable gets filled
in later with value
Guess and Verify Query
query:
conclusion if guess(…,S,…) and verify(…,S,…);
?- conclusion( ) :- guess( ) , verify( )
find solution to guess( ) and match them against verify( ).
If match then conclusion( ).
Example:
?- overlap(X,Y) :- member(M,X) , member(M,Y)
find M from list X, and verify M also appears in list Y. If
so, then overlap(X,Y) .
Prolog processes from left to right.
- Watch out for efficiency and unexpected.

example:
?- X = [1,2,3] , member(a,X).
X is a list of [1,2,3]. Is ‘a’ a member of X ?

?- member(a,X) , X = [1,2,3].
find all solution where a is member of X. ‘a’ can
be anywhere in X, so finds infinite possibilities for
a, but doesn’t find match in X.
Variable as place holders.
open list - list with variable at end
closed list - no variable at end

Example:
[ a, b | X ] ==> open list
[ a , b ] ==> closed list
Prolog uses machine generated
variables to represent variable at the
end of list. Uses underscore + integer.

example:

?- L = [ a , b | X ]

L = [ a , b | _1]
X = _1

variable _1 now corresponds to end marker X


Expand on previous example:
?- L = [ a , b | X ] , X = [ c , Y ]

X = _1
L = [ a , b | _1 ]
X = _1 = [ c , Y ] = [ c | _2 ]

L = [ a , b | _1] = [ a , b | [ c | 2 ] ]
= [ a , b , c | _2]

_1 unifies with [ c | _2 ] -- like assignment


Example: Queue Manipulation
enter( a, Q , R ) ==> when element ‘a’ enters
queue Q, we get queue R

leave( a , Q , R ) ==> when element ‘a’ leaves


queue Q, we get queue R

in queue q( L,E )
L = open list
E = end marker ( some suffix of L )
content = elements of L, but not in E
Queue Manipulation Cont.
Rules:
setup( q( X , X ) ).
enter( A , q( X , Y ) , q( X , Z ) :- Y = [ A | Z ].
leave( A , q( X , Z ) , q( X , Y ) :- Y = [ A | Y ].
wrapup( q( [ ] , [ ] ) ).

What do these mean ?


setup( q( X , X ) ) returns q( open list , end marker )

Example:
?- setup( Q )
Q = q( X , X )
Q = q( _1 , _1 )
enter( A , q ( X,Y) , q(X,Z) ) :- Y = [A | Z].

In plain English:

To enter element ‘A’ into queue q( X,Y)


bind/unify/assign Y to list [ A | Z ]
where Z is new end marker, and
return resulting query q( X, Z)
Example:
?- setup(Q)
Q = q( X , X )
Q = q( _1 , _1 )

?- enter( a , Q , R )
rule: enter( a , q( X, Y) , q( X, Z ) ) :- Y = [ a | Z ]
enter( a , q( _1 , _1) , q( X,Z ) )
X = _1 , Y = _1
Y binds to [ a | Z ] , Z = new marker _2
X = _1 = Y = [ a | _ 2 ]
R = q ( X , Z ) --> q ( [ a | _2 ] , _2 )
Now R = q( [ a | _2 ] , _2 )

?- enter( b , R , S )
rule: enter( b , q ( X ,Y ) , q ( X , Z ) ) :- Y = [ b | Z ]
enter( b , q ( [ a | _2 ] , _2 ) , q ( X , Z ) )
X = [ a | _2 ] , Y = _2
Y = [ b | Z ] , where Z = _3
Y = _2 = [ b | _3 ]
X = [ a | _2 ] = [ a | [ b | _3] ] = [ a , b | _3 ]

S=q(X,Z)
S = q( [ a,b | _3 ] , _3 )
Leave( A , q( X , Z ) , q( Y , Z ) ) :- X = [ A | Y ].
In plain English:

To leave element ‘A’ from queue q( X , Z )


bind X to list [ A | Y ] and return
q( Y , Z )

Example:
S = q( [ a , b | _3] , _3 )
?- leave( X , S , T )
leave( elemX , q( X,Z) , q(Y,Z) ) :- X = [elemX | Y ]
leave( elemX , q( [a,b | _3] , _3 ) , q( Y,Z ))
X = [a,b | _3 ] , Z = _3
X = [ elemX | Y ] = [ a,b | _3]
elemX = a ,Y = [ b | _3 ]

T = q( Y,Z ) = q( [b |_3] , _3 )
More examples

T = q( [ b | _3 ] , _3 )

?- leave( Y , T , U )
leave( elemY , q( X,Z ) , q( Y,Z) ) :- X = [ elemY | Y]
leave( elemY , q( [ b | _3 ] , _3) , q( Y,Z ) )
X = [ b | _3 ] = [ elemY | Y ]
elemY = b
Y = _3
U = q( _3 , _3 )
wrapup( q( [ ] , [ ] ) )

returns empty list

?- wrapup( U )
assigns empty list to U

U was q( _3 , _3 )
wrapup( U )
U = q( [ ] , [ ] )
_3 = [ ]
Difference List

- made up of two lists L , E


- content is elements in L but not in E
- written as dl( L , E )

example:
[ a, b ] can be written as

- dl( [ a,b] , [ ] )
- dl( [ a,b,c] , [c] )
- dl( [ a,b | E ] , E ),…,etc
Control in Prolog
algorithm = logic + control

Prolog’s “flow” or search path is controlled by


- Goal Order
- Rule Order

Goal order - left to right


Rule order - top to bottom, first rule that fits
What effect does goal order and
rule order have ?
- might give you unexpected results
if used inappropriately.
i.e. infinite computation
Substitutions
Substitution is a function that takes in
a variable and returns terms.

X --> T means variable X gets mapped to term T.

Ts means result of applying a set of substitution s on T


In plain English
Example:
s = { V -> [b,c] , Y->[a,b,c] }

What is Ys ?
Substitute [ a,b,c] for Y
answer: Ys = [ a,b,c]

What is Zs ?
Zs = Z , because no substitution
general unifier

-You have terms T1, T2


- substitution that unifies T1 with T2
is a general unifier.

Example:
T1 = append( [ ] , Y ,Y)
T2 = append( [ ] , [a | V] , [a,b,c] )

general unifier = { V-> [ b,c] , Y->[ a,b,c] }


Rules for Searching Path - without backtracking

1. Look at the left most goal

2. Find first rule that applies

3. Substitute

4. Replace with the conditional part

5. Repeat until all the goals are gone


example 11.7 - search path

see rules listed in Fig 11.13


query:
?- suffix( [a] , L ) , prefix( L , [a,b,c] )

1. Consider the left most goal, suffix()


2. Find the first rule that applies to this

found rule:
suffix( Y,Z ) :- append( X,Y,Z )
find substitution:
suffix( [a] , L ) :- append( X,Y,Z)
s = { Y -> [a] , Z -> L }, X = variable _1

3. replace goal suffix with condition append:


append( _1, [a] , L ) , prefix( L,[a,b,c] )

4. look for rule that applies to append()

found rule:
append( [ ] , Y , Y )
find substitution:
append( _1 , [a] , L ) = append( [ ] ,Y,Y)
_1 = [ ]
Y = [ a ] , Y = L ,so L = [a]
Done with suffix() part, so now have only
prefix( L , [ a,b,c] ),
but L = [a] from previous, so we have

prefix( [a] , [a,b,c] )

Find rule for this and found:


prefix( X,Z ) :- append(X,Y,Z)
find substitution and get:
X = [a] , Y = _2 , Z = [a,b,c]
replace prefix() with its condition
append( [a] , _2 , [a,b,c])
Find rule for append and get:
append( [ H|X ] , Y , [ H|Z ] :- append(X,Y,Z)

find substitution for:


append( [a] , _2 , [a,b,c]) :- append( X,Y,Z)
X=[]
Y = _2
Z = [ b,c]

replace with condition to get:


append( [ ] , _2 , [ b,c] )
apply rule append( [ ] , Y , Y ) to get:
_2 = Y , Y = [b,c] , so _2 = [b,c]
How backtracking works.
When there’s no applicable rule for the term, we go back to the
point where there were more than one way to apply rules, and take
different path.
Example:

-? Suffix( [b], L ) , prefix( L,[a,b,c] )

rule: suffix( Y,Z) :- append( X , Y , Z )


Y = [b] , Z = L , X = _1
replace: suffix() with append()
append( _1 , [b] , L) , prefix( L , [a,b,c] )
rule: append( [ ] , Y , Y )
Y = [b]
prefix( [b] , [a,b,c] )
rule: prefix( X,Z) :- append( X,Y,Z)
X = [b] , Z = [a,b,c] , Y = _2
Now we have: append( [b] , _2 , [a,b,c] ),
but can’t find applicable rule.
At this point, we go back to
append( _1 , [b] , L) , prefix( L , [a,b,c] )
try rule: append( [H|X] , Y , [H|Z) :-
append( X,Y,Z)
so we get, _1 = [ _3 | _4] , X = _4
Y = [b]
L = [ _3 | _5 ] , Z = _5
append( _4,[b],_5) , prefix( [ _3|_5 ], [a,b,c] )
and solve for this.
Obviously, goal order and rule order changes the way
Prolog process.
Occurs-Check Problem.
- substitution problem.
Prolog does not check when
substituting X --> T, that X occurs
in T
Example:
?- append( [ ] , E , [ a,b | E ] )

rule: append( [ ] , Y , Y )

so , Y = E and Y = [ a , b | E ]

E = Y = [ a , b | E ] = [ a , b | [ a , b | E ] ] = ...

goes on for forever !


Cuts
- basically telling the Prolog to stop
backtracking after the cut is
applied.
Example:
having following rules:
b:- c
b:- d

means: if b:-c does not yield success, then


backtracks, and b:- d rule is used.

b:- !, c ( ! means cut here )


b:- d

this means if b:- c fail do not try b:- d rule.


Another example:

conclusion(s) :- ! , cond1(s) , cond2(2) , …

only checks for cond1(s) , if this fail then


conclusion fails.

conclusion(s) :- cond1(s) , ! , cond2(2) ,

check for cond1


check for cond2, if fail stops
Application of Cut
Using cut in not( ) operation

rule:
not( X ) :- X , ! , fail
not( _ ).
Example:
?- X = 2 , not ( X=1 )

- do X = 2 , so X unifies with 2.
- left with not ( 2 = 1 )
- use rule to get: 2 = 1 , ! , fail
- 2 = 1 fails, not reaching the cut !
- so tries next rule not( _ ) and succeeds
?- not( X = 1 ) , X = 2

- apply rule and get: X=1 , ! , fail , X = 2


- X=1 succeeds
- reaches the cut !
- reaches fail , because of cut no more condition
processed and fails.

so these would also fail

?- not( X=1 )
?- not( X=1 ) , X = 1
Applying a Rule to a Goal
A :- B1, B2, …, Bn

• A rule applies to a
subgoal G if its head A unifies with G
• Variables in the rule are renamed before
unification to keep them distinct from
variables in the subgoal.

61
A computation that succeeds without backtracking

GOAL
Suffix([a],L),prefix(L,[a,b,c]).
suffix([a],L) if append(_1,[a],L).
Append(_1,[a],L),prefix(L,[a,b,c]).
{_1[],L[a]} append([],[a],[a]).
Prefix([a],[a,b,c]).
prefix([a],[a,b,c]) if append([a],_2,[a,b,c])
append([a],_2,[a,b,c]).
prefix([a],[a,b,c]) if append([],_2,[b,c])
Append([],_2,[b,c]).
{_2[b,c]} append([],[b,c],[b,c])
yes

62
Prolog Search Trees

63
Goal Order Changes Solutions

64
Cuts
• A cut prunes or “cuts out” and unexplored
part of a Prolog search tree.
• Cuts can therefore be used to make a
computation more efficient by eliminating
futile searching and backtracking.
• Cuts can also be used to implement a form
of negation

65
Cuts
• A cut, written as !, appears as a condition
within a rule. When rule
B :- C1,…, Cj-1, !,Cj+1,…,Ck

is applied, the cut tells control to backtrack


past Cj-1,…,C1,B, without considering any
remaining rules for them.

66
A cut as the First Condition
• Consider rules of the form
B :- !, C.

• If the goal C fails, then control backtracks


past B without considering any remaining
rules for B. Thus the cut has the effect of
making B fail if C fails.

67
Example
b,G
b :- c.
b :- d. X
b :- e.
c,G !,d,G
d,G e,G
b :- c.
b :- !,d.
b :- e.
d,G

68
Example
a(X) a(X)
• ?-a(X).
b e b e
c d Yes !c d Yes
Yes
backtrack X=2 c X=2
X=1
backtrack
a(1) :- b; a(1) :- b;
a(2) :- e; a(2) :- e;
b :- c. b :- !,c.
b :- d. b :- d.

69
The Effect of Cut
• As mentioned earlier, when a rule
B :- C1,…, Cj-1, !,Cj+1,…,Ck

is applied during a computation


• The cut tells control to backtrack past Cj-
1,..C1,B without considering any remaining
rules for them.
• The effect of inserting a cut in the middle of70
a guess-and-verify rule.
The Effect of Cut
• The right side of a guess-and-verify rule has
the form guess(S), verify(S), where
guess(S) generates potential solutions until
one satisfying verify(S) is found.
• The effect of insering a cut between them,
as
Conclusion(S) :- guess(S), !, verify(S)

71
is to eliminate all but the first guess.
a(X) :- b(X). a(X) :- b(X).
a(X) :- f(X). a(X) :- f(X).
b(X) :- g(X),v(X). b(X) :- g(X),!,v(X).
b(X) :- X = 4, v(X). b(X) :- X = 4, v(X).
g(1). g(1).
g(2). g(2).
g(3). g(3).
v(X). v(X).
f(5) f(5)
(a) (b)

72
a(Z) a(Z)

b(Z) f(5) b(Z) f(5)

g(Z),v(Z) v(4) g(Z),!,v(Z) v(4)

v(1) v(2) v(3) !v(X) v(2) v(3)

v(1)
(a) (b) 73
Negation as Failure
• The not operator in Prolog is implemented
by the rules
not(X) :- X, !, fail.
not(_).

74

You might also like