Недостаточно аргументированные аргументы в `is / 2` - PullRequest
4 голосов
/ 12 ноября 2011

Для моего класса «Декларативные языки» мы должны написать прологическую программу, которая решает головоломки Tangram. Головоломка идентифицируется списком координат точек головоломки. Например, 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

При трассировке кажется, что каким-то образом значения TX и TY в Translate не создаются. Возвращаясь назад, я думаю, что каким-то образом X и Y не создаются в предикате placePieces. Если бы не осталось никаких значений, предикат просто потерпел бы ошибку, верно?

Я просматривал свой код более 5 часов и не могу найти свою ошибку. Надеюсь, у одного из вас есть время, чтобы посмотреть на это и вернуть меня в правильном направлении.

Заранее спасибо!

Ответы [ 2 ]

3 голосов
/ 28 марта 2016

Эта ошибка исчезнет, ​​если вы просто используете ограничения 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 поможет вам сократить код.
1 голос
/ 08 декабря 2011

Попробуйте получить трассировку стека с ошибкой. Некоторые системы Prolog показывают трассировку стека при возникновении ошибки: SWI Prolog, SICStus Prolog, Jekejeke Prolog.

Вы должны немного поэкспериментировать с вашей системой Prolog. По разным причинам tar в стеке может не отображаться. Например, попробуйте обычную консультацию вместо компиляции. Или попробуйте режим отладки вместо обычного выполнения.

Также вы можете не увидеть трассировку стека, если система Prolog автоматически запускает отладчик при возникновении ошибки. Но часто отладчик предлагает вам команду, чтобы показать трассировку стека. Типичная команда: g для целей (backtrace).

Когда вы видите трассировку стека, вы можете более точно определить местонахождение проблемы.

...