1 history automatic theorem proving robinson 1965 “programming in logic” kowalski, 1974...
TRANSCRIPT
1
History
Automatic Theorem Proving Robinson 1965
“PROgramming in LOGic” Kowalski, 1974 Deduction as computation
“Prolog”, Colmerauer, 1973
Edinburgh Prolog, 1977 “Prolog 10”, David Warren Warren Abstract Machine
Clocksin&Mellish, 1981
2
What kind of a thing is Prolog?
Very different from C, C++, Java, and other Procedural languages
Symbolic Programming Language
Logic Programming Language
Declarative Programming Language
3
Prolog program
A Prolog program is defined by a set of Predicates
Each Predicate has a unique Functor and Arityparent(Parent, Child)
a predicate whose functor is “parent” with arity 2.
Each Predicate is defined by a sequence of Clauses
A Clause is either a Fact or a Rule
fact(…).
head(…) :- goal1(…), … , goalN(…).
Each argument to a predicate is a Term
A Term is either: Atomic, Variable, or Compound
4
Atomic terms
Atomic terms can be either atoms or numbers
Atoms can be a sequence of alphanumeric (including ‘_’) characters starting with a lower case letter, or a sequence of any characters embedded in single quote marks:johnDowding symbsys139p ‘quoted atom’ non_quoted_atom
Numbers can be integers or floating point
5
Variables
Variables start with a capital letter or _ character X Parent _Sibling _
Variables can stand in for arbitrary Prolog terms (including other variables)
Variables that occur with the same name in the same clause represent the same variable, except for
The anonymous variable “_”, which always represents a unique variable.
6
Compound Terms
A compound term is a structure with a functor and N arguments.
functor(Arg1, Arg2, …, ArgN)
Each argument can be an arbitrary Prolog term
7
Example: Successor Arithmetic
Simple arithmetic using compound terms to represent integers:0 0
1 s(0)
2 s(s(0))
3 s(s(s(0)))
4 s(s(s(s(0))))
.
.
.
8
Structural Induction and Recursion
Inductive proofs have a base (or terminating) case and an inductive step.
Mathematical induction – over the space of integers
Structural induction – over subsets of the space of Prolog Terms.
Many Prolog predicates have this structure:is_number(0).
is_number(s(Number)) :- is_number(Number).
9
BUILT-IN Predicate: consult/1
consult(FileName)
Load the Prolog program in FileName into memory.
10
Factorial
factorial(+N, ?Factorial) fact(1) = 1 fact(N+1)= (N+1) * fact(N)
%factorial(+Number, ?Factorial)
factorial(s(0), s(0)).
factorial(s(Number), Factorial):-
factorial(Number, PartialFactorial),
mult(s(Number), PartialFactorial, Factorial).
11
Prolog Execution Model/Prolog Debugger
CALL EXIT
FAIL REDOparent(james, john).parent(james, alan).parent(florence, john).parent(florence, alan).parent(alan, elizabeth).parent(alan, emily).
Goal = parent(P, john) parent(james, john)parent(florence, john)
12
Execution Model (conjunctions)
parent(james, john).parent(james, alan).parent(florence, john).parent(florence, alan).parent(alan, elizabeth).parent(alan, emily).
female(emily).female(florence).female(elizabeth).
parent(Mother, john) female(Mother)parent(james, john) female(james)parent(florence, john) female(florence)
13
Execution Model – mult(s(s(s(0))), s(s(0)), Result)
mult(0, Term, 0):- is_number(Term).mult(s(Term1), Term2, Product):- mult(Term1, Term2, Partial), add(Term2, Partial, Product).
add(0, Sum, Sum):- is_number(Sum).add(s(Addend1), Addend2, s(Sum)):- add(Addend1, Addend2, Sum).
mult(s(s(0)),s(s(0)), Prod)
mult(s(0), s(s(0)), Partial) add(s(s(0)), Partial, Prod)
add(s(s(0)), Prod, Result)
mult(0, Term, 0):- is_number(Term).mult(s(Term1), Term2, Product):- mult(Term1, Term2, Partial), add(Term2, Partial, Product).
14
Prolog Debugger Demo
Built-In predicates: trace/0. notrace/0.
Debugger actions: ‘c’ or <cr> - creep ‘s’ – skip ‘l’ – leap ‘r’ – retry ‘f’ – fail ‘a’ - abort
15
And-Or Trees
or
andand and
ororor
ororor or
andandandandand and and
orororor
oror
or
16
And-Or Tree (cont.)
or
and and
mult(0, Term, 0):- is_number(Term).
mult(s(Term1), Term2, Product):- mult(Term1, Term2, Partial), add(Term2, Partial, Product).
or or or
is_number(Term)mult(Term1, Term2, Partial)
add(Term2,Partial,Product)
and and and and and and
17
Linked Lists
Prolog allows a special syntax for lists: [a,b,c] is a list of 3 elements [] is a special atom indicating a list with 0 elements
Internally, Prolog lists are regular Prolog terms with the functor ‘.’ (so called “dotted pairs”)[a,b,c] = ‘.’(a, ‘.’(b, ‘.’(c, []))).The symbol | in a list indicates “rest of list”, or the term that is the 2nd argument of a dotted pair.[a,b,c] = [a|[b,c]].[Head|Tail] is a common expression for dividing a list into its first element (Head) and the rest of the list (Tail).
18
Example: list/1
% list(?List)
list([]).
list([_Head|Tail]):-
list(Tail).
Since Prolog is untyped, we don’t have to know anything about Head except that it is a term.
19
Example: member/2
% member(?Element, ?List)
member(Element, [Element|_Tail]).
member(Element, [_Head|Tail]):-
member(Element, Tail).
20
Example: delete/3
% delete(+Element, +List, -NewList)
% delete/3 succeeds if NewList results from removing
% one occurrence of Element from List.
delete(Element, [Element|Tail], Tail).
delete(Element, [Head|Tail], [Head|NewTail]):-
delete(Element, Tail, NewTail).
21
Example: append/3
% append(?List1, ?List2, ?List3)
% append/3 succeds if List3 contains all the elements of
% List1, followed by all the elements of List2.
append([], List2, List2).
append([Head|List1], List2, [Head|List3]):-
append(List1, List2, List3).
22
Example: “naïve” reverse
% "naive reverse": nreverse(?List, ?ReversedList).
nreverse([], []).
nreverse([Head|Tail], ReversedList):-
nreverse(Tail, ReversedTail),
append(ReversedTail, [Head], ReversedList).
23
“Pure Prolog” and non-logical built-ins
All the examples so far have been “pure Prolog” Contain no built-ins with non-logical side-effects
Prolog has many built-in predicates: Type checking of terms Arithmetic Control execution Input and output Modify the program during execution Perform aggregation operations
Use of non-logical built-in predicates usually effects the reversability of your program.
24
Type-checking Built-in Predicates
var(X) – is true when X is an uninstantiated variable.
nonvar(X) – is true when X is not a variable.
atom(X) – is true when X is a symbolic constant.
number(X) – is true when X is a number
atomic(X) – is true when atom(X) or number(X).
compound(X) – is true when X is a compound term.
25
Term constructor/selectors: functor/3, arg/3
functor(+Term, ?Functor, ?Arity) Find the Functor and Arity of Term
functor(?Term, +Functor, +Arity) Constructs a new Term with Functor and Arity
arg(+N, +Term, ?SubTerm) Unifies SubTerm with the Nth argument of Term
26
Arithmetic: Built-In is/2
Arithmetic expressions are not normally evaluated in Prolog.Built-In infix operator is/2 evaluates it’s 2nd argument, and unifies the result with it’s 1st argument.| ?- X = 5 + 2.X = 5+2?yes| ?- X is 5 + 2.X = 7 ?yes
Any variables in the right-hand side of is/2 must be instantiated when it is evaluated.
Revisit operator and arithmetic at a later time
27
Cut (!)
The ! Symbol (pronounced “cut”) modifies the execution of your program by committing to certain choices. That is, it removes choice points.
Easy to describe what it does, more difficult to get used to using it properly.
28
Cut (cont.)
Head1 :- Goal1, Goal2, …, GoalN, !, …Head2 :- …Head3 :- ……HeadN :- …
Removes the choice point that allows Head2 …HeadNRemoves any choice points that may have been introduced in Goal1 … GoalN.We will discuss Cut in more detail later on.
29
Example: delete_first/3
% delete_first(+Element, +List, -NewList)
% removes the 1st occurrence of Element in List.
delete(Element, [Element|Tail], Tail):-
!.
delete(Element, [Head|Tail], [Head|NewTail]):-
delete(Element, Tail, NewTail).
30
Built-Ins: Term Comparison Operators
Unifies with Term1 = Term2 iff unifies Term1 and Term2 if they are unifiable
Does not unify with Term1 \= Term2, Term1 and Term2 are unchanged
Identical Term1 == Term2 iff are the same terms
Not identical Term1 \== Term2
31
Built-ins: true/0 and fail/0.
true. Always succeeds.
fail. Always fails.
32
Meta-Predicates: call/1, \+/1
Meta-predicates take a Goal as an argument, and execute it.
call/1 executes it’s one argument.
\+(Goal) succeeds if call(Goal) fails.
\+/1 could also be defined using cut and fail.
\+(Goal) :- call(Goal), !, fail.
\+(_Goal).
33
More about cut!
Common to distinguish between red cuts and green cuts Red cuts change the solutions of a predicate Green cuts do not change the solutions, but effect the efficiency
Most of the cuts we have used so far are all red cuts
%delete_all(+Element, +List, -NewList)delete_all(_Element, [], []).delete_all(Element, [Element|List], NewList) :- !, delete_all(Element, List, NewList).delete_all(Element, [Head|List], [Head|NewList]) :- delete_all(Element, List, NewList).
34
Green cuts
Green cuts can be used to avoid unproductive backtracking% identical(?Term1, ?Term2)identical(Var1, Var2):-
var(Var1), var(Var2),!, Var1 == Var2.
identical(Atomic1,Atomic2):- atomic(Atomic1), atomic(Atomic2),!, Atomic1 == Atomic2.
identical(Term1, Term2):-compound(Term1),compound(Term2),functor(Term1, Functor, Arity),functor(Term2, Functor, Arity),identical_helper(Arity, Term1, Term2).
35
Advice on cuts
Dangerous, easy to misuse
Rules of thumb: Use sparingly Use with as narrow scope as possible
36
intersect/3
%intersect(+Set1, +Set2, ?Intersection)
intersect([], _Set2, []).
intersect([Element|RestSet1], Set2, [Element|Intersection]):-
member(Element, Set2),
!,
intersect(RestSet1, Set2, Intersection).
intersect([_Element|RestSet1], Set2, Intersection):-
intersect(RestSet1, Set2, Intersection).
37
Example: Input/Output
repeat/0 is a built-in predicate that will always resucceed
% classifing terms
classify_term :-
repeat,
write('What term should I classify? '),
nl,
read(Term),
process_term(Term),
Term == end_of_file.
38
I/O Example (cont)
process_term(Atomic):-
atomic(Atomic),
!,
write(Atomic), write(' is atomic.'), nl.
process_term(Variable):-
var(Variable),
!,
write(Variable), write(' is a variable.'), nl.
process_term(Term):-
compound(Term),
write(Term), write(' is a compound term.‘), nl.
39
assert/1, asserta/1, and assertz/1
Asserting facts (most common)assert(Fact)
Asserting rulesassert( (Head :- Body) ).
asserta/1 adds the new clause at the front of the predicate
assertz/1 adds the new clause at the end of the predicate
assert/1 leaves the order unspecified
40
Built-In: retract/1
retract(Goal) removes the first clause that matches Goal.
On REDO, it will remove the next matching clause, if any.
Retract facts:retract(Fact)
Retract rules:retract( (Head :- Body) ).
41
Built-in: retractall/1
retractall(Head) removes all facts and rules whose head matches.
Could be implemented with retract/1 as:
retractall(Head) :-
retract(Head),
fail.
retract(Head):-
retract( (Head :- _Body) ),
fail.
retractall(_Head).
42
Built-In: abolish(Predicate/Arity)
abolish(Predicate/Arity) is almost the same as
retract(Predicate(Arg1, …, ArgN))
except that abolish/1 removes all knowledge about the predicate, where retractall/1 only removes the clauses of the predicate.
43
Aggregation: findall/3.
findall/3 is a meta-predicate that collects values from multiple solutions to a Goal:
findall(Value, Goal, Values)
findall(Child, parent(james, Child), Children)
Prolog has other aggregation predicates setof/3 and bagof/3, but we’ll ignore them for now.
44
findall/3 and assert/1
findall/3 and assert/1 both let you preserve information across failure.:- dynamic solutions/1.findall(Value, Goal, Solutions):-
retractall(solutions/1),assert(solutions([])),call(Goal),retract(solutions(S)),append(S, [Value], NextSolutions),assert(solutions(NextSolutions)),fail.
findall(_Value, Goal, Solutions):-solutions(Solutions).
45
Special Syntax III: Operators
Convenience in writing terms
We’ve seem them all over already:union([Element|RestSet1], Set2, [Element|SetUnion]):-
union(RestSet1, Set2, SetUnion),
\+ member(Element, SetUnion),
!.
This is just an easier way to write the term:‘:-’(union([Element|RestSet],Set2,[Element|SetUnion]),
‘,’(union(RestSet1,Set2,SetUnion),
‘,’(‘\+’(member(Element, SetUnion),
!)))
46
Operators (cont)
Operators can come before their arguments (prefix) \+
Or between their arguments (infix) , + is <
Of after their arguments (postfix) Prolog doesn’t use any of these (yet)
The same Operator can be more than one type :-
47
Precedence and Associativity
Operators also have precedence 5 * 2 + 3 = (5 * 2) + 3
Operators can be associative, or not,
Left associative or right associative
Explicit parenthesization can override defaults for associatiativity and precendence
48
Built-in: current_op/3
current_op/3 gives the precedence and associativity of all current operators.
current_op(Precedence, Associativity, Operator)
where Precedence in an integer 1-1200
and Associativity is of fx or fy for prefix operators xf or yf for postfix operators xfx, xfy, yfx, yfy for infix operators
49
Associativity
These atoms: fx, fy, xf, yf, xfx, xfy, yfx, yfy draw a “picture” of the associativity of the operator: The location of the f tells if the operator is prefix, infix,
or postfix. x means that the argument must be of lower precedence y means that the argument must be of equal or lower
precedence. A y on the left means the operator is left associative A y on the right means the operator is right associative
50
Creating new operators
Built-in op/3 creates new operators
op(+Precedence, +Associativity, +Operator)
:- op(700, xfx, equals).
:- op(650, fx, $).
:- op(650, xf, cents).
$Dollars equals Cents cents :-
Cents is 100 * Dollars.