Collecting the coefficients of a term in Sympy - sympy

I have the following expression in Sympy
s = e0*a01*d1**2*u0 - e0*a01*d1**2*u1 - e0*a11*d1**2*u0 - e0*a11*d1**2*u1 + e0*d0*a00*d1*u1 + e0*d0*a01*d1*u0 + e0*d0*a10*d1*u0 - e0*d0*a11*d1*u1 + e0*d0*b0*u0 - e0*d0*b1*u1 + e0*d1*a00*d1*u0 - e0*d1*a01*d1*u1 - e0*d1*a10*d1*u1 - e0*d1*a11*d1*u0 - e0*d1*b0*u1 - e0*d1*b1*u0 - e1*a00*d1**2*u0 + e1*a00*d1**2*u1 + e1*a10*d1**2*u0 + e1*a10*d1**2*u1 - e1*d0*a00*d1*u0 + e1*d0*a01*d1*u1 + e1*d0*a10*d1*u1 + e1*d0*a11*d1*u0 + e1*d0*b0*u1 + e1*d0*b1*u0 + e1*d1*a00*d1*u1 + e1*d1*a01*d1*u0 + e1*d1*a10*d1*u0 - e1*d1*a11*d1*u1 + e1*d1*b0*u0 - e1*d1*b1*u1
So first I simpify it:
s = sympify(s,locals=T)
(T contains all these symbols in the string, that are non commutative). And I want to get the coefficient of
d1**2*u0
after "factoring" it. So I did the following:
e=sympify(d1**2*u0,locals=T)
collected_expr = collect(s,e,exact=True)
print(collected_expr)
coeff = collected_expr.coeff(e)
print(coeff)
The result of collected_expr is ok:
d1**2*u0*(e0*a01 - e0*a11 - e1*a00 + e1*a10) - e0*a01*d1**2*u1 - e0*a11*d1**2*u1 + e0*d0*a00*d1*u1 + e0*d0*a01*d1*u0 + e0*d0*a10*d1*u0 - e0*d0*a11*d1*u1 + e0*d0*b0*u0 - e0*d0*b1*u1 + e0*d1*a00*d1*u0 - e0*d1*a01*d1*u1 - e0*d1*a10*d1*u1 - e0*d1*a11*d1*u0 - e0*d1*b0*u1 - e0*d1*b1*u0 + e1*a00*d1**2*u1 + e1*a10*d1**2*u1 - e1*d0*a00*d1*u0 + e1*d0*a01*d1*u1 + e1*d0*a10*d1*u1 + e1*d0*a11*d1*u0 + e1*d0*b0*u1 + e1*d0*b1*u0 + e1*d1*a00*d1*u1 + e1*d1*a01*d1*u0 + e1*d1*a10*d1*u0 - e1*d1*a11*d1*u1 + e1*d1*b0*u0 - e1*d1*b1*u1
But coeff is not ok, as it returns 1, but I really want
e0*a01 - e0*a11 - e1*a00 + e1*a10
EDIT: I also tried
coeff = collected_expr.coeff(u0).coeff(d1).coeff(d1)
and
coeff = collected_expr.coeff(u0).coeff(d1**2)
But both things returned 0

The docstring of Expr.coeff says
When x is noncommutative, the coefficient to the left (default) or
right of x can be returned. The keyword 'right' is ignored when
x is commutative.
collect does not seem to be noncommutative-aware, however, so the factors that were on the right may collect to the left.
>>> var("A B", commutative=False)
(A, B)
>>> collect(A*B+B*A**2,B)
B*(A + A**2)

Related

Sympy solve cannot find real solution when solving first and substituting later

