python sympy lambdify not working inside function - sympy

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()

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)

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).

My code is not plotting a square wave(python) using a Fourier series

x=1
n=1
series1=0
z=[]
t= arange(-2,2,.1)
for i in t:
series1=series1 + ((2/n/pi)*(sin(n*x)))
x+=1
z.append(series1)
my_list=z
newlist = [x+.5 for x in my_list]
plot(newlist,t)
xlabel('x-range')
ylabel('A(X)')
title('square wave')
The image represents the function I am trying to graph:
My plot graph, which does not look like a square wave:
EDIT:
More pythonic version:
import matplotlib.pyplot as plt
import numpy as np
N_max = 101 #the larger the value the steeper the transition from 0 to 1 and the more "square"
n_odds = np.arange(1,N_max,2)
xs = np.arange(-6,6,0.1)
ys = [0.5+sum(np.multiply(2/(n_odds*np.pi), np.sin(n_odds*x))) for x in xs]
plt.plot(xs, ys)
plt.show()
Here is a version that worked for me. Your biggest mistake was not cycling through odd N's. Leave a comment if you have questions about the code.
import matplotlib.pyplot as plt
import numpy as np
N_max = 101
n_odds = np.arange(1,N_max,2)
xs = np.arange(-6,6,0.1)
ys = []
for x in xs:
sum_terms = []
for n_odd in n_odds:
frac_term = 2/(n_odd*np.pi)
sin_term = np.sin(n_odd*x)
sum_term = frac_term*sin_term
sum_terms.append(sum_term)
y = 0.5+sum(sum_terms)
ys.append(y)
plt.plot(xs, ys)
plt.show()

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()

SymPy: simplifying of inverse function

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().