J2P simplify the invocation of the inference engine tuProlog (2P) from Java. The Prolog Description Language (IPL) permits to define interfaces for Prolog theories a stub generator can translate into Java classes. J2P creates Prolog theories Java wrappers and makes calls to Prolog predicates simple as invoking a Java method. Moreover J2P uses JavaBeans pattern in order to automatically traslate Java objects into Prolog predicates and viceversa using a marshaling and unmarshaling process which behaviour can be defined in the IPL definition file.

Downloads

Documentation

Abstract


Prolog is a logic programming language usually used to solve AI problems. In complex application is useful to mix imperative and logic programming, for example using Java for the user interface and Prolog for problem solving. For these pourposes, the aliCE group design tuProlog (2P) a lightweight prolog engine written in Java. It can be easly embedded inside Java applications. For example we can merge two list simply writing:
   import alice.tuprolog.*;

    public class Test2P {
        public static void main(String[] args) {
            Prolog engine = new Prolog();
            SolveInfo info = engine.solve("merge([10,15],[12],X).");
            Term t = info.getSolution();
            System.out.println(t); // X/[10,12,15]
        }
    }
The example show how it is possible to call Prolog engine in a very simple way. Althought 2P has different problems: calls to the Prolog engine must be formed as strings and must be valid Prolog predicate. So everyone wants to use the 2P engine needs to know the Prolog syntax as well. The second problem is about the result of the Prolog engine, the result is usually a Prolog term (a string) and developers has to translate terms into suitable Java Objects.
J2P try to solve these two main problems allowing developers to use Prolog legacy theories without any knowledges about the logic language. The idea behind J2P is to made a Prolog call simple as a Java method invocation. For example merging two List using the Prolog engine would be simple as:
   public class TestJ2P{
        public static void main(String[] args){
            List l1 = new List();
            l1.add(10);
            l1.add(15);
            List l2 = new List();
            l2.add(12);
            List l3 = Theory.merge(l1,l2);
            System.out.println(l3); // [10,12,15]
        }
    }
J2P acts as a stub generator that generates Java wrappers for Prolog theories and handle the marshialing and unmarshialing of Prolog terms translating Java Objects into Prolog terms and viceversa.

The IPL (Prolog Descripton Language) language


A Prolog theory might contains several predicate definition but usually developers can use only some of them. For this pourpose Prolog developers could define an interface for some predicate that says how the predicate works. For example the predicate append/3 (used in previous examples) could be defined in the sequent way:

    append({ing List},{ing List},{outg List})
where we say that this predicate get 2 (ground) Lists as input arguments and return a (ground) List as third argument. The language has the sequent syntax:

    predicate_name(({ing|outg|ing/outg type},)+ [{in|out|in/out type}])
Where:
ing: input parameter
outg: output parameter
ing/outg: input/output parameter
type: Java Object type

    predicate_name(({ing|outg|ing/outg type},| prolog_term)+ [{ing|outg|ing/outg tipo} | prolog_term] )
for example we can write: persona(id(0), ing String)

An Example


PROLOG THEOTY (file Theory.pl)
    append([],X,X).
    append([X|L1],L2,[X|L3]):-append(L1,L2,L3).
    pari(2).
    pari(X) :- X>0, X1 is X-1, dispari(X1).
    dispari(1).
    dispari(X) :- X>0, X1 is X-1, pari(X1).
IPL SPECIFICATION (file Theory.ipl)
    append({ing/outg java.util.List}, {ing/outg java.util.List}, {ing/outg java.util.List})

    pari({ing java.lang.Integer}) 
    dispari({outg java.lang.Integer})
Now we can generate the Java wrapper for the Theory simply writing:
 
    java -jar j2p.jar Theory.pl Theory.ipl
