Beispiel #1
0
def time_evolution_circuit_improved(g_list,
                                    t,
                                    kickback_phase,
                                    k,
                                    n_trotter_step=1):
    n_qubits = 3
    a_idx = 2
    phi = -(t / n_trotter_step) * g_list
    # print(phi)
    circuit = QuantumCircuit(n_qubits)
    circuit.add_H_gate(a_idx)
    # Apply kickback phase rotation to ancilla bit
    circuit.add_RZ_gate(a_idx, -np.pi * kickback_phase / 2)
    for _ in range(n_trotter_step):
        for _ in range(2**k):
            # CU(Z0)
            circuit.add_RZ_gate(0, -phi[0])
            circuit.add_CNOT_gate(a_idx, 0)
            circuit.add_RZ_gate(0, phi[0])
            circuit.add_CNOT_gate(a_idx, 0)

            # CU(Y0 Y1)
            circuit.add_S_gate(0)
            circuit.add_S_gate(1)
            circuit.add_H_gate(0)
            circuit.add_H_gate(1)
            circuit.add_CNOT_gate(1, 0)
            circuit.add_RZ_gate(0, -phi[1])
            circuit.add_CNOT_gate(a_idx, 0)
            circuit.add_RZ_gate(0, phi[1])
            circuit.add_CNOT_gate(a_idx, 0)
            circuit.add_CNOT_gate(1, 0)
            circuit.add_H_gate(0)
            circuit.add_H_gate(1)
            circuit.add_Sdag_gate(0)
            circuit.add_Sdag_gate(1)

            # CU(Z1)
            circuit.add_RZ_gate(1, -phi[2])
            circuit.add_CNOT_gate(a_idx, 1)
            circuit.add_RZ_gate(1, phi[2])
            circuit.add_CNOT_gate(a_idx, 1)

            # CU(X0 X1)
            circuit.add_H_gate(0)
            circuit.add_H_gate(1)
            circuit.add_CNOT_gate(1, 0)
            circuit.add_RZ_gate(0, -phi[3])
            circuit.add_CNOT_gate(a_idx, 0)
            circuit.add_RZ_gate(0, phi[3])
            circuit.add_CNOT_gate(a_idx, 0)
            circuit.add_CNOT_gate(1, 0)
            circuit.add_H_gate(0)
            circuit.add_H_gate(1)

    circuit.add_H_gate(a_idx)
    return circuit
Beispiel #2
0
    def test_CU_Y0Y1(self):
        n_qubits = 3
        a_idx = 2
        theta = np.pi/4
        state = QuantumState(n_qubits)
        input_states_bin = [0b001, 0b010, 0b101, 0b110]
        input_states = []
        output_states = []

        circuit = QuantumCircuit(n_qubits)
        # change basis from Z to Y
        circuit.add_S_gate(0)
        circuit.add_S_gate(1)
        circuit.add_H_gate(0)
        circuit.add_H_gate(1)
        circuit.add_CNOT_gate(1, 0)
        # RZ
        circuit.add_RZ_gate(0, -0.5*theta)
        circuit.add_CNOT_gate(a_idx, 0)
        circuit.add_RZ_gate(0, 0.5*theta)
        circuit.add_CNOT_gate(a_idx, 0)
        
        circuit.add_CNOT_gate(1, 0)
        # change basis from Z to Y
        circuit.add_H_gate(0)
        circuit.add_H_gate(1)
        circuit.add_Sdag_gate(0)
        circuit.add_Sdag_gate(1)

        for b in input_states_bin:
            psi = state.copy()
            psi.set_computational_basis(b) 
            input_states += [psi]
            psi_out = psi.copy()
            circuit.update_quantum_state(psi_out)
            output_states += [psi_out]

        p_list = []
        for in_state in input_states:
            for out_state in output_states:
                prod = inner_product(in_state, out_state)
                p_list += [prod]
        # |001>
        exp_list = [1.0, 0.0, 0.0, 0.0]
        # |010>
        exp_list += [0.0, 1.0, 0.0, 0.0]
        # |101>
        exp_list += [0.0, 0.0, np.cos(theta/2), complex(0, -np.sin(theta/2))]
        # |110> 
        exp_list += [0.0, 0.0, complex(0, -np.sin(theta/2)), np.cos(theta/2)]
        
        for result, expected in zip(p_list, exp_list):
            self.assertAlmostEqual(result, expected, places=6)
