Skip to content

Instantly share code, notes, and snippets.

@pedritomelenas
Created February 22, 2016 17:41
Show Gist options
  • Save pedritomelenas/99cc10c4e75956e4db05 to your computer and use it in GitHub Desktop.
Save pedritomelenas/99cc10c4e75956e4db05 to your computer and use it in GitHub Desktop.
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Números naturales. Inducción. Recursividad."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Naturales"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"En `python` podemos utilizar `isinstance` para determinar si un objeto es un entero"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"True"
]
},
"execution_count": 1,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"isinstance(4,int)"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"False"
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"isinstance([3,4],int)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Podemos con esta función definir otra que detecte si un objeto es un número es natural"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"def isnatural(n):\n",
" if not isinstance(n,int):\n",
" return false\n",
" return n>=0"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"True"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"isnatural(3)"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"False"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"isnatural(-3)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"La funciones sucesor y predecesor quedarían como sigue"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"sucesor = lambda x: x+1"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"3"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"sucesor(2)"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"def prec(n):\n",
" if not isnatural(n):\n",
" raise TypeError(\"El argumento debe ser un número natural\")\n",
" if n==0: \n",
" raise ValueError(\"El 0 no tiene predecesor\")\n",
" return n-1"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"0"
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"prec(1)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Con esto podemos definir una suma"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def suma(m,n):\n",
" if n == 0:\n",
" return m\n",
" return sucesor(suma(m,prec(n)))"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"5"
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"suma(2,3)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Sucesiones, inducción"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Con la librería `sympy` podemos hacer cálculo simbólico. En particular, podemos calcular el valor de algunas sumas con parámetros."
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"from sympy import *"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Cuando vamos a utilizar un símbolo tenemos que declararlo primero. Para el ejemplo que sigue vamos a utilizar `n` como entero e `i` como contador "
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"n, i = symbols(\"n, i\", integer = True)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Algunas sumatorias"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Calculemos por ejemplo $\\sum_{i=1}^n i$"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"s = Sum(i,(i,1,n))"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"Sum(i, (i, 1, n))"
]
},
"execution_count": 15,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"s"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Si queremos calcular el \"valor\" de esta sumatoria, podemos utilizar el método `doit`"
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"n**2/2 + n/2"
]
},
"execution_count": 16,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"s.doit()"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {
"collapsed": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
" 2 \n",
"n n\n",
"── + ─\n",
"2 2\n"
]
}
],
"source": [
"pprint(_)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Y una suma de potencias"
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"s=Sum(i**30,(i,1,n))"
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {
"collapsed": false,
"scrolled": true
},
"outputs": [
{
"data": {
"text/plain": [
"n**31/31 + n**30/2 + 5*n**29/2 - 203*n**27/6 + 1131*n**25/2 - 16965*n**23/2 + 216775*n**21/2 - 2304485*n**19/2 + 19959975*n**17/2 - 137514723*n**15/2 + 731482225*n**13/2 - 31795091601*n**11/22 + 8053785025*n**9/2 - 102818379585*n**7/14 + 15626519181*n**5/2 - 23749461029*n**3/6 + 8615841276005*n/14322"
]
},
"execution_count": 19,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"s.doit()"
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"a = Symbol(\"a\")"
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"Piecewise((n, a == 1), ((a - a**(n + 1))/(-a + 1), True))"
]
},
"execution_count": 21,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"Sum(a**i,(i,1,n)).doit()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Inducción"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Veamos cómo podemos utilizar `sympy` para hacer algunos ejemplos de inducción"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Por ejemplo, veamos que para todo $6\\mid 7^n-1$ para todo $n\\in \\mathbb N$. Empezamos definiendo una función que nos devuelva $7^n-1$"
]
},
{
"cell_type": "code",
"execution_count": 22,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"f = lambda n: 7**n -1"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Primero veamos qué valor tiene en el 0"
]
},
{
"cell_type": "code",
"execution_count": 23,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"0"
]
},
"execution_count": 23,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"f(0)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Si por hipótesis de inducción $f(n)$ es un múltiplo de 6, entonces para probar que $f(n+1)$ también lo es, bastará demostrar que la diferencia $f(n+1)-f(n)$ es un múltiplo de 6"
]
},
{
"cell_type": "code",
"execution_count": 24,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"6*7**n"
]
},
"execution_count": 24,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"simplify(f(n+1)-f(n))"
]
},
{
"cell_type": "code",
"execution_count": 25,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"f = lambda n: 7**(2*n)+16*n-1"
]
},
{
"cell_type": "code",
"execution_count": 26,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"0"
]
},
"execution_count": 26,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"f(0)"
]
},
{
"cell_type": "code",
"execution_count": 27,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"16*Mod(3*7**(2*n) + 1, 4)"
]
},
"execution_count": 27,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"simplify((f(n+1)-f(n)) % 64)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Por tanto, si $3\\times 7^{2n}+1$ es un múltiplo de $4$, habremos acabado"
]
},
{
"cell_type": "code",
"execution_count": 28,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"g = lambda n: 3*7**(2*n)+1"
]
},
{
"cell_type": "code",
"execution_count": 29,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"4"
]
},
"execution_count": 29,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"g(0)"
]
},
{
"cell_type": "code",
"execution_count": 30,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"0"
]
},
"execution_count": 30,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"simplify((g(n+1)-g(n))%4)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Recursividad e iteración"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Veamos cómo las funciones recursivas se pueden acelerar usando memorización de los pasos anteriores"
]
},
{
"cell_type": "code",
"execution_count": 31,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"fib = lambda n: n if n<2 else fib(n-2)+fib(n-1)"
]
},
{
"cell_type": "code",
"execution_count": 32,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"55"
]
},
"execution_count": 32,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"fib(10)"
]
},
{
"cell_type": "code",
"execution_count": 33,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"55"
]
},
"execution_count": 33,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"fibonacci(10)"
]
},
{
"cell_type": "code",
"execution_count": 34,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"import time\n"
]
},
{
"cell_type": "code",
"execution_count": 35,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"0.4115140438079834"
]
},
"execution_count": 35,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"start=time.time()\n",
"fib(30)\n",
"time.time()-start\n"
]
},
{
"cell_type": "code",
"execution_count": 36,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"0.0003228187561035156"
]
},
"execution_count": 36,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"start=time.time()\n",
"fibonacci(30)\n",
"time.time()-start"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Un posible solución a este problema es ir almacenando los resultados previos de cálculo, lo cual es conocido como [memoization](http://stackoverflow.com/questions/1988804/what-is-memoization-and-how-can-i-use-it-in-python)"
]
},
{
"cell_type": "code",
"execution_count": 37,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"import functools"
]
},
{
"cell_type": "code",
"execution_count": 38,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"@functools.lru_cache(maxsize=None)\n",
"def fibo(num):\n",
" if num < 2:\n",
" return num\n",
" else:\n",
" return fibo(num-1) + fibo(num-2)"
]
},
{
"cell_type": "code",
"execution_count": 39,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"9.799003601074219e-05"
]
},
"execution_count": 39,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"start=time.time()\n",
"fibo(30)\n",
"time.time()-start"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Resolución de ecuaciones recursivas"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Las ecuaciones en recurrencia se pueden resolver con el comando `rsolve` de `sympy`"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Empecemos con un ejemplo:\n",
"- $a(0)=0$,\n",
"- $a(1)=1$,\n",
"- $a(n+2)=5a(n+1)-6a(n)$."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Empezamos declarando `a` como función"
]
},
{
"cell_type": "code",
"execution_count": 40,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"a = Function('a')"
]
},
{
"cell_type": "code",
"execution_count": 41,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"2**n*C0 + 3**n*C1"
]
},
"execution_count": 41,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"rsolve(a(n+2)-5*a(n+1)+6*a(n),a(n))"
]
},
{
"cell_type": "code",
"execution_count": 42,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"-2**n + 3**n"
]
},
"execution_count": 42,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"rsolve(a(n+2)-5*a(n+1)+6*a(n),a(n), {a(0):0,a(1):1})"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Vamos a resolverlo mediante el polinomio característico"
]
},
{
"cell_type": "code",
"execution_count": 43,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"[2, 3]"
]
},
"execution_count": 43,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"x=Symbol(\"x\")\n",
"solve(x**2-5*x+6)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Y por tanto la solución general será de la forma $a_n=u 2^n + v 3^n$, para ciertas constantes $u$ y $v$ que tenemos que encontrar a partir de las condiciones iniciales\n",
"\n",
"Imponemos por tanto que $a_0=0=u+v$ y que $a_1=1=2u+3v$"
]
},
{
"cell_type": "code",
"execution_count": 44,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"{u: -1, v: 1}"
]
},
"execution_count": 44,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"u,v = symbols(\"u,v\")\n",
"solve([u+v,2*u+3*v-1])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Por lo que $a_n=-2^n+3^n$, como habíamos visto arriba"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Veamos un ejemplo de una que no sea homogénea"
]
},
{
"cell_type": "code",
"execution_count": 45,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"2**n*C0 + 3**n*C1 + C0*n"
]
},
"execution_count": 45,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"rsolve(a(n+2)-5*a(n+1)+6*a(n)-n,a(n))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Y ahora otro ejemplo no lineal"
]
},
{
"cell_type": "code",
"execution_count": 46,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"f=a(n)-(n-1)*(a(n-1)+a(n-2))"
]
},
{
"cell_type": "code",
"execution_count": 47,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"factorial(n)"
]
},
"execution_count": 47,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"rsolve(f,a(n),{a(0):1})"
]
},
{
"cell_type": "code",
"execution_count": 48,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"0"
]
},
"execution_count": 48,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"simplify(factorial(n)-(n-1)*(factorial(n-1)+factorial(n-2)))"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.5.1"
}
},
"nbformat": 4,
"nbformat_minor": 0
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment