Reputation: 11
I want to differentiate an expression and generate Fortran for the result. The expression is similar to at(diff(x^2*f(x,y)+y^2*g(x,y),y),x=y)
. The result contains terms such as at(diff(f(x,y),y),x=y) and at(diff(g(x,y),y),x=y)
.
Before I generate Fortran I want to remove the at-functions (I have another script to convert the diff(f(x,y),y)
and diff(g(x,y),y)
entities to subroutine calls). Hence I am trying to write a function that goes through the expression tree and does something special when the at-function is found. However, if I compare piece='at, this always evaluates to false whereas if I compare piece='sin, the sin function is detected correctly. I am completely at a loss as to why the at-function is not detected.
The code I have so far is
eliminateAt(expression) :=
block( [ops,args,result],
if atom(expression)
then expression
else
( ops: op(expression),
args: args(expression),
print("piece=",piece),
if piece='at
then processAt(first(args))
else
(
result: [],
for arg in args do (
result: endcons(eliminateAt(arg),result)
),
apply(ops,result)
)
)
);
processAt(expression) :=
block( [ops,args,result],
print("expression=",expression),
expression
);
If I run this as
eliminateAt(at(diff(f(x,y),y),x=y));
I get
(%i4) eliminateAt(at(diff(f(x,y),y),x=y));
piece= at
piece= derivative
piece= f
piece= =
!
d !
(%o4) -- (f(x, y))!
dy !
!x = y
So even though piece is printed to be "at" the function processAt is never called. If I change the line "if piece='at" to "if piece='sin" and then evaluate
eliminateAt(sin(diff(f(x,y),y)));
I get
(%i6) eliminateAt(sin(diff(f(x,y),y)));
piece= sin
d
expression= -- (f(x, y))
dy
d
(%o6) -- (f(x, y))
dy
which clearly demonstrates that the sin-function is detected no problem. So what is special about the at-function and how can I detect when I have reached it in an expression?
Upvotes: 1
Views: 90
Reputation: 17585
The problem you have encountered is that when you write 'at
by itself, that symbol is the so-called verb form of at
, while if you write 'at(...)
, then that symbol is the so-called noun form. (Yes, that's subtle and confusing.) You can get the noun form by itself by writing nounify('at)
.
But a better way in general to handle problems such as this in which you want to replace stuff in an expression tree is to use matchdeclare
and defrule
or defmatch
.
Upvotes: 1