I want to define facts which are true both ways (They all have an arity of 2). I had success with a fact expressing the relationship "opposite" this way:
oppositeDeclare(plus, minus).
opposite(X, Y) :- oppositeDeclare(Y, X).
opposite(X, Y) :- oppositeDeclare(X, Y).
I'm trying to make a simple equation solver, and I would also like to define that if A=B then B=A. I can't just write:
equal(A, B):-equal(B,A).
because I get out of local stack error. However I can't do the same as I did with the "opposite" fact because "equal" needs to work based on the some rules. ("opposite" got it's input from facts only).
Is there a way I can avoid defining all the rules for "equal" twice?
Edit:
I only want to declare simple mathematical facts to see if I can use Prolog to solve other more complicated tasks where I don't know the mechanism for the solution only simple facts.
So far I have used equal/2 to define things like: if A=B+C, then C=A-B. I want to define equal/2 two ways so that I don't have to define if B+C=A, then A-B=C. Ideally after the new rule it could solve an equation for c like this: a=(b+c)/d -> b+c=a/d -> c=(a/d)-b.
The reason I can't use swap is because I have recursive rules for equal/2.
Bear in mind that it will not always work even for simple equations, because not all necessary facts are defined.
Here's the current program with a query:
5 ?- equal(v, X).
X = opr(s, per, t)
% operators: per, times, plus, minus
% equation(LHS, RHS): used to declare physics equations
% equal(LHS, RHS): checks equality in a query
equation(s, opr(v, times, t)). % s=v*t
equation(a, opr(opr(b, plus, c), per, d)). % a=(b+c)/d
oppositeDeclare(plus, minus).
oppositeDeclare(per, times).
opposite(X, Y) :- oppositeDeclare(Y, X).
opposite(X, Y) :- oppositeDeclare(X, Y).
equal(R, opr(A, O, B)) :- equation(R, opr(A, O, B)).
% if there's an equation R=A O B , then R = A O B, where O is an operator (+-*/)
equal(A, opr(R, OY, B)) :- equal(R, opr(A, OX, B)), opposite(OY, OX).
%declaring in one go: if R=A/B then A=R*B, if R=A-B then A=R+B, if R=A+B then A=R-B, if R=A-B then A=R+B
opposite/2
forequal/2
too. Often, some form of normalization is done first, though. – falseopposite/2
. For example, factsequal_item(a, b). equal_item(a, c).
and then ruleequals(A, B) :- equal_item(A, B) ; equal_item(B, A).
The ruleequal(A, B) :- equal(B, A).
is circular logic and infinitely recursive. – lurker