Я хотел бы иметь возможность индексировать элементы набора мощности без расширения полного набора в память (a la itertools)
Кроме того, я хочу, чтобы индекс был задан мощностью. Таким образом, индекс 0 должен быть пустым, индекс 2 ** n - 1 должен быть всеми элементами
Большая часть литературы, которую я нашел до сих пор, включает индуктивную индукцию. Это не позволяет вам просто погрузиться в любой индекс. Мотивация для этой индексации - разрезать проблему для распределенного выполнения, и полезно, если удаленная машина может просто погрузиться в любом месте без совместного использования ссылки итератора через кластер.
EDIT: Blckknght предложил решение, которое я преследовал, которое показано ниже
from scipy.misc import comb
def kcombination_to_index(combination):
index = 0
combination = sorted(combination)
for k, ck in enumerate(combination):
index += comb(ck, k+1, exact=True)
return index
def index_to_kcombination(index, k):
result = []
for k in reversed(range(1, k+1)):
n = 0
while comb(n, k, exact=True) <= index:
n +=1
result.append(n-1)
index -= comb(n-1, k, exact=True)
return result
class PowerSet:
def __init__(self, elements):
self.elements = elements
def __len__(self):
return 2 ** len(self.elements)
def __iter__(self):
for i in range(len(self)):
yield self[i]
def __getitem__(self, k):
if not isinstance(k, int):
raise TypeError
#k=0 is empty set,
#k= 1 - 1+n returns subsets of size 1
for subset_size in range(len(self.elements) + 1):
number_subsets = comb(len(self.elements), subset_size, exact=True)
if k >= number_subsets:
k -= number_subsets
else:
break
#we now want the kth element of a possible permutation of subset_size elements
indeces = index_to_kcombination(k, subset_size)
return map(lambda i: self.elements[i], indeces)
if __name__ == "__main__":
print "index of combination [8, 6, 3, 1, 0] is", kcombination_to_index([8, 6, 3, 1, 0])
print "5 combination at position 72 is", index_to_kcombination(72,5)
ps = PowerSet(["a", "b", "c", "d"])
for subset_idx in range(len(ps)):
print ps[subset_idx]