Prolog Programming (Volume 4) - PowerPoint PPT Presentation

About This Presentation
Title:

Prolog Programming (Volume 4)

Description:

Mary likes any animals except reptiles: likes(mary, X) :- reptile(X), !, fail. ... likes(mary, X) :- not(reptile(X)). different(X, Y) :- not(X = Y) ... – PowerPoint PPT presentation

Number of Views:110
Avg rating:3.0/5.0
Slides: 34
Provided by: williamc4
Category:

less

Transcript and Presenter's Notes

Title: Prolog Programming (Volume 4)


1
Prolog Programming(Volume 4)
  • Dr W.F. Clocksin

2
Backtracking and Nondeterminism
  • member(X, X_).
  • member(X, _T) - member(X, T).
  • ?- member(fred, john, fred, paul, fred).
  • yes
  • ?- member(X, john, fred, paul, fred).
  • X john
  • X fred
  • X paul
  • X fred
  • no

Deterministic query
Nondeterministic query
3
The problem of controlling backtracking
?- colour(banana, X). X yellow ?-
colour(physalis, X). X unknown ?-
colour(cherry, X). X red X unknown no
  • colour(cherry, red).
  • colour(banana, yellow).
  • colour(apple, red).
  • colour(apple, green).
  • colour(orange, orange).
  • colour(X, unknown).

4
The cut
  • A built-in predicate, used not for its logical
    properties, but for its effect. Gives control
    over backtracking.
  • The cut is spelled !
  • The cut always succeeds.
  • When backtracking over a cut, the goal that
    caused the current procedure to be used fails.

5
How it works
  • Suppose that goal H is called in a program, and
    consider the following two clauses for H
  • H1 - B1, B2, ..., Bi, !, Bk, ..., Bm.
  • H2 - Bn, ... Bp.
  • If H1 matches, goals B1...Bi may backtrack among
    themselves. If B1 fails, H2 will be attempted.
    But as soon as the cut is crossed, Prolog
    commits to the current choice. All other choices
    are discarded.

6
Commitment to the clause
  • Goals Bk...Bm may backtrack amongst themselves,
    but if goal Bk fails, then the predicate fails
    (the subsequent clauses are not matched).
  • H1 - B1, B2, ..., Bi, !, Bk, ..., Bm.
  • H2 - Bn, ... Bp.

7
How to remember it
  • Think of the cut as a fence which, when
    crossed as a success, asserts a commitment to the
    current solution.
  • However, when a failure tries to cross the fence,
    the entire goal is failed.
  • H1 - B1, B2, ..., Bi, !, Bk, ..., Bm.

commit
fail calling goal
8
Cut has several uses
  • 1. To define a deterministic (functional)
    predicate. Example a deterministic version of
    member, which is more efficient for doing member
    checking because it neednt give multiple
    solutions
  • membercheck(X, X_) - !.
  • membercheck(X, _L) - membercheck(X,L).
  • ?- membercheck(fred, joe, john, fred, paul).
  • yes.
  • ?-membercheck(X, a, b, c).
  • X a
  • no.

9
Cut has several uses
  • 2. To specify exclusion of cases by committing
    to the current choice. Example the goal max(X,
    Y, Z) instantiates Z to the greater of X and Y
  • max(X, Y, X) - X gt Y.
  • max(X, Y, Y) - X lt Y.
  • Note that each clause is a logically correct
    statement about maxima. A version using cut can
    get rid of the second test, and might look like
    this
  • max(X, Y, X) - X gt Y, !.
  • max(X, Y, Y).
  • (next slide explains this)

10
Max with cut
  • max(X, Y, X) - X gt Y, !.
  • max(X, Y, Y).
  • If max is called with X ? Y, the first clause
    will succeed, and the cut assures that the second
    clause is never made. The advantage is that the
    test does not have to be made twice if XltY.
  • The disadvantage is that each rule does not stand
    on its own as a logically correct statement about
    the predicate. To see why this is unwise, try
  • ?- max(10, 0, 0).

11
Max with cut
  • So, it is better to using the cut and both tests
    will give a program that backtracks correctly as
    well as trims unnecessary choices.
  • max(X, Y, X) - X gt Y, !.
  • max(X, Y, Y) - X lt Y.
  • Or, if your clause order might suddenly change
    (because of automatic program rewriting), you
    might need
  • max(X, Y, X) - X gt Y, !.
  • max(X, Y, Y) - X lt Y, !.

