Índice

 

 
Computational Logic
 
The (ISO-)Prolog Programming Language
 

(ISO-)Prolog

Programming Interface (Writing and Running Programs)

Comparison with Imperative and Functional Languages

Comparison with Imperative and Functional Languages (Contd.)

The ISO Standard (Overview)

Additionally (not in standard):

Prolog Syntax and Terminology

Prolog Syntax — Defining Operators

Prolog Syntax — Operators (Contd.)

Prolog Syntax — Operators (Contd.)

[basicstyle=\Large\ttfamily]
     :- op( 1200, xfx, [ :-, --> ]).
     :- op( 1200,  fx, [ :-, ?- ]).
     :- op( 1150,  fx, [ mode, public, dynamic,
                         multifile, block, meta_predicate,
                         parallel, sequential ]).
     :- op( 1100, xfy, [ ; ]).
     :- op( 1050, xfy, [ -> ]).
     :- op( 1000, xfy, [ ',' ]).
     :- op(  900,  fy, [ \+, spy, nospy ]).
     :- op(  700, xfx, [ =, is, =.., ==, \==, @<, @>, @=<, @>=,
                                     =:=, =\=, <, >, =<, >= ]).
     :- op(  550, xfy, [ : ]).
     :- op(  500, yfx, [ +, -, #, /\, \/ ]).
     :- op(  500,  fx, [ +, - ]).
     :- op(  400, yfx, [ *, /, //, <<, >> ]).
     :- op(  300, xfx, [ mod ]).
     :- op(  200, xfy, [ ^ ]).

The Execution Mechanism of (classical) Prolog

grandparent(C,G) :- parent(C,P), parent(P,G).

parent(C,P) :- father(C,P).
parent(C,P) :- mother(C,P).

father(charles,philip).
father(ana,george).

mother(charles,ana).

Built-in Arithmetic

Built-in Arithmetic (Contd.) – The arithexpr type

[mathescape=true]
arithexpr :=
    | num
    | + arithexpr           | - arithexpr
    | ++ arithexpr          | -- arithexpr
    | aritexpr + arithexpr  | aritexpr - arithexpr
    | aritexpr * arithexpr  | aritexpr // arithexpr
    | aritexpr / arithexpr  | abs(arithexpr)
    | sign(arithexpr)       | float_integer_part(arithexpr)
    | float(arithexpr)      | float_fractional_part(arithexpr)
    | aritexpr ** arithexpr | exp(arithexpr)
    | log(arithexpr)        | sqrt(arithexpr)
    | sin(arithexpr)        | cos(arithexpr)
    | atan(arithexpr)       | [arithexpr]
    |$\ldots$

Other arithmetic operators that can appear in arithmetic expressions (see manuals):

Built-in Arithmetic (Contd.)

Arithmetic Programs

Dynamic Checking of Basic Types

Type Checking Predicates (Contd.)

\rightarrow Real solution: the addition of constraints to the language (CLP) –see later!

Structure Inspection

Structure Inspection (Contd.)

Example of Structure Inspection: Arrays

[basicstyle=\Large\ttfamily]
add_arrays(A,B,C) :-    % Same N below imposes equal length:
     functor(A,array,N), functor(B,array,N), functor(C,array,N),
     add_elements(N,A,B,C).

add_elements(0,_,_,_).
add_elements(I,A,B,C) :-
     I>0, arg(I,A,AI), arg(I,B,BI), arg(I,C,CI),
     CI is AI + BI, I1 is I - 1,
     add_elements(I1,A,B,C).
add_arrays_lists([],[],[]).
add_arrays_lists([X|Xs],[Y|Ys],[Z|Zs]) :-
    Z is X + Y,
    add_arrays_lists(Xs,Ys,Zs).

Example of Structure Inspection: Arrays (Contd.)

[basicstyle=\Large\ttfamily]
:- use_package(fsyntax). % Use functional notation.
  
:- op(250,xfx,@).   % Define @ as an infix operator
:- fun_eval '@'/2.  % Call @ when it appears as a term (no need for ~)

T@N := A :- arg(N,T,A).  % Define @ as simply calling arg/3

:- fun_eval arith(true). % Evaluate arithmetic expressions (I-1)
add_elements(0,_,_,_).
add_elements(I,A,B,C) :-
     I>0, 
     C@I is A@I + B@I, 
     add_elements(I-1,A,B,C).

Example of Structure Inspection: Subterms of a Term

subterm(Term,Term).  % a) A term is always a subterm of itself
subterm(Sub,Term):-  % b) The arguments are also subterms:
    functor(Term,_F,N),%  N is number of arguments of Term
    n_to_one(N, J),  %    J is a natural between N and 1
    arg(J,Term,Arg), %    Arg is the J-th argument of Term
    subterm(Sub,Arg).%    Sub are the subterms of Arg

n_to_one(N, N) :- N > 0.
n_to_one(N, X) :- N > 1, N1 is N-1, n_to_one(N1, X).
?- subterm( f(a) , g(b,f(a)) ).
?- subterm( f(b) , g(b,f(a)) ).
?- subterm( g(b,f(a)) , g(b,f(a)) ).
?- subterm( X , g(b,f(a)) ).
?- subterm( f(X) , g(b,f(a)) ).
?- subterm( X , g(X,f(a)) ).
?- subterm( f(X) , g(b,f(X)) ).

’Higher-Order’ Structure Inspection

Conversion Between Strings and Atoms (New Atom Creation)

Meta-Logical Predicates

Meta-Logical Predicates (Contd.) – choosing implementations

Meta-Logical Predicates (Contd.) – choosing implementations

run example \longmapsto

Comparing Non-ground Terms

Comparing Non-ground Terms (Contd.)

subterm_ng(Sub,Term) :- % a) A term is a subterm of another 
    Sub == Term.        %    if they are identical.
subterm_ng(Sub,Term) :- % b) The arguments are also subterms:
    functor(Term,_F,N), %    N is number of arguments of Term
    n_to_one(N, J),     %    J is a natural between N and 1
    arg(J,Term,Arg),    %    Arg is the J-th argument of Term
    subterm_ng(Sub,Arg).%    Sub are the subterms of Arg

