Matrix columns permutation python - python

I try to find a solution to found all the columns permutations of a matrix. So i wrote this code but it doesn't work.
SOLVED:
#! python
import numpy
def permutation(matrix):
if numpy.size(matrix,1) == 1:
return [matrix]
#empty list
m=[]
# Iterate the input(matrix) and calculate the permutation
for i in range(numpy.size(matrix,1)):
column = matrix[:,[i]]
# Extract column[i] or m from the matrix. remMatrix is the remaining matrix
remMatrix = numpy.concatenate((matrix[:,:i], matrix[:,i+1:]), axis=1)
# Generating all permutations where m is the first element
for p in permutation(remMatrix):
m.append(numpy.concatenate([column,p],axis=1))
return m
#driver to test the function
matrix=numpy.matrix('1 2 3; 0 0 0')
for p in permutation(matrix):
print(p)

You did not handle the base case in your recursion. If you pass a matrix with a single column, then permutation returns an empty matrix. That is because line m = numpy.concatenate((column,p),axis=1) will not be reached if remMatrix is empty.
As result m is an empty array once you return it and the print statement is not called.
I also don't fully understand what you're trying to do. Wouldn't there for most matrices be multiple column permutations? Do you want all those matrices concatenated in the end?

Related

need equal number of ones in all columns placed at random position in np array

I have made a function to get equal number of ones placed at random position in all rows.
Below is the function:
def func():
final = np.zeros((c))
for i in range(r):
data = list(range(0, c))
random.shuffle(data)
data = data[:n_of_ones_in_row]
array = np.zeros(c)
for i in data:
array[i] = 1
final = np.vstack((final,array))
final_del = np.delete(final , 0,0)
return final_del
but now if I am trying to balance equal number of ones in columns my number of ones in rows got unbalanced. Is there any way I can achieve this?
Expected output:
https://i.postimg.cc/zfQZ1PnF/b0b70fe3fb442a4c0e5bfe7d366ad467.png
import numpy as np
import random as rng
###### Input
n = number_of_ones = 2
a = square_array_dimension = 7
###### Setting up initial matrix
r = Random_ones_array = np.zeros((a,a),dtype=int)
for k in range(a):
for j in range(n):
m = j+k
r[m%a][k] = 1
print(r)
###### Shuffle indices
idx1=list(range(a))
rng.shuffle(idx1) # these functions directly modify their input...
idx2=list(range(a))
rng.shuffle(idx2)
###### Apply shuffling to matrix
r=r[idx1,:]
r=r[:,idx2]
###### Output: A shuffled matrix
print(r)
The idea is to start with an initial array that fits your criteria, then shuffle rows and columns independently in succession.
Edit: Just realized, that not all possible solutions can be obtained this way. Specifically degenerate columns or rows are not allowed, based on the initial matrix, if this is desired to be included the solution will be more complicated then what I wrote here...

How can I have two for loops in the same list but the second one to start from the next value of the first loop?

