Unify 2 random variables in a clause - prolog

I need to implement this functionality.
unify2(func1(X,Y,Z), R) => R = func1(X,X,Z)
R = func1(X,Y,X)
R = func1(X,Y,Y)
It's not necessary for the func1 to have 3 arguments, the number can be arbitrary. You can see that in the result there is always a couple of variables unified, the rest of the term is the same.
I would be grateful for some idea, I've been looking into copy_term but wasn't able to crack the nut yet.

(=..)/2 (spelled univ) it's used to decompose/assemble structures: try
unify2(T, R) :-
T =.. [F,X,Y,Z],
( R =.. [F,X,X,Z] ; R =.. [F,X,Y,Z] ; R =.. [F,X,Y,Y] ).
this works for arbitrary structures with 3 arguments.

Related

How is suffix/prefix working internally in prolog?

Can anyone explain how prolog finds a suffix(L1,L2) or prefix(L1,L2) internally?
I know the rule is suffix(L1,L2):- append(_,L2,L1).
But, I can't seem to understand how the variables _, L1 and L2 going inside append and working the query out?
append([],X,X).
append([H|T],Y, [H|W]):- append(T,Y, W).
If you understand append, then the definition
suffix( A, B) :- append( _X, B, A).
is ... well, actually, what is the meaning of append( X, B, A)?
It's that (in pseudocode) [...X, ...B] == A: the list of elements of X, followed by elements of B, together, is the list of elements in A.
This means that B is a (suffix / prefix -- make a choice, please) of A, right? and we don't care what X is. In particular it can be empty, or not.
This explains suffix. For append please see the linked answer, and the answer it links.
This gives us an idea for a follow up question:
Define the predicate proper_suffix(A, B) such that "proper_suffix of A is B" holds, i.e. B is a suffix of A, and B is not the same as A.
You write
I am not understanding how _ for the suffix's argument is going inside append([H|T], Y, [H|W]):- append(T,Y, W). How is append processing the _ for the H of the append to find whether L2 is suffix of L1? if I pass _, how does Prolog figure out the H and T, coz by anonymous variable we mean that 'we don't care about its value' .
So we have
suffix( A, B) :-
append( _X, B,
A).
Whatever the A and B were in the call to suffix(A, B), they will be the same in the call to append( _X, B, A). When that call returns with logic variables _X, A and B holding their (possibly updated) values, the call to suffix returns with its A and B holding those same values as in the append call. The value of _X is not made use of by the suffix/2 predicate, but it is found out just the same, by append/3.
You seem to be confused about the anonymous variable, _. It doesn't matter that it is named that way, it is still a variable. Forget the "don't care" thing, it is confusing and imprecise. Imagine it is named _X, as I showed. it will work exactly the same with _Y, _, Abracadabra, etc., as long as it is not the same as the other variables' names in that rule.
Just one caveat: without the leading _ Prolog will warn us about "singleton variable" i.e. a variable that isn't used anywhere else. It is with respect to this that we signal our intention that "we don't care", with the (leading) _.
Its value is still going to be found, as usual!
And when we use _, the additional convenience is that we don't have to make sure that the name is unique. Each _ is treated as if it were unique, automatically.
You ask (in the comments) how does the query append(_X, [a,b], [1,2,a,b]) work.
Prolog works by choosing a rule whose head matches the query.
This query matches the second clause's head:
append(_X, [a,b], [1,2,a,b]) = append([H|T], Y, [H|W])
with
_X = [H|T], Y = [a,b], [H|W] = [1,2,a,b]
Which also means
H = 1, W = [2,a,b],
and hence
_X = [H|T] = [1|T]
See? This doesn't deconstruct _X, it builds it up!
Since its head matches the query, the second clause of your append definition is thus chosen, and so its body is fired up as the new query under the same substitution, i.e. set of "assignments" to the logic variables involved. So it calls
_X = [H|T], Y = [a,b], [H|W] = [1,2,a,b], append(T,Y,W).
as the new query. That is,
_X = [1|T], Y = [a,b], W = [2,a,b], append(T,Y,W). %% or,
_X = [1|T1], append(T1, [a,b], [2,a,b]).
If we apply the same reasoning, we see again the second clause matching up, and end up with
_X = [1|T1], T1 = [2|T2], append(T2, [a,b], [a,b]).
But now the first clause matches,
append(T2, [a,b], [a,b]) = append([],X,X)
which entails
T2 = [].
Thus
_X = [1|T1]
T1 = [2|T2]
T2 = [].
The list now held by _X has thus been built in a top-down fashion.

