项目作者: OnurArdaB

项目描述 :
A simple simulation for percolation on square lattices.
高级语言: Jupyter Notebook
项目地址: git://github.com/OnurArdaB/Percolation.git
创建时间: 2021-06-02T02:03:33Z
项目社区:https://github.com/OnurArdaB/Percolation

开源协议:

下载


Percolation

  1. %matplotlib inline
  2. import os, sys
  3. import json
  4. import random
  5. import numpy as np
  6. import networkx as nx
  7. import pandas as pd
  8. import matplotlib
  9. from matplotlib import pyplot as plt
  10. # Import any other package you may need
  11. from pylab import *
  12. from scipy.ndimage import measurements
  13. from google.colab import drive
  14. import statistics
  15. drive.mount("gdrive")
  1. Mounted at gdrive

Helper functions for data visualization

  1. def visualize_grid(grid, params=None, figname=None):
  2. '''
  3. Generic data visualization function
  4. - grid: 2D numpy array that has integer values
  5. - params: dictionary of parameters ex: {'dim': (50,50), 'p':0.5}
  6. - figname: path and name for a figure file ex: figures/sample_05.pdf
  7. '''
  8. cmap = plt.cm.get_cmap('jet', len(np.unique(grid)))
  9. im = plt.matshow(grid, cmap=cmap, origin='lower', interpolation='none')
  10. plt.colorbar(im, fraction=0.046, pad=0.04)
  11. plt.xticks([])
  12. plt.yticks([])
  13. if params != None:
  14. plt.title(params, fontsize=10)
  15. if figname != None:
  16. plt.savefig(figname, dpi=300, bbox_inches='tight')

Simulate percolation

  1. def paint_grid(clusters,prevGrid):
  2. temp_grid = np.copy(prevGrid)
  3. for cluster in clusters:
  4. for coord in cluster:
  5. temp_grid[coord[0]][coord[1]] = 2.0
  6. return temp_grid

This function is for painting the entire percolating cluster(s) with label 2 in order to make the grid easily differentiable.

  1. def create_grid(dimensions, pthr):
  2. '''
  3. Create a grid as 2D numpy array and return the grid
  4. - dimensions: tuple or array that has height and width of the grid ex: [50,50]
  5. - pthr: threshold value for occupying a cell
  6. '''
  7. grid = np.zeros(dimensions)
  8. # FILL HERE
  9. for irow,i in enumerate(grid):
  10. for icolumn,j in enumerate(i):
  11. grid[irow][icolumn] =1 if pthr>random() else 0
  12. return grid
  13. def find_clusters(grid):
  14. '''
  15. Find clusters of occupied cells in the grid
  16. - grid: 2D numpy array
  17. Return:
  18. - cGrids: 2D numpy array that has a different integer values for each cluster cells
  19. - clusters: list of coordinates for each cluster
  20. '''
  21. clusters = list()
  22. cGrids = np.zeros(grid.shape)
  23. # FILL HERE
  24. # finds every connected component
  25. lw, num = measurements.label(grid)
  26. clusters = []
  27. for i in range(num+1):
  28. temp = []
  29. clusters.append(temp)
  30. #randomizing colors (guarantees different colors for non-occupied)
  31. labels = arange(lw.max() + 1)
  32. shuffle(labels)
  33. #assigning them to grids
  34. cGrids = labels[lw]
  35. for irow,i in enumerate(grid):
  36. for icolumn,j in enumerate(i):
  37. cGrids[irow][icolumn] = cGrids[irow][icolumn] if grid[irow][icolumn]!=0 else 0
  38. if (lw[irow][icolumn]>0):
  39. clusters[cGrids[irow][icolumn]].append((irow,icolumn))
  40. return cGrids,sorted(clusters, key=len)
  41. def check_percolation(grid, clusters):
  42. '''
  43. Check whether given grid percolated
  44. - grid: 2D numpy array
  45. Return:
  46. - grid: 2D numpy array. This function updated the value of grid to reflect percolating component
  47. - percCluster: coordinates of the cells in the percolating component
  48. '''
  49. clusters = sorted(clusters, key=len)
  50. percCluster = []
  51. temp_grid = np.zeros(grid.shape)
  52. # search for percolated cluster(s)
  53. for cluster in list(sorted(clusters,key=len,reverse=False)):
  54. # open sites
  55. left = []
  56. right = []
  57. up = []
  58. down = []
  59. # for every coordinate we check whether there exists an open site
  60. for coord in cluster:
  61. if (coord[0]==0):
  62. up.append(coord)
  63. elif (coord[1]==0):
  64. left.append(coord)
  65. elif (coord[0]==grid.shape[0]-1):
  66. down.append(coord)
  67. elif (coord[1]==grid.shape[0]-1):
  68. right.append(coord)
  69. # if any cluster connected to open sites from up to down or left to right is found
  70. # current cluster percolates
  71. if (len(down)>0 and len(up)>0):
  72. percCluster.append(cluster)
  73. break
  74. elif (len(left)>0 and len(right)>0):
  75. percCluster.append(cluster)
  76. break
  77. # if any percolating cluster(s) found, paint_grid paints them to grid and returns them
  78. if (len(percCluster)>0):
  79. return paint_grid(percCluster,grid), percCluster
  80. return temp_grid, None
  81. pval = 0.60
  82. dims = (100,100)
  83. rgrid = create_grid(dims, pval)
  84. visualize_grid(rgrid, {'p':pval, 'dims':dims})
  85. cgrid,clusters = find_clusters(rgrid)
  86. visualize_grid(cgrid, {'p':pval, 'dims':dims})
  87. pgrid, pcluster = check_percolation(rgrid, clusters)
  88. visualize_grid(pgrid, {'p':pval, 'dims':dims})

