A Prolog program is constructed from a number of clauses, the general form of which is
There are three forms of clauses based on this general pattern:
father( john, mary ).
sister( X, Y ) :-
female( X ),
parents( X, Ma, Pa ),
parents( Y, Ma, Pa ).
?- sister( alice, victoria ).
Horn clauses: Prolog allows at most one atomic expression (predication) in the head of a clause, but any number in the body.
Interpreted environment -- A user enters clauses into the Prolog environment and they are interpreted.
?- sister( alice, victoria ).the system responds yes or no.
father( john, mary ).
mother( sue, mary ).
female( mary ).
daughter( Child, Parent ) :-
father( Parent, Child ),
female( Child ).
daughter( Child, Parent ) :-
mother( Parent, Child ),
female( Child ).
?- father( john, mary ).
yes
?- mother( john, mary ).
no
?- daughter( mary, john ).
yes
The last goal unifies with the head of the fourth clause, establishing the bindings mary / Child and john / Parent, which in turn establishes the subgoals
?- father( john, mary ). ?- female( mary ).
which both succeed (due to clauses 1 and 3), so the main goal succeeds.
?- daughter( mary, john ).
would have been unified with the head of
daughter( Child, Parent ) :-
mother( Parent, Child ),
female( Child ).
Bindings: mary / Child and
john / Parent
Sub-goals:
?- mother( john, mary ).
?- female( mary ).
The first sub-goal would fail to unify with the head of any clause, and would report failure.
Since the unification
failed, the interpreter would backtrack and attempt to unify the goal
with the head of the next clause
daughter( Child, Parent ) :-
father( Parent, Child ),
female( Child ).
which, as we have seen, will succeed.
person( X ) :-
person( Y ),
mother( X, Y ).
person( adam ).
?- person( X ).
results in infinite recursion.
Alternate solutions -- Prolog interpreters may be asked to continue unifying the goal with
the rest of the clauses after they succeed in proving a goal. The user prompts for additional
solutions with ';' (or some other method, depending on the system).
E.g.,
father( john, mary ).
father( john, carol ).
mother( sue, mary ).
female( mary ).
female( carol ).
daughter( Child, Parent ) :-
father( Parent, Child ),
female( Child ).
daughter( Child, Parent ) :-
mother( Parent, Child ),
female( Child ).
?- daughter( Who, john ).
Who = mary;
Who = carol;
no
Parameters are modeless -- A given argument may be an in-parameter or an out-parameter.
E.g.,
daughter( mary, Who ). Who = john; Who = sue; no
daughter( X, Y ). X = mary, Y = john; X = carol, Y = john; X = mary, Y = sue; no
daughter( X, _ ).
EXERCISE: What is the result?
A mechanism is provided to control backtracking: ! (cut) succeeds and cannot be resatisfied.
sum_to( N, 1 ) :- N =< 1, !.
sum_to( N, R ) :-
N1 is N - 1,
sum_to( N1, R1 ),
R is R1 + N.
The cut causes this construct to behave like an if-then-else. It ensures that if N is 1 or less, the result 1 should be returned and no other rules should be tried. It is possible to write this set of clauses without a cut.
The is operator instantiates the variable on the left to the value of the arithmetic expression on the right (which is evaluated numerically). If the variable on the left is already instantiated, then is behaves like a comparison instead of like an assignment.
forced_move( Board, Square ) :-
aline( Squares ),
threatening( Squares, Board, Sq ), !.
not( P ) :- call( P ), !, fail. not( P ).
E.g.,
nonsibling( X, Y ) :- sibling( X, Y ), !, fail. nonsibling( X, Y ).
which is equivalent to
nonsibling( X, Y ) :- not( sibling( X, Y )).
The predicate not is predefined in early versions of Prolog. Newer versions use \+ (which is a typewriter analog for the "not provable" symbol of formal logic) to mean "not" or "cannot-prove" (negation as failure), typically retaining not as a synonym for backward compatibility.
Nonmonotonic logic
alive( sam ).later:
dead( sam ).E.g., furnace control -- now:
temp( 21 ).later:
temp( 18 ).
| assert( C ) | Clause C is inserted at the end of the database. |
| asserta( C ) | Same, but at the start of the database. |
| assertz( C ) | Synonym for assert. | retract( C ) | The first clause matching C is removed from the database. |
To assert a rule, the entire rule must be enclosed in an extra set of parentheses.
Negation as unsatisfiability requires procedural rather than declarative understanding.
E.g., given father( john, mary ). and goal
?- father( john, X ), write( X )., the result is
the writing of atom mary
but goal
?- not( not( father( john, X ))), write( X ).
results in writing a representation of an uninstantiated variable.
Why?
Comparisons, equality, and unification
= uses term equality.
?- one = one. yes ?- one = two. no ?- same( this, that ) = same( this, that ). yes
?- one = Two. Two = one yes ?- same( this, That ) = same( This, that ). That = that This = this yes
?- same( One, thing ) = same( Two, thing ). One = _G129 Two = _G129 yes
X \= Y means "X cannot be made
equal to Y" (not unifiable; equivalent to \+ X = Y).
E.g.,
can_marry( X, Y ) :-
X \= Y,
\+ sibling( X, Y ),
\+ cousin( X, Y ).
?- can_marry( sammy, Someone ).
no
Most versions of Prolog provide other equality operators to avoid some problems with = and \=.
== tests for literal equality without instantiating variables ("is already equal to", not "is unifiable").
E.g.,
?- one == Two. no
Two uninstantiated variables are == only if they are already sharing.
E.g.,
?- This == This. This = _G248 yes ?- This == That. no ?- This = That, This == That. This = _G249 That = _G249 yes ?- same( X, Y ) == same( P, Q ). no
\== is more appropriate than \= for specifying that two objects must be different.
can_marry( X, Y ) :-
X \== Y,
\+ sibling( X, Y ),
\+ cousin( X, Y ).
?- can_marry( sammy, Someone ).
Someone = susie;
Someone = sally;
no
=:= tests for equality
of arithmetic values. It will not instantiate variables, and fails if either expression contains
an uninstantiated variable.
E.g.,
?- X+2 =:= X+2. ERROR: Arguments are not sufficiently instantiated. ?- A = 5, A =:= a. ERROR: Arithmetic 'a' is not a function.
is forces arithmetic evaluation.
E.g.,
check( Sum ) :- Sum is 3 + 4. ?- check( 7 ). yes ?- check( What ). What = 7
The last example illustrates that is will instantiate an uninstantiated variable on the left side
unlike =.
E.g.,
test( Sum ) :- Sum = (3 + 4). ?- test( 7 ). no
is requires that there be no uninstantiated variable in the expression to its right,
so rules using it are limited in the roles of input or output parameters.
E.g.,
factorial( 0, 1 ).
factorial( N, Value ) :-
N > 0,
Prev is N - 1,
factorial( Prev, Prevfact ),
Value is Prevfact * N.
?- factorial( 3, Value ).
Value = 6
?-factorial( N, 6 ).
ERROR: Arguments are not sufficiently instantiated.