Prolog verify predicates in a loop - prolog

I have a some predicates inside the recursion verif(X1,Y1,F). The first predicate is gen(X1,Y1,X2,Y2) which receives X1 and Y1 and generates the numbers X2 and Y2. The other predicates are the ones that I want to verify. If one of this predicates returns F=1 the loop should be restarted with verif(X2,Y2,F), but I dont know how to do this. If all the predicates return F=0 the recursion ends.
Here is the example:
verif(X1,Y1,0).
verif(X1,Y1,F):-
gen(X1,Y1,X2,Y2),
pred1(X2,Y2,A,B,F),
pred2(X2,Y2,C,D,F),
pred3(X2,Y2,E,G,F),
verif(X2,Y2,F).
The problem is when the 3 predicates return diferent values for F it will fail.
One way would be to use the predicate repeat until none of the predicates fails, but this way the predicate gen(X1, Y1, X2, Y2) would always generate the same X2 and Y2 because it would allways receive the same X1 and Y1.

I think you can use different variables, and then test the values
verif(X1,Y1,F):-
gen(X1,Y1,X2,Y2),
pred1(X2,Y2,A,B,F1),
pred2(X2,Y2,C,D,F2),
pred3(X2,Y2,E,G,F3),
(( F1 == 0, F2 == 0, F3 == 0 ) -> true ; verif(X2,Y2,F)).
or simpler
verif(X1,Y1,F):-
gen(X1,Y1,X2,Y2),
pred1(X2,Y2,A,B,F1),
pred2(X2,Y2,C,D,F2),
pred3(X2,Y2,E,G,F3),
(F1 + F3 + F3 =:= 0 -> true ; verif(X2,Y2,F)).

Related

How to test a predicate on a range of numbers and return those that pass in Prolog

I am trying to write a predicate in Prolog that will use my predicate 'PAR', which tests whether a 4 digit number meets certain conditions, but return a list of all numbers which are PARs, i.e. all numbers which return true when passed into par.
pars(A, C)
:- A =< 9999,
par(A) -> append(C, A, C),
A1 is A+1,
pars(A1, C).
This is my current code, with A initially passed in as 1000 (the smallest 4 digit number), but it will only return false when the first number is tried, or timeout if the first number is a PAR.
I also want the predicate to take only one argument, e.g. pars(X) where X is then the list of PARs.
par(A)
:- number_chars(A, [W,X,Y,Z]),
unique([W,X,Y,Z]),
atom_number(W, W1),
atom_number(X, X1),
atom_number(Y, Y1),
atom_number(Z, Z1),
B1 is W1 * 10 + X1,
B2 is Y1 * 10 + Z1,
0 is mod(B1,B2).
Here is my par predicate for reference, I know this is also probably very inefficient.
Any help would be appreciated, thanks in advance.
The easy way is to use a "solution-collecting" metapredicate, i.e. findall/3, bagof/3 or setof/3:
findall(P,(between(1000,9999,P),par(P)),Bag).
In this case the subgoal is between(1000,9999,P),par(P):
Generate a number P between 1000 and 9999
Test is for "par-ity"
If there is success of the above, it will be in the list Bag when findall/3 succeeds.
If there is failure of the above, the Prolog processor backtracks to the start of the subgoal and tries again, generating and testing the next number.
This can also be written more extensively (i.e. not "inlined"):
subgoal(P) :- between(1000,9999,P),par(P).
findthem(Bag) :- findall(P,subgoal(P),Bag).
(Testing this fails because I dont't have the definition of unique/1 as used in par/1.)

Accessing coefficients in a numerical expression (clpr)

I have some clauses where the head represents the names and values of a set of variables in a linear equation and the body the actual equation. Like so:
:-use_module(library(clpr)).
relation(
independents([
var(x1, X1),
var(x2, X2),
var(x3, X3)
]),
dependent(
var(y, Y)
)
):- {Y = 3 + 0.5 * X1 + 0.6 * X2 + 0.7 * X3}.
Is there a straightforward way to (indirectly) get the coefficients for this equation? I.e. a rule which returns coefficient(VARNAME, COEFFICIENT) e.g. coefficient(x1, 0.5), coefficient(x2, 0.6) and so on.
I know this might seem like a stupid question given that it would be easy to just put all coefficients in the head of the clause. But in my application i want the head of these clauses to strictly show the values of each variable (and not their coefficients). I.e. to avoid ambiguity.
My current solution is a convoluted and unelegant one involving member/2, subtract/3, maplist/2 and setting X1, X2, X3 to one or zero to figure out each slope.
Related question:
Representing linear functions in prolog
Thanks!
/JC
This is my first use of clpr so if this is unhelpful to you I plead insanity, but to me, the key here seems to be using dump/3 to convert the constraint back into a Prolog expression and then traversing it like any other structure. So I obtain the constraint again by doing this:
?- relation(independents([var(x1,X1),var(x2,X2),var(x3,X3)]),
dependent(var(y,Y))),
dump([X1,X2,X3,Y],[x1,x2,x3,y], [y=Eqn]).
Eqn = 3.0+0.5*x1+0.6*x2+0.7*x3
I think it's worth remembering what this looks like under the hood using write_canonical:
+(+(+(3.0,*(0.5,x1)),*(0.6,x2)),*(0.7,x3))
Traversing a polynomial you should be covered by only a few simple cases; the following may actually be overkill:
coefficient(X=Y, Var, Coeff) :-
coefficient(X, Var, Coeff) ; coefficient(Y, Var, Coeff).
coefficient(X+Y, Var, Coeff) :-
coefficient(X, Var, Coeff) ; coefficient(Y, Var, Coeff).
coefficient(X-Y, Var, Coeff) :-
coefficient(X, Var, Coeff) ; coefficient(Y, Var, Coeff).
coefficient(X*Y, X, Y) :-
atomic(X), atomic(Y).
coefficient(X*Y, Var, Coeff) :-
coefficient(X, Var, Coeff) ; coefficient(Y, Var, Coeff).
Your base case really is the X*Y case where they are both atomic. The rest of the clauses are really just there to unwrap nesting. This appears to do what you want:
?- relation(independents([var(x1,X1),var(x2,X2),var(x3,X3)]),
dependent(var(y,Y))),
dump([X1,X2,X3,Y],[x1,x2,x3,y], [y=Eqn]),
coefficient(Eqn, Var, Coeff).
Eqn = 3.0+0.5*x1+0.6*x2+0.7*x3,
Var = 0.5,
Coeff = x1,
{Y=3.0+0.5*X1+0.6*X2+0.7*X3} ;
Eqn = 3.0+0.5*x1+0.6*x2+0.7*x3,
Var = 0.6,
Coeff = x2,
{Y=3.0+0.5*X1+0.6*X2+0.7*X3} ;
Eqn = 3.0+0.5*x1+0.6*x2+0.7*x3,
Var = 0.7,
Coeff = x3,
{Y=3.0+0.5*X1+0.6*X2+0.7*X3} ;
false.
To really generalize this you probably will need to use maplist et. al. to convert your independents/dependents lists into the variables you will need to pass to dump/3 and then handle the case where you have multiple equations in the result, but I don't think this will be very challenging for you.
Hope this helps!

Prolog - findall returns a list of uninstantiated variables rahter than values

I am writing a Checkers game in Prolog, and I want to write a predicate to print all possible moves.
I have a predicate who checks all the legal moves than can be made -
is_move_legal(Board,p(X1,Y1),p(X2,Y2),DoEat, Player):-
Player = w, % making sure the "right" player is playing here - white
get(Board,p(X1,Y1),w),
(
get(Board,p(X2,Y2),1); % make sure no player is in the dest cell
get(Board,p(X2,Y2),0) % make sure no player is in the dest cell
),
between(1,8,X1),between(1,8,X2),between(1,8,Y1),between(1,8,Y2),
(
(DoEat = 0, X2 is X1-1,Y2 is Y1-1); % we don't eat
(DoEat = 0, X2 is X1-1,Y2 is Y1+1);
(DoEat = 1, X2 is X1-2, Y2 is Y1-2, X3 is X1-1, Y3 is Y1-1, (get(Board,p(X3,Y3),b);get(Board,p(X3,Y3),bk)),remove(Board,p(X3,Y3))); % eat the black soldier
(DoEat = 1, X2 is X1-2, Y2 is Y1+2, X3 is X1-1, Y3 is Y1+1, (get(Board,p(X3,Y3),b);get(Board,p(X3,Y3),bk)),remove(Board,p(X3,Y3))) % eat the black soldier
).
I have similair predicates for the black soldiers and for "kings" soldiers.
This is the findall predicate -
% find all possible moves
moves(Board,Moves):-
findall((X->Y),is_move_legal(Board,P1,P2,_,b),Moves).
It seems that it does find the moves, however this it the output I get -
[(_8090->_8092),(_8078->_8080),(_8066->_8068),(_8054->_8056),(_8042->_8044),(_8030->_8032),(_8018->_8020),(_8006->_8008)]
What I am trying to do, is to satisfy the p(X1,Y1), p(X2,Y2) arguments in the is_move_legal predicate.
EDIT:
From a comment here I realized the mistake -Rather then (X->Y), write -
findall((P1->P2),is_move_legal(Board,P1,P2,_,b),Moves).
Your help is much appreciated.
Thank you!

How does the power function work

This is My First Logic Programming Language course so this is a really Dumb Question But I cannot for the life of me figure out how does this power predicate work I've tried making a search tree to trace it But I still cannot understand how is it working
mult(_ , 0 ,0).
mult(X , Y, Z):-
Y > 0,
Y1 is Y - 1,
mult(X,Y1,Z1),
Z is Z1 + X.
exp2(_ ,0 , 1).
exp2(X,Y,Z):-
Y > 0,
Y1 is Y - 1,
exp2(X , Y1 , Z1),
mult(X,Z1,Z).
I so far get that I'm going to call the exp2 predicate till I reach the point where the Y is going to be Zero then I'm going to start multiplying from there, but At the last call when it's at exp2(2 , 1 , Z) what is the Z value and how does the predicate work from there?
Thank you very much =)
EDIT: I'm really sorry for the Late reply I had some problems and couldn't access my PC
I'll walk through mult/3 in more detail here, but I'll leave exp2/3 to you as an exercise. It's similar..
As I mentioned in my comment, you want to read a Prolog predicate as a rule.
mult(_ , 0 ,0).
This rule says 0 is the result of multiplying anything (_) by 0. The variable _ is an anonymous variable, meaning it is not only a variable, but you don't care what its value is.
mult(X, Y, Z) :-
This says, Z is the result of multiplying X by Y if....
Y > 0,
Establish that Y is greater than 0.
Y1 is Y - 1,
And that Y1 has the value of Y minus 1.
mult(X, Y1, Z1),
And that Z1 is the result of multiplying X by Y1.
Z is Z1 + X.
And Z is the value of Z1 plus X.
Or reading the mult(X, Y, Z) rule altogether:
Z is the result of multiplying X by Y if Y is greater than 0, and Y1 is Y-1, and Z1 is the result of multiplying X by Y1, and Z is the result of adding Z1 to X.
Now digging a little deeper, you can see this is a recursive definition, as in the multiplication of two numbers is being defined by another multiplication. But what is being multiplied is important. Mathematically, it's using the fact that x * y is equal to x * (y - 1) + x. So it keeps reducing the second multiplicand by 1 and calling itself on the slightly reduced problem. When does this recursive reduction finally end? Well, as shown above, the second rule says Y must be greater than 0. If Y is 0, then the first rule, mult(_, 0, 0) applies and the recursion finally comes back with a 0.
If you are not sure how recursion works or are unfamiliar with it, I highly recommend Googling it to understand it. That is, indeed, a concept that applies to many computer languages. But you need to be careful about learning Prolog via comparison with other languages. Prolog is fundamentally different in it's behavior from procedural/imperative languages like Java, Python, C, C++, etc. It's best to get used to interpreting Prolog rules and facts as I have described above.
Say you want to compute 2^3 as assign result to R.
For that you will call exp2(2, 3, R).
It will recursively call exp2(2, 2, R1) and then exp2(2, 1, R2) and finally exp(2, 0, R3).
At this point exp(_, 0, 1) will match and R3 will be assigned to 1.
Then when call stack unfolds 1 will be multiplied by 2 three times.
In Java this logic would be encoded as follows. Execution would go pretty much the same route.
public static int Exp2(int X, int Y) {
if (Y == 0) { // exp2(_, 0, 1).
return 1;
}
if (Y > 0) { // Y > 0
int Y1 = Y - 1; // Y1 is Y - 1
int Z1 = Exp2(X, Y1); // exp2(X, Y1, Z1);
return X * Z1; // mult(X, Z1, Z).
}
return -1; // this should never happen.
}