png

png

png

Initially we first occupy cells with respect to a probability. In create_grid function we assign a variable in order to define the grid. After the grid is generated, we traverse every cell and check whether the generated number outruns the occupation threshold. If the occupation probability outruns the random number, then we assign 1 to the respective cell.

In find_cluster function we initially label every cluster via the implemented scipy.ndimage.measurements.label function. As a result, this method returns number of clusters and the labelled grid from top to bottom. Then we shuffle the labels in order to obtain a more spanned color spectrum on closer clusters.
Every cluster and its respective coordinate is collected from the grid and returned as a result for find_cluster function with the labelled grid as well.

Finally in check_percolation function, we traverse every cluster and check whether the observed cluster shares any coordinates from left most to right most or up most to down most. If any of the previously mentioned conditions are met, the system shares a percolating cluster and this cluster is saved as a percolating cluster. Resulting cluster is

  1. try:
  2. os.remove("/content/gdrive/MyDrive/percolation-figures/percolation_experiments.jsons")
  3. except OSError:
  4. pass
  1. # You can change the parameters below.
  2. NRANDOM = 50
  3. DIMS = (100,100)
  4. pExplore = np.linspace(0,1,21)[1:]
  5. pExpand = np.linspace(0.5,0.64,14)[1:] # Update this array to find more accurate estimation.
  6. expResults = list()
  7. for n in range(NRANDOM):
  8. # You can run simulation for pExplore and pExpand values seperately and repeat pExpand if needed.
  9. #for pval in pExplore:
  10. for pval in pExpand:
  11. rgrid = create_grid(DIMS, pval)
  12. cgrid, clusters = find_clusters(rgrid)
  13. pgrid, pclusters = check_percolation(rgrid, clusters)
  14. if n == 0:
  15. # Sample one outcome for each parameter
  16. visualize_grid(cgrid, {'p':np.round(pval,4), 'dims':dims},figname='/content/gdrive/MyDrive/percolation-figures/percvis_p{:.4f}.pdf'.format(pval))
  17. # I recommend keeping all the experiment results in a file,
  18. # so that you will have them all before your analysis
  19. expResults.append({
  20. 'p': pval,
  21. 'idx': n,
  22. 'dim': DIMS,
  23. 'isPercolated': pclusters != None,
  24. 'clusters': clusters,
  25. 'pclulen' : len(pclusters[0]) if pclusters!=None else 0
  26. })
  27. #print({k:v for k,v in expResults[-1].items() if k != 'clusters'})
  28. # Let's keep the latest experiment result on a file
  29. with open('/content/gdrive/MyDrive/percolation-figures/percolation_experiments.jsons', 'a') as fl:
  30. fl.write('{}\n'.format(json.dumps(expResults[-1])))

