SymPy: simplifying of inverse function - python-2.7

I define 2 sympy functions f, g, s.t. g is inverse of f:
import sympy as sy
g = sy.Function('g')
class f(sy.Function):
def inverse(self, argindex=1):
return g
x, y = sy.symbols('x y')
print sy.solve(y - f(x), x) # [g(y)] - correct
But if I try to evaluate f(g(x)) sympy doesnt simplify this:
print f(g(x)) # f(g(x))
print f(g(x)).doit() # f(g(x)) - why not x?
print f(g(x)).simplify() # f(g(x)) - why not x?
Question: how to say to sympy that f(g(x)) is just x?

inverse isn't implemented to do that. I opened https://github.com/sympy/sympy/issues/10487 for it. Ideally what I write below should work by default.
You can easily make it work by defining _eval_simplify, like
class f(sy.Function):
def inverse(self, argindex=1):
return g
def _eval_simplify(self, ratio, measure):
if isinstance(self.args[0], self.inverse()):
return self.args[0].args[0]
return self
If you have many classes you want to do this with you can put that in a superclass.
In [30]: f(g(x))
Out[30]: f(g(x))
In [31]: f(g(x)).simplify()
Out[31]: x
Or if you prefer for doit() to do it you can define doit().

Related

Sympy: Is there a function that gives all the factors of an expression but does not work sums?

I have an expression which is composed only of factors (e.g. (x**2+1)*(x**2)*(x+4). I want to delete the factor x**2 from it using the function .args with an if condition. However, if I have the following equation x**2+1+x+4, the .args thinks I have x**2 in the expression which is not true (I only have one factor). I have the code below.:
if q**2 in expr.args:
expr = expr.func(*[term for term in expr.args if term != q**2])
else:
expr = expr*2
By using Mul.make_args(expr) you will get a singleton if the expression is not a product, otherwise a tuple of the factors:
>>> from sympy.abc import x, y
>>> from sympy import Mul
>>> Mul.make_args(x + y)
(x + y,)
>>> Mul.make_args(x*y)
(x, y)

python sympy lambdify not working inside function

I'm trying to write a function that has a literal function as a parameter:
def derive(x, y):
x = symbols(x)
y = symbols(y)
return lambdify(x, y)
derive(5, 'x**2')
This returns a syntax error:
File "<lambdifygenerated-32>", line 1
def _lambdifygenerated(25.0):
^
SyntaxError: invalid syntax
If I write (outside the function scope):
f = lambdify(x, x**2)
f(5)
it works.
I appreciate any help on this.
In sympy you can get the derivative of a function via diff(). .subs(x, 5) fills in the value 5 for x. An example:
from sympy.abc import x
f = x**2
print(f.diff(x).subs(x,5))
Here is how a function that would calculate the derivative of a given function at a given value could look like. evalf() can be used to iron out symbolic parts (such as giving a numeric approximation for 2*pi or Sqrt(5) which sympy standard wants to keep in their exact symbolic form).
def derive_and_evaluate(x, f, xval):
return f.diff(x).subs(x, xval).evalf()
derive_and_evaluate(x, x**2, 5)
If you need the same derivative for a lot of x-values, you can do:
from sympy import lambdify
g = lambdify(x, f.diff(x)) # now `g` is a numpy function with one parameter
Or, if you want a function that does the derivation and converts to numpy form:
def derive_and_lambdify(x, f):
return lambdify(x, f.diff(x))
g = derive_and_lambdify(x, x**2)
print(g(5))
From then on, you can use g similar to other numpy functions. Here is a more elaborate example:
from sympy import lambdify, sin
from sympy.abc import x
f = sin(1 / (1 + x ** 2))
g = lambdify(x, f.diff(x))
import numpy as np
from matplotlib import pyplot as plt
xs = np.linspace(-5, 5, 100)
ys = g(xs)
plt.plot(xs, ys)
plt.show()

Sympy .replace() doesn't detect product

I'm trying to make some replacements, but .replace() is confusingly missing occurrences:
from sympy import *
x, y = symbols('x y')
f = Function('f')
expr = x*f(x)*f(y)
expr.replace(x*f(x), 1)
# Output: x*f(x)*f(y)
# Expected: f(y)
Is this a bug?
It does work when I use .subs() instead of .replace(), but I have no idea why this would be needed.
(also, I wanna use this in the context of a Sum expression where .subs() would not work).

How to rewrite an abstract derivative of a sum as a sum of derivatives in sympy?

I want to convert (L + L')' into L' + L'' using sympy and some sort of expanding or simplifying function.
import sympy
sympy.init_printing() # math as latex
z, L = sympy.symbols('z,L')
expr = sympy.Derivative(L + sympy.Derivative(L,z), z)
expr
I tried standard functions like expand, which rewrites the expression (even with a flag force=True), or doit which returns zero.
Question. Is there a way to apply sp.Derivative to sum of two functions and expand it to sum of sp.Derivative's?
If we work with derivatives, it is better to use sympy.Function instead of sympy.Symbol. In order to expand the derivative, one can use .doit() method.
Example.
import sympy
sympy.init_printing() # math as latex
z = sympy.Symbol('z')
f = sympy.Function("f")(z)
expr = sympy.Derivative(sympy.Derivative(f) + f)
expr
expr.doit()

How to prevent generation of substitions

Sympy sometimes automatically generates substitutions in my experessions:
How can I prevent this? Or, how can I remove the substitution from the expression?
from sympy import *
R, T = symbols('R T', cls=Function)
u = symbols('u', cls=Function)
x, y, z= symbols('x y z')
R(u(x,y)).diff(x)
gives
Derivative(u(x, y), x)*Subs(Derivative(R(_xi_1), _xi_1), (_xi_1,), (u(x, y),))
I'd like to have
Derivative(u(x, y), x)*Derivative(R(u(x, y), (u(x, y)))
PS: http://docs.sympy.org/latest/modules/core.html#subs says "When evaluating derivatives at a point that is not a symbol, a Subs object is returned."
The following will give you what you ask for
>>> s=R(u(x,y)).diff(x)
>>> s.replace(Subs, lambda a,b,c: a.xreplace(dict(zip(b,c))))
(It will revert to a Subs instance if you apply the doit method.)