where n_to_one/2 is identical to the previous definition.

Input/Output

Class Predicate Explanation
I/O stream control see(File) File becomes the current input stream.
seeing(File) The current input stream is File.
seen Close the current input stream.
tell(File) File becomes the current output stream.
telling(File) The current output stream is File.
told Close the current output stream.
Term I/O write(X) Write the term X on the current output stream.
nl Start a new line on the current output stream.
read(X) Read a term (finished by a full stop) from the current input stream and unify it with X.
Character I/O put_code(N) Write the ASCII character code N. N can be a string of length one.
get_code(N) Read the next character code and unify its ASCII code with N.

Input/Output (Contd.)

Class Predicate Explanation
I/O stream control open(File,M,S) Open File with mode M and return in S the stream associated with the file. M may be read, write or append.
close(S) Close the stream ‘Stream’.
Term I/O write(S,X) Write the term X on stream S.
nl(S) Start a new line on stream S.
read(S,X) Read a term (finished by a full stop) from the stream S and unify it with X.
Character I/O put_code(S,N) Write the ASCII character code N on stream S.
get_code(S,N) Read from stream S the next character code and unify its ASCII code with N.

Input/Output (Contd.)

Pruning Operator: Cut

Pruning Operator: Cut (Contd.)

s(1).          p(X,Y):- l(X), ...                  r(8).
s(2).          p(X,Y):- r(X), !, ...               r(9).
               p(X,Y):- m(X), ...

Types of Cut: White and Green Cuts

run example \longmapsto

Types of Cut: Red Cuts

run example \longmapsto

Types of Cut: Red Cuts (Contd.)

Types of Cut: Red Cuts (Contd.)

Meta-Calls and Implementing Higher Order

Meta-calls – Aggregation Predicates

run example \longmapsto

likes(bill, cider).
likes(dick, beer).
likes(tom, beer).
likes(tom, cider).
likes(harry, beer).
likes(jan, cider).
?- findall(X, likes(X,Y), S).
S = [bill,dick,tom,tom,harry,jan] ? 
yes
?- findall(X, likes(X,water), S).
S = [] ? 
yes
?- 

Meta-calls – Aggregation Predicates (Contd.)

Meta-calls – Aggregation Predicates: Examples

likes(bill, cider).
likes(dick, beer).
likes(harry, beer).
likes(jan, cider).
likes(tom, beer).
likes(tom, cider).
?- setof(X, likes(X,Y), S).
S = [dick,harry,tom],
Y = beer ? ;
S = [bill,jan,tom],
Y = cider ? ;
no

?- setof((Y,S), setof(X, likes(X,Y), S), SS).
SS = [(beer,[dick,harry,tom]),
      (cider,[bill,jan,tom])] ? ;
no

?- setof(X, Y^(likes(X,Y)), S).
S = [bill,dick,harry,jan,tom] ? ;
no

Meta-calls – Negation as Failure

Meta-calls – Negation as Failure – Ensuring Correctness

Cut-Fail

Dynamic Program Modification (I)

Dynamic Program Modification (II)

