在`is / 2`中没有充分实例化的参数

时间:2011-11-12 19:23:17

标签: prolog clpfd instantiation-error

对于我的“陈述语言”课程,我们必须编写一个解决七巧板拼图的序言程序。 通过拼图点的坐标列表来识别拼图。例如,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个小时,似乎无法找到我的错误。 希望你们中的一个人有时间来看看这个并让我朝着正确的方向前进。

提前致谢!

2 个答案:

答案 0 :(得分:3)

如果您只是使用CLP(FD)约束进行算术,则此错误将消失。只需使用约束(is)/2替换(#=)/2

:- use_module(library(clpfd)).

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

重要的是,(#=)/2可以在所有方向上使用 ,如果变量仍然出现在其参数中,也可以使用。{/ p>

其他评论:

  1. 考虑使用(-)/2来表示,即X-Y等。
  2. maplist/3将帮助您缩短代码。

答案 1 :(得分:1)

尝试使用错误获取堆栈跟踪。发生错误时,一些Prolog系统显示堆栈跟踪:SWI Prolog,SICStus Prolog,Jekejeke Prolog。

你必须对Prolog系统进行一些实验。由于各种原因,堆栈可能不会显示。例如,尝试普通的咨询而不是编译。或者尝试打开调试模式而不是正常执行。

如果Prolog系统在发生错误时自动进入调试器,您可能也看不到堆栈跟踪。但通常调试器会为您提供显示堆栈跟踪的命令。典型的命令是:g for goals(backtrace)。

当您看到堆栈跟踪时,您可以更紧密地确定问题发生的位置。