from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister, Aer, assemble, transpile

import qiskit.tools.jupyter
from qiskit.test.mock import FakeTokyo

code = QuantumRegister(5,'code')
syn = QuantumRegister(4,'syn')
out = ClassicalRegister(4,'output')

backend = FakeTokyo()

error_qubits = [0,4]

# qc_syn
qc_syn = QuantumCircuit(code,syn,out)

# left ZZZ
qc_syn.cx(code[0],syn[1])
qc_syn.cx(code[2],syn[1])
qc_syn.cx(code[3],syn[1])
qc_syn.barrier()

# right ZZZ
qc_syn.cx(code[2],syn[2])
qc_syn.cx(code[4],syn[2])
qc_syn.cx(code[1],syn[0]) #
qc_syn.cx(syn[0],syn[2])  #
qc_syn.cx(code[1],syn[0]) #
qc_syn.barrier()

# top XXX
qc_syn.h(syn[0])
qc_syn.cx(syn[0],code[0])
qc_syn.cx(syn[0],code[1])
qc_syn.cx(syn[0],code[2])
qc_syn.h(syn[0])
qc_syn.barrier()

# bottom XXX
qc_syn.h(syn[3])
qc_syn.cx(syn[3],code[2])
qc_syn.cx(syn[3],code[3])
qc_syn.cx(syn[3],code[4])
qc_syn.h(syn[3])
qc_syn.barrier()


# measure the auxilliary qubits
qc_syn.measure(syn,out)



# qc_init
qc_init = QuantumCircuit(code,syn,out)

qc_init.h(syn[0])
qc_init.cx(syn[0],code[0])
qc_init.cx(syn[0],code[1])
qc_init.cx(syn[0],code[2])
qc_init.cx(code[2],syn[0])

qc_init.h(syn[3])
qc_init.cx(syn[3],code[2])
qc_init.cx(syn[3],code[3])
qc_init.cx(syn[3],code[4])
qc_init.cx(code[4],syn[3])

qc_init.barrier()


# initial layout
initial_layout = [0,2,6,10,12,1,5,7,11]

# qc_syn
qc_syn = QuantumCircuit(code,syn,out)

# left ZZZ
qc_syn.cx(code[0],syn[1])
qc_syn.cx(code[2],syn[1])
qc_syn.cx(code[3],syn[1])
qc_syn.barrier()

# right ZZZ
qc_syn.cx(code[2],syn[2])
qc_syn.cx(code[4],syn[2])
qc_syn.cx(code[1],syn[0])
qc_syn.cx(syn[0],syn[2])
qc_syn.cx(code[1],syn[0])
qc_syn.barrier()

# top XXX
qc_syn.h(syn[0])
qc_syn.cx(syn[0],code[0])
qc_syn.cx(syn[0],code[1])
qc_syn.cx(syn[0],code[2])
qc_syn.h(syn[0])
qc_syn.barrier()

# bottom XXX
qc_syn.h(syn[3])
qc_syn.cx(syn[3],code[2])
qc_syn.cx(syn[3],code[3])
qc_syn.cx(syn[3],code[4])
qc_syn.h(syn[3])
qc_syn.barrier()


# measure the auxilliary qubits
qc_syn.measure(syn,out)



# qc_init
qc_init = QuantumCircuit(code,syn,out)



# initial layout
initial_layout = [0,2,6,10,12,1,5,7,11]

# qc_syn
qc_syn = QuantumCircuit(code,syn,out)
qc_syn.measure(syn,out)


# qc_init
qc_init = QuantumCircuit(code,syn,out)

qc_init.h(syn[0])
qc_init.cx(syn[0],code[0])
qc_init.cx(syn[0],code[1])
qc_init.cx(syn[0],code[2])
qc_init.cx(code[2],syn[0])

qc_init.h(syn[3])
qc_init.cx(syn[3],code[2])
qc_init.cx(syn[3],code[3])
qc_init.cx(syn[3],code[4])
qc_init.cx(code[4],syn[3])

qc_init.barrier()


# initial layout
initial_layout = [0,2,6,10,12,1,5,7,11]

# qc_syn
qc_syn = QuantumCircuit(code,syn,out)

# left ZZZ
qc_syn.cx(code[0],syn[1])
qc_syn.cx(code[2],syn[1])
qc_syn.cx(code[3],syn[1])
qc_syn.barrier()

# right ZZZ
qc_syn.cx(code[2],syn[2])
qc_syn.cx(code[4],syn[2])
qc_syn.cx(code[1],syn[2])
qc_syn.barrier()

# top XXX
qc_syn.h(syn[0])
qc_syn.cx(syn[0],code[0])
qc_syn.cx(syn[0],code[1])
qc_syn.cx(syn[0],code[2])
qc_syn.h(syn[0])
qc_syn.barrier()

# bottom XXX
qc_syn.h(syn[3])
qc_syn.cx(syn[3],code[2])
qc_syn.cx(syn[3],code[3])
qc_syn.cx(syn[3],code[4])
qc_syn.h(syn[3])
qc_syn.barrier()


# measure the auxilliary qubits
qc_syn.measure(syn,out)



# qc_init
qc_init = QuantumCircuit(code,syn,out)

qc_init.h(code[0])
qc_init.cx(code[0],code[1])
qc_init.cx(code[0],code[2])

qc_init.h(code[3])
qc_init.cx(code[3],code[2])
qc_init.cx(code[3],code[4])

qc_init.barrier()


# initial layout
initial_layout = list(range(9))