`is/2`中存在未充分实例化的参数。

4

我需要为我的“声明性语言”课程编写一个Prolog程序来解决七巧板难题。

一个难题由拼图点的坐标列表来确定。例如,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值未被实例化。回顾追踪,我认为在placePieces谓词中X和Y未被实例化。如果没有剩余的值,谓词会失败,对吗?

我已经看了五个小时以上的代码,但似乎找不到我的错误。希望你们中的一位有时间来检查一下,并将我带回正确的方向。

提前感谢!


你能简化代码,仅显示与错误相关的部分吗? - svick
@svick完成。我删除了所有不相关的谓词。由于我稍微改变了我的代码,我也重新表述了我的问题。 - HDW
1
如果问题仍然存在:我认为你删掉了太多。从你现在发布的代码中,我看不出任何明显的问题。但是我也无法自己尝试跟踪它,因为缺少block/2和rotatePolygon/3谓词。而且它可能是后者的问题,因为它的输出是translate/3中的输入。 - twinterer
2个回答

3
如果您只是使用CLP(FD)约束来进行算术运算,这个错误将会消失。只需用(#=)/2约束替换(is)/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 将帮助您缩短代码。

0

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

您需要对Prolog系统进行一些实验。由于各种原因,可能不会显示堆栈跟踪。例如,尝试使用普通的consult而不是compile。或者尝试打开调试模式而不是正常执行。

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

当您看到堆栈跟踪时,可以更精确地确定问题出现的位置。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接