Beispiel #3
0
def sample_observable_noisy_circuit(circuit,
                                    initial_state,
                                    obs,
                                    n_circuit_sample=1000,
                                    n_sample_per_circuit=1):
    """
    Args:
        circuit (:class:`qulacs.QuantumCircuit`)
        initial_state (:class:`qulacs.QuantumState`)
        obs (:class:`qulacs.Observable`)
        n_circuit_sample (:class:`int`):  number of circuit samples
        n_sample (:class:`int`):  number of samples per one circuit samples
    Return:
        :float: sampled expectation value of the observable
    """
    n_term = obs.get_term_count()
    n_qubit = obs.get_qubit_count()

    pauli_terms = [obs.get_term(i) for i in range(n_term)]
    coefs = [p.get_coef() for p in pauli_terms]
    pauli_ids = [p.get_pauli_id_list() for p in pauli_terms]
    pauli_indices = [p.get_index_list() for p in pauli_terms]

    exp = 0
    state = initial_state.copy()
    for c in range(n_circuit_sample):
        state.load(initial_state)
        circuit.update_quantum_state(state)
        for i in range(n_term):
            measurement_circuit = QuantumCircuit(n_qubit)
            if len(pauli_ids[i]) == 0:  # means identity
                exp += coefs[i]
                continue
            mask = ''.join([
                '1' if n_qubit - 1 - k in pauli_indices[i] else '0'
                for k in range(n_qubit)
            ])
            for single_pauli, index in zip(pauli_ids[i], pauli_indices[i]):
                if single_pauli == 1:
                    measurement_circuit.add_H_gate(index)
                elif single_pauli == 2:
                    measurement_circuit.add_Sdag_gate(index)
                    uncompute_circuit.add_H_gate(index)
            measurement_circuit.update_quantum_state(state)
            samples = state.sampling(n_sample_per_circuit)
            mask = int(mask, 2)
            exp += coefs[i] * sum(
                list(map(lambda x: (-1)**(bin(x & mask).count('1')),
                         samples))) / n_sample_per_circuit
    exp /= n_circuit_sample
    return exp
Beispiel #4
0
def sample_observable(state, obs, n_sample):
    """Function
    Args:
        state (qulacs.QuantumState):
        obs (qulacs.Observable)
        n_sample (int):  number of samples for each observable
    Return:
        :float: sampled expectation value of the observable

    Author(s): Takashi Tsuchimochi
    """
    n_term = obs.get_term_count()
    n_qubits = obs.get_qubit_count()

    exp = 0
    buf_state = QuantumState(n_qubits)
    for i in range(n_term):
        pauli_term = obs.get_term(i)
        coef = pauli_term.get_coef()
        pauli_id = pauli_term.get_pauli_id_list()
        pauli_index = pauli_term.get_index_list()

        if len(pauli_id) == 0:  # means identity
            exp += coef
            continue

        buf_state.load(state)
        measurement_circuit = QuantumCircuit(n_qubits)
        mask = "".join(["1" if n_qubits - 1 - k in pauli_index else "0"
                        for k in range(n_qubits)])
        for single_pauli, index in zip(pauli_id, pauli_index):
            if single_pauli == 1:
                measurement_circuit.add_H_gate(index)
            elif single_pauli == 2:
                measurement_circuit.add_Sdag_gate(index)
                measurement_circuit.add_H_gate(index)
        measurement_circuit.update_quantum_state(buf_state)
        samples = buf_state.sampling(n_sample)
        mask = int(mask, 2)
        exp += (coef
                *sum(list(map(lambda x: (-1)**(bin(x & mask).count("1")),
                              samples)))
                /n_sample)
    return exp
