I have a 2D grid of ones and zeros. Cluster is defined as nondiagonal set of neighboring ones. For example, if we look at a grid:
[[0 0 0 0 0]
[1 1 1 1 1]
[1 0 0 0 1]
[0 1 0 0 1]
[1 1 1 1 0]]
One cluster would be set of coordinates (actually I use lists for this, but its not important):
c1=[[1, 0], [1, 1], [1, 2], [1, 3], [1, 4], [2, 1], [2, 4], [3, 4]]
The other cluster in this grid is given by:
c2=[[3,1], [4, 0], [4, 1], [4, 2], [4, 3]]
Now, I have made a method that for a given starting coordinate (if it's value is 1), returns a cluster to which that point belongs (for example, if I choose a [1,1] coordinate it would return c1).
For testing I'll choose a point (1, 1) and a small grid. This is the output when result is good:
Number of recursions: 10
Length of cluster: 10
[[1 1 1 0 1]
[1 1 0 1 1]
[0 1 0 0 1]
[1 1 1 0 0]
[0 1 0 1 1]]
[[1 1 1 0 0]
[1 1 0 0 0]
[0 1 0 0 0]
[1 1 1 0 0]
[0 1 0 0 0]]
I was trying to get some idea how fast my algorithm is when cluster size is getting larger. If I run the program and then rerun it, and do that many times, it always gives the good result. If I use a loop, it starts giving wrong results. Here is one possible output test scenario:
Number of recursions: 10
Length of cluster: 10
[[1 1 1 0 1]
[1 1 0 1 1]
[0 1 0 0 1]
[1 1 1 0 0]
[0 1 0 1 1]]
[[1 1 1 0 0]
[1 1 0 0 0]
[0 1 0 0 0]
[1 1 1 0 0]
[0 1 0 0 0]]
Number of recursions: 8
Length of cluster: 8
[[0 1 1 1 0]
[1 1 1 0 0]
[1 0 0 0 0]
[1 1 1 0 1]
[1 1 0 0 0]]
[[0 0 0 0 0] - the first one is always good, this one already has an error
[1 1 0 0 0]
[1 0 0 0 0]
[1 1 1 0 0]
[1 1 0 0 0]]
Number of recursions: 1
Length of cluster: 1
[[1 1 1 1 1]
[0 1 0 1 0]
[0 1 0 0 0]
[0 1 0 0 0]
[0 1 1 0 1]]
[[0 0 0 0 0] - till end
[0 1 0 0 0]
[0 0 0 0 0]
[0 0 0 0 0]
[0 0 0 0 0]]
Number of recursions: 1
Length of cluster: 1
[[1 1 1 1 1]
[0 1 1 0 0]
[1 0 1 1 1]
[1 1 0 1 0]
[0 1 1 1 0]]
[[0 0 0 0 0]
[0 1 0 0 0]
[0 0 0 0 0]
[0 0 0 0 0]
[0 0 0 0 0]]
... till end
I will give the code for loop (it's no problem giving you all code, but it's too big, and the error is probably due to something I do inside a loop):
import numpy as np
from time import time
def test(N, p, testTime, length):
assert N>0
x=1
y=1
a=PercolationGrid(N) #this is a class that creates a grid
a.useFixedProbability(p) #the probability that given point will be 1
a.grid[x,y]=1 #I put the starting point as 1 manually
cluster=Cluster(a)
t0=time()
cluster.getCluster(x,y) #this is what I'm testing how fast is it
t1=time()
stats=cluster.getStats() #get the length of cluster and some other data
testTime.append(t1-t0)
testTime.sort()
length.append(stats[1]) #[1] is the length stat that interests me
length.sort() #both sorts are so I can use plot later
print a.getGrid() #show whole grid
clusterGrid=np.zeros(N*N, dtype='int8').reshape(N, N) #create zero grid where I'll "put" the cluster of interest
c1=cluster.getClusterCoordinates() #this is recursive method (if it has any importance)
for xy in c1:
k=xy[0]
m=xy[1]
clusterGrid[k, m]=1
print clusterGrid
del a, cluster, clusterGrid
testTime=[]
length=[]
p=0.59
N=35
np.set_printoptions(threshold='nan') #so the output doesn't shrink
for i in range(10):
test(N, p, testTime, length)
I assume that I do something wrong with freeing memory or something (if it's not some trivial error in loop I can't see)? I use python 2.7.3 on 64bit Linux.
EDIT:
I'm aware that people here should not review whole codes, but specific problems, but I can't find what's happening, the only suggestion is that maybe I have some static variables, but it seems to me that that is not the case. So, if someone has good will and energy you can browse through a code and maybe you'll see something. I started using classes not while ago, so be prepared for lot of bad stuff.
import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
import time
class ProbabilityGrid(object):
"""
This class gives 2D quadratic array (a grid) which is filled with
float values from 0-1, which in many cases represent probabilities
"""
def __init__(self, size=2, dataType='float16'):
"""initialization of a grid with 0. values"""
assert size>1
assert dataType=='float64' or dataType=='float32' or dataType=='float16'
self.n=size
self.dataType=dataType
self.grid=np.zeros((size, size), dtype=dataType)
def getGrid(self):
"""returns a 2D probability array"""
return self.grid
def getSize(self):
"""returns a size of a 2D array"""
return self.size
def fillRandom(self):
"""fills the grid with uniformly random values from 0 to 1"""
n=self.n
self.grid=np.random.rand(n, n)
def fixedProbabilities(self, p):
"""fills the grid with fixed value from 0 to 1"""
assert p<1.0
self.grid=p*np.ones((self.n, self.n))
class PercolationGrid(object):
"""
percolation quadratic grid filled with 1 and 0, int8
which represent a state.
Percolation grid is closly connected to probabilies grid.
ProbabilityGrid gives the starting probabilities will the [i,j] spot
be filled or not. All functions change the PercolationGrid.grid when
ProbabilityGrid.grid changes, so in a way their values are connected
"""
def __init__(self, size=2, dataType='int8'):
"""
initialization of PercolationGrid, sets uniformly 0 and 1 to grid
"""
assert size>1
assert dataType=='int64' or dataType=='int32' or dataType=='int8'
self.n=size
self.dataType=dataType
self.grid=np.zeros((size, size), dtype=dataType)
self.pGrid=ProbabilityGrid(self.n)
self.pGrid.fillRandom()
self.useProbabilityGrid()
#def fillRandom(self, min=0, max=1, distribution='uniform'):
# n=self.n
# self.grid=np.random.random_integers(min, max, n*n).reshape(n, n)
def getGrid(self):
"""returns a 2D percolation array"""
return self.grid
def useProbabilityGrid(self): #use probability grid to get Percolation grid of 0s and 1es
"""
this method fills the PercolationGrid.grid according to probabilities
from Probability.grid
"""
comparisonGrid=np.random.rand(self.n, self.n)
self.grid=np.array(np.floor(self.pGrid.grid-comparisonGrid)+1, dtype=self.dataType)
# Here I used a trick. To simulate whether 1 will apear with probability p,
# we can use uniform random generator which returns values from 0 to 1. If
# the value<p then we get 1, if value>p it's 0.
# But instead looping over each element, it's much faster to make same sized
# grid of random, uniform values from 0 to 1, calculate the difference, add 1
# and use floor function which round everything larger than 1 to 1, and lower
# to 0. Then value-p+1 will give 0 if value<p, 1 if value>p. The result is
# converted to data type of percolation array.
def useFixedProbability(self, p):
"""
this method fills the PercolationGrid according to fixed probabilities
of being filled, for example, a large grid with parameter p set to 0.33
should, aproximatly have one third of places filed with ones and 2/3 with 0
"""
self.pGrid.fixedProbabilities(p)
self.useProbabilityGrid()
def probabilityCheck(self):
""" this method checks the number of ones vs number of elements,
good for checking if the filling of a grid was close to probability
we had in mind. Of course, the accuracy is larger as grid size grows.
For smaller grid sizes you can still check the probability by
running the test multiple times.
"""
sum=self.grid.sum()
print float(sum)/float(self.n*self.n)
#this works because values can only be 0 or 1, so the sum/size gives
#the ratio of ones vs size
def setGrid(self, grid):
shape=grid.shape
i,j=shape[0], shape[1]
assert i>1 and j>1
if i!=j:
print ("The grid needs to be NxN shape, N>1")
self.grid=grid
def setProbabilities(self, grid):
shape=grid.shape
i,j=shape[0], shape[1]
assert i>1 and j>1
if i!=j:
print ("The grid needs to be NxN shape, N>1")
self.pGrid.grid=grid
self.useProbabilityGrid()
def showPercolations(self):
fig1=plt.figure()
fig2=plt.figure()
ax1=fig1.add_subplot(111)
ax2=fig2.add_subplot(111)
myColors=[(1.0, 1.0, 1.0, 1.0), (1.0, 0.0, 0.0, 1.0)]
mycmap=mpl.colors.ListedColormap(myColors)
subplt1=ax1.matshow(self.pGrid.grid, cmap='jet')
cbar1=fig1.colorbar(subplt1)
subplt2=ax2.matshow(self.grid, cmap=mycmap)
cbar2=fig2.colorbar(subplt2, ticks=[0.25,0.75])
cbar2.ax.set_yticklabels(['None', 'Percolated'], rotation='vertical')
class Cluster(object):
"""This is a class of percolation clusters"""
def __init__(self, array):
self.grid=array.getGrid()
self.N=len(self.grid[0,])
self.cluster={}
self.numOfSteps=0
#next 4 functions return True if field next to given field is 1 or False if it's 0
def moveLeft(self, i, j):
moveLeft=False
assert i<self.N
assert j<self.N
if j>0 and self.grid[i, j-1]==1:
moveLeft=True
return moveLeft
def moveRight(self, i, j):
moveRight=False
assert i<self.N
assert j<self.N
if j<N-1 and self.grid[i, j+1]==1:
moveRight=True
return moveRight
def moveDown(self, i, j):
moveDown=False
assert i<self.N
assert j<self.N
if i<N-1 and self.grid[i+1, j]==1:
moveDown=True
return moveDown
def moveUp(self, i, j):
moveUp=False
assert i<self.N
assert j<self.N
if i>0 and self.grid[i-1, j]==1:
moveUp=True
return moveUp
def listOfOnes(self):
"""nested list of connected ones in each row"""
outlist=[]
for i in xrange(self.N):
outlist.append([])
helplist=[]
for j in xrange(self.N):
if self.grid[i, j]==0:
if (j>0 and self.grid[i, j-1]==0) or (j==0 and self.grid[i, j]==0):
continue # condition needed because of edges
outlist[i].append(helplist)
helplist=[]
continue
helplist.append((i, j))
if self.grid[i, j]==1 and j==self.N-1:
outlist[i].append(helplist)
return outlist
def getCluster(self, i=0, j=0, moveD=[1, 1, 1, 1]):
#(left, right, up, down)
#moveD short for moveDirections, 1 means that it tries to move it to that side, 0 so it doesn't try
self.numOfSteps=self.numOfSteps+1
if self.grid[i, j]==1:
self.cluster[(i, j)]=True
else:
print "the starting coordinate is not in any cluster"
return
if moveD[0]==1:
try: #if it comes to same point from different directions we'd get an infinite recursion, checking if it already been on that point prevents that
self.cluster[(i, j-1)]
moveD[0]=0
except:
if self.moveLeft(i, j)==False: #check if 0 or 1 is left to (i, j)
moveD[0]=0
else:
self.getCluster(i, j-1, [1, 0, 1, 1]) #right is 0, because we came from left
if moveD[1]==1:
try:
self.cluster[(i, j+1)]
moveD[1]=0
except:
if self.moveRight(i, j)==False:
moveD[1]=0
else:
self.getCluster(i, j+1, [0, 1, 1, 1])
if moveD[2]==1:
try:
self.cluster[(i-1, j)]
moveD[2]=0
except:
if self.moveUp(i, j)==False:
moveD[2]=0
else:
self.getCluster(i-1, j, [1, 1, 1, 0])
if moveD[3]==1:
try:
self.cluster[(i+1, j)]
moveD[3]=0
except:
if self.moveDown(i, j)==False:
moveD[3]=0
else:
self.getCluster(i+1, j, [1, 1, 0, 1])
if moveD==(0, 0, 0, 0):
return
def getClusterCoordinates(self):
return self.cluster
def getStats(self):
print "Number of recursions:", self.numOfSteps
print "Length of cluster:", len(self.cluster)
return (self.numOfSteps, len(self.cluster))
Your error is coming from the getCluster method. When setting moveD to [1,1,1,1] you are essentially setting a static variable(do not quote me on this). This is causing the information from the previous executions to carry over.
Here is a link to a blog post that shows an example of this.
Below is a working version of the getCluster method that both fixes the default arguement problem and removes the extraneous moveD assignments that manifested the problematic behavior.
def getCluster(self, i=0, j=0, moveD=None):
#(left, right, up, down)
#moveD short for moveDirections, 1 means that it tries to move it to that side, 0 so it doesn't try
if moveD == None: moveD = [1, 1, 1, 1]
self.numOfSteps=self.numOfSteps+1
if self.grid[i, j]==1:
self.cluster[(i, j)]=True
else:
print "the starting coordinate is not in any cluster"
return
if moveD[0]==1:
try: #if it comes to same point from different directions we'd get an infinite recursion, checking if it already been on that point prevents that
self.cluster[(i, j-1)]
except:
if self.moveLeft(i, j)==True: #check if 0 or 1 is left to (i, j)
self.getCluster(i, j-1, [1, 0, 1, 1]) #right is 0, because we came from left
if moveD[1]==1:
try:
self.cluster[(i, j+1)]
except:
if self.moveRight(i, j)==True:
self.getCluster(i, j+1, [0, 1, 1, 1])
if moveD[2]==1:
try:
self.cluster[(i-1, j)]
except:
if self.moveUp(i, j)==True:
self.getCluster(i-1, j, [1, 1, 1, 0])
if moveD[3]==1:
try:
self.cluster[(i+1, j)]
except:
if self.moveDown(i, j)==True:
self.getCluster(i+1, j, [1, 1, 0, 1])
Related
Hello guys I am trying to do conway's game of life as a beginner, however I keep getting IndexError: list index out of range, I am not sure why it happens, can you guys help? thank you!
def count_neighbors(x, y, G):
count= 0
n=len(G)
if x>0:
if y>0:
if G[x-1][y-1]=='x':
count +=1
if y<n-1:
if G[x-1][y+1]=='x':
count +=1
if G[x-1][y]=='x':
count +=1
if y>0:
if G[x][y-1]=='x':
count +=1
if y<n-1:
if G[x][y+1] =='x':
count +=1
if x<n-1:
if y>0:
if G[x+1][y-1] =='x':
count +=1
if y<n-1:
if G[x+1][y+1] =='x':
count +=1
if G[x+1][y]=='x':
count +=1
return count
You're not checking if x < n-1 here, and therefore G[x+1] could be out of bounds:
if y<n-1:
if G[x+1][y+1] =='x':
count +=1
if G[x+1][y]=='x':
count +=1
Upon further inspection, it seems that you should just indent this block once, so that it falls under the if x<n-1: check you wrote above.
Your code is also assuming that G is a square matrix (height == width); if this is not the case, then you will also run into issues.
A more generic answer is to use loops:
def count(x,y,G):
counts = 0
for dy in (-1,0,1):
for dx in (-1,0,1):
if not (dx and dy) and x+dx in range(n) and y+dy in range(n) and G[y+dy][x+dx] == 'x':
counts += 1
return counts
Another trick I've used is to have a list of the possible moves:
dirs = (
(-1,-1), ( 0,-1), ( 1,-1),
(-1, 0), ( 1, 0),
(-1, 1), ( 0, 1), ( 1, 1)
)
def count(x,y,G):
counts = 0
for dx,dy in dirs:
if x+dx in range(n) and y+dy in range(n) and G[y+dy][x+dx] == 'x':
counts += 1
return counts
Update: I just realized I have the wrong rule for 4 neighbors! Fixing...
Update #2: Fixed 2 rules.
I have written numerous programs to play Conway's life game in many languages (including assebly language). None of the programs were easy nor short!
Here is a pure numpy solution to Conway's life game that not only computes all neighbor counts in a few lines of code but also goes on to calculate the next generation in a total of only 9 numpy statements.
import numpy as np
# A 5x5 numpy array represents a 3x3 "world" where the outer edge cells
# will always remain equal to 0.
G = np.array([[0, 0, 0, 0, 0],
[0, 1, 1, 1, 0],
[0, 0, 1, 0, 0],
[0, 1, 0, 1, 0],
[0, 0, 0, 0, 0]])
print('G ---------- Original generation')
print(G)
# Create array S (sum) where each element is the sum of the 3x3 cell surrounding
# the same element in the G array.
S = np.zeros_like(G)
S[1:-1, 1:-1] = sum(G[i:G.shape[0]-2+i, j:G.shape[1]-2+j]
for i in range(0, 3) for j in range(0, 3))
print('S ---------- Provisional neighbor counts')
print(S)
# Since the sums in S include the center cell we subtract the extra values by
# subtracting G from S!
X = np.subtract(S, G)
print('X ---------- Adjusted neighbor counts')
print(X)
# Apply Conway's rules of life
X[((X == 1) | (X > 3)) & (G == 1)] = -1 # Death
X[((X == 1) | (X > 3)) & (G == 0)] = 0 # No change if G is already equal to 0
X[X == 2] = 0 # Survival
X[(X == 3) & (G == 1)] = 0 # No change if G is already equal to 1
X[(X == 3) & (G == 0)] = +1 # Birth otherwise!
print('X ---------- Changes for the next generation')
print(X)
# Apply the calculated changes from X to G
G = np.add(G, X)
print('G ---------- Tada!!! The next generation')
print(G)
Output:
G ---------- Original generation
[[0 0 0 0 0]
[0 1 1 1 0]
[0 0 1 0 0]
[0 1 0 1 0]
[0 0 0 0 0]]
S ---------- Provisional neighbor counts
[[0 0 0 0 0]
[0 3 4 3 0]
[0 4 6 4 0]
[0 2 3 2 0]
[0 0 0 0 0]]
X ---------- Adjusted neighbor counts
[[0 0 0 0 0]
[0 2 3 2 0]
[0 4 5 4 0]
[0 1 3 1 0]
[0 0 0 0 0]]
X ---------- Changes for the next generation
[[ 0 0 0 0 0]
[ 0 0 0 0 0]
[ 0 0 -1 0 0]
[ 0 -1 1 -1 0]
[ 0 0 0 0 0]]
G ---------- Tada!!! The next generation
[[0 0 0 0 0]
[0 1 1 1 0]
[0 0 0 0 0]
[0 0 1 0 0]
[0 0 0 0 0]]
I'm having a hard time vectorializing the following function:
def find_empty_square_sizes(matrix: np.ndarray):
shape = matrix.shape
res_matrix = np.ones(shape, dtype=np.int32)
res_matrix[matrix != 0] = 0
for i in range(1, shape[0]):
for j in range(1, shape[1]):
if matrix[i][j] == 1:
res_matrix[i][j] = 0
else:
res_matrix[i][j] = np.min(np.ma.masked_array(res_matrix[i - 1:i + 1, j - 1:j + 1], mask=[[0, 0], [0, 1]])) + 1
return res_matrix
The idea is to find the biggest square sub matrix of zeros inside a matrix. What the result, res_matrix, means is if the element on row i and column j was the bottom right corner of a sub matrix, how big that sub matrix could be while having only zeros.
Running for example the following code:
m = np.zeros((6, 6), dtype=np.int32)
m[2, 2] = 1
res = find_empty_square_sizes(m)
print(m)
print(res)
Yields the following results:
[[0 0 0 0 0 0]
[0 0 0 0 0 0]
[0 0 1 0 0 0]
[0 0 0 1 0 0]
[0 0 0 0 0 0]
[0 0 0 0 0 0]]
[[1 1 1 1 1 1]
[1 2 2 2 2 2]
[1 2 0 1 2 3]
[1 2 1 0 1 2]
[1 2 2 1 1 2]
[1 2 3 2 2 2]]
I'm doing this for some image processing purposes and for HD images with over a thousand rows and columns this takes about a minute on my PC and I'd like to improve that. Any ideas on how to vectorialize the find_empty_square_sizes function or achieve a similar result through a more efficient method?
If anyone stumbles upon this with a similar problem, following Jerome Richard's advice I used Cython and the following code brought down the execution time from a minute to about 40 ms, quite a difference!
#cython: language_level=3
import cython
import numpy as np
cimport numpy as np
#cython.boundscheck(False)
#cython.wraparound(False)
def find_empty_square_sizes(matrix: np.ndarray) -> np.ndarray:
res_matrix = np.ones((matrix.shape[0], matrix.shape[1]), dtype=np.int32)
res_matrix[matrix != 0] = 0
_find_empty_square_sizes(matrix, res_matrix, matrix.shape[0], matrix.shape[1])
return res_matrix
cdef _find_empty_square_sizes(int[:, :] matrix, int[:, :] res_matrix, int x, int y):
cdef int i
cdef int j
for i in range(1, x):
for j in range(1, y):
if matrix[i][j] == 1:
res_matrix[i][j] = 0
else:
res_matrix[i][j] = _min(res_matrix[i - 1, j - 1], res_matrix[i, j - 1], res_matrix[i - 1, j]) + 1
cdef _min(int a, int b, int c):
cdef int min = a
if b < min:
min = b
if c < min:
min = c
return min
I want to create a 64 components array showing all the squares in which the two rooks of an empty chessboard could move from their current position. So far I am doing it with for and while loops.
I first create a function just to better visualize the board:
import numpy as np
def from_array_to_matrix(v):
m=np.zeros((8,8)).astype('int')
for row in range(8):
for column in range(8):
m[row,column]=v[row*8+column]
return m
and here I show how I actually build the array:
# positions of the two rooks
a=np.zeros(64).astype('int')
a[15] = 1
a[25] = 1
print from_array_to_matrix(a)
# attack_a will be all the squares where they could move in the empty board
attack_a=np.zeros(64).astype('int')
for piece in np.where(a)[0]:
j=0
square=piece+j*8
while square<64:
attack_a[square]=1
j+=1
square=piece+j*8
j=0
square=piece-j*8
while square>=0:
attack_a[square]=1
j+=1
square=piece-j*8
j=0
square=piece+j
while square<8*(1+piece//8):
attack_a[square]=1
j+=1
square=piece+j
j=0
square=piece-j
while square>=8*(piece//8):
attack_a[square]=1
j+=1
square=piece-j
print attack_a
print from_array_to_matrix(attack_a)
I have been advised to avoid for and while loops whenever it is possible to use other ways, because they tend to be time consuming. Is there any way to achieve the same result without iterating the process with for and while loops ?
Perhaps using the fact that the indices to which I want to assign the value 1 can be determined by a function.
There are a couple of different ways to do this. The simplest thing is of course to work with matrices.
But you can vectorize operations on the raveled array as well. For example, say you had a rook at position 0 <= n < 64 in the linear array. To set the row to one, use integer division:
array[8 * (n // 8):8 * (n // 8 + 1)] = True
To set the column, use modulo:
array[n % 8::8] = True
You can convert to a matrix using reshape:
matrix = array.reshape(8, 8)
And back using ravel:
array = martix.ravel()
Or reshape:
array = matrix.reshape(-1)
Setting ones in a matrix is even simpler, given a specific row 0 <= m < 8 and column 0 <= n < 8:
matrix[m, :] = matrix[:, n] = True
Now the only question is how to vectorize multiple indices simultaneously. As it happens, you can use a fancy index in one axis. I.e, the expression above can be used with an m and n containing multiple elements:
m, n = np.nonzero(matrix)
matrix[m, :] = matrix[:, n] = True
You could even play games and do this with the array, also using fancy indexing:
n = np.nonzero(array)[0]
r = np.linspace(8 * (n // 8), 8 * (n // 8 + 1), 8, False).T.ravel()
c = np.linspace(n % 8, n % 8 + 64, 8, False)
array[r] = array[c] = True
Using linspace allows you to generate multiple sequences of the same size simultaneously. Each sequence is a column, so we transpose before raveling, although this is not required.
Use reshaping to convert 1-D array to 8x8 2-D matrix and then numpy advance indexing to select rows and columns to set to 1:
import numpy as np
def from_array_to_matrix(v):
return v.reshape(8,8)
# positions of the two rooks
a=np.zeros(64).astype('int')
a[15] = 1
a[25] = 1
a = from_array_to_matrix(a)
# attack_a will be all the squares where they could move in the empty board
attack_a=np.zeros(64).astype('int')
attack_a = from_array_to_matrix(attack_a)
#these two lines replace your for and while loops
attack_a[np.where(a)[0],:] = 1
attack_a[:,np.where(a)[1]] = 1
output:
a:
[[0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 1]
[0 0 0 0 0 0 0 0]
[0 1 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0]
[0 0 0 0 0 0 0 0]]
attack_a:
[[0 1 0 0 0 0 0 1]
[1 1 1 1 1 1 1 1]
[0 1 0 0 0 0 0 1]
[1 1 1 1 1 1 1 1]
[0 1 0 0 0 0 0 1]
[0 1 0 0 0 0 0 1]
[0 1 0 0 0 0 0 1]
[0 1 0 0 0 0 0 1]]
I wanted to construct a 6 x 9 matrix with entries zeros and ones in a specific way as follows. In the zeroth row column, 0 to 2 should be 1 and in the first-row column,3 to 5 should be one and in the second-row column, 6 to 8 should be one, with all the other entries to be zeros. In the third row, element 0,3,6 should be one and the other should be zeros. In the fourth row, element 1,4,7 should be one and the other elements should be zeros. In the fifth row,2,5,8 should be one and the remaining should be zeros. Half of the rows follow one way enter the value 1 and the other half of the row follows different procedures to enter the value one. How do extend this some 20 x 100 case where the first 10 rows follow one procedure as mentioned above and the second half follows different procedures
The 6x9 by matrix looks as follows
[[1,1,1,0,0,0,0,0,0],
[0,0,0,1,1,1,0,0,0],
[0,0,0,0,0,0,1,1,1],
[1,0,0,1,0,0,1,0,0],
[0,1,0,0,1,0,0,1,0],
[0,0,1,0,0,1,0,0,1]]
EDIT: Code I used to create this matrix:
import numpy as np
m=int(input("Enter the value of m, no. of points = "))
pimatrix=np.zeros((2*m +1)*(m**2)).reshape((2*m+1),(m**2))
for i in range(2*m + 1):
for j in range(m**2):
if((i<m) and ((j<((i+1)*m) and j>=(i*m)))):
pimatrix[i][j]=1
if (i>(m-1)):
for k in range(-1,m-1,1):
if(j == i+(k*m)):
pimatrix[i][j]=1
if i==2*m:
pimatrix[i][j]=1
print(pimatrix)
Try to use numpy.put function numpy.put
The best approach depends on the rules you plan to follow, but an easy approach would be to initialise the array as an array of zeroes:
import numpy as np
a = np.zeros([3, 4], dtype = int)
You can then write the logic to loop over the appropriate rows and set 1's as needed. You can simply access any element of the array by its coordinates:
a[2,1] = 1
print(a)
Result:
[[0 0 0 0]
[0 0 0 0]
[0 1 0 0]]
Without a general rule, it's hard to say what your intended logic is exactly, but assuming these rules: the top half of the array has runs of three ones on each consecutive row, starting in the upper left and moving down a row at the end of every run, until it reaches the bottom of the top half, where it wraps around to the top; the bottom half has runs of single ones, following the same pattern.
Implementing that, with your given example:
import numpy as np
a = np.zeros([6, 9], dtype=int)
def set_ones(a, run_length, start, end):
for n in range(a.shape[1]):
a[start + ((n // run_length) % (end - start)), n] = 1
set_ones(a, 3, 0, a.shape[0] // 2)
set_ones(a, 1, a.shape[0] // 2, a.shape[0])
print(a)
Result:
[[1 1 1 0 0 0 0 0 0]
[0 0 0 1 1 1 0 0 0]
[0 0 0 0 0 0 1 1 1]
[1 0 0 1 0 0 1 0 0]
[0 1 0 0 1 0 0 1 0]
[0 0 1 0 0 1 0 0 1]]
I have a 2-dimensional array of integers, we'll call it "A".
I want to create a 3-dimensional array "B" of all 1s and 0s such that:
for any fixed (i,j) sum(B[i,j,:])==A[i.j], that is, B[i,j,:] contains A[i,j] 1s in it
the 1s are randomly placed in the 3rd dimension.
I know how I would do this using standard python indexing but this turns out to be very slow.
I am looking for a way to do this that takes advantage of the features that can make Numpy fast.
Here is how I would do it using standard indexing:
B=np.zeros((X,Y,Z))
indexoptions=range(Z)
for i in xrange(Y):
for j in xrange(X):
replacedindices=np.random.choice(indexoptions,size=A[i,j],replace=False)
B[i,j,[replacedindices]]=1
Can someone please explain how I can do this in a faster way?
Edit: Here is an example "A":
A=np.array([[0,1,2,3,4],[0,1,2,3,4],[0,1,2,3,4],[0,1,2,3,4],[0,1,2,3,4]])
in this case X=Y=5 and Z>=5
Essentially the same idea as #JohnZwinck and #DSM, but with a shuffle function for shuffling a given axis:
import numpy as np
def shuffle(a, axis=-1):
"""
Shuffle `a` in-place along the given axis.
Apply numpy.random.shuffle to the given axis of `a`.
Each one-dimensional slice is shuffled independently.
"""
b = a.swapaxes(axis,-1)
# Shuffle `b` in-place along the last axis. `b` is a view of `a`,
# so `a` is shuffled in place, too.
shp = b.shape[:-1]
for ndx in np.ndindex(shp):
np.random.shuffle(b[ndx])
return
def random_bits(a, n):
b = (a[..., np.newaxis] > np.arange(n)).astype(int)
shuffle(b)
return b
if __name__ == "__main__":
np.random.seed(12345)
A = np.random.randint(0, 5, size=(3,4))
Z = 6
B = random_bits(A, Z)
print "A:"
print A
print "B:"
print B
Output:
A:
[[2 1 4 1]
[2 1 1 3]
[1 3 0 2]]
B:
[[[1 0 0 0 0 1]
[0 1 0 0 0 0]
[0 1 1 1 1 0]
[0 0 0 1 0 0]]
[[0 1 0 1 0 0]
[0 0 0 1 0 0]
[0 0 1 0 0 0]
[1 0 1 0 1 0]]
[[0 0 0 0 0 1]
[0 0 1 1 1 0]
[0 0 0 0 0 0]
[0 0 1 0 1 0]]]