Collect sinusoids of same frequency - python

I have an expression of many sinusoids. Some frequencies are repeated, so I would like to collect the coefficients for identical frequencies. Seems like either collect() or factor() should so the trick but they only work on simple expressions and fail when many variables are involved. Is there a better way to collect terms? Is there a way to help guide factor() to what variable to operate on like exists for collect()? I am trying to manually simplify the equation into a particular form and I think cse() goes too far in reworking terms. Examples below:
w, x, y, z = symbols('w x y z')
factor(z*sin(2*pi*x)+y*sin(2*pi*x), deep=True)
(y + z)⋅sin(2⋅π⋅x) #WORKS
factor(z*sin(2*pi*x*w)+y*sin(2*pi*x*w), deep=True)
(y + z)⋅sin(2⋅π⋅w⋅x) #WORKS
factor(z*sin(2*pi*x)+y*sin(2*pi*x)+z*sin(w)+2*y*sin(w), deep=True)
2⋅y⋅sin(w) + y⋅sin(2⋅π⋅x) + z⋅sin(w) + z⋅sin(2⋅π⋅x) # FAILS – expected Expected (2y + z)*sin(w) + (y+z)⋅sin(2⋅π⋅x)
collect(z*sin(2*pi*x)+y*sin(2*pi*x), x)
y⋅sin(2⋅π⋅x) + z⋅sin(2⋅π⋅x) # FAILS expected (y+z)⋅sin(2⋅π⋅x)
collect(z*sin(2*pi*x)+y*sin(2*pi*x)+z*sin(w)+2*y*sin(w), x)
2⋅y⋅sin(w) + y⋅sin(2⋅π⋅x) + z⋅sin(w) + z⋅sin(2⋅π⋅x) #FAILS Expected (2y + z)*sin(w) + (y+z)⋅sin(2⋅π⋅x)

It is:
>>> from sympy import *
>>> w, x, y, z = symbols('w x y z')
>>> ex= z*sin(2*pi*x)+y*sin(2*pi*x)+z*sin(w)+2*y*sin(w)
>>> ex
2*y*sin(w) + y*sin(2*pi*x) + z*sin(w) + z*sin(2*pi*x)
>>> collect(ex, [sin(w), sin(2*pi*x)])
(y + z)*sin(2*pi*x) + (2*y + z)*sin(w)
Reference: https://docs.sympy.org/latest/modules/simplify/simplify.html?highlight=collect

Related

Breaking an equation step by step based on the arithmetic dependencies in Python

I am trying to break an equation step by step by checking the arithmetic dependencies. I have tried using the sympy.simplify() and sympy.expand(), but I am not getting the desired output.
Input:
m = 10*((9*(x**3) + 2*(y**4))**3) + 3*(y**3 + z)
Expected Output:
An array containing all the possibilities as mentioned below
output_list = ['10*((9*(x**3) + 2*(y**4))**3)',
'(9*(x**3) + 2*(y**4))**3',
'9*(x**3) + 2*(y**4)',
'9*(x**3)',
'x**3',
'x',
'2*(y**4)',
'y**4',
'y',
'3*(y**3 + z)',
'y**3 + z',
'y**3',
'y',
'z']
I split the equation every time by observing the main dependency to get the next possible dependent equation and finally to the dependent variables.
In the above equation, 10(9(x^3) + 2(y^4))^3, 10 is multiplied after substituting the values of x and y. So, I first removed 10.
Then, I have removed the cube, followed by the addition symbol, and etc. to get the output_list.
How can I get the output_list using Python?
This pretty closely gives your expected output by printing the args of the expression recursively:
def go(eq):
if eq.is_Number:return
if not eq.args:
print(eq)
else:
print(eq)
for a in eq.args:
go(a)
>>> go(m)
10*(9*x**3 + 2*y**4)**3 + 3*(y**3 + z)
10*(9*x**3 + 2*y**4)**3
(9*x**3 + 2*y**4)**3
9*x**3 + 2*y**4
9*x**3
x**3
x
2*y**4
y**4
y
3*(y**3 + z)
y**3 + z
y**3
y
z
You might also take a look at preorder_traversal and postorder_traversal which are both in sympy.core.traversal.

Solving a multiple variable equation with python

