I'm trying to get a subexpression of a larger expression under a common denominator. However, when I use replace() for this, it applies to sums of functions, even though there's no ratio.
>>> x = Function('x')(t)
>>> f = Function('f')(t)
>>> g = Function('g')(t)
>>> a,b = Wild('a'), Wild('b')
>>> f + g
f(t) + g(t)
>>> (f + g).replace(a/x+b/x, (a+b)/x)
f(t)⋅x(t) + g(t)⋅x(t)
─────────────────────
x(t)
How do I get this to apply only where the original source expression has an explicit / x(t) in both terms?
Note: if either f & g, or x, are Symbols, rather than UndefinedFunctions, no replacement happens, which is what I want.
Related
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)
I am scouring the web but I cannot find how to generate random math expressions with sympy. Is it even possible?
I would like to build an expression tree by randomly selecting functions (product, sum, cosine...) and symbols from a set of predefined functions and symbols.
For instance, given the set [+,.] of sum and product and the symbols [x,y] I'd like to generate expressions such as x+y, (x+y).x, y+(x.x+y)+x etc, controlling parameters as the tree depth, width and the number of nodes.
Any hints?
Something like the following might help you get started:
from random import choice, randint
from sympy import FunctionClass, Add, Mul, cos, sin, binomial, arity, S
def args(n, atoms, funcs):
a = funcs+atoms
g = []
for _ in range(n):
ai = choice(a)
if isinstance(ai, FunctionClass):
g.append(ai(*args(arity(ai), atoms, funcs)))
else:
g.append(ai)
return g
def expr(ops, atoms, funcs=()):
types = [Add, Mul]
atoms = tuple(atoms)
while 1:
e = S.Zero
while e.count_ops() < ops:
_ = choice(types)(*args(randint(1,3), atoms, funcs))
e = choice(types)(e, _)
if e is S.NaN: break
else:
return e
>>> [expr(5, (-1,0,1,x,y)) for do in range(2)]
[(x - 1)*(2*x + y + 2), x + y*(x + 4*y - 2) + y]
>>> expr(5, (-1,0,1,x,y), (cos, binomial))
x*y**2 + x + cos(1)
>>> expr(5, (-1,0,1,x,y), (cos, binomial))
(y + zoo*binomial(y, x) - 2)*(y + cos(1) + 1)
To generate rational expressions you could change make the 2nd _ arg be _**choice((1,-1)).
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).
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()
I would like to find out programatically if a SymPy expression contains a symbol. E.g., for
import sympy
x = sympy.Symbol('x')
y = sympy.Symbol('y')
a = 4 + x**2 + y
b = 4 + y**2
a contains both x and y, b contains only y.
>>> x in a.free_symbols, y in a.free_symbols
(True, True)
>>> x in b.free_symbols, y in b.free_symbols
(False, True)
You can also use .atoms(Symbol) to check that. atoms(Symbol) differs from .free_symbols in some cases. free_symbols doesn't return dummy symbols, like integration variables.
it's usually what you want, since expressions don't mathematically depend on dummy symbols
example:
>>> Integral(f(x), (x, 0, 1)).atoms(Symbol)
set([x])
>>> Integral(f(x), (x, 0, 1)).free_symbols
set([])