# Why is basic arithmetic disallowed on symbolic functions?

The documentation at http://www.sagemath.org/doc/reference... states:

In Sage 4.0, basic arithmetic with unevaluated functions is no longer supported

Why? What is the intended way of manipulating equations and then, at some point, taking derivatives with respect to some dependent variable? The following approach has an undesired side-effect:

sage: var('B E H T_s')
(B, E, H, T_s)
sage: eq_B_TS = B == H/E
sage: diff(eq_B_TS.subs(B = function('B')(T_s), E = function('E')(T_s), H = function('H')(T_s)), T_s)
D(B)(T_s) == -H(T_s)*D(E)(T_s)/E(T_s)^2 + D(H)(T_s)/E(T_s)


Fine, but now my B, E and H are symbolic functions and I cannot do any basic arithmetic with them any more:

sage: B*E
Traceback (click to the left of this block for traceback)
...
TypeError: unsupported operand type(s) for *: 'NewSymbolicFunction' and 'NewSymbolicFunction'


edit retag close merge delete

Sort by » oldest newest most voted

A part of your question seems to amount to "can I have both a function and a variable with the same print name" and indeed you can. The only slightly tricky bit is that, of course, you cannot have both bound to the same python identifier at the same time. So one solution is:

sage: A_as_a_var=var('A')
sage: A_as_a_function=function('A')
sage: A_as_a_function(A_as_a_var)
A(A)


The fact that the python identifier A is now bound to one of the two as a side-effect is perhaps confusing. If you use other "var" and "function" then you can avoid this problem.

sage: from sage.symbolic.function_factory import function as lib_function
sage: lib_var=SR.var
sage: A_as_a_var=lib_var('A')
sage: A_as_a_function=lib_function('A')
sage: A_as_a_function(A_as_a_var)
A(A)
sage: A
NameError: name 'A' is not defined


i.e., A is bound to neither, so no confusion about what it is bound to.

more

Wow, this is confusing, but actually solves my question, as long as the assignment of A_as_a_function = function('A') comes before var('A'). The example in my question then becomes:

sage: B_f = function('B')
sage: E_f = function('E')
sage: H_f = function('H')
sage: var('B E H T_s')
sage: eq_B = B == H/E
sage: eq1 = diff(eq_B.subs(B = B_f(T_s), H = H_f(T_s), E = E_f(T_s)), T_s)


Now B, E and E are still expressions, while E(T_s) is obtained by typing E_f(T_s). I wonder what other problems this will cause...

I just found a way to deal with this, which would be to define a python function that creates a new symbolic function out of an already defined variable, while keeping the latex representation of the original variable for illustration purposes:

def f(var1, var2):
'''
Creates a symbolic function out of existing variable,
where the name of the function is f-underscore followed
by the name of the existing variable, while the latexname
of the original variable, if defined, stays the same.
Returns the function evaluated at another defined variable
given as var2.
Example:
sage: var('B E H T_s')
sage: eq_B = B == H/E
sage: eq1 = diff(eq_B.subs(B = f(B,T_s), H = f(H,T_s), E = f(E,T_s)), T_s)
sage: latex(eq1)
D\left(B\right)\left(T_{s}\right) = -\frac{H\left(T_{s}\right)
D\left(E\right)\left(T_{s}\right)}{E\left(T_{s}\right)^{2}} +
\frac{D\left(H\right)\left(T_{s}\right)}{E\left(T_{s}\right)}
'''
name = 'f_'+str(var1)
z = function(name,latex_name = latex(var1))
return z(var2)

more

Note that, as with the ugly var, the function() function injects its returned value in the namespace, even if it is used during a .subs() call:

sage: function('aze')
aze
sage: aze
aze

sage: b = function('qsd')(x)
sage: b
qsd(x)
sage: qsd
qsd


Why don't you just define B, E and H directly as symbolic functions ?

sage: var('T_s')
T_s
sage: B = function('B')(T_s)
sage: E = function('E')(T_s)
sage: H = function('H')(T_s)
sage: eq_B_TS = B == H/E
sage: diff(eq_B_TS, T_s)
D(B)(T_s) == -H(T_s)*D(E)(T_s)/E(T_s)^2 + D(H)(T_s)/E(T_s)
sage: B*E
B(T_s)*E(T_s)

more

B = function('B')(T_s)

is very odd, as it creates a symbolic function called 'B' and then overwrites it immediately by a symbolic expression relating to function 'B' evaluated at 'T_s', if I understand http://trac.sagemath.org/ticket/17447 correctly. It also prints 'B(T_s)' every time, which is not desired, as it clutters equations and suggests that B is only a function of T_s. However in other contexts, B can also be a function of time or whatever.

B = function('B')(T_s)
H = function('H')(T_s)
E = function('E')(T_s)
eq_B = B == H/E
eq_B


B(T_s) == H(T_s)/E(T_s)

1

In ticket #17477 there is discussion about splitting var and function into var/declare_var and function/declare_function which would prevent such misunderstandings better.