Beispiel #5
0
def sample_observable(state, obs, n_sample):
    """
    Args:
        state (qulacs.QuantumState):
        obs (qulacs.Observable)
        n_sample (int):  number of samples for each observable
    Return:
        :float: sampled expectation value of the observable
    """
    n_term = obs.get_term_count()
    n_qubit = obs.get_qubit_count()

    pauli_terms = [obs.get_term(i) for i in range(n_term)]
    coefs = [p.get_coef() for p in pauli_terms]
    pauli_ids = [p.get_pauli_id_list() for p in pauli_terms]
    pauli_indices = [p.get_index_list() for p in pauli_terms]

    exp = 0
    measured_state = state.copy()
    for i in range(n_term):
        state.load(measured_state)
        measurement_circuit = QuantumCircuit(n_qubit)
        if len(pauli_ids[i]) == 0:  # means identity
            exp += coefs[i]
            continue
        mask = ''.join([
            '1' if n_qubit - 1 - k in pauli_indices[i] else '0'
            for k in range(n_qubit)
        ])
        for single_pauli, index in zip(pauli_ids[i], pauli_indices[i]):
            if single_pauli == 1:
                measurement_circuit.add_H_gate(index)
            elif single_pauli == 2:
                measurement_circuit.add_Sdag_gate(index)
                measurement_circuit.add_H_gate(index)
        measurement_circuit.update_quantum_state(state)
        samples = state.sampling(n_sample)
        mask = int(mask, 2)
        exp += coefs[i] * sum(
            list(map(lambda x:
                     (-1)**(bin(x & mask).count('1')), samples))) / n_sample

    return exp
Beispiel #6
0
def adaptive_sample_observable(state, obs, n_sample):
    """
    Args:
        state (qulacs.QuantumState):
        obs (qulacs.Observable)
        n_sample (int):  number of samples for each observable
    Return:
        :float: sampled expectation value of the observable
    """
    n_term = obs.get_term_count()
    n_qubits = obs.get_qubit_count()

    exp = 0
    buf_state = QuantumState(n_qubits)

    ### check the coefficients for each term...
    coef_list = np.array([abs(obs.get_term(i).get_coef())
                          for i in range(n_term)])
    sum_coef = np.sum(coef_list)

    ### sort
    sorted_indices = np.argsort(-coef_list)
    coef_list.sort()
    #sorted_coef_list = [coef_list[i] for i in sorted_indices]
    ### determine sampling wight
    n_sample_total = n_sample*n_term
    n_sample_list = n_sample_total*coef_list//sum_coef
    n_count = np.sum(n_sample_list)
    n_rest = n_sample_total - n_count
    n_sample_list[sorted_indices[:n_rest]] += 1

    j = 0
    for i in range(n_term):
        if n_sample_list[i] == 0:
            continue
        j += n_sample_list[i]

        pauli_term = obs.get_term(i)
        coef = pauli_term.get_coef()
        pauli_id = pauli_term.get_pauli_id_list()
        pauli_index = pauli_term.get_index_list()

        if len(pauli_id) == 0:  # means identity
            exp += coef
            continue

        buf_state.load(state)
        measurement_circuit = QuantumCircuit(n_qubits)
        mask = "".join(["1" if n_qubits - 1 - k in pauli_index else "0"
                        for k in range(n_qubits)])
        for single_pauli, index in zip(pauli_id, pauli_index):
            if single_pauli == 1:
                measurement_circuit.add_H_gate(index)
            elif single_pauli == 2:
                measurement_circuit.add_Sdag_gate(index)
                measurement_circuit.add_H_gate(index)
        measurement_circuit.update_quantum_state(buf_state)
        samples = buf_state.sampling(n_sample_list[i])
        mask = int(mask, 2)
        exp += (coef
                *sum(list(map(lambda x: (-1)**(bin(x & mask).count("1")),
                              samples)))
                /n_sample_list[i])
    return exp
