Opened 5 years ago

# substitute_function with var argument

Reported by: Owned by: rws minor sage-6.5 symbolics N/A

### Description

```sage: a,y,z=var('a,y,z')
sage: (x*sin(sin(x + y + 2*a))).substitute_function(sin,cos)
x*cos(cos(2*a + x + y))
sage: (x*sin(sin(x + y + 2*a))).substitute_function(sin,z)
/home/ralf/sage/local/lib/python2.7/site-packages/sage/symbolic/expression_conversions.py:223: DeprecationWarning: Substitution using function-call syntax and unnamed arguments is deprecated and will be removed from a future release of Sage; you can use named arguments instead, like EXPR(x=..., y=...)
See http://trac.sagemath.org/5930 for details.
return self.composition(ex, operator)
(2*a + x + y)*x
```

The method would be expected to give a meaningful error when seeing a variable as second argument.

### comment:2 follow-up: ↓ 3 Changed 2 years ago by schymans

Actually, the docstring of `.substitute_function()` is grammatically incorrect and totally misleading:

```Docstring:
Return this symbolic expressions all occurrences of the function
*original* replaced with the function *new*.
```

I assume that it is supposed to replace all occurrences of the function *original* with the function *new*, so it should return an error whenever one of the arguments is not a function. However, it is quite useful to substitute an expression for a function (see also https://ask.sagemath.org/question/26114/why-is-basic-arithmetic-disallowed-on-symbolic-functions/):

```var('T', 'x')
BT = function('B')(T)
eq_T = BT == x*T
eq_dT = diff(eq_T, T)
print eq_dT
f(T,x) = T^2
print eq_dT.substitute_function(B, f)
```

returns

```diff(B(T), T) == x
2*T == x
```

Note, actually that T is a callable symbolic expression. In the below example, I do a less meaningful substitution, which again gives the right result if I substitute a callable symbolic expression, but if I substitute an expression, it gives the wrong result:

```g(T,x) = x^2
print eq_dT.substitute_function(B, g)
print eq_dT.substitute_function(B, x^2)
print eq_dT.substitute_function(B, g(T,x))
```

This returns

```0 == x
2*T == x
2*T == x
```

Only the first result is correct. In the other two, `x^2` is treated as if it was `T^2`. Surely, this is a bug.

### comment:3 in reply to: ↑ 2 Changed 2 years ago by egourgoulhon

This returns

```0 == x
2*T == x
2*T == x
```

Only the first result is correct. In the other two, `x^2` is treated as if it was `T^2`. Surely, this is a bug.

Note that the second and third results are accompanied by a deprecation warning:

```/home/eric/sage/8.0.rc0/local/lib/python2.7/site-packages/sage/symbolic/expression_conversions.py:1969: DeprecationWarning: Substitution using function-call syntax and unnamed arguments is deprecated and will be removed from a future release of Sage; you can use named arguments instead, like EXPR(x=..., y=...)
See http://trac.sagemath.org/5930 for details.
return operator.change_function(self.new)(*[self(_) for _ in ex.operands()])
```

So, after the deprecation period is over, they will return an error, as it should.

### comment:4 Changed 2 years ago by schymans

Thanks, I might have turned off warnings in the notebook. However, in the console,the deprecation warning is misleading, as it only asks for named arguments, which isn't even an option for `substitute_function`:

```┌────────────────────────────────────────────────────────────────────┐
│ SageMath version 7.6, Release Date: 2017-03-25                     │
│ Type "notebook()" for the browser-based notebook interface.        │
│ Type "help()" for help.                                            │
└────────────────────────────────────────────────────────────────────┘
sage: var('T', 'x')
(T, x)
sage: BT = function('B')(T)
sage: eq_T = BT == x*T
sage: eq_dT = diff(eq_T, T)
sage: f(T,x) = T^2
sage: print eq_dT.substitute_function(B, f)
2*T == x
sage: g(T,x) = x^2
sage: print eq_dT.substitute_function(B, g)
0 == x
sage: print eq_dT.substitute_function(B, x^2)
/home/sschyman/Programs/sage-upgrade/local/lib/python2.7/site-packages/sage/symbolic/expression_conversions.py:1963: DeprecationWarning: Substitution using function-call syntax and unnamed arguments is deprecated and will be removed from a future release of Sage; you can use named arguments instead, like EXPR(x=..., y=...)
See http://trac.sagemath.org/5930 for details.
return operator.change_function(self.new)(*[self(_) for _ in ex.operands()])
2*T == x

```
Last edited 2 years ago by schymans (previous) (diff)
Note: See TracTickets for help on using tickets.