12
A larger example.
  • Well define several versions of the disjoint
    partial map split.
  • split(list of integers, non-negatives,
    negatives).
  • 1. A version not using cut. Good code (each can
    be read on its own as a fact about the program).
    Not efficient because choice points are retained.
    The first solution is desired, but we must ignore
    backtracked solutions.
  • split(, , ).
  • split(HT, HZ, R) - H gt 0, split(T, Z,
    R).
  • split(HT, R, HZ) - H lt 0, split(T, R, Z).

13
A larger example.
  • 2. A version using cut. Most efficient, but not
    the best defensively written code. The third
    clause does not stand on its own as a fact about
    the problem. As in normal programming languages,
    it needs to be read in context. This style is
    often seen in practice, but is deprecated.
  • split(, , ).
  • split(HT, HZ, R) - H gt 0, !, split(T, Z,
    R).
  • split(HT, R, HZ) - split(T, R, Z).
  • Minor modifications (adding more clauses) may
    have unintended effects. Backtracked solutions
    invalid.

14
A larger example.
  • 3. A version using cut which is also safe. The
    only inefficiency is that the goal H lt 0 will be
    executed unnecessarily whenever H lt 0.
  • split(, , ).
  • split(HT, HZ, R) - H gt 0, !, split(T, Z,
    R).
  • split(HT, R, HZ) - H lt 0, split(T, R, Z).
  • Recommended for practical use. Hidden problem
    the third clause does not capture the idea that
    H lt 0 is a committal. Here committal is the
    default because H lt 0 is in the last clause. Some
    new compilers detect that H lt 0 is redundant.

15
A larger example.
  • 3. A version with unnecessary cuts
  • split(, , ) - !.
  • split(HT, HZ, R) - H gt 0, !, split(T, Z,
    R).
  • split(HT, R, HZ) - H lt 0, !, split(T, R,
    Z).
  • First cut unnecessary because anything matching
    first clause will not match anything else anyway.
    Most Prolog compilers can detect this.
  • Why is the third cut unnecessary? Because Hlt0 is
    in the last clause. Whether or not Hlt0 fails,
    there are no choices left for the caller of
    split. However, the above will work for any order
    of clauses.

16
Mapping with Cut
  • Remember squint? Map integers to their squares,
    map anything else to itself
  • squint(, ).
  • squint(XT, YL) -
  • integer(X), !, Y is X X, squint(T, L).
  • squint(XT, XL) - squint(T, L).

17
More Mapping with Cut
  • Extract the even numbers...
  • evens(, ).
  • evens(XT, XL) - 0 is X mod 2, !, evens(T,
    L).
  • evens(XT, L) - evens(T, L).
  • Extract the unique members...
  • setify(, ).
  • setify(XT, L) - member(X, T), !,
    setify(T,L).
  • setify(XT, XL) - setify(T,L).

18
Negation as Failure
  • Using cut together with the built-in predicate
    fail, we may define a kind of negation. Examples
  • Mary likes any animals except reptiles
  • likes(mary, X) - reptile(X), !, fail.
  • likes(mary, X) - animal(X).
  • A utility predicate meaning something like not
    equals
  • different(X, X) - !, fail.
  • different(_,_).

19
Negation as Failure
  • We can use the same idea of cut fail to define
    the predicate not, which takes a term as an
    argument. not will call the term, that is
    evaluate it as though it is a goal
  • not(G) fails if G succeeds
  • not(G) succeeds if G does not succeed.
  • In Prolog,
  • not(G) - call(G), !, fail.
  • not(_).
  • Call is a built-in predicate.

20
Negation as Failure
  • Most Prolog systems have a built-in predicate
    like not. SICStus Prolog calls it \. Remember,
    not does not correspond to logical negation,
    because it is based on the success/failure of
    goals. It can, however, be useful
  • likes(mary, X) - not(reptile(X)).
  • different(X, Y) - not(X Y).

21
Negation as Failure can be Misleading
  • Once upon a time, a student who missed some of
    these lectures was commissioned to write a Police
    database system in Prolog. The database held the
    names of members of the public, marked by whether
    they are innocent or guilty of some offence.
    Suppose the database contains the following
  • innocent(peter_pan). innocent(X) -
    occupation(X, nun). innocent(winnie_the_pooh). i
    nnocent(julie_andrews) guilty(X) -
    occupation(X, thief). guilty(joe_bloggs). guilty
    (rolf_harris).
  • Consider the following dialogue
  • ?- innocent(st_francis).
  • no.

22
Problem.
  • This cannot be right, beause everyone knows that
    St Francis is innocent. But in Prolog the above
    happens because st_francis is not in the
    database. Because the database is hidden from the
    user, the user will believe it because the
    computer says so.
  • How to solve this?

