1

我目前正在尝试使用 gnu.prolog (http://www.gnu.org/software/gnuprologjava/)从java中使用prolog。

感谢CapelliC的大力帮助,我现在有了一个非常适合我的目的的 prolog 程序。问题是 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/3setarg/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).

我尝试使用JPLfromSWI 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吗?到目前为止,我花了一天半的时间没有任何结果。相当令人沮丧...

4

2 回答 2

1

抱歉,我建议使用 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 来完成...

于 2013-04-05T17:56:36.507 回答
1

我要疯了……

正如我上面已经提到的,Java 中的 Prolog 和 SWI 中的 Prolog 之间存在一些差异。

我目前正在使用此代码:

% 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

您可以清楚地看到,有一条从191221的路径。但是,我没有返回这个结果 ( 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;
    }
于 2013-04-06T12:44:51.393 回答