I'm trying to create a program to solve this equation:
2.5x + 3.5y + 4.5z + 5.5t + 6.5w + 10.5f = d
I want to be able to set a value for d and get posite and whole numbers as a result for each variable.
import sympy as sp
import numpy as np
x, y, z, t, w, f = sp.var('x y z t w f', Naturals0=True, positive=True)
var = [x, y, z, t, w, f]
d = 14
Eqn = sp.Eq(2.5*x + 3.5*y + 4.5*z + 5.5*t + 6.5*w + 10.5*f, d)
for i in var:
print(sp.solveset(Eqn, i, domain=sp.S.Naturals0))
I'm using the code above but I'm having 2 problems, first it give me back only the relative answers for each variable and I've not found a way to "control" the answer for being only positive and whole.
I know that maybe I get a lot of results depending on the number I set for d, but I need results in therms of numbers, nos equations.
Last but not least, I've already tried doing with numpy and matrix solving, but not suceeded.
Thanks in advance
When you want integer solutions for multiple variables in an equation you might be wanting to use diophantine; solveset is more for solving for a single variable in terms of the others.
For diophantine give it the equation as an expression with integer coefficients:
>>> from sympy import Add, nsimplify, Eq, symbols, ordered
>>> s = d, f, t, w, x, y, z=symbols('d, f, t, w, x, y, z')
>>> e = Eq(2.5*x + 3.5*y + 4.5*z + 5.5*t + 6.5*w + 10.5*f, d)
>>> nsimplify(e.rewrite(Add), rational=True)
-d + 21*f/2 + 11*t/2 + 13*w/2 + 5*x/2 + 7*y/2 + 9*z/2
>>> eq = _
Now get an integer solution:
>>> from sympy import diophantine
>>> isol = diophantine(eq, syms=s); isol
{(t_0, t_1, t_1 + t_2, t_1 + t_2 + t_3, t_1 + t_2 + t_3 + t_4,
8*t_0 - 191*t_1 - 107*t_2 - 63*t_3 - 11*t_4 + 9*t_5,
-6*t_0 + 143*t_1 + 80*t_2 + 47*t_3 + 8*t_4 - 7*t_5)}
This is a set of tuples (in this case 1) of either integers or variables representing integers that are a solution to the equation. In this case, 6 parameters are free to be chosen and then a particular solution can be found. We'll create a function f that can be used to see particular solutions easily:
>>> from sympy import Tuple, Dict, Lambda
>>> tsol = Tuple(*isol.pop())
>>> dsol = Dict(*zip(v, tsol))
>>> p = tuple(ordered(tsol.free_symbols))
>>> f = Lambda(p, dsol)
Now we can see a particular solution and see that it satisfies the original expression:
>>> f(1,2,3,4,5,6)
{d: 1, f: 2, t: 5, w: 9, x: 14, y: -948, z: 706}
>>> eq.subs(_)
0
So there are an infinite number of solutions governed by 6 arbitrary integers from which the other two are determined.

Python sympy symbols

When I use "x" and "z" as symbols, I have no problem with this code:
from sympy import *
x, z = symbols('x z')
y = -6*x**2 + 2*x*z**0.5 + 50*x - z
solve((diff(y, x), diff(y, z)))
y.subs({x: 5, z: 25})
But when I use "q" and "a", solve does not give me any solution.
q, a = symbols('q a')
y = -6*q**2 + 2*q*a**0.5 + 50*q - a
solve((diff(y, q), diff(y, a)))
y.subs({q: 5, a: 25})
As you can see I use "subs" to check that there is no typo in the objective function.
UPDATE: I used "Symbol" to set each variable individually, but again using "q" and "a" does not work.
# This works
x = Symbol('x')
z = Symbol('z')
y = -6*x**2 + 2*x*z**0.5 + 50*x - z
solve((diff(y, x), diff(y, z)))
# This does not work
q = Symbol('q')
a = Symbol('a')
y = -6*q**2 + 2*q*a**0.5 + 50*q-a
solve((diff(y, q), diff(y, a)))
Thank you.
Got it!
It all depends on an alphabetic order of your variables.
If you substitute x for z and z for x in your first example it will also stop working.
Internally solve sends the expression to the function _solve in sympy.solvers which then tries to solve your equation and fails many times.
Finally as a last effort what it does is it tries to solve -sqrt(a) + q or x - sqrt(z) by picking symbols from it through an internal function _ok_syms, with an argument that sorts those alphabetically (even without this argument it still would, but if wrapped with reversed it magically makes your examples works in the exactly opposite way).
And so it does solve x - sqrt(z) as x: sqrt(z) and -sqrt(a) + q as a: q**2.
While in the first case it ends up with an easily solvable 50 - 10*sqrt(z), in the second case it is lost on -12*q + 2*sqrt(q**2) + 50 as it is not able to simplify sqrt(q**2).
source:
a lot of testing on:
https://github.com/sympy/sympy/blob/master/sympy/solvers/solvers.py

i want to solve the equations: x**2*y**2 + x**2 -10*x*y + 4*y**2 + 9.0=0,Is there any way to get the real solutions?