(you need the 2P jar in the same directory in order to run J2P, 2P jar can be found here)
The stub will generate a Java wrapper for the prolog theory, Theory.java.
  class J2PTest{
       public static void main(String[] args){
          List l3 = new ArrayList(); l3.add(1); l3.add(2);
          List l1 = new ArrayList(); l1.add(1);
          List l2 = Theory.append(l1,null,l3).ret1;

         boolean result = Theory.pari(10);
       }
    }

Custom Objects and JavaBeans


The IPL language allows to handle different kind of Objects: Lists, Strings and Numbers; but somethins in Prolog we use complex terms and we need a way to map any kind of such terms into Java Objects. This is made possible with the IPL language.
  [$]java_class:predicate_name([{in|out|in/out type property}](,{in|out|in/out type property})*)
In this way we can specify how to translate a Java Class into a Prolog term using the JavaBeans pattern. For example considering the class Person:
    class Person {
       String name = null;
       Integer age = null;
       String sex = null;

       public Person() {}

       public Person(String name, Integer age, String sex) {
          this.name = name;
          this.age = age;
         this.sex = sex;
       }

       public String getName() {return name;}
       public Integer getAge() {return age;}
       public String getSex() {return sex;}
    }
We can write the IPL definition as:
    Person: person({out String Name},{out Integer Age},{out String Sex})
This definition says how to translate a Person instance into a Prolog term, for example the instance p = new Person("Simone",24,"male") will be traslated into the Prolog term person('Simone',24,'male'). In this way we can use the class Person in Prolog calls and the J2P support take care about marshialing and unmarshialing of Objects/terms. Considering the sequent Prolog theory:
    person('melissa',19,'female').
    person('fabio',20,'male').
    female(person(X,Y,'female')) :- person(X,Y,'female').
    male(person(X,Y,'male')) :- person(X,Y,'male').
In the IPL file we can simply write:
    female(in/out Person)
    male(in/out Person)
and in the Java file use the Java Wrapper as:
    Person f = Theory.female(null).ret0;
    System.out.println("Name: "+f.getName()+" age: "+f.getAge());
or:
    Person m = new Person("Simone",19,"male"); 
    boolean result = Theory.female(m);
    System.out.println("Is " + m + " a female? " + result);
The character '$' is used in order to define beans can be handled as variables. For example we can create a JavaBean with some non-filled properties and then let the Prolog engine fill them. For example fefining the Person bean as:
    $Person: person({out String Name},{out Integer Age},{out String Sex})
The sequent Class structure will be automatically generated by the J2P stub generator (use the -c option e.g. java -jar j2p.jar -c Theory.pl Theory.ipl). In this way we have the possibility to fill Java Objects using Prolog, J2P takes care about everything and for example we can write:
    PersonaVar p = new PersonaVar();
    p.seName("melissa"); 
    p.setSex("female"); 
    p.setAge(new Variable());
    System.out.println("Name: " + p.getName() + 
    " Age: " + p.getAge());
    // Name: melissa Age: null
    Theory.female(p);
    System.out.println("Name: " + p.getName() + 
    " Age: " + p.getAge());
    // Name: melissa Age: 19

Beans Hierarchies


Now we have the ability to use each kind of Java Object (who respect the JavaBeans pattern) inside the Prolog engine and a way for translate every JavaBeans into a Prolog term and viceversa. Usually Prolog is useful in order to manage complex data structure such as trees. Trees are usually structured as hierarchal Java Objects and the IPL language must be extendend in order to handle this kind of data.
    hierarchy_root:[ [bean_definition] (,bean_definition)* ]
For example we can define a kind of list very closed to the Prolog concept of list ([H|T], in Prolog lists are defined in recorsvely way). For this pourpose we can define the VarList Class structured as showed in the figure. We can define this hierarchy using the IPL language as sequent:
    VarList: [ $NotEmptyList: list({in/out Object Head},{in/out VarList Tail}) | EmptyList: nil ]