I have a system of two equations that calculate the coordinates of two points T1(u1,v1) and T2(u2,v2), where lines starting from point A to those points are tangent with a given circle. Point A is always outside of the circle, so there should always be two solutions.
The system of equations is given as follows:
eq1 = Eq((xpos-u)**2 + (ypos-v)**2, tglensq)
eq2 = Eq((oxpos-u)**2 + (oypos-v)**2, radsq)
where xpos,ypos are coordinates of A, and oxpos, oypos are coordinates of the center of the circle. tglensq represents the length of the tangent squared, and radsq the radius of the circle squared.
The solutions need to be calculated continuously in a loop.
I want to solve the equation first for u and v, and then plugin the other values (as described here). Solving for each iteration of the loop turns out to be quite expensive, although it always produces the two solutions.
After getting the solution, in the loop I substitute the other values, like so:
u1 = first_solution[0].subs([(xpos, robot_pos[0]), (ypos, robot_pos[1]), (oxpos, obstacle_pos[0]), (oypos, obstacle_pos[1]), (tglensq, tangent_len_squared), (minkradsq, minkowski_radius_sq)])
However, sympy fails to find the real solutions, and ends up giving imaginary ones, like:
628644.458063364 - 3693.82126269719*I
I saw here a similar issue about solving first then substituting, but I am not sure how to proceed from here. Any help would be greatly appreciated :).
Does defining the location of one circle relative to the other help? Let dx,dy = Point(oxpos,oypos)-Point(xpos,ypos) so the equations are
>>> dx,dy = symbols('dx,dy') # and your other symbols
>>> eq1,eq2 = Eq((u)**2 + (v)**2, tglensq),Eq((dx-u)**2 + (dy-v)**2, radsq)
>>> sol=solve((eq1,eq2), (u,v))
>>> sol[0]
(-(-dx**2 - dy**2 + 2*dy*(-dx*sqrt(-dx**4 - 2*dx**2*dy**2 + 2*dx**2*radsq + 2*dx**2*tglensq - dy**4 + 2*dy**2*radsq + 2*dy**2*tglensq - radsq**2 + 2*radsq*tglensq - tglensq**2)/(2*(dx**2 + dy**2)) + dy*(dx**2 + dy**2 - radsq + tglensq)/(2*(dx**2 + dy**2))) + radsq - tglensq)/(2*dx), -dx*sqrt(-dx**4 - 2*dx**2*dy**2 + 2*dx**2*radsq + 2*dx**2*tglensq - dy**4 + 2*dy**2*radsq + 2*dy**2*tglensq - radsq**2 + 2*radsq*tglensq - tglensq**2)/(2*(dx**2 + dy**2)) + dy*(dx**2 + dy**2 - radsq + tglensq)/(2*(dx**2 + dy**2)))
>>> sol[1]
(-(-dx**2 - dy**2 + 2*dy*(dx*sqrt(-dx**4 - 2*dx**2*dy**2 + 2*dx**2*radsq + 2*dx**2*tglensq - dy**4 + 2*dy**2*radsq + 2*dy**2*tglensq - radsq**2 + 2*radsq*tglensq - tglensq**2)/(2*(dx**2 + dy**2)) + dy*(dx**2 + dy**2 - radsq + tglensq)/(2*(dx**2 + dy**2))) + radsq - tglensq)/(2*dx), dx*sqrt(-dx**4 - 2*dx**2*dy**2 + 2*dx**2*radsq + 2*dx**2*tglensq - dy**4 + 2*dy**2*radsq + 2*dy**2*tglensq - radsq**2 + 2*radsq*tglensq - tglensq**2)/(2*(dx**2 + dy**2)) + dy*(dx**2 + dy**2 - radsq + tglensq)/(2*(dx**2 + dy**2)))
To calculate u,v try
>>> dif = (Point(oxpos,oypos)-Point(xpos,ypos)).subs(dict(zip((xpos,ypos,oxpos,oypos),(1,2,3,4))))
>>> Tuple(*sol).subs(dict(zip((tglensq,radsq),(5,6)))).subs(dict(zip((dx,dy),dif)))
Replace 1,2,3,4,5,6 with the actual values. Does that give you two real solutions?