Arithmetic expression in prolog solving

given an expression:
(x*0+6)*(x-x+3+y*y) and value of y:2 the Predicate should give only one
solution (x*0+6)*(x-x+3+4).
when 6*(3+x*x) and x:2 is given then it should give the output 42 .
I have been coding for hours and i could manage to get only the second part of it .my code is posted below .can some one help me with solution .
partial_eval(Expr0, Var,Val, Expr) :-
evaluate(Expr0,[Var:Val],Expr).
evaluate(Exp, LstVars, Val) :-
analyse(LstVars, Exp, NewExp),
Val is NewExp.
analyse(LstVars, Term,R) :-
functor(Term, Term, 0), !,
( member(Term : V, LstVars)
-> R = V
; R = Term ).
analyse(LstVars, Term, V) :-
functor(Term, Name, _),
Term =.. [Name | Lst],
maplist(analyse(LstVars), Lst, LstV),
V =.. [Name|LstV].
This problem can be broken down into two: One is substituting in values for variables. The other is recursively evaluating arithmetic subexpressions. Prolog is nondeterministic but both of these operations are deterministic, so that's something to keep in mind while implementing them.
You seem to have a good generic recursion structure (using =..) for the substitution part. For the arithmetic evaluation part you may find it easier to use + and * terms in the recursion. Hope that helps you get started, ask if you get stuck and need more advice.

Prolog - simplify derivative

