Note: I am brand new to sympy and trying to figure it out how it works.
What I have now: I do get the correct solutions but it takes 35 - 50 seconds.
Goal: To speed it up the calculations by defining symbolic equation once and then reusing it with different variables.
Set up: I need to calculate a polynomial G(t) (t = 6 roots) for every iteration of the loop. (220 iterations total) G(t) have 6 other variables, which are calculated and are known on every iterations. These variables are different on every iteration.
First try (slow): I simply put every into one python function, where I defined Gt symbolically and solved for t. It was running around 35 - 40 seconds. function_G is called on every iteration.
def function_G(f1, f2, a, b, c, d):
t = sp.symbols('t')
left = t * ((a * t + b)**2 + f2**2 * (c*t+d)**2)**2
right = (a*d-b*c) * (1+ f1**2 * t**2)**2 * (a*t+b) * (c*t+d)
eq = sp.expand(left - right)
roots = sp.solveset(Gt, t)
return roots
- Then a person gave me a hint that:
You should only need to (symbolically) solve for the coefficients of the polynomial once, as a preprocessing step. After that, when processing each iterations, you simply calculate the polynomial coefficients, then solve for the roots.
- I asked for clarification the person added:
So I defined the function g(t) and then used sympy.expand to work out all parenthesis/exponents, and then sympy.collect to collect terms by powers of t. Finally I used .coeff on the output of collect to get the coefficients to feed into numpy.root.
Second try: To followed the advice, I defined a G(t) symbolically first and passed it to the function that runs the loop along with its symbolic parameters. Function constructGt() thus is called only once.
def constructGt():
t, a, b, c, d, f1, f2 = sp.symbols('t a b c d f1 f2')
left = t * ((a * t + b)**2 + f2**2 * (c*t+d)**2)**2
right = (a*d-b*c) * (1+ f1**2 * t**2)**2 * (a*t+b) * (c*t+d)
gt = sp.Eq(left - right, 0)
expanded = sp.expand(gt)
expanded = sp.collect(expanded, t)
g_vars = {
"a": a,
"b": b,
"c": c,
"d": d,
"f1": f1,
"f2": f2
}
return expanded, g_vars
then on every iteration I was passing the function and its parameters to get the roots:
#Variables values:
#a = 0.00011713490404073987
#b = 0.00020253296124588926
#c = 4.235688216068313e-07
#d = 0.012262546040805029
#f1= -0.012553203944721956
#f2 = 0.018529776776949003
def function_G(f1_, f2_, a_, b_, c_, d_, Gt, v):
Gt = Gt.subs([(v['a'], a_), (v['b'], b_),
(v['c'], c_), (v['d'], d_),
(v['f1'], f1_), (v['f2'], f2_)])
roots = sp.solveset(Gt, t)
return roots
But it got even slower around 56 seconds.
Question: I do not understand what Am I doing wrong? I also do not understand how this person is using .coeff() and then np.roots on the results.