In [1]:
from ipythonblocks import BlockGrid as bg
from IPython.html.widgets import interact, interactive, fixed
from IPython.html import widgets
import random
import numpy as np
from IPython.display import Image
In [2]:
#create random x by x grid of 0s,1s,2s
def array_city(x, p1, p2):
p0 = 1-(p1+p2)
p1 = 1-(p0+p2)
p2 = 1-(p0+p1)
grid = (np.random.choice([0, 1 , 2], size = (x, x), p = [p0, p1, p2]))
print (grid)
return grid
In [3]:
interact(array_city,x = (0,20,1), p1 = (0,1,0.1), p2 = (0,1,0.1));
In [4]:
#return value of surrounding neighbors at position (row,col) of grid
def get_neighbors(row,col,grid):
x = len(grid)
#4corners
#top left
if row == 0 and col == 0:
return grid[(1,0)],grid[(1,1)],grid[(0,1)]
#bottom left
elif row == x-1 and col == 0:
return grid[(x-2,0)],grid[(x-1,1)],grid[(x-2,1)]
#bottom right
elif row == x-1 and col == x-1:
return grid[(x-2,x-1)],grid[(x-2,x-2)],grid[(x-1,x-2)]
#top right
elif row == 0 and col == x-1:
return grid[(0,x-2)],grid[(1,x-1)],grid[(1,x-2)]
#edges
#top
elif row == 0 and 1 <= col <= x-2:
return grid[(0,col-1)],grid[(1,col-1)],grid[(1,col)],grid[(1,col+1)],grid[(0,col+1)]
#bottom
elif row == x-1 and 1 <= col <= x-2:
return grid[(x-1,col-1)],grid[(x-2,col-1)],grid[(x-2,col)],grid[(x-2,col+1)],grid[(x-1,col+1)]
#right
elif 1 <= row <= x-2 and col == x-1:
return grid[(row-1,x-1)],grid[(row-1,x-2)],grid[(row,x-2)],grid[(row+1,x-2)],grid[(row+1,x-1)]
#left
elif 1 <= row <= x-2 and col == 0:
return grid[(row-1,0)],grid[(row-1,1)],grid[(row,1)],grid[(row+1,1)],grid[(row+1,0)]
#all middle spaces
else:
return grid[(row-1,col-1)],grid[(row,col-1)],grid[(row+1,col-1)],grid[(row+1,col)],grid[(row+1,col+1)],grid[(row,col+1)],grid[(row-1,col+1)],grid[(row-1,col)]
In [5]:
#create a fixed 3x3 and 10x10 grid for testing
test_grid = np.array([[0,1,2],[2,1,0],[1,0,2]])
presentation_grid = np.array([[1,2,2,0,2,1,2,2,1,0],[1,2,1,2,0,0,0,2,1,2],[0,0,2,1,1,2,2,0,1,2],[2,2,1,1,0,2,1,1,2,0],[0,2,2,1,1,1,0,0,2,1],[0,2,1,2,2,1,0,0,2,1],[2,1,2,1,1,1,2,0,2,1],[0,0,2,1,1,2,2,0,2,1],[0,2,1,2,1,0,2,1,0,0],[0,0,2,2,1,1,2,2,1,2]])
print (test_grid)
print ()
print (presentation_grid)
In [6]:
#test each position in 3x3 grid
assert get_neighbors(0,0,test_grid) == (2,1,1) #top left
assert get_neighbors(0,2,test_grid) == (1,0,1) #top right
assert get_neighbors(2,0,test_grid) == (2,0,1) #bottom left
assert get_neighbors(2,2,test_grid) == (0,1,0) #bottom right
assert get_neighbors(0,1,test_grid) == (0,2,1,0,2) #top
assert get_neighbors(2,1,test_grid) == (1,2,1,0,2)#bottom
assert get_neighbors(1,0,test_grid) == (0,1,1,0,1) #left
assert get_neighbors(1,2,test_grid) == (2,1,1,0,2) #right
assert get_neighbors(1,1,test_grid) == (0,2,1,0,2,0,2,1)#middle
In [7]:
#compute satisfaction of position (row,col) in grid
def sat_per(row,col,grid):
n = get_neighbors(row,col,grid)
zeros,ones,twos = 0,0,0
for i in n:
if i == 0:
zeros += 1
elif i == 1:
ones += 1
else:
twos += 1
p = (zeros/len(n),ones/len(n),twos/len(n))
if grid[row,col] == 0:
return p[0]
elif grid[row,col] == 1:
return p[1]
else:
return p[2]
In [9]:
assert sat_per(0,0,test_grid) == 0 #top left
assert sat_per(0,2,test_grid) == 0 #top right
assert sat_per(2,2,test_grid) == 0 #bottom right
assert sat_per(0,1,test_grid) == 0.2 #top
assert sat_per(2,1,test_grid) == 0.2 #bottom
assert sat_per(1,0,test_grid) == 0 #left
assert sat_per(1,2,test_grid) == 0.2 #right
assert sat_per(1,1,test_grid) == 0.25#middle
In [10]:
#return coordinates of every block that is satisfied in grid
def sat(satisfaction,grid):
sat = []
x = len(grid)
for row in range(0,x):
for col in range(0,x):
if grid[row,col] == 1 and sat_per(row,col,grid) >= satisfaction:
sat.append((row,col))
elif grid[row,col] == 2 and sat_per(row,col,grid) >= satisfaction:
sat.append((row,col))
else:
pass
np.random.shuffle(sat)
return sat
In [13]:
assert sat(0.34,test_grid) == []
#Cannot write more assert cases because of the np.random.shuffle(sat) line
In [14]:
#return coordinates of every unsatisfied block in grid
def unsat(satisfaction,grid):
unsat = []
x = len(grid)
for row in range(0,x):
for col in range(0,x):
if grid[row,col] == 1 and sat_per(row,col,grid) < satisfaction:
unsat.append((row,col))
elif grid[row,col] == 2 and sat_per(row,col,grid) < satisfaction:
unsat.append((row,col))
else:
pass
np.random.shuffle(unsat)
return unsat
In [17]:
#return coordinates of every empty block in grid
def empty(grid):
empty = []
x = len(grid)
for row in range(0,x):
for col in range(0,x):
if grid[row,col] == 0:
empty.append((row,col))
#np.random.shuffle(empty)
return empty
In [20]:
#return True if changing position (row,col) to new_value makes position (row,col) satisfied, else return False
def should_move(grid,row,col,satisfaction,new_value):
temp_grid = grid.copy()
temp_grid[row,col] = new_value
if sat_per(row,col,temp_grid) >= satisfaction:
return True
else:
return False
In [23]:
assert should_move(test_grid,2,1,0.4,1) == True
assert should_move(test_grid,2,1,0.4,2) == True
assert should_move(test_grid,1,2,0.4,1) == True
assert should_move(test_grid,1,2,0.4,2) == True
assert should_move(test_grid,0,0,1,1) == False
assert should_move(test_grid,2,1,0.7,1) == False
In [24]:
#take value of position (row,col), assign that value to a random empty position. If satisfied, swap values.
def do_move(grid,row,col,satisfaction):
value = grid[row,col]
#reason for np.random.shuffle
e = empty(grid)
for i,j in e:
if should_move(grid,i,j,satisfaction,value):
grid[row,col] = 0
grid[i,j] = value
break
In [25]:
#run do_move on every coordinate in list of unsatisfied positions
def move_all(satisfaction,grid):
u = unsat(satisfaction,grid)
for i,j in u:
do_move(grid,i,j,satisfaction)
In [26]:
#keep running move_all on grid until every block reaches satisfaction
def sat_all(grid,satisfaction):
x = len(grid)
i = 0
for row in range(0,x):
for col in range(0,x):
if sat_per(row,col,grid) < satisfaction:
move_all(satisfaction,grid)
i+=1
else:
if sat_per(row,col,grid) >= satisfaction:
pass
print ("Number of loops:",i)
In [28]:
def visualize_rwb(grid):
g = bg(grid.shape[0], grid.shape[0],block_size = 7)
for row in range(g.height):
for col in range(g.width):
block = g[row,col]
if grid[row,col] == 0:
block.blue = 1000
block.red = 1000
block.green = 1000
if grid[row,col] == 1:
block.blue = 1000
block.red = 0
block.green = 0
if grid[row,col] == 2:
block.red = 1000
block.green = 0
block.blue = 0
return g
In [29]:
#visualize a grid using camo
def visualize(grid):
g = bg(grid.shape[0], grid.shape[0],block_size = 7)
for row in range(g.height):
for col in range(g.width):
block = g[row,col]
if grid[row,col] == 0:
block.blue = 1000
block.red = 1000
block.green = 1000
if grid[row,col] == 1:
block.blue = 39
block.red = 99
block.green = 50
if grid[row,col] == 2:
block.red = 30
block.green = 99
block.blue = 39
return g
In [30]:
g = array_city(100,0.45,0.45)
visualize_rwb(g)
Out[30]:
In [31]:
sat_all(g,0.4)
visualize_rwb(g)
Out[31]:
In [32]:
sat_all(g,0.4)
visualize(g)
Out[32]:
In [ ]: