I have a little question about my code : (it can be interpreted as a grid for example)
free(1,1).
free(1,3).
free(2,3).
free(2,1).
free(1,5).
free(5,6).
free(5,2).
free(5,4).
busy(5,1,white,pion).
busy(1,2,black,pion).
busy(1,4,black,pion).
busy(1,6,black,pion).
busy(5,3,white,pion).
busy(5,5,white,pion).
%all clauses for move/6
move(X,Y, X2,Y2,white,pion) :-
busy(X,Y,white,pion), free(X2,Y2), X2=X-1, Y2=Y-1.
move(X,Y, X2,Y2,white,pion) :-
busy(X,Y,white,pion), free(X2,Y2), X2=X-1, Y2=Y+1.
move(X,Y, X2,Y2,black,pion) :-
busy(X,Y,black,pion), free(X2,Y2), X2=X+1, Y2=Y-1.
move(X,Y, X2,Y2,black,pion) :-
busy(X,Y,black,pion), free(X2,Y2), X2=X+1, Y2=Y+1.
When I execute this :
move(1,2,X,Y,black,pion).
in SWI-Prolog it says : false. whereas it should says true and return two statements :
X2 =2 , Y2= 1
X2=2, Y2=3
I do not understand why it doesn't work, could you please help me ?
It is simply because you use = ("make sure that left-hand-side and right hand side unify") instead of is/2 (evaluate the arithmetic expression on the right-hand side and unify with the left-hand-side) or even better #= (constrain the arithmetic values to be the same, even if not all the variables can be resolved yet), here:
X2=X-1, Y2=Y-1.
This unifies X2 with the actual structure -(X,1). Which will fail, as X2 will be a value.
Use:
:- use_module(library(clpfd)). % for #= predicate
move(X,Y, X2,Y2,white,pion) :-
busy(X,Y,white,pion), free(X2,Y2), X2 #= X-1, Y2 #= Y-1.
Also, move the test forwards:
move(X,Y, X2,Y2,white,pion) :-
busy(X,Y,white,pion), X2 #= X-1, Y2 #= Y-1, free(X2,Y2).
Related
I have an add2 predicate which resolves like this where s(0) is the successor of 0 i.e 1
?- add2(s(0)+s(s(0)), s(s(0)), Z).
Z = s(s(s(s(s(0)))))
?- add2(0, s(0)+s(s(0)), Z).
Z = s(s(s(0)))
?- add2(s(s(0)), s(0)+s(s(0)), Z).
Z = s(s(s(s(s(0)))))
etc..
I'm trying to do add in a predecessor predicate which will work like so
?- add2(p(s(0)), s(s(0)), Z).
Z = s(s(0))
?- add2(0, s(p(0)), Z).
Z = 0
?- add2(p(0)+s(s(0)),s(s(0)),Z).
Z = s(s(s(0)))
?- add2(p(0), p(0)+s(p(0)), Z).
Z = p(p(0))
I can't seem to find a way to do this. My code is below.
numeral(0).
numeral(s(X)) :- numeral(X).
numeral(X+Y) :- numeral(X), numeral(Y).
numeral(p(X)) :- numeral(X).
add(0,X,X).
add(s(X),Y,s(Z)) :- add(X,Y,Z).
add(p(X),Y,p(Z)) :- add(X,Y,Z).
resolve(0,0).
resolve(s(X),s(Y)) :-
resolve(X,Y).
resolve(p(X),p(Y)) :-
resolve(X,Y).
resolve(X+Y,Z) :-
resolve(X,RX),
resolve(Y,RY),
add(RX,RY,Z).
add2(A,B,C) :-
resolve(A,RA),
resolve(B,RB),
add(RA,RB,C).
In general, adding with successor arithmetic means handling successor terms, which have the shape 0 or s(X) where X is also a successor term. This is addressed completely by this part of your code:
add(0,X,X).
add(s(X),Y,s(Z)) :- add(X,Y,Z).
Now you have to make a decision; you can either handle the predecessors and the addition terms here, in add/3, or you can wrap this predicate in another one that will handle them. You appear to have chosen to wrap add/3 with add2/3. In that case, you will definitely need to create a reducing term, such as you've built here with resolve/2, and I agree with your implementation of part of it:
resolve(0,0).
resolve(s(X),s(Y)) :-
resolve(X,Y).
resolve(X+Y,Z) :-
resolve(X,RX),
resolve(Y,RY),
add(RX,RY,Z).
This is all good. What you're missing now is a way to handle p(X) terms. The right way to do this is to notice that you already have a way of deducting by one, by using add/3 with s(0):
resolve(p(X), R) :-
resolve(X, X1),
add(s(0), R, X1).
In other words, instead of computing X using X = Y - 1, we are computing X using X + 1 = Y.
Provided your inputs are never negative, your add2/3 predicate will now work.
I wanted to ask how I can simplify expressions like:
1+2+a*5+0/b-c*0
= 3+a*5
And especially how can I separate such expressions in lists.
It's actually kind of fun in Prolog, because you don't need to do anything too magical to make it work.
?- X-Y = 1+2+a*5+0/b-c*0.
X = 1+2+a*5+0/b,
Y = c*0.
So you could start by doing something like this:
simplify(C, C) :- atom(C) ; number(C).
simplify(X+Y, X1+Y1) :- simplify(X, X1), simplify(Y, Y1).
simplify(X*Y, X1*Y1) :- simplify(X, X1), simplify(Y, Y1).
simplify(X/Y, X1/Y1) :- simplify(X, X1), simplify(Y, Y1).
simplify(X-Y, X1-Y1) :- simplify(X, X1), simplify(Y, Y1).
This is an identity transform: it doesn't do anything.
?- simplify(1+2+a*5+0/b-c*0, Result).
Result = 1+2+a*5+0/b-c*0.
Now you can add rules for specific cases:
simplify(X*0, 0).
simplify(0*X, 0).
Now you get multiple results:
?- simplify(1+2+a*5+0/b-c*0, Result).
Result = 1+2+a*5+0/b-c*0 ;
Result = 1+2+a*5+0/b-0 ;
You could add a rule for constant folding:
simplify(X+Y, C) :- number(X), number(Y), C is X+Y.
You know, just have fun with it.
Lists aren't really any easier to work with, but you can make them using the "univ" operator: =..:
?- 1+2+a*5+0/b-c*0 =.. R.
R = [-, 1+2+a*5+0/b, c*0].
It's possible to simplify expressions in Prolog using unification, but this sometimes leads to unexpected results. In this example, two different variables in an expression are unified when "matching" a pattern, even if they were intended to be distinct:
:- initialization(main).
simplify(A+A,2*A).
main :-
simplify(A+B,C),
writeln(C).
In this case, simplify(A+B,C) would unify A with B.
To solve this problem, I use subsumes_term/2 to match a pattern without unifying the variables in an expression. subsumes_term(A+A,Input) will not match A+B unless A is already unified with B:
simplify(Input,2*A) :-
subsumes_term(A+A,Input).
This subsumes_term/2 predicate is often useful for metaprogramming: I used it to write a Prolog-to-Minizinc compiler.
p(0,0).
p(0,1).
p(0,2).
p(0,3).
p(0,4).
p(1,1).
p(1,2).
p(1,3).
p(1,4).
p(1,0).
p(2,0).
p(2,1).
p(2,2).
p(2,3).
p(2,4).
p(3,0).
p(3,1).
p(3,2).
p(3,3).
p(3,4).
p(4,0).
p(4,1).
p(4,2).
p(4,3).
p(4,4).
adjacent(p(X,Y),p(X,Z)) :-
p(X,Y),
p(X,Z),
Z is Y+1.
adjacent(p(X,Y),p(X,Z)) :-
p(X,Y),
p(X,Z),
Z is Y-1.
adjacent(p(X,Y),p(Z,Y)) :-
p(X,Y),
p(X,Z),
Z is X+1.
adjacent(p(X,Y),p(Z,Y)) :-
p(X,Y),
p(X,Z),
Z is X-1.
adjacentC(X,Y) :-
adjacent(X,Y).
adjacentC(X,Y) :-
adjacent(X,Z),
adjacentC(Z,Y).
I don't know why this code I wrote isn't working.
e.g.:
?- adjacentC((0,0),(4,4)). ERROR
Quick answer: The following works and terminates always using closure/3 defined elsewhere.
adjacentD(X,Y) :-
closure(adjacent,X,Y).
However, this approach is extremely slow, due to the inefficient definition of adjacent/3. Here is a better one / oh forget it, here is a more correct one, first:
adjacent2(p(X0,Y0),p(X,Y)) :-
p(X0,Y0),
( X0 = X,
p(X,Y),
abs(Y0-Y) =:= 1
; Y0 = Y,
p(X,Y),
abs(X0-X) =:= 1
).
I have this Prolog code that returns: [[vincent,vincent],[vincent,marcellus],[marcellus,vincent],[marcellus,marcellus],[pumpkin,pumpkin],[honey_bunny,honey_bunny]].
:- initialization main.
loves(vincent, mia).
loves(marcellus, mia).
loves(pumpkin, honey_bunny).
loves(honey_bunny, pumpkin).
jealous(X, Y) :-
loves(X, Z),
loves(Y, Z).
main :-
findall([X, Y], jealous(X, Y), L),
write(L),
halt.
How to get the only results when X != Y?
I tried the following code to get the same results as before.
jealous(X, Y) :-
X \== Y,
loves(X, Z),
loves(Y, Z).
With \=, I got [].
How to get only [vincent,marcellus] as a result?
The order of the goals in your attempted solution is wrong. When called with two distinct variables, the (\==)/2 standard predicate always succeed. The solution is to call the predicate only when its arguments are instantiated:
jealous(X, Y) :-
loves(X, Z),
loves(Y, Z),
X \== Y.
With this fix, your query now returns:
?- findall([X, Y], jealous(X, Y), L).
L = [[vincent, marcellus], [marcellus, vincent]].
So, no one is jealous of himself anymore. But you still get a redundant solution. We can modify the jealous/2 predicate to sort the names in the returned solutions. For example:
jealous(X, Y) :-
loves(X0, Z),
loves(Y0, Z),
X0 \== Y0,
( X0 #< Y0 ->
X = X0, Y = Y0
; X = Y0, Y = X0
).
Now, by using setof/3 instead of findall/3, we get:
?- setof([X, Y], jealous(X, Y), L).
L = [[marcellus, vincent]].
One final observation. A list is a poor solution for representing a pair. The traditional way is to use either X-Y or (X, Y).
Whenever possible, use dif/2 instead of (\==)/2.
dif/2 will help you write logically sound programs.
For details, look at prolog-dif!
I've got these definitions:
memberx(X, [X|_]).
memberx(X, [_|T]) :- memberx(X, T).
intersectionx([], _, []).
intersectionx([H|T], Y, [_|Z]) :- memberx(H, Y), !, intersectionx(T, Y, Z).
intersectionx([_|T], Y, Z) :- intersectionx(T, Y, Z).
I get the following result:
?- intersectionx([1], [1], Z).
Z = [_G305].
Why doesn't it result in Z = [1]??
Z = [_G305].
means that this answer is true for all terms. That is, it is not
only true for Z = [1] - as you expect, but it is also true for Z = [2].
Clearly, that is not what you expected.
So where is the error? A simple way to detect it is to watch out for anonymous
variables denoted _.
Consider:
intersectionx([H|T], Y, [_|Z]) :- memberx(H, Y), !, intersectionx(T, Y, Z).
^^^
What you have written means that the intersection of a list starting with
H and another list will be (provided the goals on the right hand side
are all true) a list starting with anything... Replace anything by that H!