Използване на (nb_)setarg/3 с gnu.prolog в Java

В момента се опитвам да използвам prolog извън Java, използвайки gnu.prolog (http://www.gnu.org/software/gnuprologjava/).

Благодарение на голямата помощ на CapelliC вече имам пролог програма, която работи идеално за моята цел. Проблемът е, че gnu.prolog не поддържа reverse/2, нито поддържа nb_setarg/3. Java ще изведе грешка:

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

Не е голям проблем да внедря reverse/2 сам, но нямам представа как да заменя nb_setarg/3 (setarg/3 също не работи)

Ето моят пролог код:

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).

Опитах се да използвам JPL от SWI Prolog, но не можах да го стартирам поради сериозни изключения, които посочваха, че Eclipse не успя да намери библиотеката правилно. Винаги получавам едно от следните изключения:

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]

Дори след като следвате това и това ръководство Не можах да разреша проблемите си. Нито на Windows (32 бита), нито на Ubuntu (64 бита).

Имате ли решения за мен как мога да стартирам JPL или как да мога да използвам nb_setarg/3? До сега изкарах ден и половина без резултат. Доста разочароващо...


person Markus    schedule 05.04.2013    source източник
comment
Предполагам, че искате да използвате съоръжението за глобални променливи на GNU Prolog вместо SWI . Затова опитайте g_assign/2 и g_read/2 вместо това.   -  person Daniel Lyons    schedule 05.04.2013


Отговори (2)


Съжалявам, но предложението ми да използвам GProlog setarg като заместител на SWI-Prolog nb_setarg беше грешно. Сега преработих кода по по-прост и (надявам се) по-ефективен начин, работейки под всеки 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).

Ако искате да закрепите малко, има много проста евристика, която трябва да бъде приложима: а именно направете findPath алчен, избирайки първите клонове с по-ниска цена. Това може да се направи с setof+member...

person CapelliC    schedule 05.04.2013
comment
Дори ако retractall/1 е посочен в Ръководството на GNU-Prolog, което Daniel е свързал, той все още се проваля, когато става въпрос за тази команда. retract/1 обаче работи. Затова сега замених retractall с retract_all, докато retract_allима следната реализация: retract_all(Term):- retract(Term),fail. оттегли_всички(_). Сега кодът се изпълнява. Но изпълнението на този код в SWI Prolog връща резултат за 0,016 секунди. Изпълнението на абсолютно същия код в Java връща резултат за повече от 15 секунди... - person Markus; 06.04.2013
comment
Също така разбрах, че Java доставя различни резултати в даден момент!!! Моля, вижте отговора ми по-долу. - person Markus; 06.04.2013

Ще полудея с това...

Както вече споменах по-горе, има някои разлики между Prolog в Java и Prolog чрез SWI.

В момента използвам този код:

% this data is from original Prolog Dijkstra' algorithm implementation
:- dynamic(best_so_far/2).


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) :-
    retract_all(best_so_far(_, _)),
    asserta(best_so_far(50, [])),
    findPath([Start], Goal, Cost, 0, Path),
    % if we get here, it's because a lower Cost exists
    retract_all(best_so_far(_,_)),
    asserta(best_so_far(Cost, Path)),
    fail
    ;
    best_so_far(BestLen, BestPath).


retract_all(Term):-
    retract(Term),fail.
retract_all(_).

Искам резултат в SWI Prolog, ще получа отговор след 0,016 секунди. Java се нуждае от 15 секунди за същия резултат!

Освен това и още по-лошо: в даден момент gnu prolog дава напълно различен резултат.

Ето някои очертания на Java:

From 190 to 221
pathList: [221, 191, 190]
distance: 2

From 191 to 221
pathList: [221, 251, 252, 253, 223, 193, 194, 195, 196, 197, 198, 199, 169, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129, 128, 127, 126, 125, 124, 123, 122, 121, 151, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191]
distance: 43

From 190 to 221
pathList: [221, 191, 190]
distance: 2

Ясно се вижда, че има пътека от 191 до 221. Но вместо да върна този резултат (pathList: [221,191]), получавам съвсем различна пътека, водеща назад от мястото, където дойде призракът ми. Изпълнението на заявката searchPath(191,221, Distance, Path) в SWI Prolog (незабавно) връща

7 ?- searchPath(191,221, Cost, Path).
Cost = 1,
Path = [221, 191].

Още веднъж: използвам абсолютно същия код. Копирах и поставих го, за да се уверя. И предавам правилните аргументи (затова ги отпечатвам).

Наистина не знам как да ви благодаря (особено на CapelliC). Сигурен съм, че вече отделихте твърде много време за мен. Но определено съм на ръба на акъла

Редактиране: Мислех, че може да е полезно да видя моя Java код:

private int decideHunterMovement() {
        // term which contains the result of the prolog method
        VariableTerm pathTerm = new VariableTerm("Path");
        VariableTerm distanceTerm = new VariableTerm("Distance");
        Integer movement;
        List<IntegerTerm> pathList = new LinkedList<IntegerTerm>();

        // Create the arguments to the compound term which is the question
        IntegerTerm hunterPosition = new IntegerTerm(hunter.getPosition());
        IntegerTerm targetPosition = new IntegerTerm(pacman.getPosition()); // target for hunter is the pacman position

        long time= System.nanoTime ();
        Term[] arguments = { hunterPosition, targetPosition, distanceTerm, pathTerm};
        // Construct the question
        CompoundTerm goalTerm = new CompoundTerm(AtomTerm.get("searchPath"), arguments);
        // Execute the goal and return the return code.
        int rc;
        System.out.println("From " + hunterPosition + " to " + targetPosition);
        try{
            // Create the answer
            rc = interpreter.runOnce(goalTerm);
            time = (System.nanoTime () - time) / 1000 / 1000;
            System.out.println("Result in:" + time+ "ms");
            // If it succeeded.
            if (rc == PrologCode.SUCCESS || rc == PrologCode.SUCCESS_LAST){
                // Get hold of the actual Terms which the variable terms point to
                Term path = pathTerm.dereference();
                Term distance = distanceTerm.dereference();
                // Check it is valid
                if (path != null){
                    if (path instanceof CompoundTerm){
                        // convert CompoundTerm to a Java LinkedList
                        convertToList((CompoundTerm) path, pathList);
                        if(VERBOSE_MODE){
                            System.out.println("pathList: " + pathList);
                            System.out.println("distance: " + (IntegerTerm) distance + "\n");
                        }
                    }else{
                            throw new NoAnswerException("PROLOG ERROR: Answer is not a CompundTerm: (" + path + ")");
                    }
                }else{
                    throw new NoAnswerException("PROLOG ERROR: Answer null when it should not be null");
                }
            }else{
                throw new NoAnswerException("PROLOG ERROR: Goal failed");
            }
        } catch (NoAnswerException e) {
            e.printStackTrace();
        } catch (PrologException e1) {
            e1.printStackTrace();
        }

        movement = decideMovement(pathList);
        return movement;
    }
person Markus    schedule 06.04.2013
comment
Най-накрая успях да използвам JPL от SWI Prolog. С тази рамка всичко работи добре... - person Markus; 08.04.2013
comment
Създаването на такава среда може да бъде трудно, но това е възнаграждаваща стъпка в перспектива. - person CapelliC; 08.04.2013