4

私の「宣言型言語」クラスでは、タングラム パズルを解くプロローグ プログラムを作成する必要があります。パズルは、パズルのポイントの座標のリストによって識別されます。たとえば、puzzle(7,[(0,0),(8,0),(4,4)])は識別子 7 のパズルで、三角形を表します。

これを解決する私の(素朴な)方法は次のとおりです。実行は を呼び出すことから始まりtangram(Puzzle, Puts)ます。プログラムは、パズルのすべての可能なピースから始まります。次に、ピースを選び、位置と回転を試して、パズルの有効な位置が得られたら、パズルを配置します。(= プログラムの最後に返される Puts リストにブロックを配置します。) これらすべての可能性をバックトラックします。コードは次のとおりです。

    %Harm De Weirdt
%3e Bachelor Informatica
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%        MAIN PROGRAM         %%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%    
%All possible rotations of a piece.
angle(0).
angle(90).
angle(180).
angle(270).

%Puzzle is a list of the coordinates of the corners of the puzzle to be solved.
%Puts is a list of 7 elements indicating how each piece should be placed in order to solve the puzzle.
tangram(Puzzle, Puts):-
    findall(block(BlockId, PointList), block(BlockId, PointList), PossiblePieces),
    placePieces(PossiblePieces, Puts, Puzzle).

%placePieces(Pieces, Puts)
%Place all the puzzle pieces from Pieces on the puzzle.
%Puts is a list containing the position of all the pieces.
placePieces([], _,_).
placePieces([block(BlockId, PointList)|OtherPieces], Puts, Puzzle):-    
    between(0,8,X),
    between(0,6,Y),
    angle(Angle),
    allowedPosition(PointList, (X,Y), Angle, Puzzle, Puts),
    append(Puts, [put(BlockId, ((X,Y), Angle))], NewPuts),
    placePieces(OtherPieces, NewPuts, Puzzle),
    write(Puts).

allowedPosition(Block, (X,Y), Angle, Puzzle, Puts):-    
    rotatePolygon(Block, Angle, RotatedPolygon),
    translatePolygon(RotatedPolygon, (X,Y), TranslatedPolygon),
    insideFigure(TranslatedPolygon, Puzzle),
    noOverlap(TranslatedPolygon, Puts).

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%       EXTRA PREDICATES      %%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%   
%translate(Point, TranslationVector, TranslatedPoint)
%TranslatedPoint is the result of Translating Point with TranslationVector
translate((X, Y), (TX, TY), (RX, RY)):-
    RX is X + TX,
    RY is Y + TY.

%translatePolygon(Polygon, TranslationVector, TranslatedPolygon)
%Translates a Polygon, defined by a list of its Points, by  a given TranslationVector,
%resulting in the TranslatedPolygon
translatePolygon([], _Vector, []).
translatePolygon([(X,Y)|Rest], (TX, TY), TranslatedPolygon):-
    translatePolygon(Rest, (TX, TY), PartiallyTranslatedPolygon),
    translate((X, Y), (TX, TY), (NewX, NewY)),
    TranslatedPolygon = [(NewX, NewY)| PartiallyTranslatedPolygon].

考えられるパズル:

[(0,0),(4,0),(4,4),(0,4)]
[(3,0),(5,2),(5,4),(4,5),(2,5),(0,3)]
[(0,0),(6,0),(7,1),(7,3),(3,3)]

これを実行したときの問題は、次のエラーが発生することです。

 ERROR: is/2: Arguments are not sufficiently instantiated

トレースすると、Translate の TX 値と TY 値がインスタンス化されていないように見えます。さかのぼってみると、どういうわけか X と Y が placePieces 述語でインスタンス化されていないと思います。値が残っていない場合、述語は失敗するだけですよね?

コードを 5 時間以上調べていますが、間違いを見つけることができないようです。うまくいけば、あなたの1人がこれを見直して、私を正しい方向に戻す時間があることを願っています.

前もって感謝します!

4

2 に答える 2

3

算術演算に CLP(FD) 制約を使用するだけで、このエラーは解消されます。単に(is)/2制約に置き換えます(#=)/2:

:- use_module(library(clpfd)).

translate((X, Y), (TX, TY), (RX, RY)):-
    RX #= X + TX,
    RY #= Y + TY.

重要なことは、すべての方向(#=)/2で使用できることです。また、その引数に変数がまだ含まれている場合も同様です。

他のコメント:

  1. ペア(-)/2表すために使用することを検討してください。X-Y
  2. は、コードを短くするのmaplist/3に役立ちます。
于 2016-03-28T11:47:57.020 に答える
1

エラーのあるスタック トレースを取得してみてください。SWI Prolog、SICStus Prolog、Jekejeke Prolog などの一部の Prolog システムでは、エラーが発生したときにスタック トレースが表示されます。

Prolog システムで少し実験する必要があります。さまざまな理由で、スタック tarce が表示されない場合があります。たとえば、コンパイルの代わりに通常のコンサルトを試してください。または、通常の実行ではなく、デバッグ モードをオンにしてみてください。

また、エラーが発生したときに Prolog システムが自動的にデバッガーに入ると、スタック トレースが表示されない場合があります。ただし、多くの場合、デバッガーはスタック トレースを表示するコマンドを提供します。典型的なコマンドは次のとおりです: g ゴール (バックトレース)。

スタック トレースを見ると、問題が発生している場所をより正確に突き止めることができます。

于 2011-12-08T17:17:12.500 に答える