Sympy: simplification of elementary expression fails - python-2.7

I don't understand why the expression a * (... + 1) - a is not being removed while simplification. The example below shows the bug:
import sympy as sy
a,b,c = sy.symbols('a b c')
expr = a * (b - c + 1) - a + (b - c) * (a - b)
print expr # printed: a*(b - c + 1) - a + (a - b)*(b - c)
print expr.simplify() # printed: a*(b - c + 1) - a + (a - b)*(b - c)
On the other side, if I change the expression by
expr = a * (b - c + 1) - a
and call simplify(), I will obtain the expected result a * (b - c).
Sympy version is 1.1rc1.

simplify usually can only do a limited amount of magic. It could be arguably more in this case, but if you want that, you need to make a feature request. In any case it’s better to tell SymPy what specific kind of modifications you want to make.
Here, the following will probably satisfy you:
print(expr.factor()) # (2*a - b)*(b - c)

Related

how to work with equations with mathematical constraints on variables in sympy

I try to simplify and solve equations using sympy with mathematical constraints. I didn't find in tutorials in the net how to inform sympy to take into account for those constraints.
I have an example equation (see next code) and I want sympy to take into account for the listed constraints on these variables when working on it. But i didn't succeed to find how to inform sympy about those constraints (limitations / boundaries).
import sympy
D1,D2,D3,A,B,C,d,e,f = sympy.symbols('D1 D2 D3 A B C d e f')
equation = (-A*e + e*(A*d + (1.0 - d)*(D1 + 0.5*D2 + 0.5*D3)) + (1.0 - e)*( D1*d - D1 + 0.5*D2*d - 0.5*D2 + 0.5*D3*d - 0.5*D3 + A**2*(1.0 - d) + 0.5*A*B*(2.0 - 2.0*d) + 0.5*A*C*(2.0 - 2.0*d)))**2
#constraints: my trouble: how to take them into account in simplify, collect, solve?
A+B+C=1
D1+0.5*D2+0.5D3 = f
0.<=D1,D2,D3,A,B,C,d,e,f<=1.
print(sympy.latex(sympy.collect(equation,[f,A]))
thanks for enlightening me.

sympy CSE: avoid pow/powf

When Sympy generates C code,
is there a way to enforce CSE optimizations for pow (or powf) occurrences in an expression?
For example, this code snippet
c, s = symbols('c s')
myexpr = c**6/1800 - c**5/100 - 0.00833333333333333*c**4*s**2 + 19*c**4/200 + 0.1*c**3*s**2 - 9*c**3/20 + c**2*s**4/120 - 0.57*c**2*s**2 + 43*c**2/40 - c*s**4/20 + 1.35*c*s**2 + 23*c/50 - 0.000555555555555556*s**6 + 19*s**4/200 - 1.075*s**2 - 2107/1800
import sympy
from sympy.codegen.ast import real, float64
sub_exprs,final_expr = sympy.cse([myexpr])
for var,expr in sub_exprs : print "const real", printing.ccode(expr, standard='C99', assign_to=var, type_aliases={real: float64})
print "return ",printing.ccode(final_expr[0], standard='C99', type_aliases={real: float64}),";"
produces the following disappointing output:
const real x0 = pow(c, 2);
const real x1 = pow(c, 3);
const real x2 = pow(c, 4);
const real x3 = pow(s, 2);
const real x4 = pow(s, 4);
return (1.0/1800.0)*pow(c, 6) - 1.0/100.0*pow(c, 5) + 1.3500000000000001*c*x3 - 1.0/20.0*c*x4 + (23.0/50.0)*c - 0.00055555555555555599*pow(s, 6) - 0.56999999999999995*x0*x3 + (1.0/120.0)*x0*x4 + (43.0/40.0)*x0 + 0.10000000000000001*x1*x3 - 9.0/20.0*x1 - 0.0083333333333333297*x2*x3 + (19.0/200.0)*x2 - 1.075*x3 + (19.0/200.0)*x4 - 2107.0/1800.0 ;
Pow optimizations have been completely ignored.
What is the workaround for this?
Remark: I saw that this issue is partially mentioned here:
"The code printers don’t print optimal code in many cases. An example of this is powers in C. x**2 prints as pow(x, 2) instead of x*x. Other optimizations (like mathematical simplifications) should happen before the code printers."
The CSE routine in sympy is not perfect (improved CSE is listed as an area for improvement), e.g.:
>>> sympy.cse([x**4, x**3*y])
([], [x**4, x**3*y])
Expanding pow in the printer or before the printer has been discussed some time, there is now a create_expand_pow optimization which can help some:
>>> expand_opt = create_expand_pow_optimization(3)
>>> expand_opt(x**5 + x**3)
x**5 + x*x*x
Note however that most compilers will already generate optimal assembly (regardless of CSE in the source code) if you pass them the right optimization flags.

Derivative of a function with different formulas on different intervals

Is there a canonical way of declaring a function by parts in Sympy? I tried
import sympy
import sympy.functions.special.delta_functions as special
sympy.init_printing()
x = sympy.symbols('x', real=True)
V = x*x * (special.Heaviside(x + 1) - special.Heaviside(x - 1)) \
+ (1 + 2*sympy.log(x)) * special.Heaviside(x - 1) \
+ (1 + 2*sympy.log(-x)) * special.Heaviside(-x - 1)
which defines a differentiable function, but
print(V.diff(x).simplify())
# Prints: (x*(x**2*(-DiracDelta(x - 1) + DiracDelta(x + 1)) - 2*x*(Heaviside(x - 1) - Heaviside(x + 1)) - (2*log(-x) + 1)*DiracDelta(x + 1) + (2*log(x) + 1)*DiracDelta(x - 1)) + 2*Heaviside(-x - 1) + 2*Heaviside(x - 1))/x
Is there a way to somehow tell Sympy to simplify DiracDelta(x - a)*f(x) to DiracDelta(x - a)*f(a)?
Piecewise-defined functions are implemented by Piecewise class. Your function would be expressed as
V = sympy.Piecewise((1 + 2*sympy.log(-x), x < -1),
(x**2, x < 1),
(1 + 2*sympy.log(x), True))
print(V.diff(x))
which prints Piecewise((2/x, x < -1), (2*x, x < 1), (2/x, True))
The (expr, cond) pairs in Piecewise are processed in the order given: the first cond that evaluates to True (if the preceding evaluated to False) causes the corresponding expr to be returned.

general expression substitution in sympy

I have two univariate functions, f(x) and g(x), and I'd like to substitute g(x) = y to rewrite f(x) as some f2(y).
Here is a simple example that works:
In [240]: x = Symbol('x')
In [241]: y = Symbol('y')
In [242]: f = abs(x)**2 + 6*abs(x) + 5
In [243]: g = abs(x)
In [244]: f.subs({g: y})
Out[244]: y**2 + 6*y + 5
But now, if I try a slightly more complex example, it fails:
In [245]: h = abs(x) + 1
In [246]: f.subs({h: y})
Out[246]: Abs(x)**2 + 6*Abs(x) + 5
Is there a general approach that works for this problem?
The expression abs(x)**2 + 6*abs(x) + 5 does not actually contain abs(x) + 1 anywhere, so there is nothing to substitute for.
One can imagine changing it to abs(x)**2 + 5*(abs(x) + 1) + abs(x), with the substitution result being abs(x)**2 + 5*y + abs(x). Or maybe changing it to abs(x)**2 + 6*(abs(x) + 1) - 1, with the result being abs(x)**2 + 6*y - 1. There are other choices too. What should the result be?
There is no general approach to this task because it's not a well-defined task to begin with.
In contrast, the substitution f.subs(abs(x), y-1) is a clear instruction to replace all occurrences of abs(x) in the expression tree with y-1. It returns 6*y + (y - 1)**2 - 1.
The substitution above of abs(x) + 1 in abs(x)**2 + 6*abs(x) + 5 is a clear instruction too: to find exact occurrences of the expression abs(x) + 1 in the syntax tree of the expression abs(x)**2 + 6*abs(x) + 5, and replace those subtrees with the syntax tree of the expression abs(x) + 1. There is a caveat about heuristics though.
Aside: in addition to subs SymPy has a method .replace which supports wildcards, but I don't expect it to help here. In my experience, it is overeager to replace:
>>> a = Wild('a')
>>> b = Wild('b')
>>> f.replace(a*(abs(x) + 1) + b, a*y + b)
5*y/(Abs(x) + 1) + 6*y*Abs(x*y)/(Abs(x) + 1)**2 + (Abs(x*y)/(Abs(x) + 1))**(2*y/(Abs(x) + 1))
Eliminate a variable
There is no "eliminate" in SymPy. One can attempt to emulate it with solve by introducing another variable, e.g.,
fn = Symbol('fn')
solve([Eq(fn, f), Eq(abs(x) + 1, y)], [fn, x])
which attempts to solve for "fn" and "x", and therefore the solution for "fn" is an expression without x. If this works
In fact, it does not work with abs(); solving for something that sits inside an absolute value is not implemented in SymPy. Here is a workaround.
fn, ax = symbols('fn ax')
solve([Eq(fn, f.subs(abs(x), ax)), Eq(ax + 1, y)], [fn, ax])
This outputs [(y*(y + 4), y - 1)] where the first term is what you want; a solution for fn.

Moving out before brackets with XOR

If I had the sum of products like z*a + z*b + z*c + ... + z*y, it would be possible to move the z factor, which is the same, out before brackets: z(a + b + c + ... y).
I'd like to know how it is possible (if it is) to do the same trick if bitwise XOR is used instead of multiplication.
z^a + z^b + ... z^y -> z^(a + b + ... + y)
Perhaps a, b, c ... should be preprocessed, such as logically negated or something else, before adding? z could change, so preprocessing, if it's needed, shouldn't depend on particular z value.
From Wikipedia:
Distributivity: with no binary function, not even with itself
So, no, unfortunately, you can't do anything like that with XOR.
To prove that a general formula does not hold you only need to prove a contradiction in a limited case.
We can reduce it to show that this does not hold:
(a^b) * c = (a^c) * (b^c)
It is trivial to show that one base case fails as such:
a = 3
b = 1
c = 1
(a^b) * c = (3^1) * 1 = 2
(a^c) * (b^c) = 2 * 0 = 0
Using the same case you can show that (a*b) ^ c = (a^c) * (b^c) and (a + b) ^ c = (a^c) + (b^c) do not hold either.
Hence, equality does not hold in a general case.
Equality can hold in special cases though, which is an entirely different subject.