我正在撰寫這個程式,它需要54個(num1)數字并把它們放在一個串列中。然后,它從這些數字中抽取16個(num2)并形成一個串列,其中包含從 "num1 "c "num2 "的所有可能組合中選擇的16個數字的串列。然后,它取這些串列并生成4x4陣列。
我的代碼可以作業,但是運行54個數字來獲得我想要的所有陣列需要很長時間。我知道這一點,因為我已經用20到40個數字對代碼進行了測驗,并對其進行了計時。
20 numbers = 0.000055 minutes
30數字=0.045088分鐘
40數字=17.46944分鐘
使用我得到的所有20個點的測驗資料,我建立了一個數學模型來預測運行54個數字需要多長時間,我得到了1740分鐘=29小時。與預測38小時的該代碼的v1版相比,這已經是一個進步了,而v0版則實際上使我的機器崩潰。
我正在聯系你,以嘗試使其運行得更快。該程式甚至不需要占用記憶體。我有8GB的記憶體和一個核心i7處理器,它根本沒有拖慢我的機器。實際上,與我以前的版本相比,它運行得非常流暢,我的電腦甚至崩潰過幾次。
你們認為有什么辦法嗎?我目前正在取樣以減少處理時間,但我希望完全不取樣,如果可能的話。我甚至沒有列印陣列來減少處理時間,我只是列印一個計數器來查看我產生了多少個組合。
這是代碼:
import numpy as np
import itertools
from itertools import combinations
from itertools import islice
from random import sample
num1 = 30 #ideally this is 54, just using 30 now so you can test it.
num2 = 16
steps = 1454226 #代表 "num1 "c "num2 "的1%,只是為了減少測驗的處理時間。
nums=list()
for i in range(1,num1 1)。
nums.append(i)
#print ("nums: ", nums) #Just to ensure that I am indeed using numbers from 1 to num1.
vun=list()
tabl=list()
counter = 0
combin = islice(itertools.combinations(nums, num2),0,None, steps)
for i in set(combin)。
vun.append(sample(i,num2))
counter = counter 1 1
p1=i[0];p2=i[1];p3=i[2]; p4=i[3] 。 p5=i[4];p6=i[5] 。 p7=i[6]; p8=i[7]; p9=i[8]
p10=i[9];p11=i[10]; p12=i[11]。 p13=i[12];p14=i[13];p15=i[14]; p16=i[15]
tun = np.array ([(p1,p2,p3,p4),(p5,p6,p7,p8),(p9,p10,p11,p12),(p13,p14,p15,p16)] )
tabl.append(tun)
# print ("TABL:" ,tabl)
# print ("vun: ", vun)
print ("combinations:", counter)
我用這段代碼得到的輸出是:
combinations: 101
事實上,這個數字將是2.109492366(10)13或至少是1%。只要它運行54x16并且不需要29個小時就可以了。
uj5u.com熱心網友回復:
主要的低效率來自于生成所有的組合(itertools.combinations(nums, num2)),只是把其中的大部分扔掉。
另一種方法是隨機生成組合,確保沒有重復的組合。
import itertools
import random
def random_combination(iterable, r) 。
"從itertools.combinations(iterable, r)中隨機選擇"。
pool = tuple(iterable)
n = len(pool)
indices = sorted(random.sample(range(n), r)
return tuple(pool[i] fori in indices)
items = list(range(1, 55))
samples = set()
while len(samples) < 100_000:
samples = random_combination(items, 16)
samples.add(sample)
for sample in samples:
board = list(sample)
random.shuffle(board)
board = [board[0:4], board[4: 8], board[8: 12], board[12: 16] ]
print(" done")
這使用了這個問題答案中的random_combination函式,該函式又來自itertools檔案。
至少在我的機器上,這段代碼在大約十秒內生成了100,000個獨特的4x4樣本。
一些說明:
- 每個樣本都是一個元組,并且對條目進行了排序;這意味著我們可以將它們存盤在一個集合中并避免重復。
- 由于第一點,我們在從它創建一個4x4板之前對每個樣本進行了洗牌;后面的代碼沒有對這些板做任何事情,但我想把它們包括進來,以獲得對時間的感覺。
- 如果你要對很大一部分空間進行采樣,有可能會出現大量的哈希碰撞,但無論如何這都是不可行的,因為這將涉及大量的資料(見下文)。
我認為你在這里試圖實作的目標有一些混淆。
54C16 = 2.1 x 10^13 ......為所有這些點存盤16個8位整數將需要2.7 x 10^15位元,也就是337.5兆位元組。這已經超出了本地磁盤所能存盤的容量。
因此,如果要覆寫1%的空間,將需要超過3TB的空間......也許在推動下有可能存盤在磁盤上。你在問題中暗示,你希望覆寫這一比例的空間。顯然,在8GB的記憶體中這是不可能的。
uj5u.com熱心網友回復:
僅僅計算組合的數量是微不足道的,因為它是只是一個公式:
import math
math.comb(30, 16)
# 145422675;/span>
math.comb(54, 16)
# 21094923659355。
麻煩的是,在我的機器上存盤30個案例中的16個案例的結果需要大約64GB的記憶體。你可能會有,但可能不會像我一樣有那么多的記憶體閑置。16/54案例需要大約9.3PB的記憶體,而現代架構都不支持這種記憶體。
你將需要采取兩種方法中的一種:
。限制在 30 分之 16 的情況下,并且不將任何結果存盤到
vun或tabl。優點。在我的測驗中,可以在5分鐘內完成作業。
缺點:對于54中的16種情況完全不起作用,沒有額外的處理是實際的
做一個蒙特卡洛模擬:生成隨機組合,直到某個大的但可達到的樣本數,并對這些組合進行計算。
優點。速度快,并支持16個30,和16個54,可能具有相同的時間性能
缺點:結果將被視為是對的。
缺點:結果會有一些隨機變化,這取決于隨機種子,應進行統計學處理以獲得有效性的置信區間。
注意:用于置信區間的公式取決于您打算用這些數字做哪些實際的數學運算,如果您只是在尋找一個估計值,那么平均數是一個好的開始。
我強烈建議選擇(2),蒙特卡洛模擬。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/326834.html
標籤:
上一篇:錯誤:呼叫未定義的方法CodeIgniter\Database\MySQLi\Connection::select()
