<jupyter_start><jupyter_text>In this notebook, we will develop a circuit modelling the quantum teleportation process. The first step of the teleportation procedure is to prepare a Bell state shared by Alice and Bob. So let us first understand how a circuit can be used to set up a Bell state. A Bell state is given by applying the unitary operator$$C_{NOT} (H \otimes I)$$to the states of the computational basis, where the qubit on which H acts is the control qubit of the CNOT gate. So as a circuit, this looks as follows (using the Qiskit tensor product order, i.e. the leftmost qubit in the tensor product is the most significant qubit).<jupyter_code>#######################################################
# Transform the computational basis into the Bell     #
# basis.                                              #
# Input: the quantum register on which we operate     #
#######################################################
def computationalBasisToBellBasis(q,*c):
    circuit = QuantumCircuit(q,*c)
    circuit.h(q[1])
    circuit.cx(q[1], q[0])
    return circuit
q = QuantumRegister(2, "q")
circuit = computationalBasisToBellBasis(q)
drawer(circuit, scale=1.4,style=my_style)<jupyter_output><empty_output><jupyter_text>Let us first test this in isolation and see whether it works. To to so, we use the state vector simulator.<jupyter_code>def stateVectorToString(vector, places = 3):
    s = ""
    count = 0
    for i in range(len(vector)):
        #
        # First format the coefficient
        #
        x = round(vector[i], places)
        if x.imag != 0:
            coeff = "(" + format(x.real,'+') +  format(x.imag,'+') + "i)"
        else:
            coeff = format(x.real,'+') 
        if (x != 0):
            s = s + coeff + "|" + format(i, '02b') + ">"
            count = count + 1
    return s


def testBellBasis():
    backend = Aer.get_backend('statevector_simulator') 
    for x in range(4):
        q = QuantumRegister(2, "q")
        transform_circuit = computationalBasisToBellBasis(q)
        init_circuit = QuantumCircuit(q)
        initial_state = np.zeros(4, dtype=complex)
        initial_state[x] = 1.0
        init_circuit.initialize(initial_state, q)
        circuit = init_circuit + transform_circuit
        job = execute(circuit, backend)
        out = job.result().get_statevector()
        #
        # print the results
        #
        print("|" + format(x, '02b') + ">" + " ----> " + stateVectorToString(out))
