示例#1
0
def S2Proj(Quket, Q, threshold=1e-8):
    """Function
    Perform spin-projection to QuantumState |Q>
            |Q'>  =  Ps |Q>
    where Ps is a spin-projection operator (non-unitary).
            Ps = \sum_i^ng   wg[i] Ug[i]
    This function provides a shortcut to |Q'>, which is unreal.
    One actually needs to develop a quantum circuit for this
    (See PRR 2, 043142 (2020)).

    Author(s): Takashi Tsuchimochi
    """
    spin = Quket.projection.spin
    s = (spin - 1) / 2
    Ms = Quket.projection.Ms / 2

    n_qubits = Q.get_qubit_count()
    state_P = QuantumState(n_qubits)
    state_P.multiply_coef(0)

    nalpha = max(Quket.projection.euler_ngrids[0], 1)
    nbeta = max(Quket.projection.euler_ngrids[1], 1)
    ngamma = max(Quket.projection.euler_ngrids[2], 1)
    for ialpha in range(nalpha):
        alpha = Quket.projection.sp_angle[0][ialpha]
        alpha_coef = Quket.projection.sp_weight[0][ialpha] * np.exp(
            1j * alpha * Ms)

        for ibeta in range(nbeta):
            beta = Quket.projection.sp_angle[1][ibeta]
            beta_coef = (Quket.projection.sp_weight[1][ibeta] *
                         Quket.projection.dmm[ibeta])

            for igamma in range(ngamma):
                gamma = Quket.projection.sp_angle[2][igamma]
                gamma_coef = (Quket.projection.sp_weight[2][igamma] *
                              np.exp(1j * gamma * Ms))

                # Total Weight
                coef = (2 * s + 1) / (8 * np.pi) * (alpha_coef * beta_coef *
                                                    gamma_coef)

                state_g = QuantumState(n_qubits)
                state_g.load(Q)
                circuit_Rg = QuantumCircuit(n_qubits)
                set_circuit_Rg(circuit_Rg, n_qubits, alpha, beta, gamma)
                circuit_Rg.update_quantum_state(state_g)
                state_g.multiply_coef(coef)
                state_P.add_state(state_g)

    # Normalize
    norm2 = state_P.get_squared_norm()
    if norm2 < threshold:
        error(
            "Norm of spin-projected state is too small!\n",
            "This usually means the broken-symmetry state has NO component ",
            "of the target spin.")
    state_P.normalize(norm2)
    # print_state(state_P,name="P|Q>",threshold=1e-6)
    return state_P
