From 47c28079959670d70c98f50fe5086c20b28509ab Mon Sep 17 00:00:00 2001 From: joaquinpolonuer Date: Wed, 28 Sep 2022 12:39:06 -0300 Subject: [PATCH] algunos ejercicios de Markov --- Practica 3/Clase 10 - Markov.ipynb | 341 +++++++++++++++++++++++++++++ Practica 3/Ejercicios Guia 3.ipynb | 239 +++++++++++++++++++- tp1/tp1.ipynb | 4 +- 3 files changed, 574 insertions(+), 10 deletions(-) create mode 100644 Practica 3/Clase 10 - Markov.ipynb diff --git a/Practica 3/Clase 10 - Markov.ipynb b/Practica 3/Clase 10 - Markov.ipynb new file mode 100644 index 0000000..c24266b --- /dev/null +++ b/Practica 3/Clase 10 - Markov.ipynb @@ -0,0 +1,341 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "\n", + "# Acá les dejo un regalito. \n", + "# Para que todo lo que printeamos tenga 3 decimales y sin notación científica\n", + "np.set_printoptions(precision=3)\n", + "np.set_printoptions(suppress=True)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Defino algunas funciones que nos van a servir" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [], + "source": [ + "def matriz_ruina_apostador(n,p):\n", + " \"\"\"Devuelve la matriz de transición de la ruina del apostador \n", + " de tamaño nxn, cuando se gana con probabilidad p\"\"\"\n", + " \n", + " A = np.zeros((n,n))\n", + " A[0,0] = 1\n", + " A[-1,-1] = 1\n", + " for j in range(1,n-1):\n", + " A[j-1,j] = 1-p\n", + " A[j+1,j] = p\n", + " return(A)" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [], + "source": [ + "def p_inf_v(P, v ,k , tol = 10**-6):\n", + " \"\"\"Itera v = P@v hasta que converja o se llegue a k iteraciones.\n", + " tol es como el espilón del límite, si la distancia entre dos iteraciones\n", + " consecutivas es menor a tol consideramos que llegamos al límite\"\"\"\n", + " \n", + " for i in range(k):\n", + " if np.linalg.norm(P @ v - v) < tol:\n", + " break\n", + " else:\n", + " v = P @ v\n", + " return(v)" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [], + "source": [ + "def canonico(n,j):\n", + " \"\"\"Devuelve el canoninco e_j de R^n\"\"\"\n", + "\n", + " v = np.zeros(n)\n", + " v[j] = 1\n", + " return(v)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Tenis" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[[1. 0.333 0. 0. 0. ]\n", + " [0. 0. 0.333 0. 0. ]\n", + " [0. 0.667 0. 0.333 0. ]\n", + " [0. 0. 0.667 0. 0. ]\n", + " [0. 0. 0. 0.667 1. ]]\n" + ] + } + ], + "source": [ + "#Armo la matriz de proceso\n", + "n=5\n", + "p=2/3\n", + "\n", + "P = matriz_ruina_apostador(n,p)\n", + "print(P)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[0. 0. 1. 0. 0.]\n" + ] + } + ], + "source": [ + "# Estado inicial 40-40 (deuce), o sea el tercer canoninco\n", + "v = canonico(n,2) # Acuerdense que python cuenta desde 0\n", + "print(v)" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[0.2 0. 0. 0. 0.8]\n" + ] + } + ], + "source": [ + "# Iteramos\n", + "v_inf = p_inf_v(P,v,1000)\n", + "print(v_inf)" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([0.2 , 0.8 , 1.275, 0.778, 0. ])" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Cómo se escribe v en base de autovectores?\n", + "\n", + "Cbe = np.linalg.eig(P)[1]\n", + "np.linalg.solve(Cbe,v)" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[[1. 0.467 0.2 0.067 0. ]\n", + " [0. 0. 0. 0. 0. ]\n", + " [0. 0. 0. 0. 0. ]\n", + " [0. 0. 0. 0. 0. ]\n", + " [0. 0.533 0.8 0.933 1. ]]\n" + ] + } + ], + "source": [ + "# Cómo se ve P^inf\n", + "\n", + "P_inf = np.linalg.matrix_power(P,1000)\n", + "print(P_inf)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "¿Qué nos dicen las columnas de $ P^\\infty $ ?" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Figuritas" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": {}, + "outputs": [], + "source": [ + "def matriz_figuritas(n):\n", + " \"\"\"Devuelve la matriz de transición para el problema de n figuritas\"\"\"\n", + " \n", + " diag = np.linspace(0,1,n+1) # esto me arma la suc k/n con k de 0 hasta n\n", + " \n", + " # Armo una matriz diagonal con diag en la diagonal\n", + " P = np.diag(diag)\n", + "\n", + " # abajo de la diagonal recorro la suc k/n al revés desde n hasta 1\n", + " for i in range(1,n+1):\n", + " P[i,i-1] = diag[-i] \n", + " return(P)" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": {}, + "outputs": [], + "source": [ + "P = matriz_figuritas(638)\n", + "v = canonico(639,0)" + ] + }, + { + "cell_type": "code", + "execution_count": 27, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[0. , 0. , 0. , ..., 0. , 0. , 0. ],\n", + " [1. , 0.002, 0. , ..., 0. , 0. , 0. ],\n", + " [0. , 0.998, 0.003, ..., 0. , 0. , 0. ],\n", + " ...,\n", + " [0. , 0. , 0. , ..., 0.997, 0. , 0. ],\n", + " [0. , 0. , 0. , ..., 0.003, 0.998, 0. ],\n", + " [0. , 0. , 0. , ..., 0. , 0.002, 1. ]])" + ] + }, + "execution_count": 27, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "P" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "5553\n", + "[0. 0. 0.005 0.095 0.9 ]\n" + ] + } + ], + "source": [ + "# Itero hasta que la última coordeanda de v sea mayor o igual a 0.9\n", + "# y cuento cuantas figuritas compre\n", + "figus = 0\n", + "while v[-1] < 0.9:\n", + " v = P @ v\n", + " figus += 1 # esto equivale a figus = figus + 1\n", + "print(figus)\n", + "print(v[-5:])" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Neccesito comprar 1111 paquetes para tener un 90% de probabilidades de llenar el álbum\n" + ] + } + ], + "source": [ + "# Suponiendo 5 figuritas por paquete:\n", + "print('Neccesito comprar', round(figus/5), 'paquetes para tener un 90% de probabilidades de llenar el álbum')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### ¿Se les ocurren otros juegos o problemas que se puedan modelar con procesos de Markov?" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "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.8.10" + }, + "vscode": { + "interpreter": { + "hash": "369f2c481f4da34e4445cda3fffd2e751bd1c4d706f27375911949ba6bb62e1c" + } + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/Practica 3/Ejercicios Guia 3.ipynb b/Practica 3/Ejercicios Guia 3.ipynb index 062c66a..456dbdb 100644 --- a/Practica 3/Ejercicios Guia 3.ipynb +++ b/Practica 3/Ejercicios Guia 3.ipynb @@ -2,14 +2,26 @@ "cells": [ { "cell_type": "code", - "execution_count": 44, + "execution_count": 73, "id": "7999349e", "metadata": {}, "outputs": [], "source": [ "from scipy.linalg import null_space\n", "import numpy as np\n", - "from numpy.linalg import eigvals, norm, inv\n" + "from numpy.linalg import eigvals, norm, inv\n", + "import matplotlib.pyplot as plt" + ] + }, + { + "cell_type": "code", + "execution_count": 79, + "id": "b700ee38", + "metadata": {}, + "outputs": [], + "source": [ + "np.set_printoptions(precision=3)\n", + "np.set_printoptions(suppress=True)" ] }, { @@ -22,7 +34,7 @@ }, { "cell_type": "code", - "execution_count": 100, + "execution_count": 3, "id": "94b30bd2", "metadata": {}, "outputs": [], @@ -32,7 +44,7 @@ }, { "cell_type": "code", - "execution_count": 101, + "execution_count": 4, "id": "7591e8cb", "metadata": {}, "outputs": [], @@ -48,7 +60,7 @@ }, { "cell_type": "code", - "execution_count": 102, + "execution_count": 5, "id": "986fdf71", "metadata": {}, "outputs": [ @@ -59,7 +71,7 @@ " [ 1., 1.]])" ] }, - "execution_count": 102, + "execution_count": 5, "metadata": {}, "output_type": "execute_result" } @@ -70,7 +82,7 @@ }, { "cell_type": "code", - "execution_count": 103, + "execution_count": 6, "id": "c0eee91e", "metadata": {}, "outputs": [ @@ -99,10 +111,221 @@ " print(mi_super_formula_de_fibonacci(n))\n" ] }, + { + "cell_type": "markdown", + "id": "5fd058d4", + "metadata": {}, + "source": [ + "# Markov" + ] + }, + { + "cell_type": "code", + "execution_count": 69, + "id": "cec30aa5", + "metadata": {}, + "outputs": [], + "source": [ + "def p_inf_v(P, v ,k , tol = 10**-6):\n", + " \"\"\"Itera v = P@v hasta que converja o se llegue a k iteraciones.\n", + " tol es como el espilón del límite, si la distancia entre dos iteraciones\n", + " consecutivas es menor a tol consideramos que llegamos al límite\"\"\"\n", + " \n", + " for i in range(k):\n", + " if np.linalg.norm(P @ v - v) < tol:\n", + " break\n", + " else:\n", + " v = P @ v\n", + " return(v)" + ] + }, + { + "cell_type": "markdown", + "id": "233003c1", + "metadata": {}, + "source": [ + "### Ejercicio 17: Ratones" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "0830867d", + "metadata": {}, + "outputs": [], + "source": [ + "A = (1/4) * np.array([[1,2,2,2], [1,2,0,0], [1,0,2,0], [1,0,0,2]])\n", + "avals = eigvals(A)\n", + "avecs = [null_space(A - l*np.eye(4)) for l in avals]" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "5d643c59", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([8.046875, 3.984375, 3.984375, 3.984375])" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "v = [20,0,0,0]\n", + "for i in range(4):\n", + " v = A@v\n", + "v" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "id": "879a3c5f", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[[0.4 0.4 0.4 0.4]\n", + " [0.2 0.2 0.2 0.2]\n", + " [0.2 0.2 0.2 0.2]\n", + " [0.2 0.2 0.2 0.2]]\n" + ] + } + ], + "source": [ + "A = (1/4) * np.array([[1,2,2,2], [1,2,0,0], [1,0,2,0], [1,0,0,2]])\n", + "for i in range(5):\n", + " A = A@A\n", + "print(A)" + ] + }, + { + "cell_type": "markdown", + "id": "95fd856a", + "metadata": {}, + "source": [ + "### Ejercicio 18: Borracho" + ] + }, + { + "cell_type": "code", + "execution_count": 62, + "id": "6fcda7e4", + "metadata": {}, + "outputs": [], + "source": [ + "def matriz_de_transicion(n,p):\n", + " \"\"\"Devuelve la matriz de transición cuando la probabilidad\n", + " de ir para casa es p y la distancia es de n\n", + " \"\"\"\n", + " \n", + " A = np.zeros((n,n))\n", + " A[0,0] = 1\n", + " A[-1,-1] = 1\n", + " for j in range(1,n-1):\n", + " A[j-1,j] = p\n", + " A[j+1,j] = 1-p\n", + "\n", + " return A" + ] + }, + { + "cell_type": "code", + "execution_count": 94, + "id": "3b628429", + "metadata": {}, + "outputs": [], + "source": [ + "def calcular_estado_limite(n, p, ei):\n", + " P = matriz_de_transicion(n,p)\n", + " v = np.zeros(n)\n", + " v[ei] = 1\n", + " return p_inf_v(P, v, 10000)" + ] + }, + { + "cell_type": "markdown", + "id": "99b9a1fc", + "metadata": {}, + "source": [ + "#### Seria interesante calcular la probabilidad de quedarse en casa como una funcion de ei y p" + ] + }, + { + "cell_type": "code", + "execution_count": 97, + "id": "cbd02f3e", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Con un 47.368323441321245% de probabilidades termina en casa\n", + "Con un 52.631479986358876% de probabilidades termina en el bar\n" + ] + } + ], + "source": [ + "limite = calcular_estado_limite(20, 1/2, 10)\n", + "print(f\"Con un {limite[0]*100}% de probabilidades termina en casa\")\n", + "print(f\"Con un {limite[n-1]*100}% de probabilidades termina en el bar\")" + ] + }, + { + "cell_type": "code", + "execution_count": 98, + "id": "83184c5c", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Con un 99.99950424862773% de probabilidades termina en casa\n", + "Con un 0.0003814691861656787% de probabilidades termina en el bar\n" + ] + } + ], + "source": [ + "limite = calcular_estado_limite(20, 0.8, 10)\n", + "print(f\"Con un {limite[0]*100}% de probabilidades termina en casa\")\n", + "print(f\"Con un {limite[n-1]*100}% de probabilidades termina en el bar\")" + ] + }, + { + "cell_type": "code", + "execution_count": 101, + "id": "b9bbd86c", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Con un 94.73674467762108% de probabilidades termina en casa\n", + "Con un 5.263059119935287% de probabilidades termina en el bar\n" + ] + } + ], + "source": [ + "limite = calcular_estado_limite(20, 1/2, 1)\n", + "print(f\"Con un {limite[0]*100}% de probabilidades termina en casa\")\n", + "print(f\"Con un {limite[n-1]*100}% de probabilidades termina en el bar\")" + ] + }, { "cell_type": "code", "execution_count": null, - "id": "7bbba2ca", + "id": "48a8e313", "metadata": {}, "outputs": [], "source": [] diff --git a/tp1/tp1.ipynb b/tp1/tp1.ipynb index 89c6840..21f0a51 100644 --- a/tp1/tp1.ipynb +++ b/tp1/tp1.ipynb @@ -347,7 +347,7 @@ }, { "cell_type": "markdown", - "id": "45118922", + "id": "58fb8a2e", "metadata": {}, "source": [ "### Dudas:\n", @@ -362,7 +362,7 @@ " \n", " - lambda + K*I es autovalor de A + K*I\n", " \n", - "A medida que K es mas grande, la diferencia entre los autovalores de **A + K*I** se hace despreciable, por lo que (lambda2/lambda1) ** k tiende a 0 mas lentamente\n" + "A medida que K es mas grande, la diferencia entre los autovalores de **A + K*I** se hace despreciable (La diferencia relativa con K>>1 es chica), por lo que (lambda2/lambda1) ** k tiende a 0 mas lentamente (No confundir K con k)\n" ] }, {