png

png

png

png

png

png

png

png

png

png

png

png

png

  1. # You can change the parameters below.
  2. NRANDOM = 50
  3. DIMS = (100,100)
  4. pExplore = np.linspace(0,1,21)[1:]
  5. pExpand = np.linspace(0.5,0.64,14)[1:] # Update this array to find more accurate estimation.
  6. expResults = list()
  7. for n in range(NRANDOM):
  8. # You can run simulation for pExplore and pExpand values seperately and repeat pExpand if needed.
  9. for pval in pExplore:
  10. #for pval in pExpand:
  11. rgrid = create_grid(DIMS, pval)
  12. cgrid, clusters = find_clusters(rgrid)
  13. pgrid, pclusters = check_percolation(rgrid, clusters)
  14. if n == 0:
  15. # Sample one outcome for each parameter
  16. visualize_grid(cgrid, {'p':np.round(pval,4), 'dims':dims},figname='/content/gdrive/MyDrive/percolation-figures/percvis_p{:.4f}.pdf'.format(pval))
  17. # I recommend keeping all the experiment results in a file,
  18. # so that you will have them all before your analysis
  19. expResults.append({
  20. 'p': pval,
  21. 'idx': n,
  22. 'dim': DIMS,
  23. 'isPercolated': pclusters != None,
  24. 'clusters': clusters,
  25. 'pclulen' : len(pclusters[0]) if pclusters!=None else 0
  26. })
  27. #print({k:v for k,v in expResults[-1].items() if k != 'clusters'})
  28. # Let's keep the latest experiment result on a file
  29. with open('/content/gdrive/MyDrive/percolation-figures/percolation_experiments.jsons', 'a') as fl:
  30. fl.write('{}\n'.format(json.dumps(expResults[-1])))

png

png

png

png

png

png

png

png

png

png

png

png

png

png

png

png

png

png

png

png

Analyze outputs

  1. expRes = dict()
  2. with open('/content/gdrive/MyDrive/percolation-figures/percolation_experiments.jsons', 'r') as fl:
  3. for i,line in enumerate(fl):
  4. expRes[i] = json.loads(line.strip())
  5. expDf = pd.DataFrame.from_dict(expRes, orient='index')
  1. expDf



















































































































