<jupyter_start><jupyter_text>First let's see the result without any errors<jupyter_code>m0 = tobits("I like dogs") 
qubits = codificate(m0)
measurements = list()
for i in range(len(qubits)):
    qubit = qubits[i]
    qubit.measure(0,0)
    result = execute(qubit, backend, shots=1, memory=True).result()
    measurements.append(int(result.get_memory()[0]))
print(frombits(measurements))<jupyter_output>I like dogs<jupyter_text>Let's introduce some errors when meassuring and see the results<jupyter_code>m0 = tobits("I like dogs") 
qubits = codificate(m0)
measurements = list()
for i in range(len(qubits)):
    qubit = qubits[i]
    qubit.measure(0,0)
    result = execute(qubit, backend, shots=1, memory=True, noise_model=get_noise(0.2)).result()
    measurements.append(int(result.get_memory()[0]))
print(frombits(measurements))<jupyter_output>fl`ked$ÿW{<jupyter_text>Let's see how the error correction helps in this situation. First let's detect the errors to construct the matrix M<jupyter_code>for state in ['0','1']:
    qc = QuantumCircuit(1,1)
    if state[0]=='1':
        qc.x(0)  
    qc.measure(qc.qregs[0],qc.cregs[0])
    print(state+' becomes',
          execute(qc, Aer.get_backend('qasm_simulator'),noise_model=get_noise(0.2),shots=1000).result().get_counts())<jupyter_output>0 becomes {'0': 389, '1': 611}
1 becomes {'0': 593, '1': 407}<jupyter_text>Then, let's make a meassurement to get the $C_{noisy}$<jupyter_code>qubit = qubits[0]
result = execute(qubit, backend, shots=1000, memory=True, noise_model=get_noise(0.2)).result()
print(result.get_counts())<jupyter_output>{'0': 397, '1': 603}<jupyter_text>And after a little bit of linear algebra we have mitigated the error for only the first qubit$C_{noisy} = M ~ C_{ideal} \rightarrow C_{ideal} = M^{-1} C_{noisy}.$<jupyter_code>import numpy as np
import scipy.linalg as la

M = [[0.389,0.611],
    [0.593,0.407]]
Cnoisy = [[397],[603]]

Minv = la.inv(M)

Cmitigated = np.dot(Minv, Cnoisy)
print('C_mitigated =\n',Cmitigated)<jupyter_output>C_mitigated =
 [[1013.99019608]
 [   4.18627451]]<jupyter_text>If we take only the positive part and we take the floor of the numbers then we have the error correction of this qubit only. We need to repeat the process for every qubit....<jupyter_code>Cmitigated = np.floor(Cmitigated)
if(Cmitigated[1][0] < 0):
    Cmitigated[1][0] = 0
print('C_mitigated =\n',Cmitigated)<jupyter_output>C_mitigated =
 [[1013.]
 [   4.]]<jupyter_text>Insted of doing this process by hand we can use the qiskit libraries to build the matrices<jupyter_code>qr = QuantumRegister(1)
meas_calibs, state_labels = complete_meas_cal(qr=qr, circlabel='mcal')
backend = Aer.get_backend('qasm_simulator')
job = execute(meas_calibs, backend=backend, shots=1000,noise_model=get_noise(0.2))
cal_results = job.result()
meas_fitter = CompleteMeasFitter(cal_results, state_labels, circlabel='mcal')
print(meas_fitter.cal_matrix)
qubit = qubits[2]
qubit.measure(0,0)
results = execute(qubit, backend=backend, shots=10000, noise_model=get_noise(0.2),memory=True).result()
noisy_counts = count(results.get_memory())
print(noisy_counts)
Minv = la.inv(meas_fitter.cal_matrix)

Cmitigated = np.dot(Minv, np.array(list(noisy_counts.values())))
print('C_mitigated =\n',Cmitigated)<jupyter_output>C_mitigated =
 [5633.9869281 4366.0130719]<jupyter_text>Finally if we apply this process to all qubits, we'll have as a result:<jupyter_code>outputs = list()
for i in range(len(qubits)):
    qubit = qubits[i]
    qubit.measure(0,0)
    results = execute(qubit, backend=backend, shots=10000, memory=True, noise_model=get_noise(0.2)).result()
    noisy_counts = count(results.get_memory())
    Minv = la.inv(meas_fitter.cal_matrix)
    Cmitigated = np.dot(Minv, np.array(list(noisy_counts.values())))
    if(Cmitigated[0] > Cmitigated[1]):
        outputs.append('0')
    else:
        outputs.append('1')
print(frombits(''.join(outputs)))<jupyter_output>I like dogs<jupyter_text>But what if we didn't want to make operations with linear algebra? Well, qiskit has a built in function that do all these operations for us<jupyter_code>outputs = list()
meas_filter = meas_fitter.filter
for i in range(len(qubits)):
    qubit = qubits[i]
    qubit.measure(0,0)
    results = execute(qubit, backend=backend, shots=10000, memory=True, noise_model=get_noise(0.2)).result()
    noisy_counts = count(results.get_memory())
    # Results with mitigation
    mitigated_counts = meas_filter.apply(noisy_counts)
    if('1' not in mitigated_counts):
        outputs.append('0')
    elif('0' not in mitigated_counts):
        outputs.append('1')
    elif(mitigated_counts['0'] > mitigated_counts['1']):
        outputs.append('0')
    else:
        outputs.append('1')
print(frombits(''.join(outputs)))<jupyter_output>I like dogs
{'fraction_non_alphanumeric': 0.14249843063402384, 'fraction_numerical': 0.0389202762084118, 'mean_word_length': 5.6481223922114046, 'pattern_counts': {'":': 0, '<': 29, '<?xml version=': 0, '>': 30, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '9', 'dir': 'jupyter-structured-clean-dedup', 'id': '170793', 'license': 'Apache-2.0', 'n_tokens_mistral': 1895, 'n_tokens_neox': 1735, 'n_words': 372, 'path': 'Error mitigation in measurements.ipynb', 'repo_name': 'mentesniker/Quantum-error-mitigation', 'size': '4779'}