That says: a VarList Object can be of two different types, a NotEmptyList (that is a variable term) or an EmptyList. A NotEmptyList object will be translated in the list/2 term, where the first value will be the Head propery and the second value the Tail propery. A EmptyList object will be translated in the nil Prolog term. For example we can define now a Prolog theory which uses the list/2 term, for example we can write down a predicate that returns a list with natural numbers:
    natural_list(list(H,T)) :- not var(T), !, natural_list(T).
    natural_list(list(H,list(N,_))) :- N is H + 1.
The predicate natural_list/1 starting for example from a list(1,X) term will generate the terms: list(1,list(2,X))), list(1,list(2,list(3,X)))), ... for each predicate call. Using J2P we can simply write this Java code in order to retrieve the results of Prolog computation:
    VarList list = new NotEmptyList();
    list.setHead(new Integer(1));
    list.setTail(new Variable());
    System.out.println(list);
    // [1|_]
    Theory1.natural_list(list);
    System.out.println(list);
    // [1,[2|_]]

A case study: Expressions


Now we have everything we need to treat complex problems, for example consider language parsers; usually parsers work on tree data structure called Abstract Syntax Tree (AST). Developers use the Visitor pattern in order to browse the tree structure but sometimes algorithms related to trees should be written in Prolog in a very clear and elegant way. Consider the sequent language definition (written for javacc) that allows to define expressions with the sum and times operator with respect of operators associativity.
    ASTStart Start() #Start : {}
    {
        Expression() { return jjtThis; }
    }
    void Expression() : {}
    {
        AdditiveExpression()
    }
    void AdditiveExpression() : {} 
    {
        ( MultiplicativeExpression() ("+" AdditiveExpression())? ) #AddExpression(>1) 
    }
    void MultiplicativeExpression() : {}
    {
        ( UnaryExpression() ("*" UnaryExpression())? ) #MulExpression(>1)
    }
    void UnaryExpression() : {}
    {
        "(" Expression() ")" | IntegerLiteral()
    }
    void IntegerLiteral() #IntegerLiteral : { Token t; }
    { 
        t = <INTEGER_LITERAL> { jjtThis.setValue(Integer.parseInt(t.image)); }
    }
JavaCC plus JJTree generate a class hierarchy as showed in the figure.
Now we define, in IPL, how to translate this Class structure in prolog terms.
    ASTExpression: [ $ASTAddExpression: sum({in/out ASTExpression Left}, {in/out ASTExpression Right}) 
                    | 
                     $ASTMulExpression: mul({in/out ASTExpression Left}, {in/out ASTExpression Right})
                    | 
                     $ASTIntegerLiteral: int({in/out java.lang.Integer Value})
                   ]
Some changes has to be made in the original JavaCC class hierarchy in order to have an exact match between the prolog term and Bean structure.
Where the setLeft and setRight operation could be written as:
    public void setLeft(ASTExpression value){
       this.jjtAddChild(value, 0);
    }

    public ASTExpression getLeft(){
       return (ASTExpression)this.jjtGetChild(0);
    }
Now we can write our Prolog theory in order to parse the AST. For example we can computate the value of the expression simply writing a prolog theory:
  eval(int(N1), N1).
    eval(sum(EXP1,EXP2), R) :- eval(EXP1, N1), eval(EXP2, N2), R is N1 + N2.
    eval(mul(EXP1,EXP2), R) :- eval(EXP1, N1), eval(EXP2, N2), R is N1 * N2.
and the realtive IPL definition as:
    eval({ing ASTExpression}, {outg java.lang.Integer})
In this way, starting from an expression we can generate an AST (using the JavaCC parser) and then call the Prolog engine passing the root node and get the result of the expression.
    String exp1 = "((2+3)+(3*(4+2)))*8";
    Exp parser = new Exp(new StringReader(exp1));
    ASTStart goal = parser.Start();
    ASTExpression exp = (ASTExpression) goal.jjtGetChild(0);
    Integer result = Theory.eval(exp).ret0;
    System.out.println("eval -> " + result);
    // eval -> 184
The source code of the example is available here.