STATUS: Draft
import numpy as np
import sympy as sp
import pickle
from IPython.display import HTML
import ipywidgets as widgets
import matplotlib as mpl
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
mpl.rcParams['legend.fontsize'] = 10
import pandas as pd
import itertools
# This is commented out
#%matplotlib widget
# function to print latex
def renderListToLatex(e):
latex_rendering = []
for i in range(len(e)):
latex_rendering.append("$$" + sp.latex(e[i]) + "$$<br/>")
return(HTML("".join(latex_rendering[0:])))
Create required variables
c_0, c_1, c_2, x, t, a_0, a_1, a_2, a_3, a_4, a_5, a_6, a_7, a_8, a_9, x_1, x_2, s_1, s_2 = sp.symbols('c_0, c_1, c_2, x, t, a_0, a_1, a_2, a_3, a_4, a_5, a_6, a_7, a_8, a_9, x_1, x_2, s_1, s_2')
Recall that the original quadratic general equation sought to find solutions for $x_1$ and $x_2$ for a general quadratic
$$t + c_0x + c_1x^2 = 0$$Recall that, using a power series in $t$, value of $x_1$ and $x_2$, the following solutions could be found:
x_1 = sp.Eq(x_1, -t/c_1 - c_2*t**2/c_1**3 - 2*c_2**2*t**3/c_1**5 - 5*c_2**3*t**4/c_1**7 - 14*c_2**4*t**5/c_1**9 - 42*c_2**5*t**6/c_1**11 - 132*c_2**6*t**7/c_1**13 - 429*c_2**7*t**8/c_1**15 - 1430*c_2**8*t**9/c_1**17)
x_1
x_2 = sp.Eq(x_2, -c_1/c_2 + t/c_1 + c_2*t**2/c_1**3 + 2*c_2**2*t**3/c_1**5 + 5*c_2**3*t**4/c_1**7 + 14*c_2**4*t**5/c_1**9 + 42*c_2**5*t**6/c_1**11 + 132*c_2**6*t**7/c_1**13 + 429*c_2**7*t**8/c_1**15 + 1430*c_2**8*t**9/c_1**17)
x_2
Note that $x_1$ and $x_2$ into generative functions. $$ x_1 = -\sum_{k=1}^9 C(k - 1)\frac{c_2^{k-1}}{c_1^{2k - 1}}t^k$$
$$ x_2 = -\frac{c_1}{c_2} + \sum_{k=1}^9 C(k - 1)\frac{c_2^{k-1}}{c_1^{2k - 1}}t^k $$Note that solutions are not available $x_1$ and $x_2$ beyond degree 9. However, note the general case of generative functions:
$$ x_1 = -\sum_{k=1}^+ C(k - 1)\frac{c_2^{k-1}}{c_1^{2k - 1}}t^k$$$$ x_2 = -\frac{c_1}{c_2} + \sum_{k=1}^+ C(k - 1)\frac{c_2^{k-1}}{c_1^{2k - 1}}t^k $$Goal: Test the cubic case
Create the required variables:
a_0, a_1, a_2, a_3, a_4, a_5, a_6, t, c_1, c_2, c_3, x = sp.symbols('a_0, a_1, a_2, a_3, a_4, a_5, a_6, t, c_1, c_2, c_3, x ')
Assume that $t^8 == 0$.
Let s1 be a general cubic equation.
s1 = sp.Eq(t + c_1 * x + c_2*x**2 + c_3 * x**3, 0)
s1
Let s2 be a substitution for x.
s2 = a_0 + a_1 * t + a_2*t**2 + a_3*t**3 + a_4*t**4 + a_5*t**5 + a_6*t**6 + a_7*t**7
s2
Let s3 be s1 with the s2 subsituted for x
s3 = s1.subs(x, s2)
s3
Let s4 be the expansion of s3
s4 = s3.expand()
Enforce assumption that $t^8=0$ in s4
order = 8
coeffs = sp.Poly(s3, t).coeffs()
s4= sum(t**n * coeffs[-(n+1)] for n in range(order))
s4 = sp.Eq(s4, 0)
s4
Let s5 be the case where $t = 0$ in s4
s5 = s4.subs(t, 0)
s5
Let s6 be the factorisation of of s5. Note there are three solutions
s6 = sp.solve(s5, a_0)
renderListToLatex(s6)
Consider the case where $a_0 = 0$.
Substitute $a_0 = 0$ into s4
s7 = sp.Poly(s4.subs(a_0, 0), t)
s7
Let s8 be a system of equations to linearly solve $a_1, a_2, a_3, a_4, a_5, a_6$, and $a_7$. Append $a_0 = 0$ as a valid equation in this system.
s8 = [sp.Eq(s7.coeffs()[i], 0) for i in range(len(s7.coeffs()))]
s8.append(sp.Eq(a_0, 0))
s8
[Eq(3*a_1**2*a_5*c_3 + 6*a_1*a_2*a_4*c_3 + 3*a_1*a_3**2*c_3 + 2*a_1*a_6*c_2 + 3*a_2**2*a_3*c_3 + 2*a_2*a_5*c_2 + 2*a_3*a_4*c_2 + a_7*c_1, 0), Eq(3*a_1**2*a_4*c_3 + 6*a_1*a_2*a_3*c_3 + 2*a_1*a_5*c_2 + a_2**3*c_3 + 2*a_2*a_4*c_2 + a_3**2*c_2 + a_6*c_1, 0), Eq(3*a_1**2*a_3*c_3 + 3*a_1*a_2**2*c_3 + 2*a_1*a_4*c_2 + 2*a_2*a_3*c_2 + a_5*c_1, 0), Eq(3*a_1**2*a_2*c_3 + 2*a_1*a_3*c_2 + a_2**2*c_2 + a_4*c_1, 0), Eq(a_1**3*c_3 + 2*a_1*a_2*c_2 + a_3*c_1, 0), Eq(a_1**2*c_2 + a_2*c_1, 0), Eq(a_1*c_1 + 1, 0), Eq(a_0, 0)]
Let s9 be the solutions to this system.
variables = [a_0, a_1, a_2, a_3, a_4, a_5, a_6, a_7]
s9 = sp.nonlinsolve(s8, variables)
interimSolutions = list(list(s9)[0])
s9 = [sp.Eq(interimSolutions[i], variables[i]) for i in range(len(interimSolutions))]
s9
[Eq(0, a_0), Eq(-1/c_1, a_1), Eq(-c_2/c_1**3, a_2), Eq((c_3/c_1**3 - 2*c_2**2/c_1**4)/c_1, a_3), Eq(5*(c_2*c_3/c_1**5 - c_2**3/c_1**6)/c_1, a_4), Eq((-3*c_3**2/c_1**6 + 21*c_2**2*c_3/c_1**7 - 14*c_2**4/c_1**8)/c_1, a_5), Eq((-28*c_2*c_3**2/c_1**8 + 84*c_2**3*c_3/c_1**9 - 42*c_2**5/c_1**10)/c_1, a_6), Eq((12*c_3**3/c_1**9 - 180*c_2**2*c_3**2/c_1**10 + 330*c_2**4*c_3/c_1**11 - 132*c_2**6/c_1**12)/c_1, a_7)]
Visualise solutions for $a_1, a_2, a_3, a_4, a_5, a_6$, and $a_7$.
latex_rendering = []
for i in range(len(s9)):
latex_rendering.append("$$" + sp.latex(s9[i].simplify()) + "$$")
HTML("".join(latex_rendering[1:]))
Note that if $c_3 = 0$, the cubic term, then the quadratic case is recovered
s10 = [s9[i].subs(c_3, 0) for i in range(len(s9))]
latex_rendering = []
for i in range(len(s10)):
latex_rendering.append("$$" + sp.latex(s10[i].simplify()) + "$$")
HTML("".join(latex_rendering[1:]))
Recall the cubic case expression.
s1
Substitute back into x to find one of the solutions of this general cubic.
values_to_solve2 = variables[1:]
solutions_as_list2 = interimSolutions[1:]
solutions_as_list2
r1_5 = sp.Eq(x, s2)
r15 = r1_5.subs(values_to_solve2[0], solutions_as_list2[0])
r15 = r15.subs(values_to_solve2[1], solutions_as_list2[1].simplify())
r15 = r15.subs(values_to_solve2[2], solutions_as_list2[2].simplify())
r15 = r15.subs(values_to_solve2[3], solutions_as_list2[3].simplify())
r15 = r15.subs(values_to_solve2[4], solutions_as_list2[4].simplify())
r15 = r15.subs(values_to_solve2[5], solutions_as_list2[5].simplify())
r15 = r15.subs(values_to_solve2[6], solutions_as_list2[6].simplify())
# after going through all the solutions, subs in 0 for a_0
#r15 = r15.subs(a_0, 0)
r15
Subsitute into original equation
Summary
There still appears to be a relationship to the Catalan numbers in the cubic case, but there are numbers present also. Note the the above is only one of the solutions to a general cubic equation. It is valid to degree 7, expressing the values as an on-series in powers in t, where the coefficients are rational functions of $c_i$
Save outputs.
# Write data that will be used again
data = {'generalCubicSolutions': s9,
'solutionOfGeneralCubicInTermsOfx':r15}
f = open('./SharedOutputs/SPE3.pickle', 'wb')
pickle.dump(data, f)
f.close()