PROL
PROL Logo
An Embeddable Java Prolog Engine
(the current version 1.0.5)


Introduction
   I had bought the "PROLOG. Programming for Artificial Intelligence" book (written by Ivan Bratko) in 1989 but I read (and understood) it only in 2008 and I was amazed by the power of the language. It allows not only to write programs but include a computer into the process (of course it increases the complexity of the program development because you have to explain a program for the computer). Because I think that Prolog is very powerful (may be it is most powerful) computer language  It was very  interesting for me to use it in my developments but as you see it is very hardly today use anything which is not in mainstream of computer technologies and as I wrote on the start page, my main development language at present is Java. Because Java has now very powerful mechanism called "annotations" it opens for us very wide possibilities to make own metalanguages which will help us to develop software in other ways than it  dictates by imperative languages. Well, I developed own Java based prolog engine to use it as a meta-language and called it as PROL (cutted version of PROLog). The engine written to process prolog programms written in the Edinburgh Prolog style but not in the Turbo Prolog style. Of course you can say me that there are a lot of implementations of Prolog engine (and for Java too) already but I developed it to understand Prolog more precisily and to learn  its  basis (and to check my some ideas in the Prolog). It has been written in Java 1.6 and can't be used with early Java versions. Because the version is permanently reviewed, I don't publish the source codes but may be I'll make it in the future. May be the main useful thing which can be used in Java, it is the possibility to attach a Java object to a Prol Term and the object moves inside a Prol engine without change  as associated with the term-owner. You should understand and remember that it is just a small amateur project.

prol structure
    Because the engine works over the Java core, it can use all power of the Java technology and it does, as an example the Prol Graphics Library works over the Java Swing Layer and the  multithreading support based on the Java concurrence and threading frameworks. 

How it works (in some words)
    As you see from the introduction, the engine based on the java annotation mechanism, it is used to define predicates and can be used to add prolog operators. The core of the prol engine work is the import com.igormaznitsa.prol.logic.ProlContext class which describes the context includes and a knowledge base. To make context you need an instance of a class which implements the com.igormaznitsa.prol.io.ProlStreamManager interface but as well you can use the default class DefaultProlStreamManagerImpl implements that interface. Then you can make consultation with an instance of  the com.igormaznitsa.prol.parser.ProlConsult class and the engine has been prepared for work. You can give goals to the engine with an instance of the com.igormaznitsa.prol.logic.Goal class and solve them with the solve() method of the class. If you want to make Java implementations of prolog predicates, you need to make own class extends  the abstract class com.igormaznitsa.prol.libraries.ProlAbstractLibrary and just to add it to a context which should use your library. I'd like to say that the JVM has not been written to work with very very deep stacks and I have very strange cases in the deep stack work (as well it is needed to use -Xss to increase the stack depth in Java), under Linux (Ubuntu) the JVM works with more deep stack than under Windows XP. The tail recursion is not implemented in the engine. The predicate list of the  prol core libraries (which are placed in the engine jar) can be read through the link.

The embedded GUI micro-editor
    The library has embedded small GUI editor allows to edit and start Prol scripts. The editor has four windows and you can make dialog between the user and the script with it. May be it would be useful for beginners to research the Prolog and write small test applications.
Prol pad GUI

A Few examples
   It is very easy to describe a predicate. As an example I show you how is implemented the SORT/2 predicate in the core library. As you can see you just need place @Predicate annotation before a function (which has a Goal and TermStruct as arguments).
    @Predicate(Signature = "sort/2", Template = {"+list,?list"},Reference="True if Sorted can be unified with a list holding the elements  of List, sorted to the standard order of terms")
    @Determined
    public static final boolean predicateSORT(final Goal goal, final TermStruct predicate) {
        final Term nonsorted = Utils.getTermFromElement(predicate.getElement(0));
        final Term sorted = Utils.getTermFromElement(predicate.getElement(1));
        final Term[] bufferarray = Utils.listToArray((TermList) nonsorted);
        Arrays.sort(bufferarray, Utils.TERM_COMPARATOR);
        final TermList sortedList = Utils.arrayToList(bufferarray);
        return sorted.Equ(sortedList);
    }

