Search code examples
prologswi-prologunsatisfiedlinkerrorgnu-prolog

Using (nb_)setarg/3 with gnu.prolog in Java


I'm currently trying to use prolog out of java using gnu.prolog (http://www.gnu.org/software/gnuprologjava/).

Thanks to the great help of CapelliC I now have a prolog program which works perfect for my purpose. The problem is that gnu.prolog does not support reverse/2 nor does it support nb_setarg/3. Java will throw an error:

Exception in thread "Game" java.lang.IllegalArgumentException: The goal is not currently active

It isn't a big issue to implement reverse/2 on my own but I have no idea how to replace nb_setarg/3 (setarg/3 also doesn't work)

Here is my prolog code:

findPath(_Limit, [Goal | Rest], Goal, Temp, Temp, [Goal | Rest]) :- !.

findPath(Limit, [A | Rest], Goal, Cost, Temp, Path) :-
    path(A,B,C),
    \+member(B, Rest),
    NewCosts is (Temp + C),
    NewCosts < Limit,
    findPath(Limit, [B, A | Rest], Goal, Cost, NewCosts, Path).

searchPath(Start, Goal, Path_to_goal) :-
    S = path_len([], 50),
    repeat,
    arg(2, S, Limit),
    (   findPath(Limit, [Start], Goal, Cost, 0, Path)
    ->  (   Cost < Limit
        ->  nb_setarg(1, S, Path),
        nb_setarg(2, S, Cost),
        fail
        )
    ;   true
    ),
    arg(1, S, Rev),
    reverse(Rev, Path_to_goal).

I tried to use JPL from SWI Prolog but I wasn't able to run it because of severel exceptions pointing out, that Eclipse wasn't able to find the library correctly. I always get one of the following Exceptions:

Exception in thread "main" java.lang.UnsatisfiedLinkError: no jpl in java.library.path


UnsatisfiedLinkError: D:\Program Files\Prolog\bin\jpl.dll: Can't find dependent libraries

SWI-Prolog: [FATAL ERROR:
    Could not find system resources]

Even after following this and this guide I wasn't able to resolve my problems. Neither on Windows (32bit) nor on Ubuntu (64bit).

Do you have an solutions for me how I can either get JPL running or how to be able to use nb_setarg/3? Up to now I spent one and a half days without any results. Quite frustrating...


Solution

  • I'm sorry, but my suggestion to use GProlog setarg as replacement for SWI-Prolog nb_setarg was wrong. Now I reworked the code in a simpler and (I hope) more effective way, working under any ISO Prolog.

    % this data is from original Prolog Dijkstra' algorithm implementation
    :- initialization( consult(salesman) ).
    
    :- dynamic(best_so_far/2).
    
    path(X,Y,Z) :- dist(X, Y, Z).
    path(X,Y,Z) :- dist(Y, X, Z).
    
    findPath([Goal | Rest], Goal, Temp, Temp, [Goal | Rest]) :-
        !.
    findPath([A | Rest], Goal, Cost, Temp, Path) :-
        path(A, B, C),
        \+ member(B, Rest),
        NewCost is Temp + C,
        best_so_far(Limit, _),
        NewCost < Limit,
        findPath([B, A | Rest], Goal, Cost, NewCost, Path).
    
    % ?- searchPath(aberdeen, glasgow, L, P).
    %
    searchPath(Start, Goal, BestLen, BestPath) :-
        retractall(best_so_far(_, _)),
        asserta(best_so_far(1000000, [])),
        findPath([Start], Goal, Cost, 0, Path),
        % if we get here, it's because a lower Cost exists
        retractall(best_so_far(_, _)),
        asserta(best_so_far(Cost, Path)),
        fail
        ;
        best_so_far(BestLen, BestPath).
    

    If you want to fasten a bit, there is a very simple heuristic that should be applicable: namely make findPath greedy, selecting first lower cost branchs. That can be done with setof+member...