예제 #1
0
    def TestNoise(self):
        """
        Test for Processor with noise
        """
        # setup and fidelity without noise
        init_state = qubit_states(2, [0, 0, 0, 0])
        tlist = np.array([0., np.pi/2.])
        a = destroy(2)
        proc = Processor(N=2)
        proc.add_control(sigmax(), targets=1)
        proc.pulses[0].tlist = tlist
        proc.pulses[0].coeff = np.array([1])
        result = proc.run_state(init_state=init_state)
        assert_allclose(
            fidelity(result.states[-1], qubit_states(2, [0, 1, 0, 0])),
            1, rtol=1.e-7)

        # decoherence noise
        dec_noise = DecoherenceNoise([0.25*a], targets=1)
        proc.add_noise(dec_noise)
        result = proc.run_state(init_state=init_state)
        assert_allclose(
            fidelity(result.states[-1], qubit_states(2, [0, 1, 0, 0])),
            0.981852, rtol=1.e-3)

        # white random noise
        proc.noise = []
        white_noise = RandomNoise(0.2, np.random.normal, loc=0.1, scale=0.1)
        proc.add_noise(white_noise)
        result = proc.run_state(init_state=init_state)
예제 #2
0
    def test_numerical_evo(self):
        """
        Test of run_state with qutip solver
        """
        N = 3
        qc = QubitCircuit(N)
        qc.add_gate("RX", targets=[0], arg_value=np.pi / 2)
        qc.add_gate("CNOT", targets=[0], controls=[1])
        qc.add_gate("ISWAP", targets=[2, 1])
        qc.add_gate("CNOT", targets=[0], controls=[2])
        # qc.add_gate("SQRTISWAP", targets=[0, 2])

        with warnings.catch_warnings(record=True):
            test = DispersivecQED(N, g=0.1)
        tlist, coeff = test.load_circuit(qc)

        # test numerical run_state
        qu0 = rand_ket(2**N)
        qu0.dims = [[2] * N, [1] * N]
        rho0 = tensor(basis(10, 0), qu0)
        qu1 = gate_sequence_product([qu0] + qc.propagators())
        result = test.run_state(rho0=rho0,
                                analytical=False,
                                options=Options(store_final_state=True,
                                                nsteps=50000)).final_state
        assert_allclose(fidelity(result, tensor(basis(10, 0), qu1)),
                        1.,
                        rtol=1e-2,
                        err_msg="Numerical run_state fails in DispersivecQED")
예제 #3
0
    def test_simple_hadamard(self):
        """
        Test for optimizing a simple hadamard gate
        """
        N = 1
        H_d = sigmaz()
        H_c = sigmax()
        qc = QubitCircuit(N)
        qc.add_gate("SNOT", 0)

        # test load_circuit, with verbose info
        num_tslots = 10
        evo_time = 10
        test = OptPulseProcessor(N, drift=H_d)
        test.add_control(H_c, targets=0)
        tlist, coeffs = test.load_circuit(qc,
                                          num_tslots=num_tslots,
                                          evo_time=evo_time,
                                          verbose=True)

        # test run_state
        rho0 = qubit_states(1, [0])
        plus = (qubit_states(1, [0]) + qubit_states(1, [1])).unit()
        result = test.run_state(rho0)
        assert_allclose(fidelity(result.states[-1], plus), 1, rtol=1.0e-6)

        # test add/remove ctrl
        test.add_control(sigmay())
        test.remove_pulse(0)
        assert_(len(test.pulses) == 1,
                msg="Method of remove_pulse could be wrong.")
        assert_allclose(test.drift.drift_hamiltonians[0].qobj, H_d)
        assert_(sigmay() in test.ctrls,
                msg="Method of remove_pulse could be wrong.")
예제 #4
0
    def test_multi_gates(self):
        N = 2
        H_d = tensor([sigmaz()]*2)
        H_c = []

        test = OptPulseProcessor(N, H_d, H_c)
        test.add_ctrl(sigmax(), cyclic_permutation=True)
        test.add_ctrl(sigmay(), cyclic_permutation=True)
        test.add_ctrl(tensor([sigmay(), sigmay()]))

        # qubits circuit with 3 gates
        setting_args = {"SNOT": {"num_tslots": 10, "evo_time": 1},
                        "SWAP": {"num_tslots": 30, "evo_time": 3},
                        "CNOT": {"num_tslots": 30, "evo_time": 3}}
        qc = QubitCircuit(N)
        qc.add_gate("SNOT", 0)
        qc.add_gate("SWAP", targets=[0, 1])
        qc.add_gate('CNOT', controls=1, targets=[0])
        test.load_circuit(qc, setting_args=setting_args,
                          merge_gates=False)

        rho0 = rand_ket(4)  # use random generated ket state
        rho0.dims = [[2, 2], [1, 1]]
        U = gate_sequence_product(qc.propagators())
        rho1 = U * rho0
        result = test.run_state(rho0)
        assert_(fidelity(result.states[-1], rho1) > 1-1.0e-6)