Integrating a function with sympy - sympy.polys.polyerrors.PolynomialDivisionFailed error

I'm new to using Sympy, and wish to use it to integrate the following function. Although, I get this error which I'm not sure how to resolve.
import sympy as sy
A = sy.Symbol('A')
B = sy.Symbol('B')
C = sy.Symbol('C')
D = sy.Symbol('D')
x = sy.Symbol('x', positive=True)
y = sy.Symbol('y', positive=True)
def func(x,y):
return (1.0/(4.0*x*y))*(A*sy.log( ((y+x)**2 + C**2)/((y-x)**2 + C**2) ) - B*sy.log( ((y+x)**2 + D**2)/((y-x)**2 + D**2) ))
sy.integrate(func(x,y), (x,0,10))
Although, when I run this I get the following error and I'm not sure how to resolve this.
sympy.polys.polyerrors.PolynomialDivisionFailed: couldn't reduce degree in a polynomial division
algorithm when dividing [(-1.13305359211433e+221*y**2 + 5.66526796057163e+220*D**2 +
5.66526796057163e+220*C**2)/1.57368554460323e+219, 0.0, (3.39916077634298e+221*y**4 -
1.13305359211433e+221*y**2*D**2 - 1.13305359211433e+221*y**2*C**2 + 5.66526796057163e+220*D**4 +
2.26610718422865e+221*D**2*C**2 + 5.66526796057163e+220*C**4)/1.57368554460323e+219, 0.0,
(-3.39916077634298e+221*y**6 - 1.69958038817149e+221*y**4*D**2 - 1.69958038817149e+221*y**4*C**2
- 1.69958038817149e+221*y**2*D**4 + 6.79832155268595e+221*y**2*D**2*C**2 -
1.69958038817149e+221*y**2*C**4 + 1.69958038817149e+221*D**4*C**2 +
1.69958038817149e+221*D**2*C**4)/1.57368554460323e+219, 0.0, (1.13305359211433e+221*y**8 +
2.26610718422865e+221*y**6*D**2 + 2.26610718422865e+221*y**6*C**2 +
1.13305359211433e+221*y**4*D**4 + 4.5322143684573e+221*y**4*D**2*C**2 +
1.13305359211433e+221*y**4*C**4 + 2.26610718422865e+221*y**2*D**4*C**2 +
2.26610718422865e+221*y**2*D**2*C**4 + 1.13305359211433e+221*D**4*C**4)/1.57368554460323e+219,
0.0] by [(-2.0203139355353e+661*y**6 + 3.93961217429382e+662*y**4*D**2 +
3.93961217429382e+662*y**4*C**2 - 2.42437672264235e+662*y**2*D**4 -
3.03047090330294e+662*y**2*D**2*C**2 - 2.42437672264235e+662*y**2*C**4 +
2.52539241941912e+661*D**6 - 1.51523545165146e+661*D**4*C**2 - 1.51523545165146e+661*D**2*C**4 +
2.52539241941912e+661*C**6)/3.15674052427389e+659, 0.0, (6.06094180660588e+661*y**8 -
8.08125574214117e+662*y**6*D**2 - 8.08125574214117e+662*y**6*C**2 +
3.18199444846809e+662*y**4*D**4 + 2.47488457103073e+663*y**4*D**2*C**2 +
3.18199444846809e+662*y**4*C**4 - 1.51523545165147e+661*y**2*D**6 -
7.92973219697602e+662*y**2*D**4*C**2 - 7.92973219697602e+662*y**2*D**2*C**4 -
1.51523545165147e+661*y**2*C**6 + 2.52539241941911e+661*D**8 + 1.51523545165147e+661*D**6*C**2 -
2.02031393553529e+661*D**4*C**4 + 1.51523545165147e+661*D**2*C**6 +
2.52539241941911e+661*C**8)/3.15674052427389e+659, 0.0, (-6.06094180660588e+661*y**10 +
3.93961217429382e+662*y**8*D**2 + 3.93961217429382e+662*y**8*C**2 -
6.06094180660588e+661*y**6*D**4 + 9.6975068905694e+662*y**6*D**2*C**2 -
6.06094180660588e+661*y**6*C**4 + 1.38707976084194e+646*y**4*D**6 -
4.24265926462411e+662*y**4*D**4*C**2 - 4.24265926462411e+662*y**4*D**2*C**4 +
1.38707976084194e+646*y**4*C**6 - 3.03047090330294e+661*y**2*D**8 -
2.42437672264235e+662*y**2*D**6*C**2 - 2.42437672264235e+662*y**2*D**4*C**4 -
2.42437672264235e+662*y**2*D**2*C**6 - 3.03047090330294e+661*y**2*C**8 +
3.03047090330294e+661*D**8*C**2 + 1.73384970105243e+646*D**6*C**4 +
1.73384970105243e+646*D**4*C**6 + 3.03047090330294e+661*D**2*C**8)/3.15674052427389e+659, 0.0,
(2.02031393553529e+661*y**12 + 2.02031393553529e+661*y**10*D**2 +
2.02031393553529e+661*y**10*C**2 - 1.51523545165147e+661*y**8*D**4 +
1.01015696776765e+661*y**8*D**2*C**2 - 1.51523545165147e+661*y**8*C**4 -
1.01015696776765e+661*y**6*D**6 - 3.03047090330294e+661*y**6*D**4*C**2 -
3.03047090330294e+661*y**6*D**2*C**4 - 1.01015696776765e+661*y**6*C**6 +
5.05078483883823e+660*y**4*D**8 - 1.01015696776765e+661*y**4*D**6*C**2 -
1.01015696776765e+661*y**4*D**4*C**4 - 1.01015696776765e+661*y**4*D**2*C**6 +
5.05078483883823e+660*y**4*C**8 + 1.01015696776765e+661*y**2*D**8*C**2 +
1.01015696776765e+661*y**2*D**6*C**4 + 1.01015696776765e+661*y**2*D**4*C**6 +
1.01015696776765e+661*y**2*D**2*C**8 + 5.05078483883823e+660*D**8*C**4 +
1.01015696776765e+661*D**6*C**6 + 5.05078483883823e+660*D**4*C**8)/3.15674052427389e+659].
This can happen when it's not possible to detect zero in the coefficient domain. The domain of
computation is RR(B,y,D,C). Zero detection is guaranteed in this coefficient domain. This may
indicate a bug in SymPy or the domain is user defined and doesn't implement zero detection
properly.
Has anyone had this issue before and if so, how exactly can this be solved? I have varied the limits of $x$ but I get the same error!
Thank you in advance!

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.

