October 3, 2016: conjectures
September 30, 2016: cleaning, matrix-vector product
September 29, 2016: ordered set-wise spec representation, terms cache subs & project
September 28, 2016: graphical representations, simple unfolding
In [1]:
%run "../src/start_session.py"
%run "../src/recurrences.py"
%run "../src/sums.py"
In [2]:
from oeis import oeis_search, ListData
import knowledge
In [3]:
sys.setrecursionlimit(10000000)
We start our study asking the OEIS the sequence of Fibonacci numbers, which is denoted by A000045:
In [3]:
s = oeis_search(id=45)
s(data_only=True, data_representation=ListData(upper_limit=20))
Out[3]:
In [145]:
with bind(IndexedBase('f'), single=True) as f:
fibonacci_rec_spec = recurrence_spec(recurrence_eq=Eq(f[n+2],f[n+1]+f[n]), recurrence_symbol=f, variables=[n])
In [7]:
fibonacci_rec_spec
Out[7]:
In [146]:
unfolded = fibonacci_rec_spec.unfold(depth=5)
In [147]:
unfolded
Out[147]:
In [148]:
unfolded.involute(depth=1)
Out[148]:
In [149]:
unfolded.involute()
Out[149]:
In [150]:
subsumed=unfolded.subsume()
In [151]:
subsumed
Out[151]:
We can abstract the following conjecture: $ f_{n+k-2d+2} = f_{k} f_{n-2d} + f_{k+1} f_{n-2d+1} $, for $k\in\{0,\ldots, 2d-1\}$
In [14]:
im=knowledge.fibonacci_numbers_inverted_mapping(start=2, limit=20)
im
Out[14]:
In [15]:
subsumed.subs(im)
Out[15]:
In [16]:
unfolded.instantiate(strategy=raw(substitutions={n:20}))
Out[16]:
In [17]:
instantiated = unfolded.instantiate(strategy=based(arity=unary_indexed()))
In [18]:
instantiated
Out[18]:
In [19]:
almost_valued = instantiated.subsume(additional_terms={f[0]:Integer(0), f[1]:Integer(1)})
almost_valued
Out[19]:
In [20]:
almost_valued.involute()
Out[20]:
In [ ]:
ipython_latex_description(fibonacci_rec_spec, depths=range(13), arity=unary_indexed())
In [5]:
m, v, r, eqs = fibonacci_rec_spec.matrix_vector_product(depth=10, arity=unary_indexed(),
segment=[n-k for k in range(-2, 19)])
In [6]:
latex_array_src(eqs)
Out[6]:
In [7]:
m, v, r
Out[7]:
In [8]:
example={n:30}
to_check = Eq(m*v.subs(example), r.subs(example))
to_check
Out[8]:
In [9]:
to_check.subs(knowledge.fibonacci_numbers(), simultaneous=True)
Out[9]:
In [10]:
m, v, r, eqs = fibonacci_rec_spec.matrix_vector_product(depth=10, arity=unary_indexed(),
segment=[Integer(k) for k in range(0, 11)],
based_instantiation=True)
In [11]:
latex_array_src(eqs)
Out[11]:
In [12]:
m,v,r
Out[12]:
In [13]:
m = symbols('m')
thm = Eq(f[n], Sum(binomial(m,k)*f[n-2*m+k], (k,0,m)))
thm
Out[13]:
which is known but left as an exercise by Benjamin and Quinn, in the following form:
In [143]:
benjamin_quinn_thm = thm.subs({n:n+m})
benjamin_quinn_thm
Out[143]:
instantiating $m=n$ we get a closed representation of the matrix-vector product seen before:
In [144]:
benjamin_quinn_thm.subs({m:n})
Out[144]:
A little application of the previous identity is in the following cells:
In [19]:
def expand_sum_in_eq(eq_term, in_lhs=False, in_rhs=True):
lhs, rhs = eq_term.lhs, eq_term.rhs
return Eq(expand_Sum(lhs) if in_lhs else lhs, expand_Sum(rhs) if in_rhs else rhs)
symbolic expansion of the Sum
object:
In [20]:
expanded_eq = expand_sum_in_eq(thm.subs({m:20}))
expanded_eq
Out[20]:
instantiate to let $f_{0}$ appears in the identity (our concept of based instantiation):
In [21]:
subsed = expanded_eq.subs(n, 40)
subsed
Out[21]:
finally, check the consistency using the sequence of Fibonacci numbers:
In [22]:
subsed.subs(knowledge.fibonacci_numbers())
Out[22]:
In [23]:
fibs = knowledge.fibonacci_numbers()
we build the sum for each diagonal, manually: it is ugly, so we hope to refactor it and introduce a function to do so:
In [26]:
f2_diag = f[0]
f4_diag = f[0]+f[1]
f6_diag = f[0]+2*f[1]
f8_diag = f[0]+3*f[1]+f[2]
f10_diag = f[0]+4*f[1]+3*f[2]
f12_diag = f[0]+5*f[1]+6*f[2]+f[3]
f14_diag = f[0]+6*f[1]+10*f[2]+4*f[3]
f16_diag = f[0]+7*f[1]+15*f[2]+10*f[3]+f[4]
f18_diag = f[0]+8*f[1]+21*f[2]+20*f[3]+5*f[4]
f20_diag = f[0]+9*f[1]+28*f[2]+35*f[3]+15*f[4]+f[5]
f22_diag = f[0]+10*f[1]+36*f[2]+56*f[3]+35*f[4]+6*f[5]
f24_diag = f[0]+11*f[1]+45*f[2]+84*f[3]+70*f[4]+21*f[5]+f[6]
f26_diag = f[0]+12*f[1]+55*f[2]+120*f[3]+126*f[4]+56*f[5]+7*f[6]
diagonals = [Eq(f2_diag, f2_diag.subs(fibs)),
Eq(f4_diag, f4_diag.subs(fibs)),
Eq(f6_diag, f6_diag.subs(fibs)),
Eq(f8_diag, f8_diag.subs(fibs)),
Eq(f10_diag, f10_diag.subs(fibs)),
Eq(f12_diag, f12_diag.subs(fibs)),
Eq(f14_diag, f14_diag.subs(fibs)),
Eq(f16_diag, f16_diag.subs(fibs)),
Eq(f18_diag, f18_diag.subs(fibs)),
Eq(f20_diag, f20_diag.subs(fibs)),
Eq(f22_diag, f22_diag.subs(fibs)),
Eq(f24_diag, f24_diag.subs(fibs)),
Eq(f26_diag, f26_diag.subs(fibs))]
latex_array_src(diagonals)
Out[26]:
looking at the sequence composed by coeffients in the rhs of each equation we recognize A059633. According to the reference, the sequence is built by the following recurrence: $a_{n} = 2a_{n-1}-a_{n-3}+a_{n-4}$, as the following expansion confirms:
In [27]:
def A059633_gf(x):
return 1/(1-2*x+x**3-x**4)
A059633_gf(t).series(t,n=14)
Out[27]:
therefore we can conjecture the following identity: $$ \sum_{k\geq 0}{{{n-k}\choose{k}}}f_{k} = [t^{n}]\frac{t}{1-2t+t^{3}-t^{4}}$$
In [28]:
def do_memberwise_on_eqs(an_eq, another_eq, operator=lambda x, y: Add(x,y,evaluate=True)):
return Eq(operator(an_eq.lhs, another_eq.lhs), operator(an_eq.rhs, another_eq.rhs))
def swap_eq(eq_term): return Eq(eq_term.rhs, eq_term.lhs)
In [29]:
reduce(do_memberwise_on_eqs, eqs)
Out[29]:
In [32]:
even_subscript_fibonacci_eq = Eq(f[2*n+1]-1, Sum(f[2*k],(k,0,n)))
even_subscript_fibonacci_eq
Out[32]:
In [65]:
example = even_subscript_fibonacci_eq.subs(n,21)
example_expanded = expand_sum_in_eq(example)
example_expanded, example_expanded.subs(fibs)
Out[65]:
In [123]:
from itertools import accumulate
enum_range = range(0,50,2)
def worker(accumulated_pair, current_pair):
index, current = current_pair
_, accumulated = accumulated_pair
summed_eq = do_memberwise_on_eqs(accumulated, current)
return index, summed_eq
def subs_fib_thm(pair):
index, current_eq = pair
expanded_thm = expand_sum_in_eq(even_subscript_fibonacci_eq.subs({n:Integer(index)/2}))
return index, current_eq, expanded_thm
#def eq_to_subs_dict(eq_term): return {eq_term.lhs:eq_term.rhs}
def apply_subs_on_lhs(triple):
index, current_eq, thm = triple
return current_eq.subs({thm.rhs:thm.lhs})
def latex_array_env_of_eqs(mapped):
from string import Template
template = Template(r"""\begin{array}{c}$content\end{array}""")
return template.substitute(content="\n".join(mapped))
In [131]:
triangle = accumulate(zip(enum_range, eqs), worker)
In [132]:
triangle = map(subs_fib_thm, triangle)
In [133]:
triangle = list(map(apply_subs_on_lhs, triangle))
triangle[0] = Eq(f[1]-1,f[0])
In [134]:
latex_array_src(triangle)
Out[134]:
In [135]:
all(map(lambda eq: eq.subs(fibs), triangle))
Out[135]:
In [136]:
to_matrix_notation(triangle, f , range(0, 11))
Out[136]:
In [137]:
triangle = [eq.subs({f[0]:fibs[f[0]]}, simultaneous=True) for eq in triangle[1:]]
latex_array_src(triangle)
Out[137]:
In [139]:
to_matrix_notation(triangle, f, range(1,11))
Out[139]:
The following quoted content is kept from a page in the OEIS.
Figure drawn by Henry Bottomley, July 27 2000.
If turned sideways (so that the red node at the left is at the bottom), this may be regarded as the Fibonacci Tree, which grows according to the rules that:
- every red node turns blue after a year
- every blue node produces one blue node and one red node after a year
- initially there is a single red node
At the $n$th year there are $F_n$ nodes.
Here is a different representation of the same tree, also from the same source:
This grows according to the rules that every mature branch sprouts a new branch at the end of each year, and new branches take a year to reach maturity.Mature branches are indicated by heavy lines. At the end of the nth year there are $F_n$ branches:
Another version of the Fibonacci tree can be constructed as follows:
Start with a node labeled 0. From any given node, draw branches extending up from it labeled $n+1$ and $2n$. In this way every node is labeled with a unique nonnegative integer, and every nonnegative integer appears exactly once. This is the "state diagram" for the process "if $n$ is even divide by 2, if $n$ is odd subtract 1".
Another funny image, taken from a italian book for children, is the following:
This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.