예제 #5
0
    def test_multi_qubits(self):
        """
        Test for multi-qubits system.
        """
        N = 3
        H_d = tensor([sigmaz()] * 3)
        H_c = []

        # test empty ctrls
        num_tslots = 30
        evo_time = 10
        test = OptPulseProcessor(N)
        test.add_drift(H_d, [0, 1, 2])
        test.add_control(tensor([sigmax(), sigmax()]), cyclic_permutation=True)
        # test periodically adding ctrls
        sx = sigmax()
        iden = identity(2)
        # print(test.ctrls)
        # print(Qobj(tensor([sx, iden, sx])))
        assert_(Qobj(tensor([sx, iden, sx])) in test.ctrls)
        assert_(Qobj(tensor([iden, sx, sx])) in test.ctrls)
        assert_(Qobj(tensor([sx, sx, iden])) in test.ctrls)
        test.add_control(sigmax(), cyclic_permutation=True)
        test.add_control(sigmay(), cyclic_permutation=True)

        # test pulse genration for cnot gate, with kwargs
        qc = [tensor([identity(2), cnot()])]
        test.load_circuit(qc,
                          num_tslots=num_tslots,
                          evo_time=evo_time,
                          min_fid_err=1.0e-6)
        rho0 = qubit_states(3, [1, 1, 1])
        rho1 = qubit_states(3, [1, 1, 0])
        result = test.run_state(rho0, options=Options(store_states=True))
        assert_(fidelity(result.states[-1], rho1) > 1 - 1.0e-6)
예제 #6
0
    def test_simple_hadamard(self):
        N = 1
        H_d = sigmaz()
        H_c = [sigmax()]
        qc = QubitCircuit(N)
        qc.add_gate("SNOT", 0)

        # test load_circuit, with verbose info
        num_tslots = 10
        evo_time = 10
        test = OptPulseProcessor(N, H_d, H_c)
        tlist, coeffs = test.load_circuit(
            qc, num_tslots=num_tslots, evo_time=evo_time, verbose=True)

        # test run_state
        rho0 = qubit_states(1, [0])
        plus = (qubit_states(1, [0]) + qubit_states(1, [1])).unit()
        result = test.run_state(rho0)
        assert_allclose(fidelity(result.states[-1], plus), 1, rtol=1.0e-6)

        # test add/remove ctrl
        test.add_ctrl(sigmay())
        test.remove_ctrl(0)
        assert_(
            len(test.ctrls) == 1,
            msg="Method of remove_ctrl could be wrong.")
        assert_allclose(test.drift, H_d)
        assert_(
            sigmay() in test.ctrls,
            msg="Method of remove_ctrl could be wrong.")
예제 #7
0
    def test_numerical_evo(self):
        """
        Test run_state with qutip solver
        """
        N = 3
        qc = QubitCircuit(N)
        qc.add_gate("RX", targets=[0], arg_value=np.pi / 2)
        qc.add_gate("CNOT", targets=[0], controls=[1])
        qc.add_gate("ISWAP", targets=[2, 1])
        qc.add_gate("CNOT", targets=[0], controls=[2])
        qc.add_gate("SQRTISWAP", targets=[0, 2])
        qc.add_gate("RZ", arg_value=np.pi / 2, targets=[1])

        # CircularSpinChain
        test = CircularSpinChain(N)
        tlist, coeffs = test.load_circuit(qc)

        init_state = rand_ket(2**N)
        init_state.dims = [[2] * N, [1] * N]
        rho1 = gate_sequence_product([init_state] + qc.propagators())
        result = test.run_state(
            init_state=init_state,
            analytical=False,
            options=Options(store_final_state=True)).final_state
        assert_allclose(
            fidelity(result, rho1),
            1.,
            rtol=1e-6,
            err_msg="Numerical run_state fails in CircularSpinChain")

        # LinearSpinChain
        test = LinearSpinChain(N)
        tlist, coeffs = test.load_circuit(qc)

        init_state = rand_ket(2**N)
        init_state.dims = [[2] * N, [1] * N]
        rho1 = gate_sequence_product([init_state] + qc.propagators())
        result = test.run_state(
            init_state=init_state,
            analytical=False,
            options=Options(store_final_state=True)).final_state
        assert_allclose(fidelity(result, rho1),
                        1.,
                        rtol=1e-6,
                        err_msg="Numerical run_state fails in LinearSpinChain")
