Not enough argument instances in `is / 2`

For my Declarative Languages โ€‹โ€‹class, we have to write a prologue program that solves the mysteries of Tangram. The puzzle is identified by the list of coordinates of the puzzle points. For example, puzzle(7,[(0,0),(8,0),(4,4)]) is a puzzle with identifier 7 and is a triangle.

Here is my (naive) way to solve this. Execution begins with a call to tangram(Puzzle, Puts) . The program begins with all possible pieces of the puzzle. Then I select a piece, try the position and rotation, and if this gives the correct position for the puzzle, I place the puzzle. (= put the block on the Puts list, which will be returned at the end of the program.) I will return to these possibilities. Here is the code:

  %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]. 

Some possible puzzles:

 [(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)] 

The problem when I run this is that I get the following error:

  ERROR: is/2: Arguments are not sufficiently instantiated 

When tracing, it seems that somehow the TX and TY values โ€‹โ€‹are not created in the translation. Track backwards I think that X and Y are somehow not created at the placePieces predicate place. If there were no values โ€‹โ€‹left, the predicate simply failed, right?

I have been looking at my code for more than 5 hours and it seems I cannot find my error. I hope one of you has time to look at it and get me back in the right direction.

Thanks in advance!

+4
source share
2 answers

This error will disappear if you simply use CLP (FD) constraints for arithmetic. Just replace (is)/2 with the restriction (#=)/2 :

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

It is important to note that (#=)/2 can be used in all directions , also if the variables are still found in its arguments.

Other comments:

  • consider the use of (-)/2 to represent pairs , i.e. XY etc.
  • maplist/3 will help you shorten the code.
+3
source

Try to get a stack trace with an error. Some Prolog systems show a stack trace when an error occurs: SWI Prolog, SICStus Prolog, Jekejeke Prolog.

You need to experiment a bit with your Prolog system. For various reasons, the stack plate may not be displayed. For example, try performing a regular check instead of compiling. Or try debugging mode instead of normal execution.

You may also not see the stack trace if the Prolog system automatically enters the debugger when an error occurs. But often the debugger offers you a command to display the stack trace. Typical command: g for goals (backtrace).

When you see a stack trace, you can more accurately determine where the problem occurred.

+1
source

Source: https://habr.com/ru/post/1380941/


All Articles