前幾天的實驗都是基於無噪音版本的BB84通訊協定,由於現實世界總是會有一些雜訊發生,這在通訊上會產生錯誤。
在無噪音版本的協定中,我們遇到一個錯誤,我們就會立即停止通訊,但這在現實世界是很浪費的事情。
因此我們會再BB84工作流程中加入資訊協調的步驟來實現
資訊協調是 Asja 和 Balvis 之間透過經典通道進行的一種糾錯形式。
目標是修正最終金鑰字串中的錯誤,以確保兩個金鑰相同。
同時,我們需要為 QBER 值設定一定的閾值,這樣即使金鑰字串的某些部分包含錯誤,我們也可以繼續。
下面的程式將加入NoisyChannel來模擬真實環境,NoisyChannel將引入12.5%的錯誤量子位進入通訊中
# import all necessary objects and methods for quantum circuits
from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit, execute, Aer
from random import randrange
#Initial source: awards/teach_me_qiskit_2018/cryptography/Cryptography.ipynb
#Code modified to introduce noise in communication channel
def NoisyChannel(qc1, qc2, qc1_name):
''' This function takes the output of a circuit qc1 (made up only of x and
h gates, simulate noisy quantum channel, where Pauli errors (X - bit flip; Z - phase flip
will occur in qc2 and then initializes another circuit qc2 with introduce noise.
'''
# Quantum state is retrieved from qasm code of qc1
qs = qc1.qasm().split(sep=';')[4:-1]
# Process the code to get the instructions
for index, instruction in enumerate(qs):
qs[index] = instruction.lstrip()
# Parse the instructions and apply to new circuit
for instruction in qs:
if instruction[0] == 'x':
if instruction[5] == '[':
old_qr = int(instruction[6:-1])
else:
old_qr = int(instruction[5:-1])
qc2.x(qreg[old_qr])
elif instruction[0] == 'h':
if instruction[5] == '[':
old_qr = int(instruction[6:-1])
else:
old_qr = int(instruction[5:-1])
qc2.h(qreg[old_qr])
elif instruction[0] == 'm': # exclude measuring:
pass
else:
raise Exception('Unable to parse instruction')
### Introducing noise
for instruction in qs:
if randrange(7)<1:
if instruction[5] == '[':
old_qr = int(instruction[6:-1])
else:
old_qr = int(instruction[5:-1])
qc2.x(qreg[old_qr]) #apply bit-flip error
if randrange(7)<1:
if instruction[5] == '[':
old_qr = int(instruction[6:-1])
else:
old_qr = int(instruction[5:-1])
qc2.z(qreg[old_qr]) #apply phase-flip error
下面將NoisyChannel引入Sifting和QBER
def print_outcomes_in_reserve(counts): # takes a dictionary variable
for outcome in counts: # for each key-value in dictionary
reverse_outcome = ''
for i in outcome: # each string can be considered as a list of characters
reverse_outcome = i + reverse_outcome # each new symbol comes before the old symbol(s)
return reverse_outcome
qreg = QuantumRegister(16) # quantum register with 16 qubits
creg = ClassicalRegister(16) # classical register with 16 bits
send=[] #Initial bit string to send
asja_basis=[] #Register to save information about encoding basis
balvis_basis=[] #Register to save information about decoding basis
#Asja
asja = QuantumCircuit(qreg, creg, name='Asja')
for i in range(16):
bit = randrange(2)
send.append(bit)
for i, n in enumerate(send):
if n==1: asja.x(qreg[i]) # apply x-gate
for i in range(16):
r=randrange(2) #Asja randomly pick a basis
if r==0: #if bit is 0, then she encodes in Z basis
asja_basis.append('Z')
else: #if bit is 1, then she encodes in X basis
asja.h(qreg[i])
asja_basis.append('X')
balvis = QuantumCircuit(qreg, creg, name='Balvis') #Defining Balvis circuit
NoisyChannel(asja, balvis, 'Asja') #Asja sends noisy states to Balvis
#Balvis
for i in range(16):
r=randrange(2) #Balvis randomly pick a basis
if r==0: #if bit is 0, then measures in Z basis
balvis.measure(qreg[i],creg[i])
balvis_basis.append('Z')
else: #if bit is 1, then measures in X basis
balvis.h(qreg[i])
balvis.measure(qreg[i],creg[i])
balvis_basis.append('X')
job = execute(balvis,Aer.get_backend('qasm_simulator'),shots=1)
counts = job.result().get_counts(balvis)
counts = print_outcomes_in_reserve(counts)
received = list(map(int, counts))
#Sifting
asja_key=[] #Asjas register for matching rounds
balvis_key=[] #Balvis register for matching rounds
for j in range(0,len(asja_basis)): #Going through list of bases
if asja_basis[j] == balvis_basis[j]: #Comparing
asja_key.append(send[j])
balvis_key.append(received[j]) #Keeping key bit if bases matched
else:
pass #Discard round if bases mismatched
#QBER
rounds = len(asja_key)//3
errors=0
for i in range(rounds):
bit_index = randrange(len(asja_key))
tested_bit = asja_key[bit_index]
if asja_key[bit_index]!=balvis_key[bit_index]: #comparing tested rounds
errors=errors+1 #calculating errors
#removing tested bits from key strings
del asja_key[bit_index] #Use del to specify the index of the element you want to delete
del balvis_key[bit_index]
QBER=errors/rounds #calculating QBER
print("QBER value =", QBER)
print("Asja's secret key =", asja_key)
print("Balvis' secret key =", balvis_key)
參考資料:womanium教材