# On mutating a variable to a function

In looking to the page https://doc.sagemath.org/html/en/reference/calculus/sage/calculus/tests.html by accident, I have discovered an incredible feature of Sagemath : the fact that a variable can be transformed in a function and vis-versa. It is very nice for an economist (not only but it is what I am) in the following code

var('x y p_x p_y R λ')
U(x,y)= x*y
L(x,y,λ)= U(x,y)+λ*(R-p_x*x-p_y*y)
sol = solve([L(x,y,λ).diff(x)==0,L(x,y,λ).diff(y)==0,L(x,y,λ).diff(λ)==0], (x,y,λ))
show(sol)
x = function('x')
x = sol.rhs()
show(LatexExpr(r'\frac{dx}{dR} = '),x.diff(R).simplify())


My question : is there a shorten way to have access to x than writting x = sol.rhs() since show(sol) display the relation correctly (but without x = sol.rhs(), I can't obtain the desired result).

Incidently, I think that this incredible feature is not enough publicized.

edit retag close merge delete

Sort by » oldest newest most voted

No.

No, no, no, no, no.

And no.

You didn't "change a variable to a function". You redefined (twice !) the Python variable x.

Initially, you didn't define x, which means that by default, the Python variable x is bound to a Python object representing the symbolic variable $x$. This definition is active for lines 1-5 of your code.

Line 6, you redefine the Python variable x, binding it to a Python object representing an (undefined) symbolic function $x$.

Line 7, you redefine the Python variable x again, which binds it to the symbolic expression sol.rhs(), which turns out to be 1/2*R/p_x.

This symbolic expression has a .diff method :

Let e such a sumbolic expression ; e.diff(u) will return e.fiunction(u).diff(u), meaning *" take e as the body of a function of u and differentiate it with respect to u".

Therefore, x.diff(R).simplify()) is 1/2*R/p_x.function(R).diff(R).simplify() which evaluates to $\frac{p_x}{2}$.

See a Python tutorial (or the Python documentation) to understand the meaning of = in Python : a variable is just a label attached to a Python object ; this is quite different of a Sage symbolic variable, which is a Python object representing such a (mathematical) variable in the sage.symbolic.expression.Expression class.

The problem is compounded by the (hopefully convenient) shortcut of defining var("a") as a shortcut meaning a = SR.var("a"), meaning :

• Create a sage.symbolic.expression.Expression representing the mathematical variable $a$, then

• bind this object to the Python variable a.

This convenient shortcut is confusing to beginners...

HTH,

more

Emmanuel you are the expert not me. But in the documentation I have read and cited in the beginning of my question it is written explicitely "Restoring variables after they have been turned into functions". I have modestly tried to apply what I have read.

The example you quoted means that the Python variable x has been bound to the (undefined) symbolic function $x$. The restore? documentation is pretty clear. Extract :

Docstring:
Restore predefined global variables to their default values.

INPUT:

* "vars" - string or list (default: None), if not None, restores
just the given variables to the default value.


BTW :

sage: var("a")
a
sage: a
a
sage: restore("a")
sage: a
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In , line 1
----> 1 a

NameError: name 'a' is not defined


restore works only for the predefined global variables.

I think that this wording in the documentation is a bit misleading: "Restoring variables after they have been turned into functions". This suggests that after executing x = function('x'), Sage still remembers that x used to be a variable, when in fact it doesn't. As Emmanuel says, any assignment of the form x = ... completely replaces the old value of x with the new one. There is nothing magical about the letter x: deleting the line x = function('x') and then using z = sol.rhs() and z.diff(R) works just as well.

This is not a short way but without rhs:

var('x y p_x p_y R λ')
U(x,y)= x*y
L(x,y,λ)= U(x,y)+λ*(R-p_x*x-p_y*y)
sol = solve([L(x,y,λ).diff(x)==0,L(x,y,λ).diff(y)==0,L(x,y,λ).diff(λ)==0],
(x,y,λ),solution_dict=True)
show(x==sol[x])
show(LatexExpr(r'\frac{dx}{dR} = '),sol[x].diff(R))
`
more

Nice but you are obliged to change the name of the variable.