我给引号,因为我的意思是例如:
B = [[1,2,3,4,5],
[6,7,8,9,10],
[11,12,13,14,15],
[16,17,18,19,20]]
假设我们选择第2,4行和第1,3行,交叉点将给我们
A = [[6,8],
[16,18]]
我的问题是假设我有A和B,有没有办法可以找出从B中选择哪些行和列来给A?
顺便说一下,如果你能用python / numpy给出答案,那将是最好的。但只是在数学或其他编程语言中也会很好。
答案 0 :(得分:10)
这是一个非常困难的组合问题。实际上Subgraph Isomorphism Problem可以简化为你的问题(如果矩阵A
只有0-1条目,你的问题恰好是子图同构问题)。已知这个问题是NP完全的。
这是一个递归回溯解决方案,它比强制执行所有可能的解决方案要好一些。请注意,在最坏的情况下,这仍然需要指数时间。但是,如果您假设存在解决方案并且没有歧义(例如B
中的所有条目都不同),则会在线性时间内找到解决方案。
def locate_columns(a, b, offset=0):
"""Locate `a` as a sublist of `b`.
Yields all possible lists of `len(a)` indices such that `a` can be read
from `b` at those indices.
"""
if not a:
yield []
else:
positions = (offset + i for (i, e) in enumerate(b[offset:])
if e == a[0])
for position in positions:
for tail_cols in locate_columns(a[1:], b, position + 1):
yield [position] + tail_cols
def locate_submatrix(a, b, offset=0, cols=None):
"""Locate `a` as a submatrix of `b`.
Yields all possible pairs of (row_indices, column_indices) such that
`a` is the projection of `b` on those indices.
"""
if not a:
yield [], cols
else:
for j, row in enumerate(b[offset:]):
if cols:
if all(e == f for e, f in zip(a[0], [row[c] for c in cols])):
for r, c in locate_submatrix(a[1:], b, offset + j + 1, cols):
yield [offset + j] + r, c
else:
for cols in locate_columns(a[0], row):
for r, c in locate_submatrix(a[1:], b, offset + j + 1, cols):
yield [offset + j] + r, c
B = [[1,2,3,4,5], [6,7,8,9,10], [11,12,13,14,15], [16,17,18,19,20]]
A = [[6,8], [16,18]]
for loc in locate_submatrix(A, B):
print loc
这将输出:
([1, 3], [0, 2])
答案 1 :(得分:1)
如果您只想知道从B中选择哪些行和列来给出A并且不关心效率,那么这是一种将结果存储在数组res
res [N]中的强力方法B中A [N]的所有位置。即使A [N]存在于B的多个位置,也可以工作。
B = [[1,2,3,4,5],[6,7,8,9,10],[11,12,13,14,15],[16,17,18,19,20]]
A = [[6,8], [16,18]]
res = []
for subsetIndex, subset in enumerate(A):
k = []
res.append(k)
for supersetIndex, superset in enumerate(B):
loc = []
try:
loc = [(supersetIndex, superset.index(item)) for item in subset]
k.append(loc)
print A[subsetIndex], "is at ", loc, "in B"
except ValueError:
pass
print res
输出:
[6, 8] is at [(1, 0), (1, 2)] in B
[16, 18] is at [(3, 0), (3, 2)] in B
result = [[[(1, 0), (1, 2)]], [[(3, 0), (3, 2)]]]
答案 2 :(得分:1)
矩阵中的所有/大多数值是否唯一IE:它们只在矩阵B中出现一次?
值越独特,您对子图同构(SI)的改进就越好。如果所有值都是唯一,那么您可以对每个值进行反向查找以确定它的行/列对,并将行和列的列表联合起来(单独)。
结果是一个简单的O(N)
算法,其中N = number of rows * number of columns
。当然,价值观越不独特,你需要检查的误报就越多,你越接近SI,事情就越简单。
答案 3 :(得分:0)
如果您需要的话,这是一个强力解决方案:
rows = [i for aa in A for i,bb in enumerate(B) if np.in1d(aa, bb).all()]
cols = [i for aa in A.T for i,bb in enumerate(B.T) if np.in1d(aa, bb).all()]
submatrix = B[np.ix_(rows, cols)]
它会检查A
的每一行对B
的每一行,以确保子矩阵的所有元素都存在。然后,它对列做了同样的事情。
您可以通过将列限制仅限于相关行来加快列查找部分:
cols = [i for aa in A.T for i,bb in enumerate(B[rows].T) if np.equal(aa, bb).all()]