目錄
算法背景分析
一次測試結果分析:
代碼:一次芯片的測試
重要的假設
好芯片至少比壞芯片多一片
方法一:蠻力測試
代碼:蠻力測試
方法二:分治策略
代碼:分治策略的淘汰規則
代碼:分治策略
證明假設
算法代碼
博主自己寫的,僅僅參考了講義的僞代碼,若有錯誤請指出,謝謝。
獲取芯片
import numpy as np
import math
# 獲取芯片
def getXin(size, label=[1,0]):
"""
size: 芯片個數
label: 芯片有好有壞,1:好,0:壞
xin: 所有的芯片標籤
"""
xin = np.random.choice(label, size=size, replace=True)
if sum(xin) < size/2: # 好芯片個數至少要比壞芯片多1個
xin = 1 - xin
return xin
一次芯片的測試
# 測試芯片好壞
def test(xin, a, b, label=[1,0]):
"""
xin: 所有的芯片標籤
a,b:用芯片A測試芯片B,芯片的序號
label:芯片有好有壞,1:好,0:壞
result: 返回芯片測試結果:芯片A是好芯片,返回芯片B的真實情況;芯片A是壞芯片,隨機返回結果
"""
if xin[a] == label[0]:
return xin[b]
else:
return np.random.choice(label, size=1)[0]
分治策略的淘汰規則
def deal(xin, a, b, label=[1,0]):
# 測試
aa = test(xin, a, b)
bb = test(xin, b, a)
summ = sum([aa, bb])
if summ == 2: # 如果結果都是好,兩個要麼都是好芯片,要麼都是壞芯片,隨機留一個芯片
return np.random.choice([a,b], size=1)[0] # 隨機返回芯片序號
else: # 全部丟棄
return -1
蠻力測試
# 蠻力測試法
def rude(xin, b, label=[1,0]):
res = []
for a in range(len(xin)):
if a != b :
res.append(test(xin, a, b))
# 若測試結果多於n/2個好,芯片b是好芯片
if sum(res) > len(xin)/2:
return 1
else:
return 0
分治策略
# 分治測試法
def divide(xin, index=[], label=[1,0]):
"""
xin : 所有的芯片標籤
index: 芯片序號的列表,默認由np.arange(size)產生
label:芯片有好有壞,1:好,0:壞
"""
size = len(xin)
if len(index) != size:
index = np.arange(size) # 記錄芯片序號
while size > 3:
temp=[] # 緩存芯片序號
if size%2 == 1: # 芯片個數爲奇數
if rude(xin[index], -1) == 1:
temp.append(index[-1]) # 壞芯片淘汰,好芯片放入下一回
index = index[:-1]
size -= 1
# 兩兩測試,分組淘汰
# print(xin[index], index)
for i in range(int(size/2)):
res = deal(xin, index[i*2], index[i*2+1]) # 測試結果一好一壞,返回-1;否則返回芯片序號
if res != -1:
temp.append(res)
# print(index[i*2], index[i*2+1], temp, xin[temp])
index = temp
size = len(index)
# 遞歸結束
if size == 0:
# size=0時,中間隨機出了一點問題,打亂芯片順序再來一次
index = np.arange(len(xin))
random.shuffle(index)
i,_ = divide(xin, index)
elif size == 3:
# 測試前兩個芯片,若全好的,任取一片;否則取最後一個芯片
if deal(xin, index[0], index[1]) == -1:
i = index[2]
else:
i = np.random.choice(index[:-1], size=1)[0]
else:
# 只有1/2個,都是好芯片,隨機取一個
# 根據【重要假設:好芯片至少比壞芯片多一個】
# 缺點:當size=2時,會出現[1,0],隨機選擇會出錯
# 解決:size=2時,重新測試→這樣可能會陷入無限循環
i = np.random.choice(index, size=1)[0]
return i, xin[i]
測試
xin = getXin(10)
index, label = divide(xin)
print(xin)
print('輸出芯片序號:', index, ',現實標籤:', label)
測試結果
如果芯片個數是奇數,基本沒錯
如果芯片個數是偶數,會有0.5%的錯誤率。因爲最後的遞歸結果可能是[1,0],這樣隨機選擇有一半的錯誤率。
感覺只剩下兩個的時候,可以做一個蠻力測試。