23
not makes things worse
  • Using not will not help you. Do not try to remedy
    this by defining
  • guilty(X) - not(innocent(X)).
  • This is useless, and makes matters even worse
  • ?- guilty(st_francis).
  • yes
  • It is one thing to show that st_francis cannot be
    demonstrated to be innocent. But it is quite
    another thing to incorrectly show that he is
    guilty.

24
Negation-by-failure can be non-logical
  • Some disturbing behaviour even more subtle than
    the innocent/guilty problem, and can lead to some
    extremely obscure programming errors. Here is a
    restaurant database
  • good_standard(goedels). good_standard(hilberts).
  • expensive(goedels).
  • reasonable(R) - not(expensive(R)).
  • Consider the following dialogue
  • ?- good_standard(X), reasonable(X).
  • X hilberts
  • But if we ask the logically equivalent question
  • ?- reasonable(X), good_standard(X).
  • no.

25
Question
  • Why do we get different answers for what seem to
    be logically equivalent queries?
  • The difference between the questions is as
    follows.
  • In the first question, the variable X is always
    instantiated when reasonable(X) is executed.
  • In the second question, X is not instantiated
    when reasonable(X) is executed.
  • The semantics of reasonable(X) differ depending
    on whether its argument is instantiated.

26
Not a Good Idea!
  • It is bad practice to write programs that destroy
    the correspondence between the logical and
    procedural meaning of a program without any good
    reason for doing so.
  • Negation-by-failure does not correspond to
    logical negation, and so requires special care.

27
How to fix it?
  • One way is to specify that negation is undefined
    whenever an attempt is made to negate a
    non-ground formula.
  • A formula is ground if is has no unbound
    variables.
  • Some Prolog systems issue a run-time exception if
    you try to negate a non-ground goal.

28
Clauses and Databases
  • In a relational database, relations are regarded
    as tables, in which each element of an n-ary
    relation is stored as a row of the table having n
    columns.
  • supplier
  • jones chair red 10
  • smith desk black 50
  • Using clauses, a table can be represented by a
    set of unit clauses. An n-ary relation is named
    by an n-ary predicate symbol.
  • supplier(jones, chair, red, 10).
  • supplier(smith, desk, black, 50).

29
Clauses and Databases
  • Advantages of using clauses
  • Rules as well as facts can coexist in the
    description of a relation.
  • Recursive definitions are allowed.
  • Multiple answers to the same query are allowed.
  • There is no role distinction between input and
    output.
  • Inference takes place automatically.

30
Negation and Representation
  • Like databases, clauses cannot represent negative
    information. Only true instances are represented.
  • The battle of Waterloo occurred in 1815.
  • How can we show that the battle of Waterloo did
    not take place in 1923? The database cannot tell
    us when something is not the case, unless we do
    one of the following
  • Complete the database by adding clauses to
    specify the battle didnt occur in 1814, 1813,
    1812, ..., 1816, 1817, 1818,...
  • Add another clause saying the battle did not
    take place in another year (the battle occurred
    in and only in 1815).
  • Make the closed world assumption, implemented
    by negation by failure.

31
WS23 Frequency Distribution
  • Find the frequency distribution of a list of keys
    (integers) and sort into order. Represent N many
    Xs as NX. Example
  • ?- evens(3, 3, 2, 2, 1, 1, 2, 2, 3, 3, A).
  • A 21, 42, 43
  • There are two 1s, four 2s and four 3s.
    Something like run-length encoding, but each
    output entry gives the count (frequency) of each
    key in the whole input list. Also, note that keys
    are sorted into ascending order.

32
Frequency Distribution
  • Define the predicate freq such that the goal
    freq(L,S) succeeds for input list L and frequency
    list S
  • freq(L, S) - freq(L, , S).
  • freq(, S, S).
  • freq(NL, S1, S3) - update(N, S1, S2), freq(L,
    S2, S3).
  • All the work is done by update, which takes a key
    and the list before and after it is updated with
    the information in the key.

33
Frequency Distribution
  • / update(Key, BeforeList, AfterList) /
  • update(N, , 1N).
  • update(N, FNS, F1NS) - !, F1 is F 1.
  • update(N, FMS, 1N,FMS) - N lt M, !.
  • update(N, FMS, FMS1) -
  • N \ M, update(N, S, S1).
  • The cases are
  • 1. Reached end of list.
  • 2. Found one we have already seen.
  • 3. Found one that should be inserted before a
    seen one.
  • 4. Still searching list, just recur.
Write a Comment
User Comments (0)
About PowerShow.com