what does + sign after variable mean?

what will be the output of following code
int x,a=3;
x=+ +a+ + +a+ + +5;
printf("%d %d",x,a);
ouput is: 11 3. I want to know how? and what does + sign after a means?
I think DrYap has it right.
x = + + a + + + a + + + 5;
is the same as:
x = + (+ a) + (+ (+ a)) + (+ (+ 5));
The key points here are:
1) c, c++ don't have + as a postfix operator, so we know we have to interpret it as a prefix
2) monadic + binds more tightly (is higher precedence) than dyadic +
Funny isn't it ? If these were - signs it wouldn't look so strange. Monadic +/- is just a leading sign, or to put it another way, "+x" is the same as "0+x".
The + after a just gets seen as a + before the next value. If you use consistent spacing it is the same as:
x = + + a + + + a + + + 5;
But not all the +s are necessary so it will act the same as doing:
x = a + a + 5;
The value of a is unchanged because you have never used the incrementing operator which is ++ with no white space between the two + symbols. + and ++ are two separate operators.
Since the + operators are never two next to each other but always separated by a white space the statement
x=+ +a+ + +a+ + +5; is actually read as
x=+ (nothing)+a+(nothing) +(nothing) +a+(nothing) +(nothing) +5;
so basically the final equation becomes of the sort
x=a+a+5; and hence the result.
The code seems to be equivalent to:
x= (+(+(a)))+ (+ (+(a)))+ (+(+(5)));
I.e. x = a + a + 5. Which is 11. You know that you can put + or - sign before number, right? Now those + merely indicate sign of variable. Since sign is +, variable remains unchanged I.e. "+5" means "5", so "+a" means "a", and "+ +a" means "+(+a)" which means "a". In same fashion you could write x = + + + 3 + + + + 3 + + + + 5. Or x = - + + - 3 + - + - 3 - - + 5;.
x=+ +a+ + +a+ + +5 : This is equivalent to
x = x=+ +a+ + +a+ + +5 or
we can write it as x = + (+ a) + (+ (+ a)) + (+ (+ 5))
and the +'s are only indicating the signs which will be finally evaluated as
x = a + a + 5.