I am trying to write a code where i have a list of vectors and Ι have to find the angle between every vector and the rest of them.(I am working on mediapipe's hand landmarks).
My code so far is this one:
vectors = [thumb_cmc_vec, thumb_mcp_vec, thumb_ip_vec, thumb_tip_vec, index_mcp_vec, index_pip_vec,
index_dip_vec, index_tip_vec, middle_mcp_vec, middle_pip_vec, middle_dip_vec, middle_tip_vec,
ring_mcp_vec, ring_pip_vec, ring_dip_vec, ring_tip_vec, pinky_mcp_vec, pinky_pip_vec,
pinky_dip_vec, pinky_tip_vec]
for vector in vectors:
next_vector = vector + 1
print(vector)
for next_vector in vectors:
print(next_vector)
M = (np.linalg.norm(vector) * np.linalg.norm(next_vector))
ES = np.dot(vector, next_vector)
th = math.acos(ES / M)
list.append(th)
print(list)
where M = the multiplication of the norms of the current sets of vectors, ES = the
scalar product of the vectors and th = the angle of the vectors.
My problem is that the variable next_vector always starts the for loop from the first vector of the list even though I want it to start from the previous loop's next vector in order not to have duplicate results. Also when both of the loops are on the 3rd vector (thumb_ip_vec) I am getting this error
th = math.acos(ES / M)
ValueError: math domain error . Is there any way to solve this? Thank you!
I think you can iterate through the list indices (using range(len(vectors) - 1)) and access the elements through their indices instead of looping through each element
for i in range(len(vectors) - 1):
# Iterate from 0 to len(vectors) -1
vector = vectors[i]
for j in range(i + 1, len(vectors)):
# Iterate from index i + 1 to len(vectors)
next_vector = vectors[j]
M = (np.linalg.norm(vector) * np.linalg.norm(next_vector))
ES = np.dot(vector, next_vector)
th = math.acos(ES / M)
list.append(th)
print(list)
The efficient solution here is to iterate over combinations of vectors:
from itertools import combinations # At top of file
for vector, next_vector in itertools.combinations(vectors, 2):
M = (np.linalg.norm(vector) * np.linalg.norm(next_vector))
ES = np.dot(vector, next_vector)
th = math.acos(ES / M)
list.append(th)
It's significantly faster than looping over indices and indexing, reduces the level of loop nesting, and makes it more clear what you're trying to do (working with every unique pairing of the input).
I'm not sure I understand your question, but consider using ranges instead.
Ranges allow you to iterate, but without calling the exact value only, but by calling it's address.
Which means you can manipulate that index to access neighboring values.
for i in range(len(iterables)-1):
ii = i+1
initial_value = iterables[i]
next_value = iterables[ii]
for ii in range(len(iterables)):
# do_rest_of_code
Sort of like the mailman, you can reach someone's neighbor without knowing the neighbor's address.
The structure above generally works, but you will need to tweak it to meet your needs.

How do I get specific rows of a matrix and all columns of this rows? in Python

I have a vector of bits B[] and a matrix NxN. I'd like to get all rows of the matrix where the bit in my B[] vector is 1. For example:
basic for loop:
b = [1,0,1,1]
Matrix = [['a','b','c','d'],['e','f','g','h'],['i','j','k','l'],['m','n','o','p']]
result_matrix = []
for i in range(len(b)):
if b[i] == 1:
result_matrix.append(Matrix[i])
print (result_matrix)
what is equal list comprehension:
result_matrix = [Matrix[i] for i in range(len(b)) if b[i]]
print (result_matrix)
I would recommend using numpy arrays for various reasons. You can than use true multidimensional arrays. Than you will be able to use the following
To select specific rows of a matrix you can use:
b(4,:)
If condition is a function returning a logical list you can display all rows meeting a condition:
b(condition(),:)
In your case you can use:
result_matrix = Matrix[b[:,0] == 1,:]

Iterating over a function's parameters in Python (using a 2d numpy array and a list of decimals)

I have defined a function that takes 2 parameters: a symetric matrix M and a probability value p. I want to define a function that loops over my parameters. The loop starts with a probability 0.01 and stops when it reaches p. On each step the function picks random lines and columns from the matrix M according to the probability and removes them. Then does the same thing to the new M with the incremented probability. I am unable to obtain results with my code
range function that supports decimals
def frange(start, end, step):
tmp = start
while tmp < end:
yield tmp
tmp += step
loop function (pick random rows and columns from the matrix and remove them)
def loop(M, p):
for i in frange(0.01, p, 0.01):
indices = random.sample(range(np.shape(M)[0]),
int(round(np.shape(M)[0] * i)))
M = np.delete(M, indices, axis=0) # removes rows
M = np.delete(M, indices, axis=1) # removes columns
return M, indices
Like this, you are returning only M and p for your first index, i=0.01, this is because the loop will stop as soon as you return something. In addition, as you can use range given in python, your first function is superfluous. I suggest you to return your matrices and indices using a List for example (you can also do this with np.arrays).
def loop(M, p):
mat_list = []
indices_list = []
for i in range(0.01, p, 0.01):
indices = random.sample(range(np.shape(M)[0]),
int(round(np.shape(M)[0] * i)))
M = np.delete(M, indices, axis=0) # removes rows
M = np.delete(M, indices, axis=1) # removes columns
mat_list.append(M)
indices_list.append(indices)
return mat_list, indices_list
If you also want to include the probability p, then you have to loop through
range(0.01, p+0.01, 0.01).

How to create a list of all possible lists satisfying a certain condition?

I'm currently trying to do project Euler problem 18 (https://projecteuler.net/problem=18), using the 'brute force' method to check all possible paths. I've just been trying the smaller, 'model' triangle so far.
I was using list comprehension to create a list of lists where the inner lists would contain the indices for that line, for example:
lst = [[a,b,c,d] for a in [0] for b in [0,1] for c in [0,1,2] for d in
[0,1,2,3] if b == a or b == a + 1 if c == b or c == b + 1 if d == c or d ==
c + 1]
This gives me the list of lists I want, namely:
[[0,0,0,0],[0,0,0,1],[0,0,1,1],[0,0,1,2],[0,1,1,1],[0,1,1,2],[0,1,2,2],
[0,1,2,3]]
Note: the if conditions ensure that it only moves to adjacent numbers in the next row of the triangle, so that
lst[i][j] = lst[i][j-1] or lst[i][j] = lst[i][j]-1
After I got to this point, I intended that for each of the inner lists, I would take the numbers associated with those indices (so [0,0,0,0] would be 3,7,2,8) and sum over them, and this way get all of the possible sums, then take the maximum of those.
The problem is that if I were to scale this up to the big triangle I'd have fifteen 'for's and 'if's in my list comprehension. It seems like there must be an easier way! I'm pretty new to Python so hopefully there's some obvious feature I can make use of that I've missed so far!
What an interesting question! Here is a simple brute force approach, note the use of itertools to generate all the combinations, and then ruling out all the cases where successive row indices differ by more than one.
import itertools
import numpy as np
# Here is the input triangle
tri = np.array([[3],[7,4],[2,4,6],[8,5,9,3]])
indices = np.array([range(len(i)) for i in tri])
# Generate all the possible combinations
indexCombs = list(itertools.product(*indices))
# Generate the difference between indices in successive rows for each combination
diffCombs = [np.array(i[1:]) - np.array(i[:-1]) for i in indexCombs]
# The only combinations that are valid are when successive row indices differ by 1 or 0
validCombs = [indexCombs[i] for i in range(len(indexCombs)) if np.all(diffCombs[i]**2<=1)]
# Now get the actual values from the triangle for each row combination
valueCombs = [[tri[i][j[i]] for i in range(len(tri))] for j in validCombs]
# Find the sum for each combination
sums = np.sum(valueCombs, axis=1)
# Print the information pertaining to the largest sum
print 'Highest sum: {0}'.format(sums.max())
print 'Combination: {0}'.format(valueCombs[sums.argmax()])
print 'Row indices: {0}'.format(indexCombs[sums.argmax()])
The output is:
Highest sum: 23
Combination: [3, 7, 4, 9]
Row indices: (0, 0, 1, 0)
Unfortunately this is hugely intensive computationally, so it won't work with the large triangle - but there are definitely some concepts and tools that you could extend to try get it to work!

Categories

Resources