<jupyter_start><jupyter_text>Números de Fibonnacci complejosLos números de Fibonnacci siguen la conocida recurrencia:$$F_n = F_{n-1} + F_{n-2}$$Empezando con 0, 1 obtenemos:$$0, 1, 1, 2, 3, 5, 8, \ldots$$La secuencia puede extenderse hacia enteros negativos reordenando la relación de recurrencia:$$F_{n-2} = F_n - F_{n-1}$$Con lo que obtenemos la secuencia:$$0, 1, -1, 2, -3, 5, -8, \ldots$$Con lo que se cumple:$$F_{-n} = (-1)^{n+1} F_{n}$$ Para extender los números de Fibbonacci al campo real, podemos utilizar **la fórmula de Binet**, que nos permite obtener el n-esimo término sin recurrencia:$$F_n = \frac{\phi^n - (1 - \phi)^n}{\sqrt{5}}$$y donde $\phi = \frac{1 + \sqrt{5}}{2}$Sin embargo, como $1 - \phi$ es negativo, esta relación solo devuelve resultados reales para los números enteros.No podemos obtener números de Fibbonacci reales, **pero sí complejos**.<jupyter_code>import numpy as np
import matplotlib.pyplot as plt
import math
SQRT5 = math.sqrt(5)
PHI = (1 + SQRT5) / 2
def fibbn(n):
    """ Fibonacci numbers via Binet formula"""
    return (PHI**n - (1-PHI)**n)/SQRT5
# Complejos, parte real y parte imagianria

xx = np.linspace(0, 4, 1000)
zz = xx + 1j * 0
ii = np.arange(0, 5)

# Complejos
cfib1 = fibbn(zz)
# Enteros
ifib1 = fibbn(ii)
    
plt.axhline(y=0, color='k')
plt.axvline(x=0, color='k')
plt.plot(cfib1.real, cfib1.imag)
plt.plot(ifib1, [0 for f in ifib1], "ro")
plt.show()
plt.plot(xx, cfib1.real)
plt.plot(ii, ifib1, "ro")
plt.show()
plt.plot(xx, cfib1.imag, 'g')
plt.show()
def plot_fibb1(n1=0, n2=4):
    xx = np.linspace(n1, n2, 1000)
    zz = xx + 1j * 0
    ii = np.arange(n1, n2 + 1)

    cfib1 = fibbn(zz)
    ifib1 = fibbn(ii)

    plt.axhline(y=0, color='k')
    plt.axvline(x=0, color='k')
    plt.plot(cfib1.real, cfib1.imag)
    plt.plot(ifib1, [0 for f in ifib1], "ro")
    plt.show()
    plt.plot(xx, cfib1.real)
    plt.plot(ii, ifib1, "ro")
    plt.show()
    plt.plot(xx, cfib1.imag, 'g')
    plt.show()

plot_fibb1(-4, 0)<jupyter_output><empty_output><jupyter_text>Con widgetsCargamos el módulo `ipywidgets` y utilizamos la función `interact`<jupyter_code>from ipywidgets import interact
import ipywidgets as widgets
# interact crea controles a partir de los argumentos
# de la función. Para cada tipo de argumento (entero, cadena)
# crea un control diferente
# Utiliza los valores por defecto como valores iniciales
interact(plot_fibb1, n1=(-5, 5), n2=(0, 5));
def plot_fibb2(n1=0, n2=4):
    
    # definitions for the axes
    left, width = 0.1, 0.65
    bottom, height = 0.1, 0.65
    spacing = 0.005

    rect_scatter = [left, bottom, width, height]
    rect_histx = [left, bottom + height + spacing, width, 0.2]
    rect_histy = [left + width + spacing, bottom, 0.2, height]

    fig = plt.figure(figsize=(8, 8))

    ax1 = fig.add_axes(rect_scatter)
    ax2 = fig.add_axes(rect_histx, sharex=ax1)
    ax3 = fig.add_axes(rect_histy, sharey=ax1)
    
    xx = np.linspace(n1, n2, 1000)
    ii = np.arange(n1, n2 + 1)
    cfib1 = np.array([fibbn(x+ 1j*0) for x in xx])
    ifib1 = np.array([fibbn(i) for i in ii])
    
    ax1.plot(cfib1.real, cfib1.imag)
    ax1.plot(ifib1, [0 for f in ifib1], "ro")
    
    ax2.plot(cfib1.real, xx)
    ax2.plot(ifib1, ii, "ro")
    ax2.tick_params(axis="x", labelbottom=False)
    
    
    ax3.plot(xx, cfib1.imag)
    ax3.tick_params(axis="y", labelleft=False)

plot_fibb2()
interact(plot_fibb2, n1=(-7,0), n2=(0,7));
# En el caso de un gráfico, se actualiza para
# cada movimiento de los controles
# se puede evitar con `continuous_update=False`
# pero tenemos que crear los controles explícitamente
interact(plot_fibb2, 
         n1=widgets.IntSlider(min=-7, max=0, value=0, 
                              continuous_update=False),
         n2=widgets.IntSlider(min=0, max=7, value=4,
                              continuous_update=False)
        );<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.1482340809486981, 'fraction_numerical': 0.04382572828048466, 'mean_word_length': 3.538011695906433, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '2', 'dir': 'jupyter-structured-clean-dedup', 'id': '24757', 'license': 'BSD-3-Clause', 'n_tokens_mistral': 1697, 'n_tokens_neox': 1596, 'n_words': 407, 'path': 'cuadernos/cfibonacci.ipynb', 'repo_name': 'sergiopasra/taller-jupyter', 'size': '3879'}