I am trying to use python to solve the equations: x**2*y**2 + x**2 -10*x*y + 4*y**2 + 9.0=0, due to the equations equal to (x*y-3)**2+(x-2*y)**2=0 ,so hoping to get the real solution: x = 2*sqrt(3.0/2),y = sqrt(3.0/2)&& x = -2*sqrt(3.0/2),y = -sqrt(3.0/2) Is there any way to get this solutions?
from sympy import *
x = symbols("x")
y = symbols("y")
expression = x**2*y**2 + x**2 - 10*x*y + 4*y**2 + 9
solve(expression,(x,y))
above code only get the solution: [((5*y + I*(-2*y**2 + 3))/(y**2 + 1), y),
((5*y + I*(2*y**2 - 3))/(y**2 + 1), y)],thanks for your help and advice
It looks like what you are trying to do is find where both of the terms of the expression (x*y-3)**2+(x-2*y)**2 are simultaneously zero. Instead of expanding that, ask solve for that answer:
>>> eq = (x*y-3)**2+(x-2*y)**2
>>> terms = eq.args
>>> solve(terms, x, y)
[(-sqrt(6), -sqrt(6)/2), (sqrt(6), sqrt(6)/2)]
You can use solveset_real (although the exact equation may not have any real solutions)

Collecting like term of an expression in Sympy

I am currently dealing with functions of more than one variable and need to collect like terms in an attempt to simplify an expression.
Say the expression is written as follows:
x = sympy.Symbol('x')
y = sympy.Symbol('y')
k = sympy.Symbol('k')
a = sympy.Symbol('a')
z = k*(y**2*(a + x) + (a + x)**3/3) - k((2*k*y*(a + x)*(n - 1)*(-k*(y**2*(-a + x) + (-a + x)**3/3) + k*(y**2*(a + x) + (a + x)**3/3)) + y)**2*(-a + k*(n - 1)*(y**2 + (a + x)**2)*(-k*(y**2*(-a + x)))))
zEx = z.expand()
print type(z)
print type(zEx)
EDIT: Formatting to add clarity and changed the expression z to make the problem easier to understand.
Say z contains so many terms, that sifting through them by eye. and selecting the appropriate terms, would take an unsatisfactory amount of time.
I want to collect all of the terms which are ONLY a multiple of a**1. I do not care for quadratic or higher powers of a, and I do not care for terms which do not contain a.
The type of z and zEx return the following:
print type(z)
print type(zEx)
>>>
<class 'sympy.core.add.Add'>
<class 'sympy.core.mul.Mul'>
Does anyone know how I can collect the terms which are a multiple of a , not a^0 or a^2?
tl'dr
Where z(x,y) with constants a and k described by z and zEx and their type(): How can one remove all non-a terms from z AND remove all quadratic or higher terms of a from the expression? Such that what is left is only the terms which contain a unity power of a.
In addition to the other answers given, you can also use collect as a dictionary.
print(collect(zEx,a,evaluate=False)[a])
yields the expression
k*x**2 + k*y**2
In the end it is just an one-liner. #asmeurer brought me on the right track (check the comments below this post). Here is the code; explanations can be found below:
from sympy import *
from sympy.parsing.sympy_parser import parse_expr
import sys
x, y, k, a = symbols('x y k a')
# modified string: I added a few terms
z = x*(k*a**9) + (k**1)*x**2 - k*a**8 + y*x*(k**2) + y*(x**2)*k**3 + x*(k*a**1) - k*a**3 + y*a**5
zmod = Add(*[argi for argi in z.args if argi.has(a)])
Then zmod is
a**9*k*x - a**8*k + a**5*y - a**3*k + a*k*x
So let's look at this more carefully:
z.args
is just a collection of all individual terms in your expression (please note, that also the sign is parsed which makes things easier):
(k*x**2, a**5*y, -a**3*k, -a**8*k, a*k*x, a**9*k*x, k**2*x*y, k**3*x**2*y)
In the list comprehension you then select all the terms that contain an a using the function has. All these terms can then be glued back together using Add which gives you the desired output.
EDIT
The above returns all all the expressions that contain an a. If you only want to filter out the expressions that contain a with unity power, you can use collect and Mul:
from sympy import *
from sympy.parsing.sympy_parser import parse_expr
import sys
x, y, k, a = symbols('x y k a')
z2 = x**2*(k*a**1) + (k**1)*x**2 - k*a**8 + y*x*(k**2) + y*(x**2)*k**3 + x*k*a - k*a**3 + y*a**1
zc = collect(z2, a, evaluate=False)
zmod2 = Mul(zc[a], a)
then zmod2 is
a*(k*x**2 + k*x + y)
and zmod2.expand()
a*k*x**2 + a*k*x + a*y
which is correct.
With the updated z you provide I run:
z3 = k*(y**2*(a + x) + (a + x)**3/3) - k((2*k*y*(a + x)*(n - 1)*(-k*(y**2*(-a + x) + (-a + x)**3/3) + k*(y**2*(a + x) + (a + x)**3/3)) + y)**2*(-a + k*(n - 1)*(y**2 + (a + x)**2)*(-k*(y**2*(-a + x)))))
zc3 = collect(z3.expand(), a, evaluate=False)
zmod3 = Mul(zc3[a], a)
and then obtain for zmod3.expand():
a*k*x**2 + a*k*y**2
Is this the result you were looking for?
PS: Thanks to #asmeurer for all these helpful comments!
To iterate over the terms of an expression use expr.args.
I'm unclear what a is supposed to be, but the collect function may do what you want.

Categories

Resources