Skip to content

Instantly share code, notes, and snippets.

@josh-hernandez-exe
Last active September 17, 2020 05:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save josh-hernandez-exe/96902e9c7a488f24f8c0b9cc866f5dc0 to your computer and use it in GitHub Desktop.
Save josh-hernandez-exe/96902e9c7a488f24f8c0b9cc866f5dc0 to your computer and use it in GitHub Desktop.
Pokemon Masters Morty and Drifblim analysis on Phantom Force usage
Display the source blob
Display the rendered blob
Raw
{
"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