Let's say we have a matrix A,
A = [[1,2],
[3,4]
]
and I want to find all the submatrix ie,
1,2,3,4,(1,2),(3,4),(1,3),(2,4),(1,2,3,4)
Using basic for loops. I tried but this doesn't give correct results.
def mtx(arr):
n = len(arr)
for i in range(n,1,-1):
off_cnt = n - i + 1
for j in range(off_cnt):
for k in range(off_cnt):
for p in range(i):
for q in range(i):
print(arr[p+j][q+k])
print('--------')
# print(mtx(a)
You need to find all sizes of submatrices of N*N, which is suppose are matrices of size H*W, where H and W range from 1 to N (included) - that is your first range of for loops. Then you need to create all submatrices of this size from all possible starting coordinates, that means, given submatrix may start from a position x, y; where x, y range from start index (let's say 0) to last possible index, which is for x N - W (included) and for y N - H (included). Anything above won't fit. Then, just fill your submatrix and do whatever you want (print it?) as shown in code below:
def print_submatrices(matrix):
# all possible submatrices heights
for height in range(1, len(matrix)+1):
# all possible submatrices width
for width in range(1, len(matrix[0]) + 1):
# create empty submatrix of given size
template = list()
for i in range(height):
template.append([None]*width)
# fill submatrix
for y in range(len(matrix) - height + 1): # every possible start on y axis
for x in range(len(matrix[0]) - width + 1): # every possible start on x axis
# fill submatrix of given size starting at y, x coords
for i in range(y, y + height):
for j in range(x, x + width):
template[i-y][j-x] = matrix[i][j]
# when the matrix is filled, print it
print(template)
Related
I have to create a 5X5 matrix from a function given below.
f(x,y) = x(1-y) + y(1-x); where 0 < x,y <=5
where x indicate row position and y indicates columns. How do I create a matrix such that bottom left corner is f(0,0) and top left corner has value f(5,5)
M,N = 5,5
matrix = [[((x*(1-y))+(y*(1-x))) for y in range(M)] for x in range(N)]
for i in range(N):
print(matrix[i])
I need to draw a circle in a 2D numpy array given [i,j] as indexes of the array, and r as the radius of the circle. Each time a condition is met at index [i,j], a circle should be drawn with that as the center point, increasing all values inside the circle by +1. I want to avoid the for-loops at the end where I draw the circle (where I use p,q to index) because I have to draw possibly millions of circles. Is there a way without for loops? I also don't want to import another library for just a single task.
Here is my current implementation:
for i in range(array_shape[0]):
for j in range(array_shape[1]):
if (condition): # Draw circle if condition is fulfilled
# Create a square of pixels with side lengths equal to radius of circle
x_square_min = i-r
x_square_max = i+r+1
y_square_min = j-r
y_square_max = j+r+1
# Clamp this square to the edges of the array so circles near edges don't wrap around
if x_square_min < 0:
x_square_min = 0
if y_square_min < 0:
y_square_min = 0
if x_square_max > array_shape[0]:
x_square_max = array_shape[0]
if y_square_max > array_shape[1]:
y_square_max = array_shape[1]
# Now loop over the box and draw circle inside of it
for p in range(x_square_min , x_square_max):
for q in range(y_square_min , y_square_max):
if (p - i) ** 2 + (q - j) ** 2 <= r ** 2:
new_array[p,q] += 1 # Incrementing because need to have possibility of
# overlapping circles
If you're using the same radius for every single circle, you can simplify things significantly by only calculating the circle coordinates once and then adding the center coordinates to the circle points when needed. Here's the code:
# The main array of values is called array.
shape = array.shape
row_indices = np.arange(0, shape[0], 1)
col_indices = np.arange(0, shape[1], 1)
# Returns xy coordinates for a circle with a given radius, centered at (0,0).
def points_in_circle(radius):
a = np.arange(radius + 1)
for x, y in zip(*np.where(a[:,np.newaxis]**2 + a**2 <= radius**2)):
yield from set(((x, y), (x, -y), (-x, y), (-x, -y),))
# Set the radius value before running code.
radius = RADIUS
circle_r = np.array(list(points_in_circle(radius)))
# Note that I'm using x as the row number and y as the column number.
# Center of circle is at (x_center, y_center). shape_0 and shape_1 refer to the main array
# so we can get rid of coordinates outside the bounds of array.
def add_center_to_circle(circle_points, x_center, y_center, shape_0, shape_1):
circle = np.copy(circle_points)
circle[:, 0] += x_center
circle[:, 1] += y_center
# Get rid of rows where coordinates are below 0 (can't be indexed)
bad_rows = np.array(np.where(circle < 0)).T[:, 0]
circle = np.delete(circle, bad_rows, axis=0)
# Get rid of rows that are outside the upper bounds of the array.
circle = circle[circle[:, 0] < shape_0, :]
circle = circle[circle[:, 1] < shape_1, :]
return circle
for x in row_indices:
for y in col_indices:
# You need to set CONDITION before running the code.
if CONDITION:
# Because circle_r is the same for all circles, it doesn't need to be recalculated all the time. All you need to do is add x and y to circle_r each time CONDITION is met.
circle_coords = add_center_to_circle(circle_r, x, y, shape[0], shape[1])
array[tuple(circle_coords.T)] += 1
When I set radius = 10, array = np.random.rand(1200).reshape(40, 30) and replaced if CONDITION with if (x == 20 and y == 20) or (x == 25 and y == 20), I got this, which seems to be what you want:
Let me know if you have any questions.
Adding each circle can be vectorized. This solution iterates over the coordinates where the condition is met. On a 2-core colab instance ~60k circles with radius 30 can be added per second.
import numpy as np
np.random.seed(42)
arr = np.random.rand(400,300)
r = 30
xx, yy = np.mgrid[-r:r+1, -r:r+1]
circle = xx**2 + yy**2 <= r**2
condition = np.where(arr > .999) # np.where(arr > .5) to benchmark 60k circles
for x,y in zip(*condition):
# valid indices of the array
i = slice(max(x-r,0), min(x+r+1, arr.shape[0]))
j = slice(max(y-r,0), min(y+r+1, arr.shape[1]))
# visible slice of the circle
ci = slice(abs(min(x-r, 0)), circle.shape[0] - abs(min(arr.shape[0]-(x+r+1), 0)))
cj = slice(abs(min(y-r, 0)), circle.shape[1] - abs(min(arr.shape[1]-(y+r+1), 0)))
arr[i, j] += circle[ci, cj]
Visualizing np.array arr
import matplotlib.pyplot as plt
plt.figure(figsize=(8,8))
plt.imshow(arr)
plt.show()
ORIGINAL PROBLEM:
Given a set A={a1, . . . , an} and the matrix D of distances between the elements of A, we want to select the subset A*⊂ A of cardinal p with minimum diameter δ(A∗
) with δ(A∗) =max{d(a, a0) : a, a0 ∈ A∗}.
Write a python code that solve heuristically the particular case of n=8, p=4.
WHAT I HAVE UNDERSTOOD:
Given a matrix mxn (in this case 8x8) I am trying to look through a heuristic algorithm the max value of each sub-array of size 4x4, and store these values in a final matrix
For example:
Given the C matrix of euclidean distances 8x8:
What is the max value of a each possible sub-array 4x4?
and then store this max value in the final matrix mxn..
I have tried this but only returns one max value in the matrix.
# Python 3 Program to find the maximum
# value in a matrix which contain
# intersecting concentric submatrix
MAXN = 64
# Return the maximum value in intersecting
# concentric submatrix.
def maxValue( n, m, x, y, a):
c = [[0 for x in range(MAXN)]
for y in range(MAXN)]
# For each center of concentric sub-matrix.
for i in range( m):
# for each row
for p in range(n) :
# for each column
for q in range( n) :
# finding x distance.
dx = abs(p - x[i])
# finding y distance.
dy = abs(q - y[i])
# maximum of x distance and y distance
d = max(dx, dy)
# assigning the value.
c[p][q] += max(0, a[i] - d)
# Finding the maximum value in
# the formed matrix.
res = 0
for i in range(n) :
for j in range(n) :
res = max(res, c[i][j])
return res
# Driver Code
if __name__ == "__main__":
n = 10
m = 2
x = [ 3, 7 ]
y = [ 3, 7 ]
a = [ 4, 3 ]
print(maxValue(n, m, x, y, a))
I am wondering why y is being returned as an array. If it helps, x is a numpy array.
I have not gotten to the bit where I have to store the y values in an array yet, but I am trying to find the average of N_obs_photon(t) over a finely scaled grid to give a smoothed graph of N_obs_photon(t) over a coarsely scaled grid. I think that the part with the sum(array)/len(array) should be giving me a float but instead it is returning an array (more correctly 1001 arrays). Even if I try setting x to some array with only one value, y is still being returned as an array. And how should I write it so that I am being given the average for y?
x = np.linspace(0,1,1001)
ftc = 11
L = 10**(-3)
i = x/L
j = np.arange(0,11001,1) #end number is max(i)*ftc + 1
'''reference:
fine_grid_number = j
coarse_grid_number = i
coase_grid_width = L
fine_grid_width = L/ftc #denominator is ftc
coarse_grid_position = i*L
fine_grid_position = j*L/ftc #denominator is ftc'''
#Plan is to create an array of y values, then plot x vs y
for n in i:
q = np.arange(-0.5*(ftc-1),0.5*ftc,1)
#temp_array = np.empty([])
temp_array = []
for w in q:
t = ftc*n + w #t is fine grid number
t = t*L/ftc #convert to fine grid position
if t < 0: #drop t when it would be less than zero
t = 0
temp_array.append(t) #add to array
else:
t = N_obs_photon(t) #take through function
temp_array.append(t) #add to array
y = sum(temp_array)/len(temp_array) #average the array
print(y) #test if y is a number
#store result in y array
I have piece of code :
V = numpy.floor(3*np.random.rand(5,5))
print V
It create random result of array in 5x5 table, how to add condition "1" only generate x times, "2" only generate y times, else are "0".
Thanks
Try this:
import numpy as np
def newArray( x, y, n):
if x + y > n ** 2:
print "Values error!"
return
res = [[0 for col in range(n)] for row in range(n)]
# Create roulette
roulette = range(0, n ** 2)
printkxtimes(res, roulette, 1, x, n)
printkxtimes(res, roulette, 2, y, n)
print res
# This function draws random element from roulette,
# gets the position in array and sets value of this position to k.
# Then removes this element from roulette to prevent drawing it again
def printkxtimes(array, roulette, k, x, n):
for i in xrange(0, x):
r = int(np.floor(roulette.__len__()*np.random.rand(1))[0])
array[roulette[r] / n][roulette[r] % n] = k
roulette.pop(r)
newArray(10,2,5)
A little explanation of roulette :
Every element of table res can be represented equivalently with a number from range(0, n^2) :
z = row*n + column <=> row = int(z/n) , column= z%n
We can then represent the list of positions in table res as the table [0,1,...,n^2-1]
How about the following?
import numpy as np
shape = (5, 5)
area = shape[0] * shape[1]
np.random.permutation([1]*x + [2]*y + [0]*(area-x-y)).reshape(shape)
Seems pretty simple. You take a random permutation of [1, ... 1, 2, ... 2, 0, ... 0] and then you just turn it into a square. I'm not too sure but it also seems less computationally expensive and is also extensible to n numbers or dimensions quite easily.