Dynamic Program Modification (III)

“Those who cannot remember the past are condemned to repeat it”

Meta-Interpreters

Meta-Interpreters: extending the basic meta-interpreter

Incomplete Data Structures - Example: Difference Lists

One can also build difference (open ended) trees, dictionaries, queues, etc., by leaving variables at the ends (e.g., at the leaves for trees).

Playing with difference lists

?-  L1 = [1,2,3|X], L2 = [4,5|Y], L2=X.
L1 = [1,2,3,4,5|Y],
L2 = [4,5|Y],
X = [4,5|Y] ? 
yes

L1 contains the resulting difference list [1,2,3,4,5|Y].

Given: append_dl(B1-E1,E1-E2,B1-E2)

  ?- append_dl([1,2,3|X]-X,[4,5|Y]-Y,L).
  L = [1,2,3,4,5|Y]-Y, X = [4,5|Y] ? 

L has the resulting (appended) difference list.
But note that we have modified the first list: we cannot append to it again.

  ?- append_dl(L-X,[4,5|Y]-Y,[1,2,3,4,5|Z]-Z).
  L = [1,2,3,4,5|Y], X = [4,5|Y], Z = Y ? 

Quick-sort using standard lists and append


  
qsort([],[]).
qsort([X|L],S) :-         % Take first element of list in X
   partition(L,X,LS,LB),  % LS elements of L < X, LB els >= X
   qsort(LS,LSS),         % LSS is LS sorted 
   qsort(LB,LBS),         % LBS is LB sorted 
   append(LSS,[X|LBS],S). % We append the small ones sorted to 
                          % the big ones sorted, w/X in front
partition([],_P,[],[]).
partition([E|R],P,[E|Smalls],Bigs) :- % Take first element E
    E < P,            % If E < P add to list of smaller ones
    partition(R,P,Smalls,Bigs).
partition([E|R],P,Smalls,[E|Bigs]) :-
    E >= P,           % If E >= P add to list of larger ones
    partition(R,P,Smalls,Bigs).

run example \longmapsto

Quick-sort using standard lists and append

?- qsort([5,2,1,3,7,6], SL).
  
qsort([],[]).
qsort([X|L],S) :-            % X=5, L=[2,1,3,7,6]
   partition(L,X,LS,LB),     % LS=[2,1,3], LB=[7,6]
   qsort(LS,LSS),            % LSS=[1,2,3]
   qsort(LB,LBS),            % LBS=[6,7]
   append(LSS,[X|LBS],S).    % call: append([1,2,3],[5,6,7],S)
                             % S=[1,2,3,5,6,7]
partition([],_P,[],[]).
partition([E|R],P,[E|Smalls],Bigs) :- 
    E < P,
    partition(R,P,Smalls,Bigs).
partition([E|R],P,Smalls,[E|Bigs]) :-
    E >= P,
    partition(R,P,Smalls,Bigs).

Quick-sort using difference Lists (no append!)

                           % ?- qsort_dl([5,2,1,3,7,6], SL).

qsort_dl(L,SL) :-          % L  = [5,2,1,3,7,6]
    qsort_dl_(L,SL-SLE),   % SL = [1,2,3,5,6,7|SLE]
    SLE = [].              % SL = [1,2,3,5,6,7]

qsort_dl_([],SLE-SLE).
qsort_dl_([X|L],SL-SLE) :- % X = 5, L = [2,1,3,7,6]
    partition(L,X,S,B),    % S = [2,1,3], B = [7,6]
    qsort_dl_(S,SS-SSE),   % SS  = [1,2,3|SSE]
    qsort_dl_(B,BS-BSE),   % BS  = [6,7|BSE]
    SSE = [X|BS],          % SSE = [5,6,7|BSE]
    SL = SS,               % SL  = [1,2,3,5,6,7|BSE]
    SLE = BSE.             % SL  = [1,2,3,5,6,7|SLE]
% Partition is the same as before.

Quick-sort using difference Lists (no append!)



qsort_dl(L,SL) :-
    qsort_dl_(L,SL-[]).

    
qsort_dl_([],SLE-SLE).
qsort_dl_([X|L],SL-SLE) :-
    partition(L,X,S,B),
    qsort_dl_(S,SL-[X|BS]),
    qsort_dl_(B,BS-SLE).



% Partition is the same as before.

Quick-sort using difference Lists (no append!)



qsort_dl(L,SL) :-
    qsort_dl_(L,SL,[]).

    
qsort_dl_([],SLE,SLE).
qsort_dl_([X|L],SL,SLE) :-
    partition(L,X,S,B),
    qsort_dl_(S,SL,[X|BS]),
    qsort_dl_(B,BS,SLE).



