在某些情况下,我试图列举在计算四个玩家的Banzhaf power indices时可能出现的独特情况的数量,当没有独裁者且有四个或五个获胜联盟时。
我正在使用以下代码生成一组我想要迭代的列表。
from itertools import chain, combinations
def powerset(iterable):
s = list(iterable)
return chain.from_iterable(map(list, combinations(s, r)) for r in range(2, len(s)+1))
def superpowerset(iterable):
s = powerset(iterable)
return chain.from_iterable(map(list, combinations(s, r)) for r in range(4, 6))
set_of_lists = superpowerset([1,2,3,4])
但是,如果在重新映射下它们等效,则此集合中的两个列表不应被视为唯一。
使用以下列表作为示例:
[[1, 2], [1, 3], [2, 3], [1, 2, 4]]
如果每个元素2
重命名为3
,反之亦然,我们会得到:
[[1, 3], [1, 2], [3, 2], [1, 3, 4]]
每个子列表中的顺序并不重要,子列表的顺序也不重要。因此,交换列表可以重写为:
[[1, 2], [1, 3], [2, 3], [1, 3, 4]]
有4个值,因此可能发生P(4,4)= 24个可能的重映射(包括平凡映射)。
有没有办法轻松检查?或者,更好的是,是否有办法避免生成这些列表?
我甚至不确定如何将第一个列表转换为第二个列表(但可以从那里强制推断它)。另外,我不仅限于数据类型(在某种程度上),使用frozenset
也没关系。
编辑:tobias_k提供的解决方案回答了“检查”问题,但正如评论中所述,我认为我对这个问题采取了错误的方法。
答案 0 :(得分:1)
这可能还没有完整的解决方案,但它可能会向您展示进一步调查的方向。
您可以将每个元素映射到有关"拓扑"的某些特征,如何"连接"与其他元素。你必须小心不要考虑集合中的顺序,或者 - 显然 - 元素本身。例如,您可以考虑元素出现的频率,它出现在哪个大小的组中,以及类似的东西。将这些指标与关键函数组合,按该键对元素进行排序,并按顺序为它们分配新名称。
def normalize(lists):
items = set(x for y in lists for x in y)
counter = itertools.count()
sorter = lambda x: sorted(len(y) for y in lists if x in y)
mapping = {k: next(counter) for k in sorted(items, key=sorter)}
return tuple(sorted(tuple(sorted(mapping[x] for x in y)) for y in lists))
这会将您的两个示例列表映射到相同的"标准化"列表:
>>> normalize([[1, 2], [1, 3], [2, 3], [1, 2, 4]])
((0, 1), (0, 2), (1, 2), (1, 2, 3))
>>> normalize([[1, 3], [1, 2], [3, 2], [1, 3, 4]])
((0, 1), (0, 2), (1, 2), (1, 2, 3))
当应用于所有列表时,它会从330减少到36。我不知道这是否是最小的,但它看起来是一个好的开始。
>>> normalized = set(map(normalize, set_of_lists))
>>> len(normalized)
36