この質問は古いことは知っていますが、効率的に行う方法は次のとおりです。
現在 Python で書かれているすべてのコードは、C++ に簡単に変換できると確信しています。
- 使用される整数は 500 ビットを必要とするため (Python では問題ではありません)、特性ベクトルに整数を使用することから、ビット配列を使用するように移行することをお勧めします
。
start
組み合わせの範囲 ( 処理する数 と)、どの組み合わせから選択するかlength
のセット、および選択する項目の数をノードに配布します。items
k
start
とから直接開始の組み合わせを見つけて、各ノードを初期化しますitems
。
- 各ノードを実行して最初の組み合わせの作業を実行し、残りの組み合わせを繰り返し、関連する作業を実行します。
あなたが提案するように1を実行するには、n-choose-kを見つけて範囲に分割します-あなたの場合、500-Choose-5は、あなたが言ったように255244687600なので、node = 0から9まで配布します:
(start=node*25524468760, length=25524468760, items=items, k=5)
2を実行するには、組み合わせ数システムを使用して開始組み合わせを直接 (反復なしで) 見つけ、同時に組み合わせの特性ベクトルの整数表現 ( 3の反復に使用される) を見つけることができます。
def getCombination(index, items, k):
'''Returns (combination, characteristicVector)
combination - The single combination, of k elements of items, that would be at
the provided index if all possible combinations had each been sorted in
descending order (as defined by the order of items) and then placed in a
sorted list.
characteristicVector - an integer with chosen item's bits set.
'''
combination = []
characteristicVector = 0
n = len(items)
nCk = 1
for nMinusI, iPlus1 in zip(range(n, n - k, -1), range(1, k + 1)):
nCk *= nMinusI
nCk //= iPlus1
curIndex = nCk
for k in range(k, 0, -1):
nCk *= k
nCk //= n
while curIndex - nCk > index:
curIndex -= nCk
nCk *= (n - k)
nCk -= nCk % k
n -= 1
nCk //= n
n -= 1
combination .append(items[n])
characteristicVector += 1 << n
return combination, characteristicVector
特性ベクトルの整数表現では、組み合わせを構成するアイテムの位置に k ビットが設定されます。
3を実行するには、Gosper のハックを使用して、同じ数体系の組み合わせの次の特性ベクトル ( に対して逆に並べ替えられた組み合わせの並べ替えリストに表示される次の組み合わせ) を反復処理し、items
同時に、組み合わせ:
def nextCombination(items, characteristicVector):
'''Returns the next (combination, characteristicVector).
combination - The next combination of items that would appear after the
combination defined by the provided characteristic vector if all possible
combinations had each been sorted in descending order (as defined by the order
of items) and then placed in a sorted list.
characteristicVector - an integer with chosen item's bits set.
'''
u = characteristicVector & -characteristicVector
v = u + characteristicVector
if v <= 0:
raise OverflowError("Ran out of integers") # <- ready for C++
characteristicVector = v + (((v ^ characteristicVector) // u) >> 2)
combination = []
copiedVector = characteristicVector
index = len(items) - 1
while copiedVector > 0:
present, copiedVector = divmod(copiedVector, 1 << index)
if present:
combination.append(items[index])
index -= 1
return combination, characteristicVector
これを何度も繰り返しlength-1
ます (最初のものはすでに直接見つけているため)。
例えば:
7-choose-3 文字を処理する 5 つのノード:
>>> items = ('A','B','C','D','E','F','G')
>>> k = 3
>>> nodes = 5
>>> n = len(items)
>>> for nmip1, i in zip(range(n - 1, n - k, -1), range(2, k + 1)):
... n = n * nmip1 // i
...
>>> for node in range(nodes):
... length = n // nodes
... start = node * length
... print("Node {0} initialised".format(node))
... combination, cv = getCombination(start, items, k)
... doWork(combination)
... for i in range(length-1):
... combination, cv = nextCombination(items, cv)
... doWork(combination)
...
Node 0 initialised
Doing work with: C B A
Doing work with: D B A
Doing work with: D C A
Doing work with: D C B
Doing work with: E B A
Doing work with: E C A
Doing work with: E C B
Node 1 initialised
Doing work with: E D A
Doing work with: E D B
Doing work with: E D C
Doing work with: F B A
Doing work with: F C A
Doing work with: F C B
Doing work with: F D A
Node 2 initialised
Doing work with: F D B
Doing work with: F D C
Doing work with: F E A
Doing work with: F E B
Doing work with: F E C
Doing work with: F E D
Doing work with: G B A
Node 3 initialised
Doing work with: G C A
Doing work with: G C B
Doing work with: G D A
Doing work with: G D B
Doing work with: G D C
Doing work with: G E A
Doing work with: G E B
Node 4 initialised
Doing work with: G E C
Doing work with: G E D
Doing work with: G F A
Doing work with: G F B
Doing work with: G F C
Doing work with: G F D
Doing work with: G F E
>>>