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
pd.set_option('display.max_colwidth', None)
# 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:])))
Aim: Continue to examine solutions to the general cubic and aspects of the coefficient
Method: Examine the rows and columns of the coeffiecient matrix generated from $C$ using OEIS
Observe: the definition from Solving Polynomials (7) for the solution to a general cubic equation which generates Catalan and Fuss numbers.
$$C(m_2, m_3) \equiv(-1)^{m_3 + 1} \frac{(2 m_{2} + 3 m_{3})!}{(1 + m_{2} + 2 m_{3})!m_2!m_3!} \frac{c_0^{1 + m_{2} + 2 m_{3}} c_2^{m_2} c_3^{m_3} }{c_1^{2 m_{2} + 3 m_{3} + 1}}$$Define: $F1$ as a function implementation of $C$
def F1(m2, m3, returnCoefficientsOnly = False, returnCoefficientsOnlyWithoutSigns = False):
c_0, c_1, c_2, c_3 = sp.symbols('c_0, c_1, c_2, c_3')
s1 = (-1)**(m3 + 1)
s2 = sp.factorial(2 * m2 + 3 * m3)
s3 = sp.factorial(1 + m2 + 2 * m3) * sp.factorial(m2) * sp.factorial(m3)
s4 = c_0**(1 + m2 + 2 * m3) * c_2**m2 *c_3**m3
s5 = c_1**(2 * m2 + 3 * m3 + 1)
if returnCoefficientsOnly:
s6 = s1 * (s2 / s3)
elif returnCoefficientsOnlyWithoutSigns:
s6 = (s2 / s3)
else:
s6 = s1 * (s2 / s3) * (s4 / s5)
return(s6)
Let $P3$ be a $8 \times 8$ matrix generated from $F1$
P1 = np.arange(8)
P2 = np.array([[F1(j, i, returnCoefficientsOnlyWithoutSigns=True) for i in P1] for j in P1])
P3 = sp.Matrix(P2)
P3
Let $P5$ be a larger $20 \times 20$ matrix generated from $F1$
P4 = np.arange(20)
P5 = np.array([[F1(j, i, returnCoefficientsOnlyWithoutSigns=True) for i in P4] for j in P4])
P5 = sp.Matrix(P5)
P5
Observe: $P5$ has only natural numbers, however these numbers are created from the division of factorials
Let $F2$ be an implementation of $C$ that returns factorials without evaluation
def F2(m2, m3, returnCoefficientsOnly = False, returnCoefficientsOnlyWithoutSigns = False, returnCoefficientsAsFactorialStrings = False):
c_0, c_1, c_2, c_3 = sp.symbols('c_0, c_1, c_2, c_3')
s1 = (-1)**(m3 + 1)
s2 = sp.factorial(2 * m2 + 3 * m3)
s3 = sp.factorial(1 + m2 + 2 * m3) * sp.factorial(m2) * sp.factorial(m3)
s4 = c_0**(1 + m2 + 2 * m3) * c_2**m2 *c_3**m3
s5 = c_1**(2 * m2 + 3 * m3 + 1)
s7 = str(2 * m2 + 3 * m3) + "!"
s8 = str(1 + m2 + 2 * m3) + "!" + str(m2) + "!" + str(m3) + "!"
if returnCoefficientsOnly:
s6 = s1 * (s2 / s3)
elif returnCoefficientsOnlyWithoutSigns:
s6 = (s2 / s3)
elif returnCoefficientsAsFactorialStrings:
s6 = str(s7 + " | " + s8)
else:
s6 = s1 * (s2 / s3) * (s4 / s5)
return(s6)
Let $P6$ be an $8 \times 8$ matrix created from $F2$.
P6 = np.array([[F2(j, i, returnCoefficientsAsFactorialStrings=True) for i in P1] for j in P1])
P7 = pd.DataFrame(P6)
P7
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | |
---|---|---|---|---|---|---|---|---|
0 | 0! | 1!0!0! | 3! | 3!0!1! | 6! | 5!0!2! | 9! | 7!0!3! | 12! | 9!0!4! | 15! | 11!0!5! | 18! | 13!0!6! | 21! | 15!0!7! |
1 | 2! | 2!1!0! | 5! | 4!1!1! | 8! | 6!1!2! | 11! | 8!1!3! | 14! | 10!1!4! | 17! | 12!1!5! | 20! | 14!1!6! | 23! | 16!1!7! |
2 | 4! | 3!2!0! | 7! | 5!2!1! | 10! | 7!2!2! | 13! | 9!2!3! | 16! | 11!2!4! | 19! | 13!2!5! | 22! | 15!2!6! | 25! | 17!2!7! |
3 | 6! | 4!3!0! | 9! | 6!3!1! | 12! | 8!3!2! | 15! | 10!3!3! | 18! | 12!3!4! | 21! | 14!3!5! | 24! | 16!3!6! | 27! | 18!3!7! |
4 | 8! | 5!4!0! | 11! | 7!4!1! | 14! | 9!4!2! | 17! | 11!4!3! | 20! | 13!4!4! | 23! | 15!4!5! | 26! | 17!4!6! | 29! | 19!4!7! |
5 | 10! | 6!5!0! | 13! | 8!5!1! | 16! | 10!5!2! | 19! | 12!5!3! | 22! | 14!5!4! | 25! | 16!5!5! | 28! | 18!5!6! | 31! | 20!5!7! |
6 | 12! | 7!6!0! | 15! | 9!6!1! | 18! | 11!6!2! | 21! | 13!6!3! | 24! | 15!6!4! | 27! | 17!6!5! | 30! | 19!6!6! | 33! | 21!6!7! |
7 | 14! | 8!7!0! | 17! | 10!7!1! | 20! | 12!7!2! | 23! | 14!7!3! | 26! | 16!7!4! | 29! | 18!7!5! | 32! | 20!7!6! | 35! | 22!7!7! |
Observe: the different degrees of numerator and denominator in $P6$.
Aim: find a combnatorial or number theoretic interpretation for numbers appearing in $P5$ (which non evaluated in $P6$) and account for the appearrance of natural numbers only.
Method: Examine similiar structures (the multinomial coefficient) and draw similiarities
Observe: the structure of the numbers returned by $F2$ are very similiar multinomial coefficients. However, while multinomial coefficients have the same degree in numerator and denomiator, the numbers returned by by 1.
Observe: it is possible to see this difference using a specific multinomial coefficient (i.e the trinomial coefficient)
Definition: Trinomial Coefficient for the values $a^k b^l c^m $ in $ (a + b + c)^n$ where $n = k + l + m$ is:
$$ \binom{n}{k, l, m} \equiv \frac{n!}{k!l!m!} = \frac{(k + l + m)!}{k!l!m!} $$Let $P8$ be another example of a multinomial expression (a quinomial coefficient)
a, b, c = sp.symbols('a b c')
P8 = sp.expand((a + b + c)**5)
P8
Observe: in the case of $P8$, for the term $20a^3bc$, the coefficient can be computed as $\binom{5}{3, 1, 1} = \frac{5!}{3!1!1!} = 20$. This is generally the case for all terms. Note the numerator and denomiator have the same degree.
Observe: In general case, the multinomial can always be described as per above.
Observe: a Trinomial can be intuiated as the number of ways of obtaining $a^k b^l c^m $ in $ (a + b + c)^n$.
Observe: This is equivalent to the number of ways to:
Observe: the resulting product is:
$$ \binom{n}{k} \binom{n -k}{l} \binom{n - k - l}{m} = \frac{n!}{k!(n - k)!} \frac{(n - k)!}{l!(n - k - l)!} \frac{(n - k - l)!}{m!(n - k - l - m)!} = \frac{n!}{k!l!m!}$$Observe: The numbers $ C(m_2, m_3) \equiv \frac{(2 m_{2} + 3 m_{3})!}{(1 + m_{2} + 2 m_{3})!m_2!m_3!} $ are similiar to the multinomial coeffient, however the degree of the denominator is 1 more than the numerator.
Definition: A Sub-multinomial Coefficient is a rational number of the form $ \frac{n!}{m_1!m2! \ldots m_k!} $ where $ n, m_1, m2 \ldots, m_k$ are natural numbers and $ n = m_1 + m_2 + \ldots + m_k -1$
Aim: Investigate the Submultinomial Coeffients that appear in the generating function $C$.
Method: Collect data generated from the submultinomial coefficient generating function in order to ascertain those cases where it does and does not not return natural numbers. This will allow the the discovery of the conditions that can be placed on $m_1, m_2 \ldots m_k$ to return a natural number.
Observe: The case of one variable : $ \frac{(m - 1)!}{m!} = \frac{1}{m}$. In the case of one variable, a natural number will usually not be returned.
Observe: The case of two variables: $$J(m_1, m_2) = \frac{(m_1 + m_2 - 1)!}{m_1!m_2!} $$
Define: $F3$ as generating function return submultinomial for two given variables.
def F3(m1, m2):
return (sp.factorial(m1 + m2 - 1) / (sp.factorial(m1) * sp.factorial(m2)))
Let $P9$ a $F3$ evaluated at $(4, 5)$.
P9 = F3(4,5)
P9
Observe: THis is a natural number. However more data should be collected for the two variable case.
Let $P12$ be $F3$ evaluated for values in an array.
# we can get values again
P10 = np.arange(1,11)
P11 = np.array([[F3(j, i) for i in P10] for j in P10])
P12 = sp.Matrix(P11)
P12
Observe: returned values in $P12$ not always integers.
Observe: the Catalan Numbers appear on the diagonals
Let $F4$ be a function that returns submultinomial values for an arbitrary number of input values
def F4(entries):
numerator = sp.factorial(sum(entries) - 1)
denominator = 1
for i in entries:
denominator = denominator * sp.factorial(i)
return(numerator / denominator)
Let $P13$ be $F4$ evaluated for different inputs.
renderListToLatex([F4([2,3,4]), F4([3,5,7]), F4([9,3,2,1])])
Let $P16$ be $F4$ evaluated for 3 values, where 1 value is fixed.
P14 = np.arange(1,11)
P15 = np.array([[F4([j, i, 3]) for i in P10] for j in P14])
P16 = sp.Matrix(P15)
P16
Observe: values returned in $P16$ not always integers.
Aim: Compare the count of natural numbers and rational numbers across differen choices of inputs to $F4$.
Method: Run multiple iterations and place data in data frames to explore
Observe: It is possible to place data returned from $F4$ into a data frame and ascertain answers if answers returned are Integer Types or Rational Number Types
Let $P19$ be value counts for types returned from $F4$
P17 = np.arange(1,11)
P18 = np.array([[type(F4([j, i, 3])) for i in P17] for j in P17])
P19 = pd.DataFrame(P18.flatten())
P19.value_counts()
<class 'sympy.core.numbers.Integer'> 94 <class 'sympy.core.numbers.Rational'> 6 dtype: int64
Observe: It is possible to expand this approach for a greater number of entries.
Let $P23$ be a larger sample of values of values returned from $F4$.
P20 = np.arange(1,50)
P21 = np.array([[[type(F4([j, i, k])) for i in P20] for j in P20] for k in range(1,51)])
P22 = [[P21[j].flatten(), [j for i in range(len(P21[j].flatten()))]] for j in np.arange(1,50)]
P23 = pd.DataFrame(columns=['type', 'staticNumber'])
for i in range(0,len(P22)):
df = pd.DataFrame([P22[i][0], P22[i][1]]).T
df.columns = ["type", "staticNumber"]
P23 = pd.concat([P23, df])
P23.head(2)
type | staticNumber | |
---|---|---|
0 | <class 'sympy.core.numbers.Integer'> | 1 |
1 | <class 'sympy.core.numbers.Integer'> | 1 |
Let $P24$ be a Data Framew sorted by static number and type to display instances of Integers.
P24 = pd.DataFrame(P23.value_counts(subset=['staticNumber', 'type'])).sort_values(by = ['staticNumber', 'type'])
P24.head(3)
0 | ||
---|---|---|
staticNumber | type | |
1 | <class 'sympy.core.numbers.Integer'> | 2245 |
<class 'sympy.core.numbers.Rational'> | 156 | |
2 | <class 'sympy.core.numbers.Integer'> | 2294 |
Conclusion
More exploration is needed. There are no obvious pattern that emerge when considering diffeheadt values. Alternatives to look more closely at all $i, j$ and $k$ values as inputs to see if there are correlations