Define predicate from following the rules Prolog - prolog

I'm new to Prolog and I would like to convert given rules to Prolog language.
I have to define a predicate p(X1, Y1, X2, Y2) ,where X1, Y1 are integers, and X2 and Y2 are obtained from X1, Y1 following these rules:
if Y1 ≤ 0 and |X1|≤−Y1 then X2 is X1 + 1 and Y2 is Y1
else if X1 > 0 and |Y1| < X1 then X2 is X1, and Y2 is Y1+1
else if Y1 > 0 and −Y1 < X1 ≤ Y1 then X2 is X1−1, and Y2 is Y1
else X2 is X1 and Y2 is Y1−1

I'll provide a steer, here is rule 1:
p(X1, Y1, X2, Y2) :-
Y1 =< 0,
abs(X1) =< -Y1,
% Cut, to prevent processing alternatives
!,
X2 is X1 + 1,
Y2 is Y1.
Sample output in swi-prolog:
?- p(-3, -5, X2, Y2).
X2 = -2,
Y2 = -5.

Related

Moving within a list, by giving the possible moves. Prolog

So I recently started to learn Prolog and I had a question regarding making a predicate which gives u all the possible solutions (next moves) as the current spot is given. The best example is a maze. So this is my data which tells me 'w = white' and 'b = black' within a 5x5 maze:
grid([ [w, w, w, b, w],
[b ,b, w, w, w],
[w, w, w, b, w],
[w, b, b, b, b],
[w, w, w, w, w] ]).
I also implemented a predicated called white/1, which tells me if the given spot in the maze is white:
white(X/Y) :-
grid(M),
nth1(X, M, Line),
nth1(Y, Line, w).
What I now want to do is make a predicate that gives me all the possible moves within the maze. For example if I query:
?- move(5/2, NextState).
NextState = 4/2 ;
NextState = 5/1 ;
NextState = 5/3 ;
No
This is my code, but it gives false and I know it's completely wrong, but I don't know how to implement such a predicate:
move(5/5, _).
move(X/Y, NextState) :-
white(X/Y),
X1 is X + 1,
X1 =< 5,
move(X1/Y, NextState),
Y1 is Y + 1,
Y1 =< 5,
move(X/Y1, NextState),
X2 is X - 1,
X2 >= 5,
move(X2/Y, NextState),
Y2 is Y - 1,
Y2 >= 0,
move(X/Y2, NextState).
If someone could help me, I would really appreciate it! :)
EDIT:
move(X/Y, _) :-
white(X/Y).
move(X/Y, X/Y) :-
X1 is X + 1,
move(X/Y, X1/Y);
X2 is X - 1,
move(X/Y, X2/Y);
Y1 is Y + 1,
move(X/Y, X/Y1);
Y2 is Y - 1,
move(X/Y, X/Y2).
If I query it gives me:
?- move(3/3, NextState).
true ;
NextState = 3/3 ;
NextState = 3/3 ;
NextState = 3/3 ;
NextState = 3/3 ;
move(X/Y, X1/Y1, Xm/Ym) :-
X1 is X + 1, Y1 = Y, X1 =< Xm;
X1 is X - 1, Y1 = Y, X1 > 0;
X1 = X, Y1 is Y + 1, Y1 =< Ym;
X1 = X, Y1 is Y - 1, Y1 > 0.
For each line in the above predicate we have a new direction. The Xm/Ym are bounds of the maze.
| ?- move(5/2, X, 5/5).
X = 4/2 ? ;
X = 5/3 ? ;
X = 5/1
yes
You can remove Xm/Ym as an argument and just put 5 in the body. Or you can define a new predicate
move1(Current, Next) :- move(Current, Next, 5/5)
Instead of disjunctions, we can also write multiple clauses.
move(X/Y, X1/Y) :- X1 is X + 1, X1 =< 5.
move(X/Y, X1/Y) :- X1 is X - 1, X1 > 0.
move(X/Y, X/Y1) :- Y1 is Y + 1, Y1 =< 5.
move(X/Y, X/Y1) :- Y1 is Y - 1, Y1 > 0.
Both are equivalent and this is even clearer.