so I just got started with Prolog this semester, and got the homework to implement a pretty basic d(function, variable, derivative) which I did like this:
d(X,X,1) :- !.
d(C,X,0) :- atomic(C). %, (C \= X).
d(X**E,X,E*X**(E-1)).
d(U+V,X,A+B) :- d(U,X,A), d(V,X,B).
d(U-V,X,A-B) :- d(U,X,A), d(V,X,B).
d(U*V,X,DU*V+U*DV) :- d(U,X,DU), d(V,X,DV).
d(U/V,X,(DU*V-U*DV)/(V*V)) :- d(U,X,DU), d(V,X,DV).
I know this is not complete, but it covers all the tasks required in the exercise.
However,
?- d((x*x+2*x+3)/(3*x),x,R).
leads to
R = ((1*x+x*1+ (0*x+2*1)+0)* (3*x)- (x*x+2*x+3)* (0*x+3*1))/ (3*x* (3*x)).
which doesn't look pretty at all. is/2 unfortunately doesn't like my x as it is not a number...
Is there a simple solution to achieve a cleaner result?
I would rather see this as two separate problems:
First, get derivation right (you're probably getting close, depending on your concrete requirements).
Then, work on simplifying expressions on an algebraic level. Exploit algebraic identities, see if applying the laws of commutativity / associativity / distributivity on some subexpressions enable their rewriting into something equivalent (but simpler / more compact).
As a starting point, you may want to look at the somewhat related question "Replacing parts of expression in prolog".
Here's a simplistic sketch how you could do the simplification—using iwhen/2 to safeguard against insufficient instantiation:
expr_simplified(A, B) :-
iwhen(ground(A), xpr_simplr(A,B)).
xpr_simplr(A, B) :-
( atomic(A)
-> A = B
; ( A = X+0 ; A = 0+X ; A = 1*X ; A = X*1 )
-> xpr_simplr(X, B)
; ( A = 0*_ ; A = _*0 )
-> B = 0
; A = X+X
-> B = X*2
; A = X*X
-> B = X**2
; A = X**1
-> B = X
; A =.. [F|Xs0], % defaulty catch-all
maplist(xpr_simplr, Xs0, Xs),
B =.. [F|Xs]
).
Let's see what it does with the expression you gave. We apply expr_simplified/2 until we reach a fixed point:
?- A = ((1*x+x*1+(0*x+2*1)+0)*(3*x)-(x*x+2*x+3)*(0*x+3*1))/(3*x*(3*x)),
expr_simplified(A,B),
expr_simplified(B,C),
expr_simplified(C,D).
A = ((1*x+x*1+(0*x+2*1)+0)*(3*x)-(x*x+2*x+3)*(0*x+3*1))/(3*x*(3*x)),
B = ((x+x+(0+2))*(3*x)-(x**2+2*x+3)*(0+3))/(3*x)**2,
C = ((x*2+2)*(3*x)-(x**2+2*x+3)*3)/(3*x)**2,
D = C. % fixed point reached
As imperfect as the simplifier is, the expression got a lot more readable.
a possibility to get a number is to replace each instance of variable x with a value, visiting the derived tree. You should do writing a clause to match each binary operator, or use a generic visit, like
set_vars(E, Vs, Ev) :-
E =.. [F,L,R],
set_vars(L, Vs, Lv),
set_vars(R, Vs, Rv),
Ev =.. [F,Lv,Rv].
set_vars(V, Vs, N) :- memberchk(V=N, Vs).
set_vars(V, _, V).
that yields
?- d((x*x+2*x+3)/(3*x),x,R), set_vars(R,[x=5],E), T is E.
R = ((1*x+x*1+ (0*x+2*1)+0)* (3*x)- (x*x+2*x+3)* (0*x+3*1))/ (3*x* (3*x)),
E = ((1*5+5*1+ (0*5+2*1)+0)* (3*5)- (5*5+2*5+3)* (0*5+3*1))/ (3*5* (3*5)),
T = 0.29333333333333333
but, there is a bug in your first clause, that once corrected, will allow to evaluate directly the derived expression:
d(X,V,1) :- X == V, !.
...
now, we can throw away the utility set_vars/3, so
?- d((T*T+2*T+3)/(3*T),T,R), T=8, V is R.
T = 8,
R = ((1*8+8*1+ (0*8+2*1)+0)* (3*8)- (8*8+2*8+3)* (0*8+3*1))/ (3*8* (3*8)),
V = 0.3177083333333333.

Number of occurrences of X in the List L in prolog

I am trying to find the number of occurrences of X in the List L
For eg :-
occurrences(a, [b, a, b, c, a, d, a], N ).
N =3
My code not working .Here is my code.
occ(K,L,N) :- N1=0, occ1(K,L,N1,N).
occ1(K,[],N1,N) :- N=N1.
occ1(K,L,N1,N) :-
L=[X|L1],
( K=X -> N1 is N1+1, occ1(K,L1,N1,N) ; occ1(K,L1,N1,N) ).
Can anybody tell me what's wrong in the code.
While the answer given by #Kay is spot-on as far as fixing the bug is concerned, it completely circumvents a much bigger issue: The code of occ1/4 is logically impure.
This may not appear very important to you right now,
but using impure code has several negative consequences:
Impure code cannot be read declaratively, only procedurally.
Debugging impure code is often tedious and pain-staking.
Impure predicates are less "relational" than their pure counterparts.
Logical impurity hampers code re-use.
Because it is non-monotone, impure code is prone to lead to logically unsound answers, particularly when working with non-ground terms.
To show that these problems persisted in your code after having been "fixed" as suggested #Kay, let us consider the "corrected" code and some queries. First, here's the corrected code:
occ(K,L,N) :- N1=0, occ1(K,L,N1,N).
occ1(_,[],N1,N) :- N=N1.
occ1(K,L,N1,N) :-
L=[X|L1],
( K=X -> N2 is N1+1, occ1(K,L1,N2,N) ; occ1(K,L1,N1,N) ).
Here's the query you gave in your question:
?- occ(a,[b,a,b,c,a,d,a],N).
N = 3 ;
false.
Okay! What if we write the query differently?
?- A=a,B=b,C=c,D=d, occ(a,[B,A,B,C,A,D,A],N).
A = a, B = b, C = c, D = d, N = 3 ;
false.
Okay! What if we reorder goals? Logical conjunction should be commutative...
?- occ(a,[B,A,B,C,A,D,A],N), A=a,B=b,C=c,D=d.
false.
Fail! It seemed that occ1/4 is fine, but now we get an answer that is logically unsound.
This can be avoided by using logically pure code:
Look at the pure and monotone code I gave in my answer to the related question "Prolog - count repititions in list (sic)".
The problem is
N1 is N1+1
Variables cannot be "overwritten" in Prolog. You need to just a new variable, e.g.
N2 is N1+1, occ1(K,L1,N2,N)
To your question "Can we replace a particular list element. If yes, what is the syntax?":
You can only build a new list:
replace(_, _, [], []).
replace(Old, New, [H0|T0], [H1|T1]) :-
(H0 = Old -> H1 = New; H1 = H0),
replace(Old, New, T0, T1).

SWI-Prolog. Check correctness of mathematical expression

I try to check the correctness of student mathematical expression using Prolog (SWI-Prolog). So, for example if the student were asked to add three variable x, y, and z, and there's a rule that the first two variable that must be added are: x and y (in any order), and the last variable that must be added is z then I expect that prolog can give me true value if the student's answer is any of these:
x+y+z
(x+y)+ z
z+(x+y)
z+x+y
y+x+z
and many other possibilities.
I use the following rule for this checking:
addData :-
assert(variable(v1)),
assert(variable(v2)),
assert(variable(v3)),
assert(varName(v1,x)),
assert(varName(v2,y)),
assert(varName(v3,z)),
assert(varExpr(v1,x)),
assert(varExpr(v2,y)),
assert(varExpr(v3,z)).
add(A,B,R) :- R = A + B.
removeAll :- retractall(variable(X)),
retractall(varName(X,_)),
retractall(varExpr(X,_)).
checkExpr :-
% The first two variable must be x and y, in any combination
( (varExpr(v1,AExpr), varExpr(v2,BExpr));
(varExpr(v2,AExpr), varExpr(v1,BExpr))
),
add(AExpr, BExpr, R1),
% store the expression result as another variable, say v4
retractall(variable(v4)),
retractall(varName(v4, _)),
retractall(varExpr(v4, _)),
assert(variable(v4)),
assert(varName(v4, result)),
assert(varExpr(v4, R1)),
% add the result from prev addition with Z (in any combination)
( (varExpr(v3,CExpr), varExpr(v4,DExpr));
(varExpr(v4,CExpr), varExpr(v3,DExpr))
),
add(CExpr, DExpr, R2),
R2 = z + x + y. % will give me false
% R2 = z + (x + y). % will give me true
% Expected: both should give me true
checkCorrect :- removeAll,
addData,
checkExpr.
You should try to specify a grammar and write a parser for your expressions.
Avoid assert/retract, that make the program much more difficult to understand, and attempt instead to master the declarative model of Prolog.
Expressions are recursive data structures, using operators with known precedence and associativity to compose, and parenthesis to change specified precedence where required.
See this answer for a parser and evaluator, that accepts input from text. In your question you show expressions from code. Then you are using Prolog' parser to do the dirty work, and can simply express your requirements on the resulting syntax tree:
expression(A + B) :-
expression(A),
expression(B).
expression(A * B) :-
expression(A),
expression(B).
expression(V) :-
memberchk(V, [x,y,z]).
?- expression(x+y+(x+z*y)).
true .
edit: we can provide a template of what we want and let Prolog work out the details by means of unification:
% enumerate acceptable expressions
checkExpr(E) :-
member(E, [F = A + D, F = D + A]),
F = f,
A = c * N,
N = 1.8,
D = d.
And so on...
Test:
?- checkExpr(f=(c*1.8)+d).
true.
?- checkExpr(f=(c*1.8)+e).
false.
?- checkExpr(f=d+c*1.8).
true.

Resources