% Partition is the same as before.

Parsing (using append and traditional lists)

?- myphrase([t,h,e,’ ’,p,l,a,n,e,’ ’,f,l,i,e,s]). run example \longmapsto

myphrase(X) :-
    % A must be at the beginning of X, T1 is the rest:
    article(A),  append(A,T1,X),
    spaces(S1),  append(S1,T2,T1),
    noun(N),     append(N,T3,T2),
    spaces(S2),  append(S2,V,T3),
    verb(V).

article([a]).             spaces([' ']).
article([t,h,e]).         spaces([' ' | Y]) :- spaces(Y).

noun([c,a,r]).            verb([f,l,i,e,s]).
noun([p,l,a,n,e]).        verb([d,r,i,v,e,s]).

Parsing (using difference lists)

?- myphrase([t,h,e,’ ’,p,l,a,n,e,’ ’,f,l,i,e,s],[]). run example \longmapsto

myphrase(X,CV) :-
% Head of article is head of phrase, tail head of spaces
    article(X,CA), spaces(CA,CS1),
    noun(CS1,CN),  spaces(CN,CS2),
    verb(CS2,CV).


   
article([a|X],X).         spaces([' ' | X],X).
article([t,h,e|X],X).     spaces([' ' | Y],X) :- spaces(Y,X).

noun([c,a,r | X],X).      verb([f,l,i,e,s | X],X).
noun([p,l,a,n,e | X],X).  verb([d,r,i,v,e,s | X],X).

Parsing (same, using string syntax)

?- myphrase("the plane flies",[]).run example \longmapsto

myphrase(X,CV) :-
    % This clause does not change
    article(X,CA), spaces(CA,CS1),
    noun(CS1,CN),  spaces(CN,CS2),
    verb(CS2,CV).


% Here we use strings "..." 
article("a"   || X, X).   spaces(" " || X, X).
article("the" || X, X).   spaces(" " || Y, X) :- spaces(Y, X).

noun( "car"   || X, X).   verb( "flies" || X, X).
noun( "plane" || X, X).   verb( "drives"|| X, X).

Parsing (same, using additional syntax: DCGs)

:- use_package(dcg).

myphrase --> article, spaces, noun, spaces, verb.




article --> "a".                spaces --> " ".
article --> "the".              spaces --> " ", spaces.

noun --> "car".                 verb --> "flies".
noun --> "plane".               verb --> "drives".

?- myphrase("the plane flies",[]).   or, use the “phrase/2” builtin:
?- phrase(myphrase,"the plane flies").

Parsing (same, using additional syntax: DCGs)

:- use_package(dcg).

myphrase --> article, spaces, noun, spaces, verb.
% Translates to: myphrase(X,CV) :- article(X,CA),
% spaces(CA,CS1), noun(CS1,CN), spaces(CN,CS2), verb(CS2,CV).

%       v----- translates to: article( "a"   || X, X).
article --> "a".                spaces --> " ".
article --> "the".              spaces --> " ", spaces.

noun --> "car".                 verb --> "flies".
noun --> "plane".               verb --> "drives".

?- myphrase("the plane flies",[]).   or, use the “phrase/2” builtin:
?- phrase(myphrase,"the plane flies").

Parsing + actions (calling plain Prolog from DCGs)

Example: we add an additional argument to count number of characters parsed:

?- myphrase(NChars,"the plane flies",[]).
?- phrase(myphrase(N),"the plane flies").run example \longmapsto

:- use_package(dcg).

myphrase(N) --> article(AC), spaces(S1), noun(NC), spaces(S2),
                verb(VC), { N is AC + S1 + NC + S2 + VC}.

article(1) --> "a".        spaces(1) --> " ".
article(3) --> "the".      spaces(N) --> " ", spaces(N1), 

noun(3) --> "car".         verb(5) --> "flies".
noun(5) --> "plane".       verb(6) --> "drives".

Other issues in Prolog (see “The Art of Prolog” and Bibliography)

Some Typical Libraries in Prolog Systems

Arrays Assoc Attributes Heaps
Lists Term Utilities Ordset Queues
Random System Utilities Tree UGraphs
WGraphs Sockets Linda/Distribution Persistent DB
CLPB CLPQR CLPFD Objects
GCLA TclTk Tracing Chars I/O
Runtime Utilities Timeout Xrefs WWW
Java Interface ... ... ...

Some Additional Libraries and Extensions (Ciao)

Other systems may offer additional extensions. Some examples from Ciao:

Some Additional Libraries and Extensions (Ciao, Contd.)

Some Additional Libraries and Extensions (Ciao, Contd.)