示例#2
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

    Author(s): Unknown
    """
    exp = 0
    state = QuantumState(obs.get_qubit_count())
    for _ in range(n_circuit_sample):
        state.load(initial_state)
        circuit.update_quantum_state(state)
        exp += sample_observable(state, obs, n_sample_per_circuit)
    exp /= n_circuit_sample
    return exp
示例#3
0
 def _simulate_on_qulacs(
     self,
     data: _StateAndBuffer,
     shape: tuple,
     qulacs_state: qulacs.QuantumState,
     qulacs_circuit: qulacs.QuantumCircuit,
 ) -> None:
     data.buffer = data.state
     cirq_state = np.array(data.state).flatten().astype(np.complex64)
     qulacs_state.load(cirq_state)
     qulacs_circuit.update_quantum_state(qulacs_state)
     data.state = qulacs_state.get_vector().reshape(shape)
示例#4
0
def fci2qubit(norbs, nalpha, nbeta, fci_coeff):
    """Function
    Perform mapping from fci coefficients to qubit representation

    Args:
        norbs (int): number of active orbitals
        nalpha (int): number of alpha electrons
        nbeta (int): number of beta electrons
        fci_coeff (ndarray): FCI Coefficients in a (NDetA, NDetB) array with
                             NDetA = Choose(norbs, nalpha)
                             NDetB = Choose(norbs, nbeta)
    """
    #printmat(fci_coeff)
    NDetA = Binomial(norbs, nalpha)
    NDetB = Binomial(norbs, nbeta)
    if NDetA is not fci_coeff.shape[0] or NDetB is not fci_coeff.shape[1]:
        error(f"NDetA = {NDetA}  NDetB = {NDetB}  "
              f"fci_coeff = {fci_coeff.shape}"
              f"Wrong dimensions fci_coeff in fci2qubit")
    listA = list(combinations(range(norbs), nalpha))
    listB = list(combinations(range(norbs), nbeta))

    for isort in range(nalpha):
        listA = sorted(listA, key=itemgetter(isort))
    for isort in range(nbeta):
        listB = sorted(listB, key=itemgetter(isort))

    j = 0
    n_qubits = norbs * 2
    opt = f"0{n_qubits}b"
    vec = np.zeros(2**n_qubits)
    for ib in range(NDetB):
        occB = np.array([n * 2 + 1 for n in listB[ib]])

        for ia in range(NDetA):
            occA = np.array([n * 2 for n in listA[ia]])
            #prints("Det {} {}".format(ia,ib),  "  occA ",occA, '  occB ',occB)
            k = np.sum(2**occA) + np.sum(2**occB)
            vec[k] = fci_coeff[ia, ib] if ia <= ib else -fci_coeff[ia, ib]
            #if abs(fci_coeff[ia, ib]) > 1e-4:
            #    prints(f"    Det# {j+1}: ", end="");
            #    prints(f"| {format(k, opt)} > : {fci_coeff[ia, ib]}")
            #j += 1
    fci_state = QuantumState(n_qubits)
    fci_state.load(vec)
    return fci_state
示例#5
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
示例#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
示例#7
0
def cost_phf_sample(Quket, print_level,
                    qulacs_hamiltonian, qulacs_hamiltonianZ, qulacs_s2Z,
                    qulacs_ancZ, coef0_H, coef0_S2, ref, theta_list,
                    samplelist):
    """Function:
    Sample Hamiltonian and S**2 expectation values with PHF and PUCCSD.
    Write out the statistics in csv files.

    Author(s): Takashi Tsuchimochi
    """
    t1 = time.time()

    noa = Quket.noa
    nob = Quket.nob
    nva = Quket.nva
    nvb = Quket.nvb
    n_electrons = Quket.n_electrons
    n_qubit_system = n_qubits
    n_qubits = Quket.n_qubits + 1
    anc = n_qubit_system
    ndim1 = Quket.ndim1

    state = QuantumState(n_qubits)
    circuit_rhf = set_circuit_rhfZ(n_qubits, n_electrons)
    circuit_rhf.update_quantum_state(state)

    if ref == "phf":
        circuit_uhf = set_circuit_uhfZ(n_qubits, noa, nob, nva, nvb, theta_list)
        circuit_uhf.update_quantum_state(state)
        print("pHF")
    elif ref == "puccsd":
        circuit = set_circuit_uccsd(n_qubits, noa, nob, nva, nvb, theta_list,
                                    ndim1)
        for i in range(rho):
            circuit.update_quantum_state(state)
        print("UCCSD")

    if print_level > -1:
        print("State before projection")
        utils.print_state(state, n_qubit_system)
    #### Set post-measurement states ####
    #poststate0 = state.copy()
    #poststate1 = state.copy()
    #circuit0 = QuantumCircuit(n_qubits)
    #circuit1 = QuantumCircuit(n_qubits)
    #### Projection to anc = 0 or anc = 1 ###
    #circuit0.add_gate(P0(0))
    #circuit1.add_gate(P1(0))
    #circuit0.update_quantum_state(poststate0)
    #circuit1.update_quantum_state(poststate1)
    #### Renormalize each state ###
    #norm0 = poststate0.get_squared_norm()
    #norm1 = poststate1.get_squared_norm()
    #poststate0.normalize(norm0)
    #poststate1.normalize(norm1)

    ### grid loop ###
    Ng = 4
    beta = [-0.861136311594053, -0.339981043584856,
             0.339981043584856,  0.861136311594053]
    wg = [0.173927422568724, 0.326072577431273,
          0.326072577431273, 0.173927422568724]

    Ng = 2
    beta = [0.577350269189626, -0.577350269189626]
    wg = [0.5, 0.5]

    ### a list to compute the probability to observe 0 in ancilla qubit
    p0_list = np.full(n_qubits, 2)
    p0_list[-1] = 0

    ### Array for <HUg>, <S2Ug>, <Ug>
    # samplelist = [10,100,1000,10000,100000,1000000,10000000]
    ncyc = 4
    prints("", filepath="./log2.txt")
    for i_sample in samplelist:
        i_sample_x = i_sample
        if i_sample == 10000000:
            print("OK")
            ncyc = ncyc*10
            i_sample_x = 1000000
        sampleHUg1 = []
        sampleHUg2 = []
        sampleHUg3 = []
        sampleHUg4 = []
        sampleS2Ug1 = []
        sampleS2Ug2 = []
        sampleS2Ug3 = []
        sampleS2Ug4 = []
        sampleUg1 = []
        sampleUg2 = []
        sampleUg3 = []
        sampleUg4 = []
        # sampleEn = []
        # sampleS2 = []
        sampleHUg = np.zeros((ncyc, Ng))
        sampleS2Ug = np.zeros((ncyc, Ng))
        sampleUg = np.zeros((ncyc, Ng))
        sampleEn = np.zeros((ncyc, 1))
        sampleS2 = np.zeros((ncyc, 1))

        for icyc in range(ncyc):
            prints(f"n_sample = {i_sample_x}  ({icyc} / {ncyc})",
                   filepath="./log2.txt")
            HUg = []
            S2Ug = []
            Ug = []
            Ephf = S2 = Norm = 0
            for i in range(Ng):
                ### Copy quantum state of UHF (cannot be done in real device) ###
                state_g = QuantumState(n_qubits)
                state_g.load(state)
                ### Construct Ug test
                circuit_ug = QuantumCircuit(n_qubits)
                ### Hadamard on anc
                circuit_ug.add_H_gate(anc)
                controlled_Ug(circuit_ug, n_qubits, anc, np.arccos(beta[i]))
                circuit_ug.add_H_gate(anc)
                circuit_ug.update_quantum_state(state_g)

                ### Set post-measurement states ####
                poststate0 = state_g.copy()
                poststate1 = state_g.copy()
                circuit0 = QuantumCircuit(n_qubits)
                circuit1 = QuantumCircuit(n_qubits)
                ### Projection to anc = 0 or anc = 1 ###
                circuit0.add_gate(P0(anc))
                circuit1.add_gate(P1(anc))
                circuit0.update_quantum_state(poststate0)
                circuit1.update_quantum_state(poststate1)
                ### Renormalize each state ###
                norm0 = poststate0.get_squared_norm()
                norm1 = poststate1.get_squared_norm()
                poststate0.normalize(norm0)
                poststate1.normalize(norm1)
                ### Set ancilla qubit of poststate1 to zero (so that it won't be used) ###
                circuit_anc = QuantumCircuit(n_qubits)
                circuit_anc.add_X_gate(anc)
                circuit_anc.update_quantum_state(poststate1)
                print(
                        test_transition_observable(
                            state_g, qulacs_hamiltonianZ,
                            poststate0, poststate1, 100000))
                # exit()

                ### Probabilities for getting 0 and 1 in ancilla qubit ###
                p0 = state_g.get_marginal_probability(p0_list)
                p1 = 1 - p0

                ### Compute expectation value <HUg> ###
                HUg.append(sample_observable(state_g,
                                             qulacs_hamiltonianZ,
                                             i_sample_x).real)
                #HUg.append(adaptive_sample_observable(state_g,
                #                                      qulacs_hamiltonianZ,
                #                                      i_sample_x).real)
                ### <S2Ug> ###
                S2Ug.append(sample_observable(state_g,
                                              qulacs_s2Z,
                                              i_sample_x).real)
                #S2Ug.append(adaptive_sample_observable(state_g,
                #                                       qulacs_s2Z,
                #                                       i_sample_x).real)
                #S2Ug.append(qulacs_s2Z.get_expectation_value(state_g))
                #HUg.append(0)
                #S2Ug.append(0)

                #Ug.append(p0 - p1)
                n_term = qulacs_hamiltonianZ.get_term_count()
                n_sample_total = i_sample_x * n_term
                # in the worst-case scenario,
                # Ug is measured as many times as n_sample_total
                #(required to evaluate HUg)
                Ug.append(sample_observable(state_g,
                                            qulacs_ancZ,
                                            i_sample_x*n_term).real)
                #p0_sample = 0
                #for j_sample in range(n_sample_total):
                #   if(p0 > np.random.rand()):
                #      p0_sample += 1
                #Ug.append(2*p0_sample/n_sample_total - 1)
                ### Norm accumulation ###
                Norm += wg[i]*Ug[i]
                sampleHUg[icyc, i] = HUg[i]
                sampleS2Ug[icyc, i] = S2Ug[i]
                sampleUg[icyc, i] = Ug[i]
            #print('p0 : ',p0,'  p1 : ',p1,  '  p0 - p1 : ',p0-p1)

            sampleHUg1.append(HUg[0])
            sampleHUg2.append(HUg[1])
            #sampleHUg3.append(HUg[2])
            #sampleHUg4.append(HUg[3])
            sampleS2Ug1.append(S2Ug[0])
            sampleS2Ug2.append(S2Ug[1])
            #sampleS2Ug3.append(S2Ug[2])
            #sampleS2Ug4.append(S2Ug[3])
            sampleUg1.append(Ug[0])
            sampleUg2.append(Ug[1])
            #sampleUg3.append(Ug[2])
            #sampleUg4.append(Ug[3])

            ### Energy calculation <HP>/<P> and <S**2P>/<P> ###
            Ephf = 0
            for i in range(Ng):
                Ephf += wg[i]*HUg[i]/Norm
                S2 += wg[i]*S2Ug[i]/Norm
            # print(" <S**2> = ", S2, '\n')
            Ephf += coef0_H
            S2 += coef0_S2
            sampleEn[icyc, 0] = Ephf
            sampleS2[icyc, 0] = S2
            # print(" <E[PHF]> (Nsample = ",i_sample,") = ", Ephf)
        #print(f"(n_sample = {i_sample}):  sample HUg1\n",sampleHUg1)
        #print(f"(n_sample = {i_sample}):  sample HUg2\n",sampleHUg2)
        #print(f"(n_sample = {i_sample}):  sample HUg3\n",sampleHUg3)
        #print(f"(n_sample = {i_sample}):  sample HUg4\n",sampleHUg4)
        #print(f"(n_sample = {i_sample}):  sample S2Ug1\n",sampleS2Ug1)
        #print(f"(n_sample = {i_sample}):  sample S2Ug2\n",sampleS2Ug2)
        #print(f"(n_sample = {i_sample}):  sample S2Ug3\n",sampleS2Ug3)
        #print(f"(n_sample = {i_sample}):  sample S2Ug4\n",sampleS2Ug4)
        #print(f"(n_sample = {i_sample}):  sample Ug1\n",sampleUg1)
        #print(f"(n_sample = {i_sample}):  sample Ug2\n",sampleUg2)
        #print(f"(n_sample = {i_sample}):  sample Ug3\n",sampleUg3)
        #print(f"(n_sample = {i_sample}):  sample Ug4\n",sampleUg4)
        #print(f"(n_sample = {i_sample}):  sample HUg1\n",sampleHUg1)
        #print(f"(n_sample = {i_sample}):  sample HUg2\n",sampleHUg2)
        #print(f"(n_sample = {i_sample}):  sample HUg3\n",sampleHUg3)
        #print(f"(n_sample = {i_sample}):  sample HUg4\n",sampleHUg4)
        #print(f"(n_sample = {i_sample}):  sample En\n",sampleEn)
        #print(f"(n_sample = {i_sample}):  sample S2\n",sampleS2)
        with open(f"./Ug_{i_sample}.csv", "w") as fUg:
            writer = csv.writer(fUg)
            writer.writerows(sampleUg)
        with open(f"./HUg_{i_sample}.csv", "w") as fHUg:
            writer = csv.writer(fHUg)
            writer.writerows(sampleHUg)
        with open(f"./S2Ug_{i_sample}.csv", "w") as fS2Ug:
            writer = csv.writer(fS2Ug)
            writer.writerows(sampleS2Ug)
        with open(f"./En_{i_sample}.csv", "w") as fEn:
            writer = csv.writer(fEn)
            writer.writerows(sampleEn)
        with open(f"./S2_{i_smaple}.csv", "w") as fS2:
            writer = csv.writer(fS2)
            writer.writerows(sampleS2)
    return Ephf, S2
示例#8
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
示例#9
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
示例#10
0
def cost_proj(Quket,
              print_level,
              qulacs_hamiltonianZ,
              qulacs_s2Z,
              coef0_H,
              coef0_S2,
              kappa_list,
              theta_list=0,
              threshold=0.01):
    """Function:
    Energy functional for projected methods (phf, puccsd, puccd, opt_puccd)

    Author(s): Takashi Tsuchimochi
    """
    t1 = time.time()

    noa = Quket.noa
    nob = Quket.nob
    nva = Quket.nva
    nvb = Quket.nvb
    n_electrons = Quket.n_electrons
    rho = Quket.rho
    DS = Quket.DS
    anc = Quket.anc
    n_qubit_system = Quket.n_qubits
    n_qubits = n_qubit_system + 1
    # opt_psauccdとかはndimの計算が異なるけどこっちを使う?
    #ndim1 = noa * nva + nob * nvb
    #ndim2aa = int(noa * (noa - 1) * nva * (nva - 1) / 4)
    #ndim2ab = int(noa * nob * nva * nvb)
    #ndim2bb = int(nob * (nob - 1) * nvb * (nvb - 1) / 4)
    #ndim2 = ndim2aa + ndim2ab + ndim2bb
    ndim1 = Quket.ndim1
    ndim2 = Quket.ndim2
    ndim = Quket.ndim
    ref = Quket.ansatz

    state = QuantumState(n_qubits)
    if noa == nob:
        circuit_rhf = set_circuit_rhfZ(n_qubits, n_electrons)
    else:
        circuit_rhf = set_circuit_rohfZ(n_qubits, noa, nob)
    circuit_rhf.update_quantum_state(state)

    if ref == "phf":
        circuit_uhf = set_circuit_uhfZ(n_qubits, noa, nob, nva, nvb,
                                       kappa_list)
        circuit_uhf.update_quantum_state(state)
    elif ref == "sghf":
        circuit_ghf = set_circuit_ghfZ(n_qubits, noa + nob, nva + nvb,
                                       kappa_list)
        circuit_ghf.update_quantum_state(state)
    elif ref == "puccsd":
        # First prepare UHF determinant
        circuit_uhf = set_circuit_uhfZ(n_qubits, noa, nob, nva, nvb,
                                       kappa_list)
        circuit_uhf.update_quantum_state(state)
        # Then prepare UCCSD
        theta_list_rho = theta_list / rho
        circuit = set_circuit_uccsd(n_qubits, noa, nob, nva, nvb, 0,
                                    theta_list_rho, ndim1)
        for i in range(rho):
            circuit.update_quantum_state(state)
    elif ref == "puccd":
        # First prepare UHF determinant
        circuit_uhf = set_circuit_uhfZ(n_qubits, noa, nob, nva, nvb,
                                       kappa_list)
        circuit_uhf.update_quantum_state(state)
        # Then prepare UCCD
        theta_list_rho = theta_list / rho
        circuit = set_circuit_uccd(n_qubits, noa, nob, nva, nvb,
                                   theta_list_rho)
        for i in range(rho):
            circuit.update_quantum_state(state)
    elif ref == "opt_puccd":
        if DS:
            # First prepare UHF determinant
            circuit_uhf = set_circuit_uhfZ(n_qubits, noa, nob, nva, nvb,
                                           theta_list)
            circuit_uhf.update_quantum_state(state)
            # Then prepare UCCD
            theta_list_rho = theta_list[ndim1:] / rho
            circuit = set_circuit_uccd(n_qubits, noa, nob, nva, nvb,
                                       theta_list_rho)
            for i in range(rho):
                circuit.update_quantum_state(state)
        else:
            # First prepare UCCD
            theta_list_rho = theta_list[ndim1:] / rho
            circuit = set_circuit_uccd(n_qubits, noa, nob, nva, nvb,
                                       theta_list_rho)
            for i in range(rho):
                circuit.update_quantum_state(state)
            # then rotate
            circuit_uhf = set_circuit_uhfZ(n_qubits, noa, nob, nva, nvb,
                                           theta_list)
            circuit_uhf.update_quantum_state(state)
    elif ref == "opt_psauccd":
        # ここが問題
        # ndim2が他と異なる
        #theta_list_rho = theta_list[ndim1 : ndim1+ndim2]/rho
        theta_list_rho = theta_list[ndim1:] / rho
        circuit = set_circuit_sauccd(n_qubits, noa, nva, theta_list_rho)
        for i in range(rho):
            circuit.update_quantum_state(state)
        circuit_uhf = set_circuit_uhfZ(n_qubits, noa, nob, nva, nvb,
                                       theta_list)
        circuit_uhf.update_quantum_state(state)

    if print_level > 0:
        if ref in ("uhf", "phf", "suhf", "sghf"):
            SaveTheta(ndim, kappa_list, cf.tmp)
        else:
            SaveTheta(ndim, theta_list, cf.tmp)
    if print_level > 1:
        prints("State before projection")
        print_state(state, n_qubits=n_qubit_system)
        if ref in ("puccsd", "opt_puccd"):
            print_amplitudes(theta_list, noa, nob, nva, nvb, threshold)

    ### grid loop ###
    ### a list to compute the probability to observe 0 in ancilla qubit
    ### Array for <HUg>, <S2Ug>, <Ug>
    Ep = S2 = Norm = 0
    nalpha = max(Quket.projection.euler_ngrids[0], 1)
    nbeta = max(Quket.projection.euler_ngrids[1], 1)
    ngamma = max(Quket.projection.euler_ngrids[2], 1)
    HUg = np.empty(nalpha * nbeta * ngamma)
    S2Ug = np.empty(nalpha * nbeta * ngamma)
    Ug = np.empty(nalpha * nbeta * ngamma)
    ig = 0
    for ialpha in range(nalpha):
        alpha = Quket.projection.sp_angle[0][ialpha]
        alpha_coef = Quket.projection.sp_weight[0][ialpha]

        for ibeta in range(nbeta):
            beta = Quket.projection.sp_angle[1][ibeta]
            beta_coef = (Quket.projection.sp_weight[1][ibeta] *
                         Quket.projection.dmm[ibeta])

            for igamma in range(ngamma):
                gamma = Quket.projection.sp_angle[2][igamma]
                gamma_coef = Quket.projection.sp_weight[2][igamma]

                ### Copy quantum state of UHF (cannot be done in real device) ###
                state_g = QuantumState(n_qubits)
                state_g.load(state)
                ### Construct Ug test
                circuit_ug = QuantumCircuit(n_qubits)
                ### Hadamard on anc
                circuit_ug.add_H_gate(anc)
                #circuit_ug.add_X_gate(anc)
                #controlled_Ug(circuit_ug, n_qubits, anc, beta)
                controlled_Ug_gen(circuit_ug, n_qubits, anc, alpha, beta,
                                  gamma)
                #circuit_ug.add_X_gate(anc)
                circuit_ug.add_H_gate(anc)
                circuit_ug.update_quantum_state(state_g)

                ### Compute expectation value <HUg> ###
                HUg[ig] = qulacs_hamiltonianZ.get_expectation_value(state_g)
                ### <S2Ug> ###
                # print_state(state_g)
                S2Ug[ig] = qulacs_s2Z.get_expectation_value(state_g)
                ### <Ug> ###
                p0 = state_g.get_zero_probability(anc)
                p1 = 1 - p0
                Ug[ig] = p0 - p1

                ### Norm accumulation ###
                Norm += alpha_coef * beta_coef * gamma_coef * Ug[ig]
                Ep += alpha_coef * beta_coef * gamma_coef * HUg[ig]
                S2 += alpha_coef * beta_coef * gamma_coef * S2Ug[ig]
                ig += 1
    #        print('p0 : ',p0,'  p1 : ',p1,  '  p0 - p1 : ',p0-p1)
    #    print("Time: ",t2-t1)
    ### Energy calculation <HP>/<P> and <S**2P>/<P> ###
    Ep /= Norm
    S2 /= Norm
    Ep += coef0_H
    S2 += coef0_S2

    t2 = time.time()
    cpu1 = t2 - t1
    if print_level == -1:
        prints(f"Initial E[{ref}] = {Ep:.12f}  <S**2> = {S2:17.15f}  "
               f"rho = {rho}")
    elif print_level == 1:
        cput = t2 - cf.t_old
        cf.t_old = t2
        cf.icyc += 1
        prints(f"{cf.icyc:5d}: E[{ref}] = {Ep:.12f}  <S**2> = {S2:17.15f}  "
               f"CPU Time = {cput:5.2f}  ({cpu1:2.2f} / step)")
    elif print_level > 1:
        prints(f"Final: E[{ref}] = {Ep:.12f}  <S**2> = {S2:17.15f}  "
               f"rho = {rho}")
        print_state(state, n_qubits=n_qubits - 1)
        if ref in ("puccsd", "opt_puccd"):
            print_amplitudes(theta_list, noa, nob, nva, nvb)
        prints("HUg", HUg)
        prints("Ug", Ug)

    # Store wave function
    Quket.state = state
    return Ep, S2
示例#11
0
class QulacsDevice(QubitDevice):
    """Qulacs device"""

    name = "Qulacs device"
    short_name = "qulacs.simulator"
    pennylane_requires = ">=0.11.0"
    version = __version__
    author = "Steven Oud and Xanadu"
    gpu_supported = GPU_SUPPORTED

    _capabilities = {
        "model": "qubit",
        "tensor_observables": True,
        "inverse_operations": True
    }

    _operation_map = {
        "QubitStateVector": None,
        "BasisState": None,
        "QubitUnitary": None,
        "Toffoli": gate.TOFFOLI,
        "CSWAP": gate.FREDKIN,
        "CRZ": crz,
        "SWAP": gate.SWAP,
        "CNOT": gate.CNOT,
        "CZ": gate.CZ,
        "S": gate.S,
        "T": gate.T,
        "RX": gate.RX,
        "RY": gate.RY,
        "RZ": gate.RZ,
        "PauliX": gate.X,
        "PauliY": gate.Y,
        "PauliZ": gate.Z,
        "Hadamard": gate.H,
        "PhaseShift": phase_shift,
    }

    _observable_map = {
        "PauliX": "X",
        "PauliY": "Y",
        "PauliZ": "Z",
        "Identity": "I",
        "Hadamard": None,
        "Hermitian": None,
    }

    operations = _operation_map.keys()
    observables = _observable_map.keys()

    # Add inverse gates to _operation_map
    _operation_map.update({k + ".inv": v for k, v in _operation_map.items()})

    def __init__(self, wires, shots=1000, analytic=True, gpu=False, **kwargs):
        super().__init__(wires=wires, shots=shots, analytic=analytic)

        if gpu:
            if not QulacsDevice.gpu_supported:
                raise DeviceError(
                    "GPU not supported with installed version of qulacs. "
                    "Please install 'qulacs-gpu' to use GPU simulation.")

            self._state = QuantumStateGpu(self.num_wires)
        else:
            self._state = QuantumState(self.num_wires)

        self._circuit = QuantumCircuit(self.num_wires)

        self._pre_rotated_state = self._state.copy()

    def apply(self, operations, **kwargs):
        rotations = kwargs.get("rotations", [])

        self.apply_operations(operations)
        self._pre_rotated_state = self._state.copy()

        # Rotating the state for measurement in the computational basis
        if rotations:
            self.apply_operations(rotations)

    def apply_operations(self, operations):
        """Apply the circuit operations to the state.

        This method serves as an auxiliary method to :meth:`~.QulacsDevice.apply`.

        Args:
            operations (List[pennylane.Operation]): operations to be applied
        """

        for i, op in enumerate(operations):
            if i > 0 and isinstance(op, (QubitStateVector, BasisState)):
                raise DeviceError(
                    "Operation {} cannot be used after other Operations have already been applied "
                    "on a {} device.".format(op.name, self.short_name))

            if isinstance(op, QubitStateVector):
                self._apply_qubit_state_vector(op)
            elif isinstance(op, BasisState):
                self._apply_basis_state(op)
            elif isinstance(op, QubitUnitary):
                self._apply_qubit_unitary(op)
            elif isinstance(op, (CRZ, PhaseShift)):
                self._apply_matrix(op)
            else:
                self._apply_gate(op)

    def _apply_qubit_state_vector(self, op):
        """Initialize state with a state vector"""
        wires = op.wires
        input_state = op.parameters[0]

        if len(input_state) != 2**len(wires):
            raise ValueError("State vector must be of length 2**wires.")
        if input_state.ndim != 1 or len(input_state) != 2**len(wires):
            raise ValueError("State vector must be of length 2**wires.")
        if not np.isclose(np.linalg.norm(input_state, 2), 1.0, atol=tolerance):
            raise ValueError("Sum of amplitudes-squared does not equal one.")

        input_state = _reverse_state(input_state)

        # call qulacs' state initialization
        self._state.load(input_state)

    def _apply_basis_state(self, op):
        """Initialize a basis state"""
        wires = op.wires
        par = op.parameters

        # translate from PennyLane to Qulacs wire order
        bits = par[0][::-1]
        n_basis_state = len(bits)

        if not set(bits).issubset({0, 1}):
            raise ValueError(
                "BasisState parameter must consist of 0 or 1 integers.")
        if n_basis_state != len(wires):
            raise ValueError(
                "BasisState parameter and wires must be of equal length.")

        basis_state = 0
        for bit in bits:
            basis_state = (basis_state << 1) | bit

        # call qulacs' basis state initialization
        self._state.set_computational_basis(basis_state)

    def _apply_qubit_unitary(self, op):
        """Apply unitary to state"""
        # translate op wire labels to consecutive wire labels used by the device
        device_wires = self.map_wires(op.wires)
        par = op.parameters

        if len(par[0]) != 2**len(device_wires):
            raise ValueError(
                "Unitary matrix must be of shape (2**wires, 2**wires).")

        if op.inverse:
            par[0] = par[0].conj().T

        # reverse wires (could also change par[0])
        reverse_wire_labels = device_wires.tolist()[::-1]
        unitary_gate = gate.DenseMatrix(reverse_wire_labels, par[0])
        self._circuit.add_gate(unitary_gate)
        unitary_gate.update_quantum_state(self._state)

    def _apply_matrix(self, op):
        """Apply predefined gate-matrix to state (must follow qulacs convention)"""
        # translate op wire labels to consecutive wire labels used by the device
        device_wires = self.map_wires(op.wires)
        par = op.parameters

        mapped_operation = self._operation_map[op.name]
        if op.inverse:
            mapped_operation = self._get_inverse_operation(
                mapped_operation, device_wires, par)

        if callable(mapped_operation):
            gate_matrix = mapped_operation(*par)
        else:
            gate_matrix = mapped_operation

        # gate_matrix is already in correct order => no wire-reversal needed
        dense_gate = gate.DenseMatrix(device_wires.labels, gate_matrix)
        self._circuit.add_gate(dense_gate)
        gate.DenseMatrix(device_wires.labels,
                         gate_matrix).update_quantum_state(self._state)

    def _apply_gate(self, op):
        """Apply native qulacs gate"""

        # translate op wire labels to consecutive wire labels used by the device
        device_wires = self.map_wires(op.wires)
        par = op.parameters

        mapped_operation = self._operation_map[op.name]
        if op.inverse:
            mapped_operation = self._get_inverse_operation(
                mapped_operation, device_wires, par)

        # Negating the parameters such that it adheres to qulacs
        par = np.negative(par)

        # mapped_operation is already in correct order => no wire-reversal needed
        self._circuit.add_gate(mapped_operation(*device_wires.labels, *par))
        mapped_operation(*device_wires.labels,
                         *par).update_quantum_state(self._state)

    @staticmethod
    def _get_inverse_operation(mapped_operation, device_wires, par):
        """Return the inverse of an operation"""

        if mapped_operation is None:
            return mapped_operation

        # if an inverse variant of the operation exists
        try:
            inverse_operation = getattr(gate,
                                        mapped_operation.get_name() + "dag")
        except AttributeError:
            # if the operation is hard-coded
            try:
                if callable(mapped_operation):
                    inverse_operation = np.conj(mapped_operation(*par)).T
                else:
                    inverse_operation = np.conj(mapped_operation).T

            # if mapped_operation is a qulacs.gate and np.conj is applied on it
            except TypeError:
                # else, redefine the operation as the inverse matrix
                def inverse_operation(*p):
                    # embed the gate in a unitary matrix with shape (2**wires, 2**wires)
                    g = mapped_operation(*p).get_matrix()
                    mat = reduce(np.kron, [np.eye(2)] *
                                 len(device_wires)).astype(complex)
                    mat[-len(g):, -len(g):] = g

                    # mat follows PL convention => reverse wire-order
                    reverse_wire_labels = device_wires.tolist()[::-1]
                    gate_mat = gate.DenseMatrix(reverse_wire_labels,
                                                np.conj(mat).T)
                    return gate_mat

        return inverse_operation

    def analytic_probability(self, wires=None):
        """Return the (marginal) analytic probability of each computational basis state."""
        if self._state is None:
            return None

        all_probs = self._abs(self.state)**2
        prob = self.marginal_prob(all_probs, wires)
        return prob

    def expval(self, observable):
        if self.analytic:
            qulacs_observable = Observable(self.num_wires)
            if isinstance(observable.name, list):
                observables = [
                    self._observable_map[obs] for obs in observable.name
                ]
            else:
                observables = [self._observable_map[observable.name]]

            if None not in observables:
                applied_wires = self.map_wires(observable.wires).tolist()
                opp = " ".join([
                    f"{obs} {applied_wires[i]}"
                    for i, obs in enumerate(observables)
                ])

                qulacs_observable.add_operator(1.0, opp)
                return qulacs_observable.get_expectation_value(
                    self._pre_rotated_state)

            # exact expectation value
            eigvals = self._asarray(observable.eigvals, dtype=self.R_DTYPE)
            prob = self.probability(wires=observable.wires)
            return self._dot(eigvals, prob)

        # estimate the ev
        return np.mean(self.sample(observable))

    @property
    def state(self):
        # returns the state after all operations are applied
        return _reverse_state(self._state.get_vector())

    def reset(self):
        self._state.set_zero_state()
        self._pre_rotated_state = self._state.copy()
        self._circuit = QuantumCircuit(self.num_wires)
class QulacsDevice(Device):
    """Qulacs device"""
    name = 'Qulacs device'
    short_name = 'qulacs.simulator'
    pennylane_requires = '>=0.5.0'
    version = __version__
    author = 'Steven Oud'

    _capabilities = {'model': 'qubit', 'tensor_observables': True}

    _operations_map = {
        'QubitStateVector': None,
        'BasisState': None,
        'QubitUnitary': None,
        'Toffoli': toffoli,
        'CSWAP': CSWAP,
        'CRZ': crz,
        'Rot': None,
        'SWAP': gate.SWAP,
        'CNOT': gate.CNOT,
        'CZ': gate.CZ,
        'S': gate.S,
        'Sdg': gate.Sdag,
        'T': gate.T,
        'Tdg': gate.Tdag,
        'RX': gate.RX,
        'RY': gate.RY,
        'RZ': gate.RZ,
        'PauliX': gate.X,
        'PauliY': gate.Y,
        'PauliZ': gate.Z,
        'Hadamard': gate.H
    }
    _observable_map = {
        'PauliX': X,
        'PauliY': Y,
        'PauliZ': Z,
        'Hadamard': H,
        'Identity': I,
        'Hermitian': hermitian
    }

    operations = _operations_map.keys()
    observables = _observable_map.keys()

    def __init__(self, wires, gpu=False, **kwargs):
        super().__init__(wires=wires)

        if gpu:
            if not GPU_SUPPORTED:
                raise DeviceError(
                    'GPU not supported with installed version of qulacs. '
                    'Please install "qulacs-gpu" to use GPU simulation.')

            self._state = QuantumStateGpu(wires)
        else:
            self._state = QuantumState(wires)

        self._circuit = QuantumCircuit(wires)
        self._first_operation = True

    def apply(self, operation, wires, par):
        par = np.negative(par)
        if operation == 'BasisState' and not self._first_operation:
            raise DeviceError(
                'Operation {} cannot be used after other Operations have already been applied '
                'on a {} device.'.format(operation, self.short_name))

        self._first_operation = False

        if operation == 'QubitStateVector':
            if len(par[0]) != 2**len(wires):
                raise ValueError('State vector must be of length 2**wires.')

            self._state.load(par[0])
        elif operation == 'BasisState':
            if len(par[0]) != len(wires):
                raise ValueError('Basis state must prepare all qubits.')

            basis_state = 0
            for bit in reversed(par[0]):
                basis_state = (basis_state << 1) | bit

            self._state.set_computational_basis(basis_state)
        elif operation == 'QubitUnitary':
            if len(par[0]) != 2**len(wires):
                raise ValueError(
                    'Unitary matrix must be of shape (2**wires, 2**wires).')

            unitary_gate = gate.DenseMatrix(wires, par[0])
            self._circuit.add_gate(unitary_gate)
        elif operation == 'Rot':
            self._circuit.add_gate(
                gate.merge([
                    gate.RZ(wires[0], par[0]),
                    gate.RY(wires[0], par[1]),
                    gate.RZ(wires[0], par[2])
                ]))
        elif operation in ('CRZ', 'Toffoli', 'CSWAP'):
            mapped_operation = self._operations_map[operation]
            if callable(mapped_operation):
                gate_matrix = mapped_operation(*par)
            else:
                gate_matrix = mapped_operation

            dense_gate = gate.DenseMatrix(wires, gate_matrix)
            self._circuit.add_gate(dense_gate)
        else:
            mapped_operation = self._operations_map[operation]
            self._circuit.add_gate(mapped_operation(*wires, *par))

    @property
    def state(self):
        return self._state.get_vector()

    def pre_measure(self):
        self._circuit.update_quantum_state(self._state)

    def expval(self, observable, wires, par):
        bra = self._state.copy()

        if isinstance(observable, list):
            A = self._get_tensor_operator_matrix(observable, par)
            wires = [item for sublist in wires for item in sublist]
        else:
            A = self._get_operator_matrix(observable, par)

        dense_gate = gate.DenseMatrix(wires, A)
        dense_gate.update_quantum_state(self._state)

        expectation = inner_product(bra, self._state)

        return expectation.real

    def probabilities(self):
        states = itertools.product(range(2), repeat=self.num_wires)
        probs = np.abs(self.state)**2

        return OrderedDict(zip(states, probs))

    def reset(self):
        self._state.set_zero_state()
        self._circuit = QuantumCircuit(self.num_wires)

    def _get_operator_matrix(self, operation, par):
        A = self._observable_map[operation]
        if not callable(A):
            return A

        return A(*par)

    def _get_tensor_operator_matrix(self, obs, par):
        ops = [self._get_operator_matrix(o, p) for o, p in zip(obs, par)]
        return functools.reduce(np.kron, ops)
示例#13
0
def __run_all(qcirc=None,
              shots=1,
              cid=None,
              backend=None,
              proc='CPU',
              out_state=False):

    if qcirc is None:
        raise ValueError("quantum circuit must be specified.")

    qubit_num = qcirc.qubit_num
    cmem_num = qcirc.cmem_num

    if cid is None:
        cid = list(range(cmem_num))

    if cmem_num < len(cid):
        raise ValueError(
            "length of cid must be less than classical resister size of qcirc")

    #
    # initialize
    #

    if proc == 'CPU':
        qstate = QuantumState(qubit_num)
    else:
        from qulacs import QuantumStateGpu
        qstate = QuantumStateGpu(qubit_num)
    cmem = [0] * cmem_num

    #
    # before measurement gate
    #

    while True:
        kind = qcirc.kind_first()
        if kind is None or kind is cfg.MEASURE or kind is cfg.RESET:
            break

        (kind, qid, para, c, ctrl) = qcirc.pop_gate()
        if ctrl is None or (ctrl is not None and cmem[ctrl] == 1):
            __qulacs_operate_qgate(qstate,
                                   qubit_num,
                                   kind=kind,
                                   qid=qid,
                                   phase=para[0],
                                   phase1=para[1],
                                   phase2=para[2])

    if kind is None:

        result = Result()
        result.qubit_num = qubit_num
        result.cmem_num = cmem_num
        result.cid = cid
        result.shots = shots
        result.frequency = None
        result.backend = backend
        if out_state is True:
            result.qstate = __transform_qlazy_qstate(qstate)
            result.cmem = __transform_qlazy_cmem(cmem)
        return result

    #
    # after measurement gate
    #

    if set(qcirc.kind_list()) == {cfg.MEASURE}:
        q_list = []
        while True:
            kind = qcirc.kind_first()
            if kind is None:
                break
            (kind, qid, para, c, ctrl) = qcirc.pop_gate()
            q_list.append(qid[0])

        frequency, qstate = __qulacs_measure_shots(qstate, q_list, shots)

        result = Result()
        result.qubit_num = qubit_num
        result.cmem_num = cmem_num
        result.cid = cid
        result.shots = shots
        result.frequency = frequency
        result.backend = backend
        if out_state is True:
            result.qstate = __transform_qlazy_qstate(qstate)
            result.cmem = __transform_qlazy_cmem(cmem)

        return result

    frequency = Counter()
    qstate_tmp = None
    for _ in range(shots):

        qstate_tmp = qstate.copy()
        qcirc_tmp = qcirc.clone()

        while True:

            kind = qcirc_tmp.kind_first()
            if kind is None:
                break

            if kind == cfg.MEASURE:
                (kind, qid, para, c, ctrl) = qcirc_tmp.pop_gate()
                mval = __qulacs_measure(qstate_tmp, qubit_num, qid[0])
                if c is not None:
                    cmem[c] = mval

            elif kind == cfg.RESET:
                (kind, qid, para, c, ctrl) = qcirc_tmp.pop_gate()
                __qulacs_reset(qstate_tmp, qubit_num, qid[0])

            else:
                (kind, qid, para, c, ctrl) = qcirc_tmp.pop_gate()
                if (ctrl is None or (ctrl is not None and cmem[ctrl] == 1)):
                    __qulacs_operate_qgate(qstate_tmp,
                                           qubit_num,
                                           kind=kind,
                                           qid=qid,
                                           phase=para[0],
                                           phase1=para[1],
                                           phase2=para[2])

        if len(cmem) > 0:
            mval = ''.join(map(str, [cmem[i] for i in cid]))
            frequency[mval] += 1

    if qstate_tmp is not None:
        qstate.load(qstate_tmp.get_vector())

    if len(frequency) == 0:
        frequency = None

    result = Result()
    result.qubit_num = qubit_num
    result.cmem_num = cmem_num
    result.cid = cid
    result.shots = shots
    result.frequency = frequency
    result.backend = backend
    if out_state is True:
        result.qstate = __transform_qlazy_qstate(qstate)
        result.cmem = __transform_qlazy_cmem(cmem)

    return result