对一个复杂但又简单的矩阵运算进行排序。我想查找并最大化行数,以使至少有x
列,其中那些行所约束的矩阵都是1。
行本身不需要连续,列也不需要。并且矩阵假设所有行至少有x
个行,因此,我没有删除任何没有最小x
的行。
我的初始方法如下:进入第一行。查找前一个带有“ 1”的“ x”列。然后对于这些列,检查多少行也有1。跟踪我发现了多少行。从每一行开始执行此操作。
但是,这是行不通的,因为即使对于第一行,我也需要考虑所有不同的列组合,这些组合仍然为我提供最少x
列中带有1的列,而不仅仅是第一列{ {1}}列。
为此,计算时间迅速耗尽。有没有一种有效的方法来解决这个问题?
我正在尝试使用python。
请考虑以下示例和x
。
这没有解决方案,因为最初删除了行1、3、5。然后,对于第2行和第4行,在两行中都没有3列。
但是在这里,第2行和第4行至少有3列,全为1。因此,这是一个解决方案,最大行数为 2 。
答案 0 :(得分:1)
您似乎要描述的是对关联规则学习问题的改写,例如可以使用Apriori算法解决。
这里是一个快速示例,展示了该算法的基础。它可能需要一些改进,不确定是否有错误。
此外,它也不要求必须找到所有给出最少“ x”行的不同列组合。它仅使用'x'来更快地过滤所有解决方案,最终返回的解决方案是具有至少'x'行的最大列数。
from operator import itemgetter, or_
from itertools import combinations, starmap
from collections import Counter
from math import factorial
class Apriori:
def __init__(self, input, x):
self.input = input
self.cols = len(input[0])
self.rows = len(input)
self.x = x
def _get_freq_combs(self, comb):
return sum(map(lambda row:
sum([bool(e) for i, e in enumerate(row)
if i in comb]) // len(comb), self.input))
def _make_new_combs(self, combs, comb_size):
candidates = Counter(map(frozenset,
starmap(or_, combinations(combs, 2))))
possible_candidate_freq = factorial(comb_size) // factorial(2) \
// factorial(comb_size - 2)
for c, f in candidates.items():
if f == possible_candidate_freq:
yield c
def solve(self):
"""Returns a list of sets with the most common items, at least x."""
freq = [self._get_freq_combs([i]) for i in range(self.cols)]
most_freq = [{ind} for ind in range(self.cols) if freq[ind] >= x]
comb_size = 2
while most_freq:
old_freq = most_freq
most_freq = [c for c in self._make_new_combs(most_freq, comb_size)
if self._get_freq_combs(c) >= x]
comb_size += 1
return old_freq
if __name__ == '__main__':
input = [[1, 0, 1, 0],
[0, 1, 1, 0],
[0, 1, 1, 1],
[0, 0, 0, 1]]
x = 2
apriori = Apriori(input, x)
print(apriori.solve())