simplify (a + b*(c+d)) / (c+d) in sympy - python

Given an expression like
a + b⋅(c + d)
─────────────
c + d
I would like to use sympy to simplify it to:
a
───── + b
c + d
It works when I substitute (c+d) to e and back:
import sympy as sp
a,b,c,d,e = sp.symbols('a b c d e')
expr = (a + b*(c+d)) / (c+d)
expr = expr.subs({(c+d):e}).simplify().subs({e:c+d})
print( sp.pretty(expr) )
# prints
# a
# ───── + b
# c + d
Why is this? Is there a way to do it without substitution?

Using apart helps simplifying fractions :
expr = sp.apart((a + b*(c + d))/(c + d), a)
Output is:
a
───── + b
c + d

Related

How to multiply all terms of a fraction by something in sympy?

I have this equation:
u = -J/4 + (J*exp(-J*β) + bz*(-exp(bz*β) + exp(-bz*β)))/(exp(bz*β) + 1 + exp(-bz*β) + exp(-J*β))
The fraction part is this:
(J*exp(-J*β) + bz*(-exp(bz*β) + exp(-bz*β)))/(exp(bz*β) + 1 + exp(-bz*β) + exp(-J*β))
I'm trying to multiply the fraction by exp(-bz*β) in both the numerator and the denominator to get this exactly
u = -J/4 + (J*exp(-(J+bz)*β) + bz*(-1 + exp(-2*bz*β)))/(1 + exp(-bz*β) + exp(-2*bz*β) + exp(-(J+bz)*β))
How do I do it?
epath might be able to help with this but I would just take the expression apart and put it back together:
>>> eq.args
(-J/4, (J*exp(-J*ß) + bz*(-exp(bz*ß) + exp(-bz*ß)))/(exp(bz*ß) + 1 + exp(-bz*ß)
+ exp(-J*ß)))
>>> j, f = _
>>> c = exp(-bz*β)
>>> n, d = fraction(f)
>>> powsimp(expand(c*n))/(powsimp(expand(c*d)))
(J*exp(-ß*(J + bz)) - bz + bz*exp(-2*bz*ß))/(exp(-J*ß - bz*ß) + 1 + exp(-bz*ß) +
exp(-2*bz*ß))
>>> collect(_,bz)
(J*exp(-ß*(J + bz)) + bz*(-1 + exp(-2*bz*ß)))/(exp(-J*ß - bz*ß) + 1 + exp(-bz*ß)
+ exp(-2*bz*ß))
>>> factor_terms(_)
(J*exp(-ß*(J + bz)) + bz*(-1 + exp(-2*bz*ß)))/(1 + exp(-ß*(J + bz)) + exp(-bz*ß)
+ exp(-2*bz*ß))
>>> j + _
-J/4 + (J*exp(-ß*(J + bz)) + bz*(-1 + exp(-2*bz*ß)))/(1 + exp(-ß*(J + bz)) + exp
(-bz*ß) + exp(-2*bz*ß))
Note the use of expand(c*n)/expand(c*d) -- without expansion, the c will cancel out automatically in the ratio.

Setting terms of specific powers in a sympy expression to zero

I have a sympy expression of the following form:
a, b = symbols('a b')
expr = a + a/b + a/b**2 + a**2/b**2 + a/b**3
I want to set any terms where the exponent of b is larger than the exponent of a to zero, such that the result is like this:
newexpr = a + a/b + a**2/b**2
How can I achieve this?
I managed to solve this by doing:
import sympy as sp
a, b, c = sp.symbols('a b c')
expr = a + a/b + a/b**2 + a**2/b**2 + a/b**3
newexpr = sp.limit(expr.subs(a/b, c), b, sp.oo).subs(c, a/b)
newexpr
out[1]: a + a/b + a**2/b**2
Here is a short plan for this:
we make the substitution 1/b -> c
we rewrite the resulting expression as a multivariate polynomial in a,c
we decompose the poly into monomials and only keep those terms that have exp_a >= exp_c , and we finish by substituting back c -> 1/b
#!/usr/bin/python3
from sympy import *
a, b = symbols('a b')
expr = a + a/b + a/b**2 + a**2/b**2 + a/b**3
def truncate(e):
c = symbols('c')
e1 = e.subs(S(1)/b,c)
p = 0
for m in poly(e1,a,c).monoms():
exp_a,exp_c = m
if exp_c <= exp_a:
p += a**exp_a * (1/b)**exp_c
return p
truncated_expr = truncate(expr)
print(truncated_expr)
OUTPUT:
a**2/b**2 + a + a/b

