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.
Related
See the code. I am trying to simulate an array called 'xx'. Following the code, I am simulating each component in the matrix one by one. This is super time-consuming when M and N are very large. The reason why I do this is because in the function 'func', for each column data, the 'samplesize 'is different. Is there any faster way to generate this numpy array please? Thank you.
import numpy as np
def func ( x , n):
samplesize = np.random.poisson(x)
return np.random.uniform(0, 2, samplesize)
def singlerow(x, n ,N):
rowdata = np.zeros(N)
rowdata[0] = 0
for i in range(1, N):
rowdata[i] = rowdata[i-1] + np.sum(func(x, n))
return rowdata
def simulatematrix( x,n ,M, N):
result = np.zeros((M,N))
for m in range(M):
result[m] = singlerow(x,n, N)
return result
M = 100
N = 10
xx = simulatematrix(40, 10, M, N)
Let's take the following square matrix:
import numpy as np
A = np.array([[10.0, -498.0],
[-2.0, 100.0]])
A will be singular if its determinant (A[0,0]*A[1,1]-A[0,1]*A[1,0]) is zero. For example, A will be singular if A[0,1] takes the value -500.0 (all else unchanged):
from sympy import symbols, Eq, solve
y = symbols('y')
eq = Eq(A[0,0]*A[1,1]-y*A[1,0])
sol = solve(eq)
sol
How to find all values (A[0,0],A[0,1],...) for which A (or any given square matrix) becomes singular efficiently (I work with large matrices)? Many thanks in advance.
The trick is to use Laplace expansion to calculate the determinant. The formula is
det(A) = sum (-1)^(i+j) * a_ij * M_ij
So to make a matrix singular, you just need to use the above formula, change the subject to a_ij and set det(A) = 0. It can be done like this:
import numpy as np
def cofactor(A, i, j):
A = np.delete(A, (i), axis=0)
A = np.delete(A, (j), axis=1)
return (-1)**(i+j) * np.linalg.det(A)
def make_singular(A, I, J):
n = A.shape[0]
s = 0
for i in range(n):
if i != J:
s += A[I, i] * cofactor(A, I, i)
M = cofactor(A, I, J)
if M == 0:
return 'No solution'
else:
return -s / M
Testing:
>>> M = np.array([[10.0, -498.0],
[-2.0, 100.0]])
>>> make_singular(M, 0, 1)
-500.0000000000002
>>> M = np.array([[10.0, -498.0],
[0, 100.0]])
>>> make_singular(M, 0, 1)
'No solution'
This thing works for square matrices...
What it does is it bruteforces through every item in the matrix and check if its singular, (so theres a lot of messy output, ue it if you like it tho)
And also very important, it is a Recursive function that returns a matrix if it is singular. So it throws RecursiveError recursively....:|
This is the code i have come up with, you can use it if its okay for you
import numpy as np
def is_singular(_temp_int:str, matrix_size:int):
kwargs = [int(i) for i in _temp_int]
arr = [] # Creates the matrix from the given size
temp_count = 0
for i in range(matrix_size):
arr.append([])
m = arr[i]
for j in range(matrix_size):
m.append(int(_temp_int[temp_count]))
temp_count += 1
n_array = np.array(arr)
if int(np.linalg.det(n_array)) == 0:
print(n_array) # print(n_array) for a pretty output or print(arr) for single line output of the determinant matrix
_temp_int = str(_temp_int[:-len(str(int(_temp_int)+1))] + str(int(_temp_int)+1))
is_singular(_temp_int, matrix_size)
# Only square matrices, so only one-digit integer as input
print("List of singular matrices in the size of '3x3': ")
is_singular('112278011', 3)
# Just give a temporary integer string which will be converted to matrix like [[1, 1, 2], [2, 7, 8], [0, 1, 1]]
# From the provided integer string, it adds up 1 after every iteration
I think this is the code you want, let me know if its not working
I'm trying to sum a two dimensional function using the array method, somehow, using a for loop is not outputting the correct answer. I want to find (in latex) $$\sum_{i=1}^{M}\sum_{j=1}^{M_2}\cos(i)\cos(j)$$ where according to Mathematica the answer when M=5 is 1.52725. According to the for loop:
def f(N):
s1=0;
for p1 in range(N):
for p2 in range(N):
s1+=np.cos(p1+1)*np.cos(p2+1)
return s1
print(f(4))
is 0.291927.
I have thus been trying to use some code of the form:
def f1(N):
mat3=np.zeros((N,N),np.complex)
for i in range(0,len(mat3)):
for j in range(0,len(mat3)):
mat3[i][j]=np.cos(i+1)*np.cos(j+1)
return sum(mat3)
which again
print(f1(4))
outputs 0.291927. Looking at the array we should find for each value of i and j a matrix of the form
mat3=[[np.cos(1)*np.cos(1),np.cos(2)*np.cos(1),...],[np.cos(2)*np.cos(1),...]...[np.cos(N+1)*np.cos(N+1)]]
so for N=4 we should have
mat3=[[np.cos(1)*np.cos(1) np.cos(2)*np.cos(1) ...] [np.cos(2)*np.cos(1) ...]...[... np.cos(5)*np.cos(5)]]
but what I actually get is the following
mat3=[[0.29192658+0.j 0.+0.j 0.+0.j ... 0.+0.j] ... [... 0.+0.j]]
or a matrix of all zeros apart from the mat3[0][0] element.
Does anybody know a correct way to do this and get the correct answer? I chose this as an example because the problem I'm trying to solve involves plotting a function which has been summed over two indices and the function that python outputs is not the same as Mathematica (i.e., a function of the form $$f(E)=\sum_{i=1}^{M}\sum_{j=1}^{M_2}F(i,j,E)$$).
The return statement is not indented correctly in your sample code. It returns immediately in the first loop iteration. Indent it on the function body instead, so that both for loops finish:
def f(N):
s1=0;
for p1 in range(N):
for p2 in range(N):
s1+=np.cos(p1+1)*np.cos(p2+1)
return s1
>>> print(f(5))
1.527247272700347
I have moved your code to a more numpy-ish version:
import numpy as np
N = 5
x = np.arange(N) + 1
y = np.arange(N) + 1
x = x.reshape((-1, 1))
y = y.reshape((1, -1))
mat = np.cos(x) * np.cos(y)
print(mat.sum()) # 1.5272472727003474
The trick here is to reshape x to a column and y to a row vector. If you multiply them, they are matched up like in your loop.
This should be more performant, since cos() is only called 2*N times. And it avoids loops (bad in python).
UPDATE (regarding your comment):
This pattern can be extended in any dimension. Basically, you get something like a crossproduct. Where every instance of x is matched up with every instance of y, z, u, k, ... Along the corresponding dimensions.
It's a bit confusing to describe, so here is some more code:
import numpy as np
N = 5
x = np.arange(N) + 1
y = np.arange(N) + 1
z = np.arange(N) + 1
x = x.reshape((-1, 1, 1))
y = y.reshape((1, -1, 1))
z = z.reshape((1, 1, -1))
mat = z**2 * np.cos(x) * np.cos(y)
# x along first axis
# y along second, z along third
# mat[0, 0, 0] == 1**2 * np.cos(1) * np.cos(1)
# mat[0, 4, 2] == 3**2 * np.cos(1) * np.cos(5)
If you use this for many dimensions, and big values for N, you will run into memory problems, though.
I have two arrays n and k and I would like to create a matrix with the formula n + ik. I would like the matrix to have the following form;
n[0]+ik[0] n[0]+ik[1] n[0]+ik[2] etc.
n[1]+ik[0] n[1]+ik[1] n[0]+ik[2] etc.
etc.
so far I have;
z = 0 + 1j
for i,j in n
for i,j in k
n_com = n + k*z
but I know that its not working, and I realise it doesnt really make any sense. Do I have to use append?
I think the following code is clear
n = [1, 2, 3]
k = [4, 5, 6]
mat = []
for i in range(len(n)):
row = [] # ready to make a row
for j in range(len(k)):
row.append(n[i] + 1j * k[j])
mat.append(row) # add the row to the mat
print(mat) # we get it
A more pythonic way would be (if you are interested)
mat = [[x + 1j * y for y in k] for x in n]
Further, many science people would use numpy, you may expect better performance and usability when matrix is large.
import numpy as np
n = np.array(n)
k = np.array(k).reshape((-1, 1))
mat = n + k.repeat(len(n), 1) * 1j
In the example below I have a 2D array that has some real results that are shifted and padded. The shifts depend on the row (the padding is used to make the array rectangular as required by numpy). Is it possible to extract the real results without a Python loop?
import numpy as np
# results are 'shifted' where the shift depends on the row
shifts = np.array([0, 8, 4, 2], dtype=int)
max_shift = shifts.max()
n = len(shifts)
t = 10 # length of the real results we care about
a = np.empty((n, t + max_shift), dtype=int)
b = np.empty((n, t), dtype=int)
for i in range(n):
a[i] = np.concatenate([[0] * shifts[i], # shift
(i+1) * np.arange(1, t+1), # real data
[0] * (max_shift - shifts[i]) # padding
])
print "shifted and padded\n", a
# I'd like to remove this Python loop if possible
for i in range(n):
b[i] = a[i, shifts[i]:shifts[i] + t]
print "real data\n", b
You can use two array to get the data out:
a[np.arange(4)[:, None], shifts[:, None] + np.arange(10)]
or:
i, j = np.ogrid[:4, :10]
a[i, shifts[:, None]+j]
This is called Advanced indexing in NumPy document.