Beispiel #7
0
def test_transition_observable(state, obs, poststate0, poststate1, n_sample):
    """
    Args:
        state (qulacs.QuantumState): This includes entangled ancilla
                                     (n_qubits = n_qubit_system + 1)
        obs (qulacs.Observable): This does not include ancilla Z
                                 (n_qubit_system)
        poststate0 (qulacs.QuantumState): post-measurement state
                                          when ancilla = 0 (n_qubit_system)
        poststate1 (qulacs.QuantumState): post-measurement state
                                          when ancilla = 1 (n_qubit_system)
        n_sample (int):  number of samples for each observable

    Return:
        :float: sampled expectation value of the observable
    """
    n_term = obs.get_term_count()
    n_qubits = obs.get_qubit_count()
    p0 = state.get_zero_probability(n_qubits - 1)
    p1 = 1 - p0
    opt = f"0{n_qubits}b"

    prints(f"p0: {p0}  p1: {p1}")
    print_state(poststate0, name="post(0)")
    prints("post(1)")
    print_state(poststate1, name="post(1)")

    expH = 0
    exp = []
    coef = []
    buf_state = QuantumState(n_qubits)
    for i in range(n_term):
        pauli_term = obs.get_term(i)
        coef.append(pauli_term.get_coef().real)
        pauli_id = pauli_term.get_pauli_id_list()
        pauli_index = pauli_term.get_index_list()

        if len(pauli_id) == 0:  # means identity
            exp.extend(coef)
            continue

        buf_state.load(state)
        measurement_circuit = QuantumCircuit(n_qubits)
        mask = "".join(["1" if n_qubits - 1 - k in pauli_index else "0"
                        for k in range(n_qubits)])

        measure_observable = QubitOperator((), 1)
        #measure_observable = QubitOperator('Z%d' % n_qubits)
        for single_pauli, index in zip(pauli_id, pauli_index):
            if single_pauli == 1:
                ###  X
                measurement_circuit.add_H_gate(index)
                measure_observable *= QubitOperator(f"X{index}")
            elif single_pauli == 2:
                ###  Y
                measurement_circuit.add_Sdag_gate(index)
                measurement_circuit.add_H_gate(index)
                measure_observable *= QubitOperator(f"Y{index}")
            elif single_pauli == 3:
                ###  Z
                measure_observable *= QubitOperator(f"Z{index}")
        qulacs_measure_observable \
                = create_observable_from_openfermion_text(
                        str(measure_observable))
        ### p0 ###
        H0 = qulacs_measure_observable.get_expectation_value(poststate0)
        ### p1 ###
        H1 = qulacs_measure_observable.get_expectation_value(poststate1)
        prob = p0*H0 - p1*H1
        # print(prob, qulacs_measure_observable.get_expectation_value(state), obs.get_expectation_value(state))
        prob = qulacs_measure_observable.get_expectation_value(state)
        expH += coef[i]*prob

        # measurement_circuit.update_quantum_state(buf_state)
        # samples = buf_state.sampling(n_sample)
        # print('samples? ',format(samples[0],opt))
        # print("I = :",'%5d' % i, "  h_I ", '%10.5f' % coef[i], "    <P_I> ", '%10.5f' % exp[i])
        # mask = int(mask, 2)
        # print(sum(list(map(lambda x: (-1) **(bin(x & mask).count('1')), samples))))
        # print(coef*sum(list(map(lambda x: (-1) **
        #                             (bin(x & mask).count('1')), samples))))
        # expH += coef[i] * exp[i]
        # samples = buf_state.sampling(n_sample)

        # mask = int(mask, 2)
        # prob = sum(list(map(lambda x: (-1) **
        #                             (bin(x & mask).count('1')), samples)))/n_sample
        # measure_list = list(map(int,np.ones(n_qubits)*2))
        # for j in pauli_index:
        #    measure_list[j] = 1
        # print(qulacs_measure_observable.get_expectation_value(state))
        # expH += coef[i] * prob
        print(f"coef: {coef[i]:10.5f}  prob: {prob:10.5f}")
    return expH