If you want to define some operators in your library, you need use a ProlOperators annotation placed before the library class declaration and fill the annotation array with Operator annotations for every operator.
@ProlOperators(Operators = {
    @ProlOperator(Priority = 700, Type = Operator.OPTYPE_XFX, Name = "is"),
    @ProlOperator(Priority = 700, Type = Operator.OPTYPE_XFX, Name = "="),
    @ProlOperator(Priority = 1000, Type = Operator.OPTYPE_XFY, Name = ","),
    @ProlOperator(Priority = 1050, Type = Operator.OPTYPE_XFY, Name = "->"),
....
    @ProlOperator(Priority = 300, Type = Operator.OPTYPE_XFX, Name = "mod"),
    @ProlOperator(Priority = 200, Type = Operator.OPTYPE_FY, Name = "\\"),
    @ProlOperator(Priority = 200, Type = Operator.OPTYPE_XFX, Name = "**")
})
public class ProlCoreLibrary extends ProlAbstractLibrary {
...


   Below you can see the source shows possibilities of the engine use in a Java program and show you the example which solves the Eight Queen task. The source below describes the task and will find all solutions for the Eight Queen chess task and print them.
           final ProlContext context = new ProlContext("test",DefaultProlStreamManagerImpl.getInstance());
           final ProlConsult consult = new ProlConsult("solution([]). solution([X/Y|Others]):-solution(Others),member(Y,[1,2,3,4,5,6,7,8]),notattack(X/Y,Others). notattack(_,[]). notattack(X/Y,[X1/Y1 | Others]):- Y=\\=Y1, Y1-Y=\\=X1-X, Y1-Y=\\=X-X1, notattack(X/Y,Others). member(Item,[Item|Rest]). member(Item,[First|Rest]):-member(Item,Rest). template([1/Y1,2/Y2,3/Y3,4/Y4,5/Y5,6/Y6,7/Y7,8/Y8]).", context);
            consult.consult();

            final Goal goal = new Goal("template(X),solution(X).", context);
            int combinatioCounter = 0;

            while (true) {
                final Term result = goal.solve();
                if (result == null) {
                    break;
                }
                Utils.printTermState(result);
            }

The multithreading support
    The engine supports multithread goal solving through predicates fork/1 and async/1, also you can wait the end of all started  parallel (for the main one) threads (started with fork/1 and async/1) with the  waitasync/0 predicate, so the predicate has to be used only from the main goal thread. There is the lock mechanism which can be used through lock/1, unlock/1 and trylock/1 predicates. The example of the multithreading use you can see below, the example paints 3000000 color dots at a graphic area (on my notebook it takes about 80 sec), dots for each color are painted from each separated thread for the color.
    threadRed(P) :- for(_, 0, P), rnd(500, X), rnd(400, Y), lock(gfx), pencolor(red), dot(X, Y), unlock(gfx), fail.
    threadGreen(P) :- for(_, 0, P), rnd(500,X), rnd(400, Y), lock(gfx), pencolor(green), dot(X, Y), unlock(gfx), fail.
    threadBlue(P) :- for(_, 0, P), rnd(500, X), rnd(400, Y), lock(gfx), pencolor(blue), dot(X,Y), unlock(gfx), fail.

    ?- P = 1000000, time((graphics(500,400), fork([threadRed(P), threadGreen(P), threadBlue(P)]))).

Download

    You can download the archive contains the JavaDoc for the engine, examples and the compiled JAR of the library. The library can be used and distributed in any kind of projects (free, commercial and other) without any restrictions. You can download the archive through the direct link.

Change history
1.0.5
  • Bugfixing
  • The trigger mechanism was added (it can be used with the regtrigger/3 predicate)
  • Corrected the assert/1 alias, now it is the alias for assertz/1
1.0.4
  • Bugfixing
  • The 'rules/1' predicate added (it allows get only rules from a knowledge base)
  • The multithreading support added: 'lock/1', 'unlock/1', 'trylock/1', 'fork/1', 'async/1', 'waitasync/0'
1.0.3
  • Bugfixing
  • The 'facts/1' predicate added (it allows get only facts from a knowledge base)
  • The PreparedGoal class added
1.0.2
  • Minor bugfixing
1.0.1
  • Bugfixing
  • The core prol library was exapnded with new predicates
  • String and graphic prol libraries were added
  • A small notepad to edit and execute prol scripts was embedded into the jar
1.0.0a
  • The initing version


Conclusion
    I can't say that the engine is "a new word" or the interpreter is very fast and optimally written (it is developed as a home project) but it is one more way to use the Prolog language from Java, it can be very useful for different applications. The engine allows really make  easier the use of both Java and Prolog in the bounds of the same application.
 

© 2003-2010 Igor A. Maznitsa. All Rights reserved.