예제 #8
0
    def test_multi_qubits(self):
        N = 3
        H_d = tensor([sigmaz()]*3)
        H_c = []

        # test empty ctrls
        num_tslots = 30
        evo_time = 10
        test = OptPulseProcessor(N, H_d, H_c)
        test.add_ctrl(tensor([sigmax(), sigmax()]),
                      cyclic_permutation=True)

        # test periodically adding ctrls
        sx = sigmax()
        iden = identity(2)
        assert_(Qobj(tensor([sx, iden, sx])) in test.ctrls)
        assert_(Qobj(tensor([iden, sx, sx])) in test.ctrls)
        assert_(Qobj(tensor([sx, sx, iden])) in test.ctrls)
        test.add_ctrl(sigmax(), cyclic_permutation=True)
        test.add_ctrl(sigmay(), cyclic_permutation=True)

        # test pulse genration for cnot gate, with kwargs
        qc = [tensor([identity(2), cnot()])]
        test.load_circuit(qc, num_tslots=num_tslots,
                          evo_time=evo_time, min_fid_err=1.0e-6)
        rho0 = qubit_states(3, [1, 1, 1])
        rho1 = qubit_states(3, [1, 1, 0])
        result = test.run_state(
            rho0, options=Options(store_states=True))
        print(result.states[-1])
        print(rho1)
        assert_(fidelity(result.states[-1], rho1) > 1-1.0e-6)

        # test save and read coeffs
        test.save_coeff("qutip_test_multi_qubits.txt")
        test2 = OptPulseProcessor(N, H_d, H_c)
        test2.drift = test.drift
        test2.ctrls = test.ctrls
        test2.read_coeff("qutip_test_multi_qubits.txt")
        os.remove("qutip_test_multi_qubits.txt")
        assert_(np.max((test.coeffs-test2.coeffs)**2) < 1.0e-13)
        result = test2.run_state(rho0,)
        assert_(fidelity(result.states[-1], rho1) > 1-1.0e-6)
예제 #9
0
 def TestUserNoise(self):
     """
     Test for the user-defined noise object
     """
     dr_noise = DriftNoise(sigmax())
     proc = Processor(1)
     proc.add_noise(dr_noise)
     proc.tlist = np.array([0, np.pi / 2.])
     result = proc.run_state(rho0=basis(2, 0))
     assert_allclose(fidelity(result.states[-1], basis(2, 1)),
                     1,
                     rtol=1.0e-6)
예제 #10
0
    def test_analytical_evo(self):
        """
        Test of run_state with exp(-iHt)
        """
        N = 3
        qc = QubitCircuit(N)
        qc.add_gate("RX", targets=[0], arg_value=np.pi/2)
        qc.add_gate("CNOT", targets=[0], controls=[1])
        qc.add_gate("ISWAP", targets=[2, 1])
        qc.add_gate("CNOT", targets=[0], controls=[2])
        qc.add_gate("SQRTISWAP", targets=[0, 2])
        qc.add_gate("RZ", arg_value=np.pi/2, targets=[1])

        # CircularSpinChain
        test = CircularSpinChain(N)
        tlist, coeffs = test.load_circuit(qc)

        rho0 = rand_ket(2**N)
        rho0.dims = [[2]*N, [1]*N]
        rho1 = gate_sequence_product([rho0] + qc.propagators())
        U_list = test.run_state(
            rho0=rho0, analytical=True)
        result = gate_sequence_product(U_list)
        assert_allclose(
            fidelity(result, rho1), 1., rtol=1e-6,
            err_msg="Analytical run_state fails in CircularSpinChain")

        # LinearSpinChain
        test = LinearSpinChain(N)
        tlist, coeffs = test.load_circuit(qc)

        rho0 = rand_ket(2**N)
        rho0.dims = [[2]*N, [1]*N]
        rho1 = gate_sequence_product([rho0] + qc.propagators())
        U_list = test.run_state(
            rho0=rho0, analytical=True)
        result = gate_sequence_product(U_list)
        assert_allclose(
            fidelity(result, rho1), 1., rtol=1e-6,
            err_msg="Analytical run_state fails in LinearSpinChain")