p idx dim isPercolated clusters pclulen
0 0.510769 0 [100, 100] False [[], [[56, 46]], [[93, 94]], [[0, 76]], [[51, … 0
1 0.521538 0 [100, 100] False [[], [[34, 47]], [[78, 24]], [[71, 89]], [[92,… 0
2 0.532308 0 [100, 100] False [[], [[60, 54]], [[43, 78]], [[54, 91]], [[86,… 0
3 0.543077 0 [100, 100] False [[], [[55, 93]], [[45, 11]], [[63, 97]], [[99,… 0
4 0.553846 0 [100, 100] False [[], [[70, 85]], [[95, 27]], [[14, 71]], [[94,… 0
1645 0.800000 49 [100, 100] True [[], [[27, 78]], [[35, 27]], [[14, 82]], [[34,… 7946
1646 0.850000 49 [100, 100] True [[], [[36, 62]], [[36, 16]], [[39, 46]], [[44,… 8528
1647 0.900000 49 [100, 100] True [[], [[41, 62]], [[0, 0], [0, 1], [0, 2], [0, … 9031
1648 0.950000 49 [100, 100] True [[], [[0, 0], [0, 1], [0, 2], [0, 3], [0, 5], … 9508
1649 1.000000 49 [100, 100] True [[], [[0, 0], [0, 1], [0, 2], [0, 3], [0, 4], … 10000

1650 rows × 6 columns


  1. percolatedCounts = {}
  2. for line in expDf.iterrows():
  3. if(line[1].isPercolated==True):
  4. if (line[1].p not in percolatedCounts):
  5. percolatedCounts[line[1].p] = 1
  6. else:
  7. percolatedCounts[line[1].p] += 1
  8. else:
  9. if (line[1].p not in percolatedCounts):
  10. percolatedCounts[line[1].p] = 0
  11. for key in percolatedCounts:
  12. percolatedCounts[key]/=NRANDOM
  13. percolatedCounts = dict(sorted(percolatedCounts.items()))
  14. plt.figure(figsize=(10,5))
  15. plt.plot(list(percolatedCounts.keys()),list(percolatedCounts.values()),marker='o',color='r',markersize=3)
  16. plt.plot([0.59274]*11,[0.0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1.0],color='b')
  17. plt.title("Percolation Probabilites for different P values")
  18. plt.xlabel("Occupation Probability (P)")
  19. plt.ylabel("Fraction of system percolating")
  20. plt.show()

png

  1. averageClusterS = {}
  2. for line in expDf.iterrows():
  3. sumC = 0
  4. clusters = line[1].clusters
  5. for c in clusters:
  6. sumC+=len(c)
  7. if (line[1].pclulen!=None):
  8. sumC-=line[1].pclulen
  9. avgC = sumC/(len(clusters)-1) # clusters have an empty cluster in beginning, we remove its effect by using one smaller len
  10. if (line[1].p not in averageClusterS):
  11. averageClusterS[line[1].p] = [avgC]
  12. else:
  13. averageClusterS[line[1].p].append(avgC)
  1. plt.figure(figsize=(15,10))
  2. xl = sorted(list(averageClusterS.keys()))
  3. averageClusterS_ = {}
  4. for index,x in enumerate(xl):
  5. xl[index] = str(x)[0:4]
  6. averageClusterS_[x] = sum(averageClusterS[x]) / len(averageClusterS[x])
  7. plt.plot(list(averageClusterS_.keys()), list(averageClusterS_.values()), color='r',marker='o')
  8. plt.plot([0.59274]*15,range(15),color='b')
  9. plt.title("Average Cluster Size of different p values")
  10. plt.xlabel("Occupation Probability (P)")
  11. plt.ylabel("Average Finite Cluster Size")
  12. plt.show()

png

  1. p_inf = {}
  2. for line in expDf.iterrows():
  3. clusters = line[1].clusters
  4. sumOthers=0
  5. largestClusterSize = 0
  6. for c in clusters:
  7. if (len(c)>largestClusterSize):
  8. largestClusterSize=len(c)
  9. if (line[1].p not in p_inf):
  10. p_inf[line[1].p] = [largestClusterSize/(DIMS[0] * DIMS[1])]
  11. else:
  12. p_inf[line[1].p].append(largestClusterSize/(DIMS[0] * DIMS[1]))
  1. keys = sorted(list(p_inf.keys()))
  2. means={}
  3. stds={}
  4. for key in keys:
  5. means[key] = statistics.mean(p_inf[key])
  6. stds[key] = statistics.stdev(p_inf[key])
  7. for index,key in enumerate(keys):
  8. keys[index] = str(key)[0:4]
  1. plt.figure(figsize=(15,10))
  2. plt.plot(list(means.keys()),list(means.values()),color='r',marker='o')
  3. plt.plot([0.59274]*11,[0.0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1.0],color='b')
  4. plt.title("P∞")
  5. plt.xlabel("Occupation Probability (P)")
  6. plt.ylabel("Mean of P∞")
  7. plt.show()

png

  1. plt.figure(figsize=(20,10))
  2. plt.plot(list(stds.keys()),list(stds.values()),color='r',marker='o')
  3. plt.plot([0.59274]*13,[0.0,0.01,0.02,0.03,0.04,0.05,0.06,0.07,0.08,0.09,0.1,0.11,0.12],color='b')
  4. plt.title("P∞")
  5. plt.xlabel("Occupation Probability (P)")
  6. plt.ylabel("STD")
  7. plt.show()

png