2011-11-12 76 views
4

對於我的「聲明性語言」類,我們必須編寫一個解決七巧板拼圖的序言程序。 謎題由謎題點的座標列表標識。例如,puzzle(7,[(0,0),(8,0),(4,4)])是一個帶有標識符7的拼圖,代表一個三角形。「is/2」中沒有充分實例化的參數

這是我的(天真的)解決這個問題的方法。執行從調用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小時,似乎無法找到我的錯誤。 希望你們中的一個有時間看這個,讓我回到正確的方向。

在此先感謝!

+0

您可以簡化代碼以向我們展示與錯誤相關的部分嗎? – svick

+0

@svick完成。我刪除了所有不相關的謂詞。由於我稍微改變了自己的代碼,我也重新制定了我的問題。 – Mental

+1

如果問題仍然存在:我認爲你太多了。從你現在發佈的代碼中,我看不到任何明顯的。但是由於block/2和rotatePolygon/3謂詞缺失,我也無法自己追蹤它。它可能是後者的一個問題,因爲它的輸出是以translate/3輸入的。 – twinterer

回答

1

嘗試獲取帶有錯誤的堆棧跟蹤。一些Prolog系統在發生錯誤時顯示堆棧跟蹤:SWI Prolog,SICStus Prolog,Jekejeke Prolog。

你必須對你的Prolog系統做一點實驗。由於各種原因,堆棧tarce可能不會顯示。例如嘗試正常的諮詢而不是編譯。或嘗試調試模式,而不是正常執行。

如果Prolog系統在發生錯誤時自動進入調試程序,您也可能看不到堆棧跟蹤。但通常調試器會爲您提供顯示堆棧跟蹤的命令。典型的命令是:g代表目標(回溯)。

當您看到堆棧跟蹤時,可以更仔細地查明問題發生的位置。

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將幫助你縮短你的代碼。