1

現在、gnu.prolog ( http://www.gnu.org/software/gnuprologjava/ ) を使用して Java からプロローグを使用しようとしています。

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

JPLfromを使用しようとしまし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か? 今まで、結果が出ずに1日半過ごしました。かなりイライラ...

4

2 に答える 2

1

申し訳ありませんが、SWI-Prolog nb_setarg の代わりに GProlog 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

191から221へのパスがあることがはっきりとわかります。しかし、この結果 ( pathList: [221,191]) を返す代わりに、ゴーストが来た場所から逆方向に向かう完全に異なるパスを取得します。SWI PrologでクエリsearchPath(191,221, Distance, Path)を実行すると (即座に) 戻ります

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 に答える