Reputation: 31
I am trying to form a matrix using a generating set of some vectors (v1, v2, v3)
, where each element represents binary data.
I want the code to use the vectors in the set and create a matrix with the zero vector, each of the row vectors, and the combinations v1+v2
, v1+v3
, v2+v3
and v1+v2+v3
, ie. all the possible linear combinations with 0
and 1
as coefficients.
I've tried using for loops, but I end up with repeats. I've also been able to do it by doing each of the operations but this isn't feasible for generating sets with many vectors.
import numpy as np
A = np.matrix([[1,1,1,1,0,0,0,0],[0,0,1,1,1,1,0,0],[0,0,0,0,1,1,1,1]])
I want to create a new matrix made from all possible linear combinations of the row vectors from the above matrix A.
The output should contain the following:
[0,0,0,0,0,0,0,0],
[1,1,1,1,0,0,0,0],
[0,0,1,1,1,1,0,0],
[0,0,0,0,1,1,1,1],
[1,1,0,0,1,1,0,0],
[0,0,1,1,0,0,1,1],
[1,1,1,1,1,1,1,1],
[1,1,0,0,0,0,1,1]
Upvotes: 1
Views: 375
Reputation: 43524
The way I look at this problem is that you have a set of coefficients:
coeffs = [0, 1]
The goal is to get all combinations of the coefficients multiplied by the vectors. Mathematically, you want to apply the following coefficients to your vectors:
from itertools import chain, combinations_with_replacement, permuations
import numpy as np
A = np.matrix([[1,1,1,1,0,0,0,0],[0,0,1,1,1,1,0,0],[0,0,0,0,1,1,1,1]])
N = len(A)
all_coeffs = (
chain.from_iterable(
list(set(permutations(x, N))) for x in combinations_with_replacement(coeffs, N)
)
)
print(list(all_coeffs))
#[(0, 0, 0),
# (1, 0, 0),
# (0, 1, 0),
# (0, 0, 1),
# (0, 1, 1),
# (1, 1, 0),
# (1, 0, 1),
# (1, 1, 1)]
So you need to take the dot product of each of the coefficients with each of the rows in A
, and then "sum" the result. Since you're working with binary numbers, the addition operation can be achieved using the xor
operator. Finally you can concatenate the results together.
Putting this all together:
from functools import reduce
from operator import xor
N = len(A)
mat = np.concatenate(
[
reduce(xor, (a*b for a, b in zip(c, A)))
for c in (
chain.from_iterable(
list(set(permutations(x, N))) for x in
combinations_with_replacement(coeffs, N)
)
)
]
)
print(mat)
#[[0 0 0 0 0 0 0 0]
# [1 1 1 1 0 0 0 0]
# [0 0 1 1 1 1 0 0]
# [0 0 0 0 1 1 1 1]
# [0 0 1 1 0 0 1 1]
# [1 1 0 0 1 1 0 0]
# [1 1 1 1 1 1 1 1]
# [1 1 0 0 0 0 1 1]]
Upvotes: 0
Reputation: 101
I think this is what you want.
import numpy as np
from itertools import combinations
v = np.array([[1,1,1,1,0,0,0,0],[0,0,1,1,1,1,0,0],[0,0,0,0,1,1,1,1]]) # v1, v2, v3
l = [] # creating a list of possible combinations [(0, 1), (0, 2), (1, 2), (0, 1, 2)]
for j in range(2, v.shape[0]+1):
comb = combinations(np.arange(v.shape[0]), j)
for i in list(comb):
l.append(i)
final = np.zeros((len(l), v.shape[1])) # creating final matrix
for i in range(len(l)): # filling final matrix based on combinations
for j in (l[i]):
final[i] += v[j]
final = np.concatenate((np.zeros((1,v.shape[1])), v, final%2), axis=0)
#array([[0., 0., 0., 0., 0., 0., 0., 0.],
# [1., 1., 1., 1., 0., 0., 0., 0.],
# [0., 0., 1., 1., 1., 1., 0., 0.],
# [0., 0., 0., 0., 1., 1., 1., 1.],
# [1., 1., 0., 0., 1., 1., 0., 0.],
# [1., 1., 1., 1., 1., 1., 1., 1.],
# [0., 0., 1., 1., 0., 0., 1., 1.],
# [1., 1., 0., 0., 0., 0., 1., 1.]])
Upvotes: 1