Align the latex output of sympy?

The display of LaTeX equations in sympy appear as an unbroken line:
a = b + c + d(e - fg) + hij
I would like this to appear as something like
a = b
+ c
+ d(e
-
fg)
+ hij
or perhaps customizing how long the line can be before wrapping and aligning, like for example:
a = b + c
+ d(e - fg)
+ hij
Is such a thing possible?

Check equality using conditions sympy

I want to proove that (x/a)^2 + (y/b)^2 + (z/c)^2 == 1, if conditions x/a + y/b + z/c ==1 and a/x + b/y + c/z == 0 are given. I know that, for example, in Maple I can simply write
eq1 := x/a + y/b + z/c = 1;
eq2 := a/x + b/y + c/z = 0;
f := x^2/a^2 + y^2/b^2 + z^2/c^2 = 1;
simplify(lhs(f)-rhs(f), {eq1, eq2});
But I'm struggling to come up with solution using sympy.
Without loss of generality, let x <= x/a, etc...
>>> e1=Eq(x + y + z , 1)
>>> e2=Eq(1/x+1/y+1/z , 0)
>>> e3=Eq(x**2 + y**2 + z**2, 1)
Eq(x**2 + y**2 + z**2, 1)
>>> [e3.subs(i).expand() for i in solve((e1,e2))]
[True, True]
Thus, e3 is true for all values that satisfy e1 and e2

generate polynomial in python

I am trying to make a function which can print a polynomial of order n of x,y
i.e. poly(x,y,1) will output c[0] + c[1]*x + c[2]*y
i.e. poly(x,y,2) will output c[0] + c[1]*x + c[2]*y + c[3]*x**2 + c[4]*y**2 + c[5]*x*y
Could you give me some ideas? Maybe itertools?
You could try to start from something like
def poly(x,y,n):
counter = 0
for nc in range(n+1):
for i in range(nc+1):
print "c[", counter, "]",
print " * ", x, "**", i,
print " * ", y, "**", nc-i,
print " + ",
counter += 1
For example
poly("x", "y", 2)
will produce
c[ 0 ] * x ** 0 * y ** 0 + c[ 1 ] * x ** 0 * y ** 1 + c[ 2 ] * x ** 1 * y ** 0 + c[ 3 ] * x ** 0 * y ** 2 + c[ 4 ] * x ** 1 * y ** 1 + c[ 5 ] * x ** 2 * y ** 0 +
Build in ifs, if you want to suppress undesired output.
Since you wanted a functional solution with itertools, here's a one-liner:
import itertools as itt
from collections import Counter
n = 3
xy = ("x", "y") # list of variables may be extended indefinitely
poly = '+'.join(itt.starmap(lambda u, t: u+"*"+t if t else u, zip(map(lambda v: "C["+str(v)+"]", itt.count()),map(lambda z: "*".join(z), map(lambda x: tuple(map(lambda y: "**".join(map(str, filter(lambda w: w!=1, y))), x)), map(dict.items, (map(Counter, itt.chain.from_iterable(itt.combinations_with_replacement(xy, i) for i in range(n+1))))))))))
That would give you
C[0]+C[1]*x+C[2]*y+C[3]*x**2+C[4]*y*x+C[5]*y**2+C[6]*x**3+C[7]*y*x**2+C[8]*y**2*x+C[9]*y**3
Note, the order of coefficients is slightly different. This will work not only for any n, but also for any number of variables (x, y, z, etc...)
Just for laughs
Slightly more generalized:
from itertools import product
def make_clause(c, vars, pows):
c = ['c[{}]'.format(c)]
vp = (['', '{}', '({}**{})'][min(p,2)].format(v,p) for v,p in zip(vars,pows))
return '*'.join(c + [s for s in vp if s])
def poly(vars, max_power):
res = (make_clause(c, vars, pows) for c,pows in enumerate(product(*(range(max_power+1) for v in vars))))
return ' + '.join(res)
then poly(['x', 'y'], 2) returns
"c[0] + c[1]*y + c[2]*(y**2) + c[3]*x + c[4]*x*y + c[5]*x*(y**2) + c[6]*(x**2) + c[7]*(x**2)*y + c[8]*(x**2)*(y**2)"

Categories

Resources