Simple random walk on a hypercube

438 views Asked by At

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?!

  1. 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
    
  2. 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
    
  3. 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
    
  4. 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
    
  5. 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()
    
  6. I get this plot: (n=5 looks right but n=10 tapers off at a non-zero value)

enter image description here

0

There are 0 answers