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


Introduction
   I had bought the "PROLOG. Programming for Artificial Intelligence" book (written by Ivan Bratko, of course I bought the Russian translation, it was impossible in USSR to buy any original book in a bookstore) in 1989 but I read (and understood) it only in 2008 and I was amazed by the power and POTENTIAL POSSIBILITIES (!) 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), in other words the language makes computer to think (or some similar to that). 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 to use anything which is not presented in the mainstream of IT and (as I wrote on the start page) my main development language at present is Java. Because Java has now very powerful feature called "annotations" it opens for us very wide possibilities to make own metalanguages embedded into standard Java programms. Well, I developed own Java based prolog engine to use it as a meta-language and called it as PROL (a cut version of the PROLog title). The engine written to process prolog programs written in the Edinburgh Prolog style (it is incompatible with Turbo Prolog style or Visual 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 platform versions. Because the version is permanently reviewed, I don't publish the source codes but may be I'll make it in the future. You should understand and remember that it is just a small amateur project, I think it can be used for research and Prolog learning process but I don't recommend to use it in commercial projects (!).

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.  It is very often when I see as students ask questions on forums about Prolog+UI, the Prol is the easiest way to get all UI power of Java in Prolog.

How it works (in a few words)
    As you read above, the engine based on the java annotation mechanism, it is being used to define predicates and add prolog operators. The core of the prol engine work is the import com.igormaznitsa.prol.logic.ProlContext class which describes the context includes the 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 consultations 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 the Prol context as a library. I'd like to say that the JVM has very poor possibilities to work with very recursive stack calls (you should use -Xss option to increase stack memory for JVM) and there can be very strange cases when very deep stack work presented, I tried tests under Windows and Ubuntu and under Ubuntu the JVM works with more deep stack than under Windows XP, I think it depended on JVM implementation for each platform. The tail recursion is not implemented in the PROL. The predicate list of the  prol core libraries (which are placed in the engine jar) can be read via the link.

The embedded GUI micro-editor
    The library has small embedded UI based text 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 in Java. For instance, I show you how the SORT/2 predicate is implemented in the core library. As you can see you just need place @Predicate annotation before an implementing method (which has a Goal and TermStruct as arguments), pay your attention that it is very important to have such arguments in the implementing method.
    @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 more than one operator in your library, you should use the ProlOperators annotation placed before the library class declaration and then fill its "Operators" propertythe by Operator annotations for each 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 usage by a Java program to solve the well-known Eight Queen task. The source below describes the task and will print all possible solutions for the Eight Queen chess task (it will take only a few seconds but the task was unsolved a few hundred years before :)).
           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 strong multithread goal solving feature which can be used with predicates fork/1 and async/1, also you can wait the end of all executing parallel (for the main thread) threads with the  waitasync/0 predicate, the predicate should be used only in the main goal thread (!) because it is linked with the executor pool in the main context. Also there is the lock mechanism which can be used with lock/1, unlock/1 and trylock/1 predicates, they allow you to synchronize your threads just on atoms(!). You can see below an example of a multithreading application paints 3000000 color dots at the graphic form (on my notebook it takes about 80 sec, no so quickly I see), each thread paints own color dots, as you can see it is much more easy than to write similar application in Java or C++!
    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 for any kind! and for commercial projects too) without any restrictions, also it includes unit tests for the engine and you can use them as examples. You can download the archive via the direct link.

Change history
1.1.3
  • Engine: The PredicateSynonims annotation has been renamed to the correct english form and now it has the PredicateSynonyms name
  • Prol NotePad: minor improvements and bugfixing
  • Core library: the ifork/1 predicate has been added, it works like fork/1 but if there is any fail goal in the parallel goal list then all other goals will be interrupted
  • Graphics library: bindaction/2, removeallactions/0, removeaction/1 have been added, the predicates allow to register actions which can be called by a user through the form menu
1.1.2
  • Parser: fixed the float number parsing bug
  • Prol NotePad: fixed the non-asc file reading bug
  • Prol NotePad: usability improved
1.1.1
  • Refactoring, speed increased in two times
  • Bugfixing
  • More testing (97 unit tests)
  • !!/0 (local cut) added
  • tracing predicates were removed, now the engine includes TraceListener interface to trace goals
  • Now a goal works with direct data for speed so you have to be accurate with the Term data from a goal. To isolate data there is new class the IsolatedGoal.
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 initial version


Conclusion
    I can't say that the engine is "a new word" or the interpreter is very fast and optimally written (remember that it is being developed as a pet project) but it is one more way to use and research the Prolog language and link it to Java.
 

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