I am new to numpy and have an np.array with inputs that are 3 bits each, looking like this:
[[0 1 0]
[1 0 1]
[1 0 0]
[0 1 1]
[1 0 1]
[0 1 0]
[1 1 1]
[1 0 0]
[0 0 0]]
The targets should be the XOR of the first two input bits (y = XOR(x0, x1)) in another numpy array.
[1, 1, 1, 1, 1, 1, 0, 1, 0]
Use np.bitwise_xor():
np.bitwise_xor(arr[:,0], arr[:, 1])
Demo:
In [112]: np.bitwise_xor(arr[:,0], arr[:, 1])
Out[112]: array([1, 1, 1, 1, 1, 1, 0, 1, 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.
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]]
Is there a way to get this result without a loop? I've made a couple attempts at fancy indexing with W[range(W.shape[0]),... but have been so far unsuccessful.
import itertools
import numpy as np
n = 4
ct = 2
one_index_tuples = list(itertools.combinations(range(n), r=ct))
W = np.zeros((len(one_index_tuples), n), dtype='int')
for row_index, col_index in enumerate(one_index_tuples):
W[row_index, col_index] = 1
print(W)
Result:
[[1 1 0 0]
[1 0 1 0]
[1 0 0 1]
[0 1 1 0]
[0 1 0 1]
[0 0 1 1]]
You can use fancy indexing (advanced indexing) as follows:
# reshape the row index to 2d since your column index is also 2d so that the row index and
# column index will broadcast properly
W[np.arange(len(one_index_tuples))[:, None], one_index_tuples] = 1
W
#array([[1, 1, 0, 0],
# [1, 0, 1, 0],
# [1, 0, 0, 1],
# [0, 1, 1, 0],
# [0, 1, 0, 1],
# [0, 0, 1, 1]])
Try this:
[[ 1 if i in x else 0 for i in range(n) ] for x in itertools.combinations( range(n), ct )]