0

I want to create a Prolog program that can connect conveyor belts to ovens and an output belt. The program has the following facts:

factory(12,10).
oven((2,5),(4,5)). 
oven((7,5),(7,5)).
blocked(0,9).
blocked(3,1).
blocked(5,1).
blocked(4,9).
blocked(5,9). 

Where factory(X,Y) gives you the width of the factory (X) and the height (Y), oven((X,Y),(OutputX,OutputY)) gives you the x-y coordinates of the bottom leftcorner of the oven (each oven is of size 3 by 3) and their output coordinates (OutputX, OutputY), blocked(X,Y) represents a square in the factory that cannot contain an oven or a belt.

Then, given the following code pos_empty(X,Y) that returns whether a position can have a belt or not, create a term serveOven(Oven, Length, InBelts, Belts) that constructs a belt line from each starting belt in the list InBelts to the output coordinates of the Oven and that line can have a max length of Length. The code to check if a position is empty:

pos_empty(X,Y) :-
    \+(blocked(X,Y)),
    \+(has_oven(X,Y)).

has_oven(X,Y) :-
    oven((X1,Y1), _),
    X2 is X1 + 3,
    Y2 is Y1 + 3,
    between(X1, X2, X),
    between(Y1, Y2, Y).

The code I got is the following:

serveOven( oven(_, (OutX, OutY)), Length, InBelts, Belts) :-
findall(Belt, (member(InBelt, InBelts), make_belt(InBelt, OutX, OutY, Length, Belt)), Belts).

make_belt((X,Y), OutX, OutY, Length, [(X,Y) | Tail]) :-
pos_empty(X,Y),
(X = OutX, Y = OutY;
(X < OutX, NewX is X + 1, make_belt((NewX, Y), OutX, OutY, Length, Tail));
(X > OutX, NewX is X - 1, make_belt((NewX, Y), OutX, OutY, Length, Tail));
(Y < OutY, NewY is Y + 1, make_belt((X, NewY), OutX, OutY, Length, Tail));
(Y > OutY, NewY is Y - 1, make_belt((X, NewY), OutX, OutY, Length, Tail))),
length(Tail, Len),
Len < Length.

But this returns nothing. Can anybody help me? Thanks!

So, as said in the details: The code I got is the following:

serveOven( oven(_, (OutX, OutY)), Length, InBelts, Belts) :-
findall(Belt, (member(InBelt, InBelts), make_belt(InBelt, OutX, OutY, Length, Belt)), Belts).

make_belt((X,Y), OutX, OutY, Length, [(X,Y) | Tail]) :-
pos_empty(X,Y),
(X = OutX, Y = OutY;
(X < OutX, NewX is X + 1, make_belt((NewX, Y), OutX, OutY, Length, Tail));
(X > OutX, NewX is X - 1, make_belt((NewX, Y), OutX, OutY, Length, Tail));
(Y < OutY, NewY is Y + 1, make_belt((X, NewY), OutX, OutY, Length, Tail));
(Y > OutY, NewY is Y - 1, make_belt((X, NewY), OutX, OutY, Length, Tail))),
length(Tail, Len),
Len < Length.

When running the query serveOven(oven((2,5),(4,5)), 20, [(11,2)], Belts). this resulted in an empty list of Belts. Which should not happen.

Student CS
  • 53
  • 6
  • You can step through your program, to see exactly what is happening and where it is going wrong, using e.g. `trace.` - https://www.swi-prolog.org/pldoc/man?section=debugger – brebs Jan 14 '23 at 20:18
  • @brebs, I have been doing that, however, the trace is so long that I keep on getting lost where it is going wrong. I have even simplified the problem by leaving the length constraint out for now. It still does not return anything when it ends. – Student CS Jan 14 '23 at 20:51
  • So, add e.g. `writeln([X, Y]),` statements at relevant points, to show the variables. There is basically no way that you can state "I wrote this program but I cannot debug it." Just put more effort into debugging it. – brebs Jan 14 '23 at 21:55
  • 1
    @TessellatingHeckler, you are right. This should be `oven((2,5), (4,5))`. Thank you for the correction! Also, this should be bottom left, my mistake. – Student CS Jan 14 '23 at 23:14
  • There is absolutely no reason to write `oven((2,5), (4,5))`. What is preventing you from using `oven(2, 5, 4, 5)`? – TA_intern Jan 15 '23 at 09:06
  • @TA_intern, because that is how the facts are given. That is the data that you get, I did not come up with that notation. – Student CS Jan 15 '23 at 17:28

0 Answers0