Beispiel #8
0
def test_observable(state, obs, obsZ, n_sample):
    """Function

    Args:
        state (qulacs.QuantumState): This includes entangled ancilla
                                     (n_qubits = n_qubit_system + 1)
        obs (qulacs.Observable): This does not include ancilla Z
                                 (n_qubit_system)
        obsZ (qulacs.Observable): Single Pauli Z for ancilla (1)
        poststate0 (qulacs.QuantumState): post-measurement state
                                          when ancilla = 0 (n_qubit_system)
        poststate1 (qulacs.QuantumState): post-measurement state
                                          when ancilla = 1 (n_qubit_system)
        n_sample (int):  number of samples for each observable

    Return:
        :float: sampled expectation value of the observable

    Author(s): Takashi Tsuchimochi
    """
    n_term = obs.get_term_count()
    n_qubits = obs.get_qubit_count()
    p0 = state.get_zero_probability(n_qubits)
    p1 = 1 - p0
    opt = f"0{n_qubits}b"

    expH = 0
    exp = []
    coef = []
    buf_state = QuantumState(n_qubits)
    for i in range(n_term):
        pauli_term = obs.get_term(i)
        coef.append(pauli_term.get_coef().real)
        pauli_id = pauli_term.get_pauli_id_list()
        pauli_index = pauli_term.get_index_list()

        if len(pauli_id) == 0:  # means identity
            exp.extend(coef)
            continue

        buf_state.load(state)
        measurement_circuit = QuantumCircuit(n_qubits)
        mask = "".join(["1" if n_qubits - 1 - k in pauli_index else "0"
                        for k in range(n_qubits)])
        measure_observable = QubitOperator((), 1)
        for single_pauli, index in zip(pauli_id, pauli_index):
            if single_pauli == 1:
                ###  X
                measurement_circuit.add_H_gate(index)
                measure_observable *= QubitOperator(f"X{index}")
            elif single_pauli == 2:
                ###  Y
                measurement_circuit.add_Sdag_gate(index)
                measurement_circuit.add_H_gate(index)
                measure_observable *= QubitOperator(f"Y{index}")
            elif single_pauli == 3:
                ###  Z
                measure_observable *= QubitOperator(f"Z{index}")
        qulacs_measure_observable \
                = create_observable_from_openfermion_text(
                        str(measure_observable))
        measurement_circuit.update_quantum_state(buf_state)
        #exp.append(obsZ.get_expectation_value(buf_state).real)
        samples = buf_state.sampling(n_sample)
        #print(f"samples? {format(samples[0], opt)}")
        #print(f"I = {i:5d}  h_I = {coef[i]:10.5f}  <P_I> = {exp[i]:10.5f}")
        #mask = int(mask, 2)
        #print(sum(list(map(lambda x: (-1)**(bin(x & mask).count('1')),
        #                   samples))))
        #print(coef*sum(list(map(lambda x: (-1)**(bin(x & mask).count('1')),
        #                        samples))))
        expH += coef[i]*exp[i]
        samples = buf_state.sampling(n_sample)

        mask = int(mask, 2)
        prob = (sum(list(map(lambda x: (-1)**(bin(x & mask).count("1")),
                             samples)))
                /n_sample)
        measure_list = list(map(int, np.ones(n_qubits)*2))
        for j in pauli_index:
            measure_list[j] = 1
        #print(qulacs_measure_observable.get_expectation_value(state))
        expH += coef[i]*prob
        #print(f"coef: {coef[i]:10.5f}  prob: {prob:10.5f}")
    return expH