Tuesday, June 16, 2015

Day 18: A Day of Frustration and Installation - SWI Prolog and JPL

There are some days when you do absolutely nothing in lab but set up an environment. Because research scholars typically use highly random packages or developing ones, support for some of them is abysmal. So I thought if this post is to help even one other person save time, I'll be happy.

Prolog is a logic machine that I've been trying to connect with Java. SWI-Prolog comes with java support through the package JPL. But, setting it up proved to be a veritable nightmare.

And it was a nightmare even after these two very helpful tutorials here and here :P

So, here is my experience in setting up what at this time are the latest version of Prolog and JPL on Fedora 20.

Step #1 : Remove previous installations of SWI-Prolog

Some version incompatibilities lead to "Fatal Error: Could not find system resources". This is mentioned in one of the tutorials as the last step which I took the liberty of placing right on top! In Fedora, that was done using:

yum erase pl

Step #2 : Install dependencies

For JPL to access SWI Prolog, we need to compile from source. Hence, we need to manually install the dependencies first.

sudo yum install autoconf chrpath libunwind freetype-devel gmp-devel java-1.6.0-openjdk-devel jpackage-utils libICE-devel libjpeg-devel libSM-devel libX11-devel libXaw-devel libXext-devel libXft-devel libXinerama-devel libXmu-devel libXpm-devel libXrender-devel libXt-devel ncurses-devel openssl-devel pkgconfig readline-devel unixODBC-devel zlib-devel uuid-devel libarchive-devel

Step #3 : Download SWI - Prolog

The latest one is here. You need to download the source and extract into a folder.

tar xvf  swipl-7.2.1.tar.gz /usr/local/src/

Step #4 : Configure and Install

While configuring, it is important that it is done exactly as described with sharing enabled and prefix specified.

cd /usr/local/src/swipl-7.2.1
./configure --prefix=/usr/local/src/swipl-7.2.1 --enable-shared
make
make install

Step #5 : Check if SWI-Prolog is installed

Type swipl into the command prompt and see if you get "Welcome to SWI Prolog". I did not not get that message. So what I did was to check if it was working in the "bin" folder.

cd /usr/local/src/swipl-7.2.1/bin
./swipl

This worked fine for me.
Then, I copied it to usr/bin so that it can be accessed from anywhere.

cp swipl /usr/bin/swipl

Step #6 : Configure and Install JPL

This step is very simple. It develops the jpl.jar that is required for the Java Bridge.

cd /usr/local/src/swipl-7.2.1/packages/jpl
./configure
make
make install

Step #7 : Set up environment variables

I did this through Eclipse. Right click on the Java file that you are going to use and choose "Run As" and then "Run Configuration". Under the environment tab, you need to add two variables.

LD_LIBRARY_PATH = /usr/local/src/swipl-7.2.1/lib/x86_64-linux
PATH = ... : /usr/local/src/swipl-7.2.1/packages/jpl

The first path points to libswipl.so and the next one to libjpl.so. You can set these up in command line as well.

Step #8 : Set up JVM arguments

JPL requires a JVM argument. While running, you need to specify this option. In Eclipse, in the same "Run Configuration" window, choose "Arguments" tab and type the following under VM arguments.

-Djava.library.path = /usr/local/src/swipl-7.2.1/packages/jpl
Otherwise, the error would be "java.lang.UnsatisfiedLinkError: no jpl in java.library.path".

Step #9 : The moment of truth :P

Make a file, "foo.pl" which has :

foo(a).
foo(b).

Create a Java file in the same folder with the following code :

import jpl.Compound;
import jpl.Query;
import jpl.Term;
import jpl.Variable;

public class PrologBridge {

public static void main(String[] args) {
Query q1 = new Query("consult('foo.pl')");
System.out.println( "consult " + (q1.hasSolution() ? "succeeded" : "failed"));
Query q2 = new Query("foo(a)");
Boolean resp= q2.hasSolution();
System.out.println("foo(a) is " + resp.toString());
Query q3 = new Query("foo(c)");
System.out.println("foo(c) is " + ( q3.hasSolution() ? "provable" : "not provable" ));
Query q4 = new Query(new Compound("foo", new Term[] { new Variable("X")}));
while (q4.hasMoreElements())
System.out.println(q4.nextElement());
}
}

It took me a lot of time to get the correct program as the ones given in both the documentation and the tutorials were not working. That is when Stack Overflow came to my rescue!

This was my output:

foo(a) is true
foo(c) is not provable
{X=a}
{X=b}

Happy Coding! :)