예제 #11
0
 def TestChooseSolver(self):
     # setup and fidelity without noise
     init_state = qubit_states(2, [0, 0, 0, 0])
     tlist = np.array([0., np.pi/2.])
     a = destroy(2)
     proc = Processor(N=2)
     proc.add_control(sigmax(), targets=1)
     proc.pulses[0].tlist = tlist
     proc.pulses[0].coeff = np.array([1])
     result = proc.run_state(init_state=init_state, solver="mcsolve")
     assert_allclose(
         fidelity(result.states[-1], qubit_states(2, [0, 1, 0, 0])),
         1, rtol=1.e-7) 
예제 #12
0
 def test_user_defined_noise(self):
     """
     Test for the user-defined noise object
     """
     dr_noise = DriftNoise(sigmax())
     proc = Processor(1)
     proc.add_noise(dr_noise)
     tlist = np.array([0, np.pi / 2.])
     proc.add_pulse(Pulse(identity(2), 0, tlist, False))
     result = proc.run_state(init_state=basis(2, 0))
     assert_allclose(fidelity(result.states[-1], basis(2, 1)),
                     1,
                     rtol=1.0e-6)
예제 #13
0
    def TestNoise(self):
        """
        Test for Processor with noise
        """
        # setup and fidelity without noise
        rho0 = qubit_states(2, [0, 0, 0, 0])
        tlist = np.array([0., np.pi / 2.])
        a = destroy(2)
        proc = Processor(N=2)
        proc.tlist = tlist
        proc.coeffs = np.array([1]).reshape((1, 1))
        proc.add_ctrl(sigmax(), targets=1)
        result = proc.run_state(rho0=rho0)
        assert_allclose(fidelity(result.states[-1],
                                 qubit_states(2, [0, 1, 0, 0])),
                        1,
                        rtol=1.e-7)

        # decoherence noise
        dec_noise = DecoherenceNoise([0.25 * a], targets=1)
        proc.add_noise(dec_noise)
        result = proc.run_state(rho0=rho0)
        assert_allclose(fidelity(result.states[-1],
                                 qubit_states(2, [0, 1, 0, 0])),
                        0.981852,
                        rtol=1.e-3)

        # white noise with internal/external operators
        proc.noise = []
        white_noise = RandomNoise(loc=0.1, scale=0.1)
        proc.add_noise(white_noise)
        result = proc.run_state(rho0=rho0)

        proc.noise = []
        white_noise = RandomNoise(loc=0.1, scale=0.1, ops=sigmax(), targets=1)
        proc.add_noise(white_noise)
        result = proc.run_state(rho0=rho0)
예제 #14
0
    def testDrift(self):
        """
        Test for the drift Hamiltonian
        """
        processor = Processor(N=1)
        processor.add_drift(sigmax() / 2, 0)
        tlist = np.array([0., np.pi, 2 * np.pi, 3 * np.pi])
        processor.add_pulse(Pulse(None, None, tlist, False))
        ideal_qobjevo, _ = processor.get_qobjevo(noisy=True)
        assert_equal(ideal_qobjevo.cte, sigmax() / 2)

        init_state = basis(2)
        propagators = processor.run_analytically()
        analytical_result = init_state
        for unitary in propagators:
            analytical_result = unitary * analytical_result
        fid = fidelity(sigmax() * init_state, analytical_result)
        assert ((1 - fid) < 1.0e-6)
예제 #15
0
    def _fidelity(self, gates_list, used_points):
        num_qubits = len(used_points)
        q1 = QubitCircuit(num_qubits)
        q2 = QubitCircuit(num_qubits)
        #print(gates_list)
        q1.user_gates = {
            "UCNOT": mg.user_cnot,
            "RCNOT": mg.cnot_swap,
            "USWAP": mg.user_swap
        }
        q2.user_gates = {
            "UCNOT": mg.user_cnot,
            "RCNOT": mg.cnot_swap,
            "USWAP": mg.user_swap
        }
        edges = list(nx.utils.pairwise(used_points))
        #print(edges)

        i = 0
        for gate in gates_list:
            if gate == "H":
                q1.add_gate("SNOT", i)
                q2.add_gate("SNOT", i)

            elif gate == "CNOT":
                q1.add_gate("UCNOT", targets=[i, i + 1], arg_value=1)
                q2.add_gate("UCNOT",
                            targets=[i, i + 1],
                            arg_value=self.noise_dict[edges[i]])
                i += 1

            elif gate == "SWAP":
                q1.add_gate("USWAP", targets=[i, i + 1], arg_value=1)
                q2.add_gate("USWAP",
                            targets=[i, i + 1],
                            arg_value=self.noise_dict[edges[i]])
                i += 1
        #print(q1.gates)
        y = gate_sequence_product(q1.propagators()) * tensor(
            [basis(2, 0)] * num_qubits)
        y2 = gate_sequence_product(q2.propagators()) * tensor(
            [basis(2, 0)] * num_qubits)
        return fidelity(y, y2)