Compute addition and subtraction of an arithmetic expression without 'is'

How can I find the result of an arithmetic expression composed of pluses and minuses without using 'is'?
For example, to find the result of 1+2+3+4-6, I do: X is 1+2+3+4-6 and I get: X = 4.
What I've tried so far:
eval(EXPR, EXPR) :-
integer(EXPR),
!.
eval(X+Y, RES) :-
eval(X, X1),
eval(Y, Y1),
plus(X1, Y1, RES).
eval(X-Y, RES) :-
eval(X, X1),
eval(Y, Y1),
Y2 = -Y1,
plus(X1, Y2, RES).
but when I try to compute an expression containing negative numbers, I get the error: `integer' expected, found `- number` (a compound).
How can I solve it?
Add plus(Y1,Y2,0) instead of Y2 = -Y1.
In the latter case, Y2 is a structure with functor - and Argument Y1, whereas in the former case, Y1 is a number.
Take Y1 = 3 for example. [Just for fun: try it with Y1 = -3]
?- Y1 = 3, Y2 = -Y1, Y2 =.. L.
Y1 = 3,
Y2 = - 3,
L = [-, 3].
?- Y1 = 3, plus(Y1,Y2,0), Y2 =.. L.
Y1 = 3,
Y2 = -3,
L = [-3].
However, Y2 is supposed to be an argument in the predicate plus/3, which does not allow structures as arguments.
Maybe you prefer this solution:
eval(X-Y, RES) :-
eval(X, X1),
eval(Y, Y1),
plus(Y1, RES, X1).

Flattened form in WAM

The WAM: A Tutorial Reconstruction states that a query, p(Z, h(Z,W), f(W)), needs to be flattened using the following principles:
That being said, the query flattened form is:
X3=h(X2, X5), X4=f(X5), X1=p(X2, X3, X4);
I am lost with the definition of external variable, consider the following:
p(Z, h(Y, a(K, C), b(W)), f(W)).
Is Y an external variable? How should be the flattened form for this? From my understanding this would be the construction:
X1 = p(X2, X3, X4)
X2 = Z
X3 = h(X5, X6, X7)
X4 = f(X8)
X5 = Y
X6 = a(X7, X8)
X7 = K
X8 = C
X9 = b(X5)
But I am not sure, starting at X4 I got confused, should I have assigned the h inner values first?
You have the order the wrong way around: You are building terms before you have built their arguments. The text says to build the arguments before you build the outer terms. For example, you must build a(K, C) before you can build h(..., a(K, C), ...), and you must build that before you can build p(..., h(..., a(K, C), ...), ...). Here is one legal order:
X7 = K
X8 = C
X6 = a(X7, X8)
X5 = Y
X9 = b(X5)
X2 = Z
X3 = h(X5, X6, X7)
X4 = f(X8)
X1 = p(X2, X3, X4)

Knight's tour in Prolog: Stack limit exceeded

After I tried to optimize the program using Warnsdorff's rule, the compiler started issuing Stack limit exceeded. All parts separately seem to work, but I have no idea how this could be optimized. I am writing a program on an old laptop with 32-bit windows, so I can’t increase the size of the stack manually, as it is written on the official website https://www.swi-prolog.org/FAQ/StackSizes.html.
knightpath(Board, [1 / 1 | Path]) :-
Jumps is Board * Board,
the_way(Jumps, [1 / 1 | Path]).
the_way(1, [X / Y]) : -
between(1, 5, X),
between(1, 5, Y).
the_way(Jumps, [X1 / Y1, X2 / Y2 | Path]) : -
Jumps1 is Jumps - 1,
the_way(Jumps1, [X2 / Y2 | Path]),
warnsdorff(X2 / Y2, Path, X1 / Y1).
jump(X1 / Y1, X2 / Y2) : -
((X1 is X2 + 2;
X1 is X2 - 2),
(Y1 is Y2 + 1;
Y1 is Y2 - 1);
(X1 is X2 + 1;
X1 is X2 - 1),
(Y1 is Y2 + 2;
Y1 is Y2 - 2)),
between(1, 5, X1),
between(1, 5, Y1).
warnsdorff(X1 / Y1, Path, X2 / Y2) :-
find_posible(X1 / Y1, Path, Pos),
find_best(_, [X1 / Y1 | Path], Pos, X2 / Y2).
find_best(N, Path, [X / Y], X / Y) : -
find_posible(X / Y, Path, Pos),
length(Pos, N).
find_best(N1, Path, [X / Y | List], X / Y) : -
find_best(N2, Path, List, _),
find_posible(X / Y, Path, Pos),
length(Pos, N1),
N1 < N2.
find_best(N2, Path, [X1 / Y1 | List], X2 / Y2) : -
find_best(N2, Path, List, X2 / Y2),
find_posible(X1 / Y1, Path, Pos),
length(Pos, N1),
N1 >= N2.
find_posible(X1 / Y1, Path, Pos) : -
findall(X2 / Y2, jump(X2 / Y2, X1 / Y1), All_tog),
filter_path(All_tog, Path, Pos).
filter_path([], _, []).
filter_path([X / Y | All_tog], Path, [X / Y | Pos]) : -
not(member(X / Y, Path)),
filter_path(All_tog, Path, Pos).
filter_path([X / Y | All_tog], Path, Pos) : -
member(X / Y, Path),
filter_path(All_tog, Path, Pos).
This is what the compiler produces
ERROR: Stack limit (0.5Gb) exceeded
ERROR: Stack sizes: local: 0.1Gb, global: 42.7Mb, trail: 0Kb
ERROR: Stack depth: 1,863,822, last-call: 0%, Choice points: 3
ERROR: In:
ERROR: [1,863,822] user:the_way(-1863788, [length:1|_22365890])
ERROR: [1,863,821] user:the_way(-1863787, '<garbage_collected>')
ERROR: [1,863,820] user:the_way(-1863786, '<garbage_collected>')
ERROR: [1,863,819] user:the_way(-1863785, '<garbage_collected>')
ERROR: [1,863,818] user:the_way(-1863784, '<garbage_collected>')
The traceback already shows what is wrong: the the_way is called with:
[1,863,822] user:the_way(-1863788, [length:1|_22365890])
This thus means that the Jumps variable is -1863788. You did not perform proper checking in your recursion to avoid making paths longer than the threshold. You should add a constraint like:
the_way(1, [X / Y]) : -
between(1, 5, X),
between(1, 5, Y).
the_way(Jumps, [X1 / Y1, X2 / Y2 | Path]) : -
Jumps > 1,
Jumps1 is Jumps - 1,
the_way(Jumps1, [X2 / Y2 | Path]),
warnsdorff(X2 / Y2, Path, X1 / Y1).
The problem was that Warnsdorff's rule does not provide a solution for the case where the first (last in terms of the stack) square is 1/1. I have to write
knightpath(Answ) :-
Jumps is Board * Board,
the_way(Jumps, Path),
reverse(Path, Answ).
...
the_way(1, [1/1]).
By the way, if I write, as advised by Willem Van Onsem https://stackoverflow.com/a/57348007/11779964, then error can be avoided, and the compiler will simply output 'false'.

Creating a matrix from the coefficients of equations

Given the equations
eqn1 = 5 x1 + 2 x2 + 3 x3 == 8
eqn2 = 4 x1 + 7 x2 + 9 x3 == 5
eqn3 = 6 x1 + x2 + 9 x3 == 2
how do I extract the coefficients of x1, x2, x3 to form a matrix?
I tried using CoefficientArrays but the output was given as a SparseArray.
Try Normal
(Normal[CoefficientArrays[{eqn1, eqn2, eqn3}, {x1, x2, x3}]][[2]]) // MatrixForm
I am not fond of Normal
Coefficient[# /. Equal[e_, _] -> e, {x1, x2, x3}] & /# {eqn1, eqn2, eqn3}
Shorter but not as clear:
Coefficient[First##, {x1, x2, x3}] & /# {eqn1, eqn2, eqn3}

Resources