I have written a code for a lazy simple random walk on a n-dimensional hypercube. To visualize it, one can think of a 2D square or a 3D cube with the corners of the square/cube being the vertices of a graph. The walk on this graph starts at the origin and with probability 0.5 stays at a vertex and with remaining equal probability visits its neighbors. The code is running but I have a technical question. I will explain what I did in a bit but at the end, the distance between stationary distribution which is uniform and the distribution obtained by simulation has to decrease to 0 as time increases. In my simulation, for large n, say n=10, the distance between the above distributions tapers off at a non-zero value. It would be great if someone can point out where I went wrong?!
This function generates all vertices of a n-dim hypercube, output is a list of bitstring lists i.e. each vertex of the hypercube is a n-bitstring and there are 2^n such vertices.
def generateAllBinaryStrings(n, arr, l, i): if i == n: l.append(arr[:]) return arr[i] = 0 generateAllBinaryStrings(n, arr, l, i + 1) arr[i] = 1 generateAllBinaryStrings(n, arr, l, i + 1) return l
Creating a dictionary whose keys are vertices and values are the neighbors (each vertex has n neighbors)
def dictionary(v): d={} for i in range(len(v)): d[str(v[i])]=[] temp=[] for j in range(n): temp=v[i][:] if v[i][j]==1: temp[j]=0 else: temp[j]=1 d[str(v[i])].append(temp) return d
simple random walk on the n-dim cube starting at the origin (output is a list of vertices visited in time t)
def srw(d,n,t): h=[[0 for i in range(n)]] w=[1/(2*n) for i in range(n)] w.append(0.5) for i in range(t): temp=d[str(h[-1])][:] temp.append(h[-1]) h.append(random.choices(temp,weights=w)[-1]) return h
Finding L1 distance between stationary distribution and simulated distribution
def tvDist(d,n,t,num): finalstate=[] for i in range(num): temp=srw(d,n,t) finalstate.append(temp[-1]) temp2=[list(item) for item in set(tuple(row) for row in finalstate)] Xt={} for state in temp2: Xt[str(state)]=None for state in temp2: count=0 for i in finalstate: if i==state: count+=1 Xt[str(state)]=count/num dist=0 for state in d: if state in Xt: dist+=abs(Xt[str(state)]-(1/(2**n))) else: dist+=1/(2**n) dist=0.5*(dist) return dist
If you copy paste the code above and run the following (plotting the distance vs time for n=5,10)
import numpy as np import matplotlib.pyplot as plt import random import collections as cs time=30 numsim=5000 for n in range(5,11,5): l = [] arr = [None] * n vertices=generateAllBinaryStrings(n, arr, l, 0) d=dictionary(vertices) tvdistance=[] for t in range(1,time): tvdistance.append(tvDist(d,n,t,numsim)) plt.plot(tvdistance) plt.show()
I get this plot: (n=5 looks right but n=10 tapers off at a non-zero value)