예제 #16
0
    def test_analytical_evo(self):
        """
        Test of run_state with exp(-iHt)
        """
        N = 3

        qc = QubitCircuit(N)
        qc.add_gate("ISWAP", targets=[0, 1])
        qc.add_gate("RZ", arg_value=np.pi / 2, arg_label=r"\pi/2", targets=[1])
        qc.add_gate("RX", arg_value=np.pi / 2, arg_label=r"\pi/2", targets=[0])
        U_ideal = gate_sequence_product(qc.propagators())

        rho0 = rand_ket(2**N)
        rho0.dims = [[2] * N, [1] * N]
        rho1 = gate_sequence_product([rho0] + qc.propagators())

        p = DispersivecQED(N, correct_global_phase=True)
        U_list = p.run_state(rho0=rho0, qc=qc, analytical=True)
        result = gate_sequence_product(U_list)
        assert_allclose(fidelity(result, rho1),
                        1.,
                        rtol=1e-2,
                        err_msg="Analytical run_state fails in DispersivecQED")
# target state 2
#psi_targ = basis(2, 1) # ground state
psi_targ = basis(2, 0)  # excited state
#psi_targ = psi0

rho_targ = ket2dm(psi_targ)
print("rho_targ:\n{}\n".format(rho_targ))
rho_targ_vec = operator_to_vector(rho_targ)
print("rho_targ_vec:\n{}\n".format(rho_targ_vec))

#print("L0:\n{}\n".format(L0))
#print("LC_x:\n{}\n".format(LC_x))
#print("LC_y:\n{}\n".format(LC_y))
#print("LC_z:\n{}\n".format(LC_z))

print("Fidelity rho0, rho_targ: {}".format(fidelity(rho0, rho_targ)))

rho_diff = (rho0 - rho_targ)
fid_err = 0.5 * (rho_diff.dag() * rho_diff).tr()
print("fid_err: {}, fid: {}".format(fid_err, np.sqrt(1 - fid_err)))

rho0_evo_map = vector_to_operator(E_targ * rho0_vec)
print("Fidelity rho_targ, rho0_evo_map: {}".format(
    fidelity(rho_targ, rho0_evo_map)))

#Drift
drift = L0

#Controls
#ctrls = [LC_x, LC_z]
ctrls = [LC_y]
def test_fid_ref():
    assert fid_ref(bell, zero_state) == fidelity(bell, zero_state)
    assert fid_ref(bell, zero_qubit, [0]) == fidelity(bell.ptrace([0]),
                                                      zero_qubit)
