Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 1 year ago.
Improve this question
I have a matrix of 0 and 1, example:
X =
[[1, 1, 0, 0],
[1, 0, 1, 1],
[0, 0, 1, 1],
[1, 1, 1, 1],
In each row, choose only an '1' and leave orthers become 0, to get the same number of '1' in each colunm. Basically, minimum variance after get sum by columns.
Example: From X above, the answer is:
Y =
[[1, 0, 0, 0],
[0, 0, 0, 1],
[0, 0, 1, 0],
[0, 1, 0, 0],
Each column in Y have a '1'. Y choose 1st '1' from row 1 of X, choose 2nd '1' in index 4 from row 2,.... X can have any size.
How can i do that?
Sorry for my bad english.
EDIT: what follows is a brute force technique which finds every "solution". It does not work for non-square arrays because OP's problem is vague on how non-square arrays should be treated. The technique I have in mind for finding a random solution is just a simple backtracking algorithm over idxs, which I may get around to tomorrow if somebody else doesn't come up with something better.
Here's a brute force solution which takes the cartesian product of the column indices where there is a one for each row:
import itertools
import numpy as np
x = np.array([[1, 1, 0, 0],
[1, 0, 1, 1],
[0, 0, 1, 1],
[1, 1, 1, 1]])
n = x.shape[1]
rows, cols = np.argwhere(x).T
idxs = np.split(cols, np.unique(rows, return_index=True)[1][1:])
col_idxs = [t for t in itertools.product(*idxs) if len(set(t)) == n]
row_idxs = np.arange(n)
Showing all solutions for this particular X:
for t in col_idxs:
z = np.zeros_like(x)
z[row_idxs, t] = 1
print(f"{z}\n")
Output:
[[1 0 0 0]
[0 0 1 0]
[0 0 0 1]
[0 1 0 0]]
[[1 0 0 0]
[0 0 0 1]
[0 0 1 0]
[0 1 0 0]]
[[0 1 0 0]
[1 0 0 0]
[0 0 1 0]
[0 0 0 1]]
[[0 1 0 0]
[1 0 0 0]
[0 0 0 1]
[0 0 1 0]]
[[0 1 0 0]
[0 0 1 0]
[0 0 0 1]
[1 0 0 0]]
[[0 1 0 0]
[0 0 0 1]
[0 0 1 0]
[1 0 0 0]]
Related
Wrote this script to create a 4x16 matrix for all possible combinations of 4 bits:
import numpy as np
a = []
for x in range(2):
for y in range(2):
for z in range(2):
for w in range(2):
a.append([x,y,z,w])
a = np.array(a)
print(a)
Output
[[0 0 0 0]
[0 0 0 1]
[0 0 1 0]
[0 0 1 1]
[0 1 0 0]
[0 1 0 1]
[0 1 1 0]
[0 1 1 1]
[1 0 0 0]
[1 0 0 1]
[1 0 1 0]
[1 0 1 1]
[1 1 0 0]
[1 1 0 1]
[1 1 1 0]
[1 1 1 1]]
It works.. however it's 4 loops for 4 bits. Raising the number of bits means more loops, does anyone have another way of doing this?
Haven't tried much.. new to programming
with just numpy,we can use np.unpackbits
bits = 4
np.unpackbits(np.arange(2**bits, dtype=np.uint8)[...,None], count=bits, axis=1, bitorder='little')
You can just use itertools.product:
list(itertools.product(range(2), repeat=4))
Here range(2) provides the 0 and 1, and then repeat=4 says 4 bits. If you want 20 bits, use repeat=20.
This result actually gives you a list, but if you want to iterate through each option one at a time, just use itertools.product(range(2), repeat=4) on its own, as this gives you a generator. For larger numbers of bits, the number of combinations might not fit in memory. Using the generator version means you only ever have one combination in memory at a time.
You can use recursion:
def create_matrix(n, arr=[]):
if n == 0:
print(arr)
else:
for i in range(2):
create_matrix(n-1, arr + [I])
output:
> create_matrix(4)
[0, 0, 0, 0]
[0, 0, 0, 1]
[0, 0, 1, 0]
[0, 0, 1, 1]
[0, 1, 0, 0]
[0, 1, 0, 1]
[0, 1, 1, 0]
[0, 1, 1, 1]
[1, 0, 0, 0]
[1, 0, 0, 1]
[1, 0, 1, 0]
[1, 0, 1, 1]
[1, 1, 0, 0]
[1, 1, 0, 1]
[1, 1, 1, 0]
[1, 1, 1, 1]
This can be used to generate a matrix for all possible combinations of any bits.
It appends a 0 or 1 to arr and passes it on to the next recursive call until n leads to 0. When n becomes 0, it prints out arr.
UPDATE
As #Pranav Hosangadi suggestions, I've modified the code to get rid of mutable default argument and to has the return statement.
def create_matrix(n):
if n == 0:
return [[]]
else:
return [[i] + item for i in range(2) for item in create_matrix(n-1)]
P.S. It is good to learn about Recursion.
import jax.numpy as jnp
vectors and array are jnp.array(dtype=jnp.int32)
I have an array with shape [x, d, y] (3x3x3)
[[[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]]]
and vectors x = [2 0 3], y = [ 2 0 1], d = [0 0 1]
I want to have something like this by indexing but I tried and don't really know how, with jax.numpy.
[[[0 0 2],
[0 0 0],
[0 0 0]],
[[0 0 0],
[0 0 0],
[0 0 0]],
[[0 0 0],
[0 3 0],
[0 0 0]]]
Edit: I would like to specify that I wanted to put number from x with its index to the array but only when x > 0. I tried with boolean mask.
Something like this
mask = x > 0
array = array.at[mask, d, y].set(array[mask, d, y] + x)
You have a three-dimensional array, so you can index it with three arrays of indices. Since you want d and y to be associated with the second and third dimensions, you'll need to create another array of indices for the first dimension:
import jax.numpy as jnp
arr = jnp.zeros((3, 3, 3), dtype='int32')
x = jnp.array([2, 0, 3])
y = jnp.array([2, 0, 1])
d = jnp.array([0, 0, 1])
i = jnp.arange(len(x))
mask = x > 0
out = arr.at[i[mask], d[mask], y[mask]].set(x[mask])
print(out)
# [[[0 0 2]
# [0 0 0]
# [0 0 0]]
# [[0 0 0]
# [0 0 0]
# [0 0 0]]
# [[0 0 0]
# [0 3 0]
# [0 0 0]]]
In this case the result will be the same whether or not you use the mask (i.e. arr.at[i, d, y].set(x) will give the same result) but because your question explicitly specified that you only want to use values x > 0 I included it.
Please can someone help with flipping elements on the diagonal of a matrix from 1 to 0 if 1, and 0 to 1 if 0 for the matrix rmat
mat = np.random.binomial(1,.5,4)
rmat = np.array([mat,]*4)
Thank you
You can use numpy.fill_diagonal.
NB. the operation is in place
diagonal = rmat.diagonal()
np.fill_diagonal(rmat, 1-diagonal)
input:
array([[1, 1, 1, 0],
[1, 1, 1, 0],
[1, 1, 1, 0],
[1, 1, 1, 0]])
output:
array([[0, 1, 1, 0],
[1, 0, 1, 0],
[1, 1, 0, 0],
[1, 1, 1, 1]])
Try this -
Unlike the np.fill_diagonal, this method is not inplace and doesnt need explicit copy of the input rmat matrix.
n = rmat.shape[0]
output = np.where(np.eye(n, dtype=bool), np.logical_not(rmat), rmat)
output
#Original
[[0 1 0 0]
[0 1 0 0]
[0 1 0 0]
[0 1 0 0]]
#diagonal inverted
[[1 1 0 0]
[0 0 0 0]
[0 1 1 0]
[0 1 0 1]]
Another way to do this would be to use np.diag_indices along with np.logical_not
n = rmat.shape[0]
idx = np.diag_indices(n)
rmat[idx] = np.logical_not(rmat[idx])
print(rmat)
I have 2 tensors:
h=[[0 0 0]
[0 0 1]
[0 1 0]]
and
h2=[[0 0 0]
[0 0 1]
[0 0 1]]
I want to create 3 vector with values where h=h2
I mean ,i want compare h[0]=h2[0] ,h[1]=h2[1] and h[2]=h2[2]
So I want the 3 vector as:
h3=[[0 0 0]
[0 0 1]
I tried :
def fn( tensor1,i):
return tensor1[i]
tensor = [fn(h,i) for i in range(h) if tf.reduce_all(tf.equal(h[i],h2[i])) ]
but it return this error TypeError: only integer scalar arrays can be converted to a scalar index
Working code snippet
import tensorflow as tf
h=[[0,0 ,0],
[0, 0 ,1],
[0, 1 ,0]]
h2=[[0 ,0 ,0],
[0 ,0, 1],
[0, 0, 1]]
for i in range(len(h)):
if tf.reduce_all(tf.equal(h[i],h2[i])):
print(h[i])
Output
[0, 0, 0]
[0, 0, 1]
I'm trying to check elements of a 2D array (matrix) and generate a number of matrices (of equal size) depending on some conditions as below:
Consider my matrix:
x = [[1, 0, 2],[7, 0, 7],[1, 1, 1]]
I need to check for the (2) and generate two matrices where the position of (2) will be replaced by 0 and 1 respectively. I also need to check for the 7's and generate 3 combinations of the matrix with values of 7 being (0,1),(1,0),(1,1) respectively. This mean the total number of matrices generated are 6 as follows:
[[1, 0, 0],[0, 0, 1],[1, 1, 1]]
[[1, 0, 0],[1, 0, 0],[1, 1, 1]]
[[1, 0, 0],[1, 0, 1],[1, 1, 1]]
[[1, 0, 1],[0, 0, 1],[1, 1, 1]]
[[1, 0, 1],[1, 0, 0],[1, 1, 1]]
[[1, 0, 1],[1, 0, 1],[1, 1, 1]]
There can be more than 1 (2), and the position of 7's can be vertical or hirizental.
I've tried a naiive way just looping through x looking for 2's and appending:
for i in range(len(x)):
for j in range(len(x[0])):
if x[i][j] == 2:
inter[i][j] = 0
test.append(inter)
inter2[i][j] = 1
test.append(inter2)
But that only works if I have the value of 2 only. I've also tried converting to numpy array and using where() to find the indexes of 2's and 7's, but then don't know how that can be used to generate the required outcome. Any thoughts?
The conditions described are very vague. If I understand correctly, you want this:
sevens = [[0,1],[1,0],[1,1]]
twos = [0,1]
for i in twos:
for j in sevens:
m = x.copy()
m[m==2] = i
m[m==7] = j
print(m)
output:
[[1 0 0]
[0 0 1]
[1 1 1]]
[[1 0 0]
[1 0 0]
[1 1 1]]
[[1 0 0]
[1 0 1]
[1 1 1]]
[[1 0 1]
[0 0 1]
[1 1 1]]
[[1 0 1]
[1 0 0]
[1 1 1]]
[[1 0 1]
[1 0 1]
[1 1 1]]
UPDATE: per OP's comment for (2)s multiplicities:
x = np.array([[2, 0, 2],[7, 0, 7],[1, 1, 1]])
sevens = [[0,1],[1,0],[1,1]]
v = (x==2).sum()*([0,1],)
twos = np.array(np.meshgrid(*v)).T.reshape(-1,2)
for i in twos:
for j in sevens:
m = x.copy()
m[m==2] = i
m[m==7] = j
print(m)
output:
[[0 0 0]
[0 0 1]
[1 1 1]]
[[0 0 0]
[1 0 0]
[1 1 1]]
[[0 0 0]
[1 0 1]
[1 1 1]]
[[0 0 1]
[0 0 1]
[1 1 1]]
[[0 0 1]
[1 0 0]
[1 1 1]]
[[0 0 1]
[1 0 1]
[1 1 1]]
[[1 0 0]
[0 0 1]
[1 1 1]]
[[1 0 0]
[1 0 0]
[1 1 1]]
[[1 0 0]
[1 0 1]
[1 1 1]]
[[1 0 1]
[0 0 1]
[1 1 1]]
[[1 0 1]
[1 0 0]
[1 1 1]]
[[1 0 1]
[1 0 1]
[1 1 1]]