Discrete Wavelet Transform integer Daub 5/3 lifting issue

I'm trying to run an integer-to-integer lifting 5/3 on an image of lena. I've been following the paper "A low-power Low-memory system for wavelet-based image compression" by Walker, Nguyen, and Chen (Link active as of 7 Oct 2015).
I'm running into issues though. The image just doesn't seem to come out quite right. I appear to be overflowing slightly in the green and blue channels which means that subsequent passes of the wavelet function find high frequencies where there ought not to be any. I'm also pretty sure I'm getting something else wrong as I am seeing a line of the s0 image at the edges of the high frequency parts.
My function is as follows:
bool PerformHorizontal( Col24* pPixelsIn, Col24* pPixelsOut, int width, int pixelPitch, int height )
{
const int widthDiv2 = width / 2;
int y = 0;
while( y < height )
{
int x = 0;
while( x < width )
{
const int n = (x) + (y * pixelPitch);
const int n2 = (x / 2) + (y * pixelPitch);
const int s = n2;
const int d = n2 + widthDiv2;
// Non-lifting 5 / 3
/*pPixelsOut[n2 + widthDiv2].r = pPixelsIn[n + 2].r - ((pPixelsIn[n + 1].r + pPixelsIn[n + 3].r) / 2) + 128;
pPixelsOut[n2].r = ((4 * pPixelsIn[n + 2].r) + (2 * pPixelsIn[n + 2].r) + (2 * (pPixelsIn[n + 1].r + pPixelsIn[n + 3].r)) - (pPixelsIn[n + 0].r + pPixelsIn[n + 4].r)) / 8;
pPixelsOut[n2 + widthDiv2].g = pPixelsIn[n + 2].g - ((pPixelsIn[n + 1].g + pPixelsIn[n + 3].g) / 2) + 128;
pPixelsOut[n2].g = ((4 * pPixelsIn[n + 2].g) + (2 * pPixelsIn[n + 2].g) + (2 * (pPixelsIn[n + 1].g + pPixelsIn[n + 3].g)) - (pPixelsIn[n + 0].g + pPixelsIn[n + 4].g)) / 8;
pPixelsOut[n2 + widthDiv2].b = pPixelsIn[n + 2].b - ((pPixelsIn[n + 1].b + pPixelsIn[n + 3].b) / 2) + 128;
pPixelsOut[n2].b = ((4 * pPixelsIn[n + 2].b) + (2 * pPixelsIn[n + 2].b) + (2 * (pPixelsIn[n + 1].b + pPixelsIn[n + 3].b)) - (pPixelsIn[n + 0].b + pPixelsIn[n + 4].b)) / 8;*/
pPixelsOut[d].r = pPixelsIn[n + 1].r - (((pPixelsIn[n].r + pPixelsIn[n + 2].r) >> 1) + 127);
pPixelsOut[s].r = pPixelsIn[n].r + (((pPixelsOut[d - 1].r + pPixelsOut[d].r) >> 2) - 64);
pPixelsOut[d].g = pPixelsIn[n + 1].g - (((pPixelsIn[n].g + pPixelsIn[n + 2].g) >> 1) + 127);
pPixelsOut[s].g = pPixelsIn[n].g + (((pPixelsOut[d - 1].g + pPixelsOut[d].g) >> 2) - 64);
pPixelsOut[d].b = pPixelsIn[n + 1].b - (((pPixelsIn[n].b + pPixelsIn[n + 2].b) >> 1) + 127);
pPixelsOut[s].b = pPixelsIn[n].b + (((pPixelsOut[d - 1].b + pPixelsOut[d].b) >> 2) - 64);
x += 2;
}
y++;
}
return true;
}
There is definitely something wrong but I just can't figure it out. Can anyone with slightly more brain than me point out where I am going wrong? Its worth noting that you can see the un-lifted version of the Daub 5/3 above the working code and this, too, give me the same artifacts ... I'm very confused as I have had this working once before (It was over 2 years ago and I no longer have that code).
Any help would be much appreciated :)
Edit: I appear to have eliminated my overflow issues by clamping the low pass pixels to the 0 to 255 range. I'm slightly concerned this isn't the right solution though. Can anyone comment on this?
You can do some tests with extreme values to see the possibility of overflow. Example:
pPixelsOut[d].r = pPixelsIn[n + 1].r - (((pPixelsIn[n].r + pPixelsIn[n + 2].r) >> 1) + 127);
If:
pPixelsIn[n ].r == 255
pPixelsIn[n+1].r == 0
pPixelsIn[n+2].r == 255
Then:
pPixelsOut[d].r == -382
But if:
pPixelsIn[n ].r == 0
pPixelsIn[n+1].r == 255
pPixelsIn[n+2].r == 0
Then:
pPixelsOut[d].r == 128
You have a range of 511 possible values (-382 .. 128), so, in order to avoid overflow or clamping, you would need one extra bit, some quantization, or another encoding type!
I'm assuming the data have already been thresholded?
I also don't get why you're adding back in +127 and -64.
OK I can losslessly forward then inverse as long as I store my post forward transform data in a short. Obviously this takes up a little more space than I was hoping for but this does allow me a good starting point for going into the various compression algorithms. You can also, nicely, compress 2 4 component pixels at a time using SSE2 instructions. This is the standard C forward transform I came up with:
const int16_t dr = (int16_t)pPixelsIn[n + 1].r - ((((int16_t)pPixelsIn[n].r + (int16_t)pPixelsIn[n + 2].r) >> 1));
const int16_t sr = (int16_t)pPixelsIn[n].r + ((((int16_t)pPixelsOut[d - 1].r + dr) >> 2));
const int16_t dg = (int16_t)pPixelsIn[n + 1].g - ((((int16_t)pPixelsIn[n].g + (int16_t)pPixelsIn[n + 2].g) >> 1));
const int16_t sg = (int16_t)pPixelsIn[n].g + ((((int16_t)pPixelsOut[d - 1].g + dg) >> 2));
const int16_t db = (int16_t)pPixelsIn[n + 1].b - ((((int16_t)pPixelsIn[n].b + (int16_t)pPixelsIn[n + 2].b) >> 1));
const int16_t sb = (int16_t)pPixelsIn[n].b + ((((int16_t)pPixelsOut[d - 1].b + db) >> 2));
pPixelsOut[d].r = dr;
pPixelsOut[s].r = sr;
pPixelsOut[d].g = dg;
pPixelsOut[s].g = sg;
pPixelsOut[d].b = db;
pPixelsOut[s].b = sb;
It is trivial to create the inverse of this (A VERY simple bit of algebra). Its worth noting, btw, that you need to inverse the image from right to left bottom to top. I'll next see if I can shunt this data into uint8_ts and lost a bit or 2 of accuracy. For compression this really isn't a problem.