testBellBasis()<jupyter_output>|00> ----> +0.707|00>+0.707|11>
|01> ----> +0.707|01>+0.707|10>
|10> ----> +0.707|00>-0.707|11>
|11> ----> +0.707|01>-0.707|10><jupyter_text>Now let us use this in the teleportation circuit. Recall that the protocol involves three qubits that we call A,B and C. For our tests, we initialize these qubits using Qiskits initialize function. We use the mappingq1 = Aq0 = Bq2 = C<jupyter_code>q = QuantumRegister(3, "q")
c0 = ClassicalRegister(1, "c0")
c1 = ClassicalRegister(1, "c1")
c2 = ClassicalRegister(1, "c2")
init_circuit = QuantumCircuit(q, c0, c1, c2)
initial_state = np.zeros(2**3, dtype=complex)
initial_state[0] = 1.0
init_circuit.initialize(initial_state, [q[0], q[1], q[2]])<jupyter_output><empty_output><jupyter_text>We now build the actual teleportation circuit. We first create an entangled Bell state shared between Alice and Bob.<jupyter_code>teleportation_circuit = computationalBasisToBellBasis(q, c0, c1)
drawer(teleportation_circuit, style=my_style)<jupyter_output><empty_output><jupyter_text>Next Alice will measure qubits A and C, i.e. qubits q1 and q2, in the Bell basis (in that order, i.e. A is the most significant qubit). To do this, we first apply a circuit that maps the Bell basis to the standard basis and then measure in the standard basis. This transformation is easy - just apply the circuit above that we have used to transform the computational basis into the Bell basis in reverse order.<jupyter_code>teleportation_circuit.barrier()
teleportation_circuit.cx(q[1], q[2])
teleportation_circuit.h(q[1])
teleportation_circuit.barrier()
teleportation_circuit.measure(q[2], c0[0])
teleportation_circuit.measure(q[1], c1[0])
teleportation_circuit.barrier()
drawer(teleportation_circuit, style=my_style)<jupyter_output><empty_output><jupyter_text>We know apply conditional operations. If the measurement of C was one, then Bob needs to apply a bit-flip operator. If the measurement of A was 1, he needs to a apply a Z operator.<jupyter_code>teleportation_circuit.x(q[0]).c_if(c0, 1)
teleportation_circuit.z(q[0]).c_if(c1, 1)
teleportation_circuit.barrier(q)
drawer(teleportation_circuit, style=my_style)<jupyter_output><empty_output><jupyter_text>And finally, we measure qubit B into bit two of the classical register.<jupyter_code>measurement_circuit = QuantumCircuit(q,c2)
measurement_circuit.measure(q[0], c2[0])
circuit = teleportation_circuit + measurement_circuit
drawer(circuit, style=my_style)<jupyter_output><empty_output><jupyter_text>Now let us test this. As our input for the qubit C is zero in this case, we expect the measurement of bit B, i.e. c2, to be zero in all cases.<jupyter_code>backend = Aer.get_backend('qasm_simulator')
job = execute(circuit, backend)
counts = job.result().get_counts()
counts<jupyter_output><empty_output><jupyter_text>Next let us test with the state 1. We add a preparational step which simply uses a Pauli X to set qubit C (q[2]) to one. As a result, the measurement of c2 should now give us one in all cases, i.e. the leftmost bit of all outcomes should be one.<jupyter_code>prep = QuantumCircuit(q)
prep.x(q[2])
prep.barrier()
test_circuit = prep + teleportation_circuit + measurement_circuit
drawer(test_circuit, style=my_style)
backend = Aer.get_backend('qasm_simulator')
job = execute(test_circuit, backend)
counts = job.result().get_counts()
counts<jupyter_output><empty_output><jupyter_text>Finally, we can do a more advanced test. Given any sequence of gates that we apply to qubit C (q[2]), we should be able to apply the inverse sequence to qubit B (q[0]) after doing the teleportation and should always get the initial state $|0\rangle$ back. Let us try this with the Hadamard gate.<jupyter_code>prep = QuantumCircuit(q)
prep.h(q[2])
#prep.u1(0.6, q[2])
prep.barrier()
post = QuantumCircuit(q)
#post.u1(-0.6, q[0])
post.h(q[0])
test_circuit = prep + teleportation_circuit + post + measurement_circuit
drawer(test_circuit, style=my_style)
backend = Aer.get_backend('qasm_simulator')
job = execute(test_circuit, backend)
counts = job.result().get_counts()
counts
print(test_circuit.qasm())<jupyter_output>OPENQASM 2.0;
include "qelib1.inc";
qreg q[3];
creg c1[1];
creg c0[1];
creg c2[1];
h q[2];
barrier q[0],q[1],q[2];
h q[1];
cx q[1],q[0];
barrier q[0],q[1],q[2];
cx q[1],q[2];
h q[1];
barrier q[0],q[1],q[2];
measure q[2] -> c0[0];
measure q[1] -> c1[0];
barrier q[0],q[1],q[2];
if(c0==1) x q[0];
if(c1==1) z q[0];
barrier q[0],q[1],q[2];
h q[0];
measure q[0] -> c2[0];
{'fraction_non_alphanumeric': 0.13553956834532374, 'fraction_numerical': 0.027338129496402876, 'mean_word_length': 4.605645161290322, 'pattern_counts': {'":': 0, '<': 39, '<?xml version=': 0, '>': 61, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '10', 'dir': 'jupyter-structured-clean-dedup', 'id': '286816', 'license': 'MIT', 'n_tokens_mistral': 2482, 'n_tokens_neox': 2292, 'n_words': 711, 'path': 'Qiskit/QiskitQuantumTeleportation.ipynb', 'repo_name': 'christianb93/QuantumComputing', 'size': '6950'}