我正在尝试创建一个算法,该算法可以生成组大小为 n 的 m 个对象的所有唯一组合,而无需重复或重复。
重复是指至少有两个或两个以上的数字之前已经组合在一起。例如,[1, 2, 3]
和[1, 2, 4]
具有对[1, 2]
的重复。
如果不使用扩展器,则意味着所有大小为 n 的组必须大小相同。
下面的函数接受一个输入(m, n)
,如果 m 和 n 不兼容,则输出False
。如果 m 和 n 兼容,则函数返回唯一组合的数量。
def iterations (m, n):
num = (m**2) - m
den = (n**2) - n
if den <= 0 or num <= 0:
return False
if (m - 1) % (n - 1) != 0:
return False
if num % den != 0:
return False
return int(num/den)
字符串
这部分代码工作正常。我遇到的问题是如何实现生成唯一组合的算法。
这是我用来生成唯一组合的代码块:
import random
class id ():
def __init__(self, name):
self.name = name
self.comparisons = []
def update_comparisons(self, id_list):
for id in id_list:
if id in self.comparisons:
self.comparisons.remove(id)
self.comparisons.extend(id_list)
self.comparisons.sort()
if self.name in self.comparisons:
self.comparisons.remove(self.name)
return self.comparisons
def get_ids(n):
ids = []
for i in range(1,n+1):
ids.append(id(i))
return ids
def iterations(m,n):
num = (m**2) - m
den = (n**2) - n
if den <= 0 or num <= 0:
return False
if (m - 1) % (n - 1) != 0:
return False
if num % den != 0:
return False
return int(num/den)
# Checking if m and n are valid values
m = 9
n = 3
if iterations(m, n):
iter = iterations(m, n)
print(iter)
#Creating list of ids
ids_master = get_ids(m)
ids = ids_master.copy()
comparison_names = []
ids = ids_master.copy()
comparisons = []
for i in range(iter):
temp = []
pos = 0
while len(temp) < n:
id_a = ids[pos]
# Checking if the id within temp have already been compared or is a duplicate
counter = 0
for id_b in temp:
if id_b.name in id_a.comparisons or id_b.name == id_a.name:
counter += 1
# Checking if id_a has been compared to all other ids
if len(id_a.comparisons) == m - 1:
counter += 1
# If id_a has passed the checks, append it to temp_list
if counter == 0:
temp.append(id_a)
pos += 1
comparisons.append(temp)
# Updating the comparison for each id object
for comparison in comparisons:
names = [x.name for x in comparison]
names.sort()
for id in comparison:
id.update_comparisons(names)
comparison_names.append(names)
# Checking if all ids have been compared
for id in ids_master:
print(f'ID: {id.name} \n Comparisons: {id.comparisons}')
上面的代码适用于值(3,2)、(5,2)和(7,3)。然而,(9,3)带来了复杂性。
代码将在遇到路障之前生成以下比较。[[1, 2, 3], [1, 4, 5], [1, 6, 7], [1, 8, 9], [2, 4, 6], [2, 5, 7]]
在这种情况下,下一个组合将是[2, 8, 9]
。这不起作用,因为对[8,9]已经在[1, 8, 9]
中进行了比较。代码然后继续迭代位置,直到它用完了要检查的列表中的项目,并给出错误“list index out of range”。
我需要一种算法来预测这些错误的方法。例如,如果代码生成[2, 4, 9]
,那么剩余的组合 * 可能 * 会正常工作。我相信有一种方法可以实现这一点,但我不确定如何进行。
先谢谢你了!
1条答案
按热度按时间li9yvcax1#
我不能完全遵循代码中的逻辑来查看您做错了什么,但我提出了这个似乎可以满足您的要求:
个字符
编辑:根据您的评论,为了有效地生成大量的有效组合,这里有一个替代实现。这个版本存储了少量的状态,并根据请求输出有效的组合。它仍然需要花费很长时间来生成所有的m,n = 96,6值,但每个单独的组合都可以执行,而不必计算它们。
型
可以通过在生成器中使用多线程或DISC来进行一些优化。可以通过实现
itertools.combinations
的自定义版本来实现进一步的优化,其中可以将seen_pairs
的检查集成到逻辑中,从而避免生成无效组合。上次编辑:我尝试了一个修改过的
itertools.combinations
的参考实现,以从输入空间中删除块。下面是m,n=96,6
的计时结果。