Resolve quadratic equation in prolog

I got problem with quadrating equation implementation in prolog.
I know some basics but at same point I can not understand output of swish.swi console.
I would appreciate any help or suggestions from your side about my errors.
delta(A, B, C, D):- D is B*B - 4*A*C.
equation(A,B,C,X):- D1<0,delta(A,B,C,D1),X is 0. % or false... but how to retur false there?
equation(A,B,C,X):- D1 =:= 0,delta(A,B,C,D1),X is -B/2*A.
equation(A,B,C,X): D1>0,delta(A,B,C,D1),X is -B-sqrt(D1)/2*A.
equation(A,B,C,X): D1>0,delta(A,B,C,D1),X is -B+sqrt(D1)/2*A.
I am getting two errors there after runnign equation(2, 0, 1, X).
Full stop in clause-body? Cannot redefine ,/2
</2: Arguments are not sufficiently instantiated
At the last 2 predicates (the ones where D>0), you forgot to write "-" after ":". Your code works good, it was just a sintax error. Below I corrected the code for you:
delta(A, B, C, D):- D is B*B - 4*A*C.
equation(A,B,C,X):- D1<0, delta(A,B,C,D1), X is 0.
equation(A,B,C,X):- D1 =:= 0, delta(A,B,C,D1), X is -B/2*A.
equation(A,B,C,X):- delta(A,B,C,D1), D1>0, X is ((-1*B-sqrt(D1))/2*A).
equation(A,B,C,X):- delta(A,B,C,D1), D1>0, X is ((-1*B+sqrt(D1))/2*A).
about
Arguments are not sufficiently instantiated
you must swap delta/4 and the test. Also, it's better to use if/then/else, to avoid recomputing the result:
equation(A,B,C,X) :-
delta(A,B,C,D1),
( D1 < 0
-> X is 0
; D1 =:= 0
-> X is -B/2*A
; X is -B-sqrt(D1)/2*A
).

Resources