GNU Prolog

Implementation of programming language Prolog

GNU Prolog is a free Prolog compiler developed by Daniel Diaz (ports to some platforms are contributed by other people).

GNU Prolog offers both native-code compiler and an interactive interpreter (top-level) with a debugger. The language implemented conforms to ISO Prolog standard, with efficient constraint solver over Finite Domains and a lot of other useful extensions.

The development of compiler called Calypso started in January 1996. In March 1999 Calypso (beta 7) was renamed to gprolog 0.9.0, and further development went under that name. Last release of the compiler was gprolog 1.3.1, released in February 2009.

Features

Prolog system:

  • conforms to the ISO standard for Prolog (floating point numbers, streams, dynamic code,…).
  • a lot of extensions: global variables, definite clause grammars (DCG), sockets interface, operating system interface,…
  • more than 300 Prolog built-in predicates.
  • Prolog debugger and a low-level WAM (Warren Abstract Machine) debugger.
  • line editing facility under the interactive interpreter with completion on atoms.
  • powerful bidirectional interface between Prolog and C.

Compiler:

  • native-code compiler producing stand alone executables.
  • simple command-line compiler accepting a wide variety of files: Prolog files, C files, WAM files, etc.
  • direct generation of assembly code 15 times faster than wamcc + gcc.
  • most of unused built-in predicates are not linked (to reduce the size of the executables).
  • compiled predicates (native-code) as fast as wamcc on average.
  • consulted predicates (byte-code) 5 times faster than wamcc.

Constraint solver:

  • very efficient FD (Finite Domains) solver (comparable to commercial solvers).
  • FD variables well integrated into the Prolog environment (full compatibility with Prolog variables and integers). No need for explicit FD declarations.
  • high-level constraints can be described in terms of simple primitives.
  • a lot of predefined constraints: arithmetic constraints, boolean constraints, symbolic constraints, reified constraints,…
  • several predefined enumeration heuristics.
  • the user can define his own new constraints.
  • more than 50 FD built-in constraints/predicates.

Supported systems

  • ix86 / GNU/Linux
  • ix86 / Win32 using Cygwin
  • ix86 / Win32 using MinGW
  • ix86 / Win32 using MSVC++
  • ix86 / SCO
  • ix86 / Solaris
  • ix86 / FreeBSD
  • ix86 / OpenBSD
  • ix86 / NetBSD
  • ix86 / Darwin (Mac OS X)
  • x86_64 / GNU/Linux
  • x86_64 / Solaris
  • PowerPC / GNU/Linux
  • PowerPC / Darwin (Mac OS X)
  • PowerPC / NetBSD
  • sparc / SunOS (4.1.3 or higher)
  • sparc / Solaris
  • sparc / NetBSD
  • alpha / GNU/Linux
  • alpha / OSF1
  • mips / irix

Examples:

Hello, World!:

Example for versions B-Prolog 7.4 #3, Poplog 15.5 (Prolog), gprolog 1.3.0, swipl 5.6.x

This example doesn’t need any facts or rules to be evaluated. The query is executed in interactive mode, and results in the following output:

Hello, World!
yes

First line is the actual output of write predicate, and second line is the result of query evaluation.

Note that replacing single-quotes with double-quotes makes Prolog output the string as an array of ASCII-codes of individual characters:

| ?- write("Hello, World!").
[72,101,108,108,111,44,32,87,111,114,108,100,33]

yes

write('Hello, World!'), nl.

Quadratic equation:

Example for versions gprolog 1.3.0

Conditional branching in Prolog is done via ; and , predicates, which correspond to “or” and “and” logical operations. Evaluation starts with first branch (for example, check for A being 0 in line 3); all predicates separated with , are evaluated in row; if all of them evaluate to true, the whole program evaluates to true as well (and further evaluation stops), otherwise the next branch is evaluated.

read_integer is GNU Prolog extension, other implementations don’t have this predicate built-in.

q :- write('A = '),
     read_integer(A),
     (   A = 0, write('Not a quadratic equation');
         write('B = '),
         read_integer(B),
         write('C = '),
         read_integer(C),
         D is B*B-4*A*C,
         (   D = 0, write('x = '), X is -B/2/A, write(X);
             D > 0, write('x1 = '), X1 is (-B+sqrt(D))/2/A, write(X1), nl, write('x2 = '), X2 is (-B-sqrt(D))/2/A, write(X2);
             R is -B/2/A, I is abs(sqrt(-D)/2/A), 
             write('x1 = ('), write(R), write(', '), write(I), write(')'), nl,
             write('x1 = ('), write(R), write(', -'), write(I), write(')')
         )
     ).

q.

Fibonacci numbers:

Example for versions B-Prolog 7.4 #3, gprolog 1.3.0, swipl 5.6.x

Once again, the example is almost identical to Poplog Prolog one, except for the syntax of compiling/consulting a file.

% fibonacci.pl
:- dynamic(stored/1).

memo(Goal) :-
    stored(Goal) -> true;
    Goal, assertz(stored(Goal)).

fib(1,1) :- !, write('1, ').
fib(2,1) :- !, write('1, ').
fib(N,F) :-
    N1 is N-1, memo(fib(N1,F1)), 
    N2 is N-2, memo(fib(N2,F2)), 
    F is F1 + F2,
    write(F), write(', ').

% interactive
[fibonacci].
fib(16,X), write('...'), nl.

Factorial:

Example for versions B-Prolog 7.4 #3, gprolog 1.3.0, swipl 5.6.x

Almost identical to Poplog Prolog example, except for the syntax of compiling a file (doesn’t have a - before file name). However, the results of execution depend on the implementation. SWI-Prolog handles large numbers just fine, while in GNU Prolog and B-Prolog 12! overflows the numeric data type, so all values after 11! are incorrect.

| ?- [fact].
compiling /home/nickolas/Desktop/progopedia/prolog/fact.pl for byte code…
/home/nickolas/Desktop/progopedia/prolog/fact.pl compiled, 3 lines read — 1372 bytes written, 5 ms

yes
| ?- fact(16,X).
0! = 1
1! = 1
2! = 2
3! = 6
4! = 24
5! = 120
6! = 720
7! = 5040
8! = 40320
9! = 362880
10! = 3628800
11! = 39916800
12! = -57869312
13! = -215430144
14! = 205203456
15! = -143173632
16! = -143294464

X = -143294464 ?`

% fact.pl
fact(X, F) :- 
    ( X=0, F=1; 
      Y is X-1, fact(Y, Z), F is X*Z), 
    write(X), write('! = '), write(F), nl.

% interactive
[fact].
fact(16,X).

Quadratic equation:

Example for versions B-Prolog 7.4, gprolog 1.3.0, swipl 5.6.x

This is an ISO Prolog example, using standard read/1 predicate for reading input. Note that when using read/1, you have to put full stop . after each value you input.

q :- write('A = '),
     read(A),
     (   A = 0, write('Not a quadratic equation');
         write('B = '),
         read(B),
         write('C = '),
         read(C),
         D is B*B-4*A*C,
         (   D = 0, write('x = '), X is -B/2/A, write(X);
             D > 0, write('x1 = '), X1 is (-B+sqrt(D))/2/A, write(X1), nl, write('x2 = '), X2 is (-B-sqrt(D))/2/A, write(X2);
             R is -B/2/A, I is abs(sqrt(-D)/2/A), 
             write('x1 = ('), write(R), write(', '), write(I), write(')'), nl,
             write('x1 = ('), write(R), write(', -'), write(I), write(')')
         )
     ).