Last active
September 17, 2020 05:34
-
-
Save josh-hernandez-exe/96902e9c7a488f24f8c0b9cc866f5dc0 to your computer and use it in GitHub Desktop.
Pokemon Masters Morty and Drifblim analysis on Phantom Force usage
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"cells": [ | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"Here I run distreet markov chain analysis to see how likely it is use Phantom Force for a specific number of uses.\n", | |
"\n", | |
"These sources helped me out:\n", | |
"- https://en.wikipedia.org/wiki/Discrete_phase-type_distribution\n", | |
"- https://en.wikipedia.org/wiki/Absorbing_Markov_chain\n", | |
"- http://people.brandeis.edu/~igusa/Math56aS08/\n", | |
"- https://en.wikipedia.org/wiki/Monte_Carlo_method\n", | |
"\n", | |
"**Update**: A more general investigation to move point refresh is done [here](https://gist.github.com/josh-hernandez-exe/07abd3cf45090fd662b38be7ced647ea)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 1, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"# setup\n", | |
"import numpy as np\n", | |
"import sympy\n", | |
"from IPython.display import display\n", | |
"\n", | |
"p = sympy.symbols('p')" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 2, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"# Config\n", | |
"# Change this value to expeiment with how likely a signle MPR will trigger\n", | |
"mpr_rate = 0.4" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 3, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"from collections import Counter\n", | |
"def emperical(start_mp, mpr_prob, num_nodes, num_simulations, cap_mp=None):\n", | |
" \"\"\"Helper function to emprically validate analysis\"\"\"\n", | |
" counter = Counter()\n", | |
" if cap_mp is None:\n", | |
" cap_mp = start_mp\n", | |
" for _ in range(num_simulations):\n", | |
" cur_mp = start_mp\n", | |
" count = 0\n", | |
" while cur_mp > 0:\n", | |
" cur_mp -= 1\n", | |
" count += 1\n", | |
" cur_mp += sum(np.random.rand(num_nodes) < mpr_prob )\n", | |
" cur_mp = min(cur_mp, cap_mp) # since our MP isn't unbounded\n", | |
"\n", | |
" counter[count] += 1\n", | |
" \n", | |
" expected_count = sum(move_count*occurences for move_count,occurences in counter.items()) / num_simulations\n", | |
" \n", | |
" return expected_count" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 4, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/latex": [ | |
"$\\displaystyle \\left[\\begin{matrix}1 & 0 & 0 & 0\\\\1 - p & p & 0 & 0\\\\0 & 1 - p & p & 0\\\\0 & 0 & 1 - p & p\\end{matrix}\\right]$" | |
], | |
"text/plain": [ | |
"Matrix([\n", | |
"[ 1, 0, 0, 0],\n", | |
"[1 - p, p, 0, 0],\n", | |
"[ 0, 1 - p, p, 0],\n", | |
"[ 0, 0, 1 - p, p]])" | |
] | |
}, | |
"metadata": {}, | |
"output_type": "display_data" | |
}, | |
{ | |
"data": { | |
"text/latex": [ | |
"$\\displaystyle \\left[\\begin{matrix}p & 0 & 0\\\\1 - p & p & 0\\\\0 & 1 - p & p\\end{matrix}\\right]$" | |
], | |
"text/plain": [ | |
"Matrix([\n", | |
"[ p, 0, 0],\n", | |
"[1 - p, p, 0],\n", | |
"[ 0, 1 - p, p]])" | |
] | |
}, | |
"metadata": {}, | |
"output_type": "display_data" | |
} | |
], | |
"source": [ | |
"# Transition matrix for only 1 MPR node\n", | |
"A1 = sympy.Matrix(\n", | |
" [[ 1,0,0,0],\n", | |
" [(no_r:= 1-p) , (one_r:=p), 0, 0],\n", | |
" [0,no_r,one_r,0],\n", | |
" [0,0,no_r, one_r]],\n", | |
")\n", | |
"display(A1)\n", | |
"Q1 = A1[1:,1:] # transient-to-transient matrix" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 5, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/latex": [ | |
"$\\displaystyle \\left[\\begin{matrix}1 & 0 & 0 & 0\\\\\\left(1 - p\\right)^{2} & p \\left(2 - 2 p\\right) & p^{2} & 0\\\\0 & \\left(1 - p\\right)^{2} & p \\left(2 - 2 p\\right) & p^{2}\\\\0 & 0 & \\left(1 - p\\right)^{2} & 1 - \\left(1 - p\\right)^{2}\\end{matrix}\\right]$" | |
], | |
"text/plain": [ | |
"Matrix([\n", | |
"[ 1, 0, 0, 0],\n", | |
"[(1 - p)**2, p*(2 - 2*p), p**2, 0],\n", | |
"[ 0, (1 - p)**2, p*(2 - 2*p), p**2],\n", | |
"[ 0, 0, (1 - p)**2, 1 - (1 - p)**2]])" | |
] | |
}, | |
"metadata": {}, | |
"output_type": "display_data" | |
}, | |
{ | |
"data": { | |
"text/latex": [ | |
"$\\displaystyle \\left[\\begin{matrix}p \\left(2 - 2 p\\right) & p^{2} & 0\\\\\\left(1 - p\\right)^{2} & p \\left(2 - 2 p\\right) & p^{2}\\\\0 & \\left(1 - p\\right)^{2} & 1 - \\left(1 - p\\right)^{2}\\end{matrix}\\right]$" | |
], | |
"text/plain": [ | |
"Matrix([\n", | |
"[p*(2 - 2*p), p**2, 0],\n", | |
"[ (1 - p)**2, p*(2 - 2*p), p**2],\n", | |
"[ 0, (1 - p)**2, 1 - (1 - p)**2]])" | |
] | |
}, | |
"metadata": {}, | |
"output_type": "display_data" | |
} | |
], | |
"source": [ | |
"# Transition matrix for 2 MPR nodes\n", | |
"A2 = sympy.Matrix(\n", | |
" [[ 1,0,0,0],\n", | |
" [ (no_r:= (1-p)**2 ) , (one_r:= 2*(1-p)*p ), (two_r:=p**2), 0],\n", | |
" [0,no_r,one_r,two_r],\n", | |
" [0,0,no_r, 1-no_r]],\n", | |
")\n", | |
"display(A2)\n", | |
"Q2 = A2[1:,1:] # transient-to-transient matrix\n", | |
"display(Q2)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 6, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/latex": [ | |
"$\\displaystyle \\left[\\begin{matrix}1 & 0 & 0 & 0\\\\\\left(1 - p\\right)^{3} & 3 p \\left(1 - p\\right)^{2} & 3 p^{2} \\left(1 - p\\right) & p^{3}\\\\0 & \\left(1 - p\\right)^{3} & 3 p \\left(1 - p\\right)^{2} & p^{3} + 3 p^{2} \\left(1 - p\\right)\\\\0 & 0 & \\left(1 - p\\right)^{3} & 1 - \\left(1 - p\\right)^{3}\\end{matrix}\\right]$" | |
], | |
"text/plain": [ | |
"Matrix([\n", | |
"[ 1, 0, 0, 0],\n", | |
"[(1 - p)**3, 3*p*(1 - p)**2, 3*p**2*(1 - p), p**3],\n", | |
"[ 0, (1 - p)**3, 3*p*(1 - p)**2, p**3 + 3*p**2*(1 - p)],\n", | |
"[ 0, 0, (1 - p)**3, 1 - (1 - p)**3]])" | |
] | |
}, | |
"metadata": {}, | |
"output_type": "display_data" | |
}, | |
{ | |
"data": { | |
"text/latex": [ | |
"$\\displaystyle \\left[\\begin{matrix}3 p \\left(1 - p\\right)^{2} & 3 p^{2} \\left(1 - p\\right) & p^{3}\\\\\\left(1 - p\\right)^{3} & 3 p \\left(1 - p\\right)^{2} & p^{3} + 3 p^{2} \\left(1 - p\\right)\\\\0 & \\left(1 - p\\right)^{3} & 1 - \\left(1 - p\\right)^{3}\\end{matrix}\\right]$" | |
], | |
"text/plain": [ | |
"Matrix([\n", | |
"[3*p*(1 - p)**2, 3*p**2*(1 - p), p**3],\n", | |
"[ (1 - p)**3, 3*p*(1 - p)**2, p**3 + 3*p**2*(1 - p)],\n", | |
"[ 0, (1 - p)**3, 1 - (1 - p)**3]])" | |
] | |
}, | |
"metadata": {}, | |
"output_type": "display_data" | |
} | |
], | |
"source": [ | |
"# Transition matrix for 3 MPR nodes\n", | |
"A3 = sympy.Matrix(\n", | |
" [[ 1,0,0,0],\n", | |
" [ (no_r:= (1-p)**3 ) , (one_r:= 3*(1-p)**2 * p), (two_r:=3 * p**2 * (1-p)), (three_r:=p**3) ],\n", | |
" [0,no_r,one_r,two_r+three_r],\n", | |
" [0,0,no_r, 1-no_r]],\n", | |
")\n", | |
"display(A3)\n", | |
"Q3 = A3[1:,1:] # transient-to-transient matrix\n", | |
"display(Q3)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 7, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"# Helper matrix for later on\n", | |
"ones = sympy.Matrix([1,1,1])" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"## Calculations for only 1 MPR\n", | |
"\n", | |
"If `mpr = 0.3` (MPR 2) has 4.285 expected uses\n", | |
"\n", | |
"If `mpr = 0.4` (MPR 3) has 5 expected uses\n", | |
"\n", | |
"If `mpr = 0.5` (MPR 4) has 6 expected uses" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 8, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/latex": [ | |
"$\\displaystyle - \\frac{3}{p - 1}$" | |
], | |
"text/plain": [ | |
"-3/(p - 1)" | |
] | |
}, | |
"metadata": {}, | |
"output_type": "display_data" | |
} | |
], | |
"source": [ | |
"# Expected usage calculation\n", | |
"r1 = ((sympy.eye(3)-Q1)**(-1) @ ones)[2,0]\n", | |
"display(r1.simplify())" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 9, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/latex": [ | |
"$\\displaystyle 5$" | |
], | |
"text/plain": [ | |
"5" | |
] | |
}, | |
"execution_count": 9, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"r1.subs(p, sympy.Rational(str(mpr_rate)))" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 10, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"5.00000000000000\n" | |
] | |
} | |
], | |
"source": [ | |
"print(r1.evalf(subs={p:mpr_rate}))" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 11, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"5.00614" | |
] | |
}, | |
"execution_count": 11, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"# We will emprically verify this simulations\n", | |
"emperical(3, float(mpr_rate), 1, 100_000)" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"## Calculations for 2 MPR\n", | |
"\n", | |
"If `mpr = 0.3` (MPR 2) has 6.941 expected uses\n", | |
"\n", | |
"If `mpr = 0.4` (MPR 3) has 11.351 expected uses\n", | |
"\n", | |
"If `mpr = 0.5` (MPR 4) has 24 expected uses" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 12, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/latex": [ | |
"$\\displaystyle \\frac{6 p^{4} - 16 p^{3} + 20 p^{2} - 12 p + 3}{p^{6} - 6 p^{5} + 15 p^{4} - 20 p^{3} + 15 p^{2} - 6 p + 1}$" | |
], | |
"text/plain": [ | |
"(6*p**4 - 16*p**3 + 20*p**2 - 12*p + 3)/(p**6 - 6*p**5 + 15*p**4 - 20*p**3 + 15*p**2 - 6*p + 1)" | |
] | |
}, | |
"metadata": {}, | |
"output_type": "display_data" | |
} | |
], | |
"source": [ | |
"# Expected usage calculation\n", | |
"r2 = ((sympy.eye(3)-Q2)**(-1) @ ones)[2,0]\n", | |
"display(r2.simplify())" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 13, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/latex": [ | |
"$\\displaystyle \\frac{8275}{729}$" | |
], | |
"text/plain": [ | |
"8275/729" | |
] | |
}, | |
"execution_count": 13, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"r2.subs(p, sympy.Rational(str(mpr_rate)))" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 14, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"11.3511659807956\n" | |
] | |
} | |
], | |
"source": [ | |
"print(r2.evalf(subs={p:mpr_rate}))" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 15, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"11.33652" | |
] | |
}, | |
"execution_count": 15, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"# We will emprically verify this simulations\n", | |
"emperical(3, float(mpr_rate), 2, 100_000)" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"## Calculations if we had 3 MPR\n", | |
"\n", | |
"If `mpr = 0.3` (MPR 2) has 13.804 expected uses\n", | |
"\n", | |
"If `mpr = 0.4` (MPR 3) has 42.645 expected uses\n", | |
"\n", | |
"If `mpr = 0.5` (MPR 4) has 224 expected uses" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 16, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/latex": [ | |
"$\\displaystyle \\frac{- 10 p^{6} + 45 p^{5} - 81 p^{4} + 81 p^{3} - 51 p^{2} + 18 p - 3}{p^{9} - 9 p^{8} + 36 p^{7} - 84 p^{6} + 126 p^{5} - 126 p^{4} + 84 p^{3} - 36 p^{2} + 9 p - 1}$" | |
], | |
"text/plain": [ | |
"(-10*p**6 + 45*p**5 - 81*p**4 + 81*p**3 - 51*p**2 + 18*p - 3)/(p**9 - 9*p**8 + 36*p**7 - 84*p**6 + 126*p**5 - 126*p**4 + 84*p**3 - 36*p**2 + 9*p - 1)" | |
] | |
}, | |
"metadata": {}, | |
"output_type": "display_data" | |
} | |
], | |
"source": [ | |
"# Expected usage calculation\n", | |
"r3 = ((sympy.eye(3)-Q3)**(-1) @ ones)[2,0]\n", | |
"display(r3.simplify())" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 17, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/latex": [ | |
"$\\displaystyle \\frac{8275}{729}$" | |
], | |
"text/plain": [ | |
"8275/729" | |
] | |
}, | |
"execution_count": 17, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"r2.subs(p, sympy.Rational(str(mpr_rate)))" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 18, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"42.6446679876035\n" | |
] | |
} | |
], | |
"source": [ | |
"print(r3.evalf(subs={p:mpr_rate}))" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 19, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"42.64725" | |
] | |
}, | |
"execution_count": 19, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"# We will emprically verify this simulations\n", | |
"emperical(3, float(mpr_rate), 3, 100_000)" | |
] | |
} | |
], | |
"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.8.5" | |
} | |
}, | |
"nbformat": 4, | |
"nbformat_minor": 4 | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment