from qiskit import *

p = 0.01
P = 3 * p**2 * (1-p) + p**3
print('Probability of a single reply being garbled:',p)
print('Probability of a the majority of three replies being garbled:',P)

from qiskit.providers.aer.noise import NoiseModel
from qiskit.providers.aer.noise.errors import pauli_error, depolarizing_error

def get_noise(p_meas,p_gate):

    error_meas = pauli_error([('X',p_meas), ('I', 1 - p_meas)])
    error_gate1 = depolarizing_error(p_gate, 1)
    error_gate2 = error_gate1.tensor(error_gate1)

    noise_model = NoiseModel()
    noise_model.add_all_qubit_quantum_error(error_meas, "measure") # measurement error is applied to measurements
    noise_model.add_all_qubit_quantum_error(error_gate1, ["x"]) # single qubit gate error is applied to x gates
    noise_model.add_all_qubit_quantum_error(error_gate2, ["cx"]) # two qubit gate error is applied to cx gates
        
    return noise_model

noise_model = get_noise(0.01,0.01)

qc0 = QuantumCircuit(3,3,name='0') # initialize circuit with three qubits in the 0 state

qc0.measure(qc0.qregs[0],qc0.cregs[0]) # measure the qubits

# run the circuit with th noise model and extract the counts
counts = execute( qc0, Aer.get_backend('qasm_simulator'),noise_model=noise_model,shots=10000).result().get_counts()

print(counts)

qc1 = QuantumCircuit(3,3,name='0') # initialize circuit with three qubits in the 0 state
qc1.x(qc1.qregs[0]) # flip each 0 to 1

qc1.measure(qc1.qregs[0],qc1.cregs[0]) # measure the qubits

# run the circuit with th noise model and extract the counts
counts = execute( qc1, Aer.get_backend('qasm_simulator'),noise_model=noise_model,shots=10000).result().get_counts()

print(counts)

noise_model = get_noise(0.5,0.0)
counts = execute( qc1, Aer.get_backend('qasm_simulator'),noise_model=noise_model,shots=10000).result().get_counts()
print(counts)

from qiskit import *
cq = QuantumRegister(2,'code_qubit')
lq = QuantumRegister(1,'ancilla_qubit')
sb = ClassicalRegister(1,'syndrome_bit')
qc = QuantumCircuit(cq,lq,sb)
qc.cx(cq[0],lq[0])
qc.cx(cq[1],lq[0])
qc.measure(lq,sb)
print(qc)

qc_init = QuantumCircuit(cq)

print(qc_init+qc)

counts = execute( qc_init+qc, Aer.get_backend('qasm_simulator'),shots=10000).result().get_counts()
print('\nResults:',counts)

qc_init = QuantumCircuit(cq)
qc_init.x(cq)

print(qc_init+qc)

counts = execute( qc_init+qc, Aer.get_backend('qasm_simulator'),shots=10000).result().get_counts()
print('\nResults:',counts)

qc_init = QuantumCircuit(cq)
qc_init.h(cq[0])
qc_init.cx(cq[0],cq[1])


print(qc_init+qc)

counts = execute( qc_init+qc, Aer.get_backend('qasm_simulator'),shots=10000).result().get_counts()
print('\nResults:',counts)

qc_init = QuantumCircuit(cq)
qc_init.h(cq[0])
qc_init.cx(cq[0],cq[1])
qc_init.x(cq[0])


print(qc_init+qc)

counts = execute( qc_init+qc, Aer.get_backend('qasm_simulator'),shots=10000).result().get_counts()
print('\nResults:',counts)

from qiskit.ignis.verification.topological_codes import RepetitionCode
from qiskit.ignis.verification.topological_codes import lookuptable_decoding

n = 3

T = 1

code = RepetitionCode(n,T)

code.qubit_registers

code.code_qubit

for log in ['0','1']:
    print('\n========= logical',log,'=========\n')
    print( code.circuit[log] )

circuits = code.get_circuit_list()
job = execute( circuits, Aer.get_backend('qasm_simulator') )
for log in ['0','1']:
    print('\nLogical',log,':',job.result().get_counts(log))

code = RepetitionCode(n,4)

circuits = code.get_circuit_list()
job = execute( circuits, Aer.get_backend('qasm_simulator') )
for log in ['0','1']:
    print('\nLogical',log,':',job.result().get_counts(log))

code = RepetitionCode(5,4)

circuits = code.get_circuit_list()
job = execute( circuits, Aer.get_backend('qasm_simulator') )
for log in ['0','1']:
    print('\nLogical',log,':',job.result().get_counts(log))

code = RepetitionCode(n,4)

circuits = code.get_circuit_list()
job = execute( circuits, Aer.get_backend('qasm_simulator') )
for log in ['0','1']:
    print('\nLogical',log,':',job.result().get_counts(log))

code = RepetitionCode(3,1)

noise_model = get_noise(0.2,0.2)

circuits = code.get_circuit_list()
job = execute( circuits, Aer.get_backend('qasm_simulator'), noise_model=noise_model )
raw_results = {}
for log in ['0','1']:
    raw_results[log] = job.result().get_counts(log)
    print('\n========= logical',log,'=========\n')
    print(raw_results[log])

job = execute( circuits, Aer.get_backend('qasm_simulator'), noise_model=noise_model, shots=10000 )
table_results = {}
for log in ['0','1']:
    table_results[log] = job.result().get_counts(log)

P = lookuptable_decoding(raw_results,table_results)
print('P =',P)

code = RepetitionCode(3,1)

noise_model = get_noise(0.1,0.1)

circuits = code.get_circuit_list()

job = execute( circuits, Aer.get_backend('qasm_simulator'), noise_model=noise_model )
raw_results = {}
for log in ['0','1']:
    raw_results[log] = job.result().get_counts(log)

job = execute( circuits, Aer.get_backend('qasm_simulator'), noise_model=noise_model, shots=10000 )
table_results = {}
for log in ['0','1']:
    table_results[log] = job.result().get_counts(log)
    
P = lookuptable_decoding(raw_results,table_results)
print('P =',P)