예제 #19
0
def create_circuit(num_nodes, paths, current_path_index, paths_list,
                   bran_size_list, qc, best_path, highest_fidelity, noise_dict,
                   qubit_set, iterations):
    #print(paths[current_path_index])
    for i, p in enumerate(map(nx.utils.pairwise, paths[current_path_index])):

        if current_path_index == 0:
            qubit_set = set()
            other_set = set()

        if current_path_index > 0:
            other_set = set(paths[current_path_index][i])

        if len(qubit_set.intersection(
                other_set)) == 1 or current_path_index == 0:
            #print(list(p))
            cp = list(p)
            bran_size_list[current_path_index] = len(cp)
            #print(bran_size_list)
            current_paths_list = paths_list + cp
            #print(current_paths_list)
            if (current_path_index + 1) == len(paths):
                iterations += 1

                qubits = set()
                for k in range(len(current_paths_list)):
                    qubits.add(current_paths_list[k][0])
                    qubits.add(current_paths_list[k][1])
                    if len(qubits) == num_nodes:
                        break
                #print(qubits)
                num_qubits = len(qubits)
                #mapping = {list(qubits)[m]:m for m in range(num_qubits)}
                #hardware_qubits_mapped_qubit_dict = {k:k for k in range(num_qubits)}
                q1 = QubitCircuit(num_qubits)
                q2 = QubitCircuit(num_qubits)
                q1.user_gates = {
                    "NU": mg.user_cnot,
                    "CSWAP": mg.cnot_swap,
                    "USWAP": mg.user_swap
                }
                q2.user_gates = {
                    "NU": mg.user_cnot,
                    "CSWAP": mg.cnot_swap,
                    "USWAP": mg.user_swap
                }
                q1.add_gate("SNOT", 0)
                q2.add_gate("SNOT", 0)
                starting_place = 0
                ending = 0
                #print(bran_size_list)
                l = 0
                for size in bran_size_list:
                    ending = ending + size
                    #print(current_paths_list[starting_place:ending])

                    for edge in current_paths_list[starting_place:ending]:
                        # if len(current_paths_list) == 1:
                        #     q1.add_gate("NU", targets = [mapping[edge[0]],mapping[edge[1]]], arg_value = 1)
                        #     q2.add_gate("NU", targets = [mapping[edge[0]],mapping[edge[1]]], arg_value = noise_dict_index_keys[edge])

                        if l == (ending - 1):
                            q1.add_gate("NU", targets=[l, l + 1], arg_value=1)
                            q2.add_gate("NU",
                                        targets=[l, l + 1],
                                        arg_value=noise_dict[edge])
                        elif l < (ending - 1):
                            q1.add_gate("USWAP",
                                        targets=[l, l + 1],
                                        arg_value=1)
                            q2.add_gate("USWAP",
                                        targets=[l, l + 1],
                                        arg_value=noise_dict[edge])
                            #hardware_qubits_mapped_qubit_dict[mapping[edge[0]]], hardware_qubits_mapped_qubit_dict[mapping[edge[1]]] = hardware_qubits_mapped_qubit_dict[mapping[edge[1]]], hardware_qubits_mapped_qubit_dict[mapping[edge[0]]]
                        l = l + 1
                    #print(current_paths_list[starting_place:ending])
                    starting_place = starting_place + size
                y = gate_sequence_product(q1.propagators()) * tensor(
                    [basis(2, 0)] * num_qubits)
                y2 = gate_sequence_product(q2.propagators()) * tensor(
                    [basis(2, 0)] * num_qubits)
                fidel = fidelity(y, y2)
                #print(fidel)
                if fidel > highest_fidelity:
                    qc = q2
                    best_path = current_paths_list
                    highest_fidelity = fidel  #highest fidelity
                    print(highest_fidelity)
                    print(qc.gates)
                    print(best_path)

        if (i + 1) == len(paths[current_path_index]) and (current_path_index +
                                                          1) == len(paths):
            return qc, best_path, highest_fidelity, iterations
        j = current_path_index
        current_set = qubit_set

        if ((current_path_index + 1) < len(paths)
                and len(current_set.intersection(other_set))
                == 1) or (len(paths) > 1 and current_path_index == 0):
            current_set.update(paths[current_path_index][i])
            j += 1
            qc, best_path, highest_fidelity, iterations = create_circuit(
                num_nodes, paths, j, current_paths_list, bran_size_list, qc,
                best_path, highest_fidelity, noise_dict, current_set,
                iterations)
    return qc, best_path, highest_fidelity, iterations
예제 #20
0
Z = qip.sigmaz()    # z-Pauli operator
P_0 = basis(2,0)*basis(2,0).dag()   # projector onto eigenspace spanned by |0>
P_0 = gate_expand_1toN(P_0,2,0)
I = qip.qeye(2)   # identity operator
Ucnot = cnot(control=1, target=0)   # cnot gate

# initial conditions
Delta = 4*pi    # exploration range
U = I
u = I

# initial states
A = basis(2,0)  # agent in the state |0>
E = basis(2,0)*cos(t_e/2) + basis(2,1)*sin(t_e/2)*exp(1j*p_e)   # environment state

F_hist = [fidelity(E,A)]     # list to store fidelities
D_hist = [Delta/pi]     # list to store deltas

# begin iteration
for k in range(2, N+1):
    E_bar = U.dag()*E

    R = basis(2,0)  # register in the state |0>
    R_E = Ucnot*tensor(R,E_bar)  # policy
    p = P_0.matrix_element(R_E,R_E)     # p = <R_E|P_0|R_E> register measurement
    x = uniform()   # a random number to simulate the measurement result

    # this step is made for the sake of clarity
    if x < p.real:
        m=0
    else: