示例#1
0
def build_from_openfermion(OF_qubitops, time_evo_factor = 1.0):

    """
    builds a QuantumOperator instance in
    qforte from a openfermion QubitOperator instance

    :param OF_qubitops: (QubitOperator) the QubitOperator instance from openfermion.
    """

    qforte_ops = qforte.QuantumOperator()

    #for term, coeff in sorted(OF_qubitops.terms.items()):
    for term, coeff in OF_qubitops.terms.items():
        circ_term = qforte.QuantumCircuit()
        #Exclude zero terms
        if np.isclose(coeff, 0.0):
            continue
        for factor in term:
            index, action = factor
            # Read the string name for actions(gates)
            action_string = OF_qubitops.action_strings[OF_qubitops.actions.index(action)]

            #Make qforte gates and add to circuit
            gate_this = qforte.gate(action_string, index, index)
            circ_term.add_gate(gate_this)

        #Add this term to operator
        qforte_ops.add_term(coeff*time_evo_factor, circ_term)

    return qforte_ops
示例#2
0
def build_operator(Inputstr):

    ops = qforte.QuantumOperator()
    sepstr = Inputstr.split(';')
    for i in range(len(sepstr)):
        inputterm = sepstr[i].split(',')
        ops.add_term(complex(inputterm[0]), qforte.build_circuit(inputterm[1]))

    return ops
示例#3
0
文件: qite.py 项目: henankf223/qforte
    def build_expansion_pool(self):
        print('\n==> Building expansion pool <==')
        self._sig = qf.QuantumOpPool()

        if (self._expansion_type == 'complete_qubit'):
            if (self._nqb > 6):
                raise ValueError(
                    'Using complete qubits expansion will result in a very large number of terms!'
                )
            self._sig.fill_pool("complete_qubit", self._ref)

        elif (self._expansion_type == 'cqoy'):
            self._sig.fill_pool("cqoy", self._ref)

        elif (self._expansion_type
              in {'SD', 'GSD', 'SDT', 'SDTQ', 'SDTQP', 'SDTQPH'}):
            P = qf.SQOpPool()
            P.set_orb_spaces(self._ref)
            P.fill_pool(self._expansion_type)
            sig_temp = P.get_quantum_operator("commuting_grp_lex", False)

            # Filter the generated operators, so that only those with an odd number of Y gates are allowed.
            # See section "Real Hamiltonians and states" in the SI of Motta for theoretical justification.
            # Briefly, this method solves Ax=b, but all b elements with an odd number of Y gates are imaginary and
            # thus vanish. This method will not be correct for non-real Hamiltonians or states.
            for alph, rho in sig_temp.terms():
                nygates = 0
                temp_rho = qf.QuantumCircuit()
                for gate in rho.gates():
                    temp_rho.add_gate(
                        qf.gate(gate.gate_id(), gate.target(), gate.control()))
                    if (gate.gate_id() == "Y"):
                        nygates += 1

                if (nygates % 2 == 1):
                    rho_op = qf.QuantumOperator()
                    rho_op.add_term(1.0, temp_rho)
                    self._sig.add_term(1.0, rho_op)

        elif (self._expansion_type == 'test'):
            self._sig.fill_pool("test", self._ref)

        else:
            raise ValueError('Invalid expansion type specified.')

        self._NI = len(self._sig.terms())
示例#4
0
def trotterize(operator, factor=1.0, trotter_number=1, trotter_order=1):

    """
    returns a circuit equivilant to an exponentiated QuantumOperator

    :param operator: (QuantumOperator) the operator or state preparation ansatz
    (represented as a sum of pauli terms) to be exponentiated

    :param trotter_number: (int) for an operator A with terms A_i, the trotter_number
    is the exponent (N) for to product of single term
    exponentals e^A ~ ( Product_i(e^(A_i/N)) )^N

    :param trotter_number: (int) the order of the troterization approximation, can be 1 or 2
    """

    total_phase = 1.0
    troterized_operator = qforte.QuantumCircuit()

    if (trotter_number == 1) and (trotter_order == 1):
        #loop over terms in operator
        for term in operator.terms():
            term_generator, phase = qforte.exponentiate_single_term(factor*term[0],term[1])
            for gate in term_generator.gates():
                troterized_operator.add_gate(gate)
            total_phase *= phase


    else:
        if(trotter_order > 1):
            raise NotImplementedError("Higher order trotterization is not yet implemented.")

        ho_op = qforte.QuantumOperator()

        for k in range(1, trotter_number+1):
            for term in operator.terms():
                ho_op.add_term( factor * term[0] / float(trotter_number) , term[1])

        for trot_term in ho_op.terms():
            term_generator, phase = qforte.exponentiate_single_term(trot_term[0],trot_term[1])
            for gate in term_generator.gates():
                troterized_operator.add_gate(gate)
            total_phase *= phase

    return (troterized_operator, total_phase)
示例#5
0
文件: qite.py 项目: henankf223/qforte
    def do_qite_step(self):

        btot = self.build_b()
        A = qf.QuantumOperator()

        if (self._sparseSb):
            sp_idxs, S, btot = self.build_sparse_S_b(btot)
        else:
            S = self.build_S()

        x = lstsq(S, btot)[0]
        x = np.real(x)

        if (self._sparseSb):
            for I, spI in enumerate(sp_idxs):
                if np.abs(x[I]) > self._x_thresh:
                    A.add_term(-1.0j * self._db * x[I],
                               self._sig.terms()[spI][1].terms()[0][1])
                    self._n_classical_params += 1

        else:
            for I, SigI in enumerate(self._sig.terms()):
                if np.abs(x[I]) > self._x_thresh:
                    A.add_term(-1.0j * self._db * x[I], SigI[1].terms()[0][1])
                    self._n_classical_params += 1

        if (self._verbose):
            print('\nbtot:\n ', btot)
            print('\n S:  \n')
            matprint(S)
            print('\n x:  \n')
            print(x)

        eiA_kb, phase1 = trotterize(A, trotter_number=self._trotter_number)
        self._total_phase *= phase1
        self._Uqite.add_circuit(eiA_kb)
        self._qc.apply_circuit(eiA_kb)
        self._Ekb.append(np.real(self._qc.direct_op_exp_val(self._qb_ham)))

        self._n_cnot += eiA_kb.get_num_cnots()

        if (self._verbose):
            qf.smart_print(self._qc)
示例#6
0
def organizer_to_circuit(op_organizer):
    """Builds a QuantumCircuit from a operator orgainizer.

    Parameters
    ----------
    op_organizer : list
        An object to organize what the coefficient and Pauli operators in terms
        of the QuantumOperator will be.

        The orginzer is of the form
        [[coeff_a, [ ("X", i), ("Z", j),  ("Y", k), ...  ] ], [...] ...]
        where X, Y, Z are strings that indicate Pauli opterators;
        i, j, k index qubits and coeff_a indicates the coefficient for the ath
        term in the QuantumOperator.
    """
    operator = qforte.QuantumOperator()
    for coeff, word in op_organizer:
        circ = qforte.QuantumCircuit()
        for letter in word:
            circ.add_gate(qforte.gate(letter[0], letter[1], letter[1]))

        operator.add_term(coeff, circ)

    return operator
示例#7
0
def trotterize_w_cRz(operator, ancilla_qubit_idx, factor=1.0, Use_open_cRz=False, trotter_number=1, trotter_order=1):

    """
    returns a circuit equivilant to an exponentiated QuantumOperator in which each term
    in the trotterization exp(-i * theta_k ) only acts on the register if the ancilla
    qubit is in the |1> state.

    :param operator: (QuantumOperator) the operator or state preparation ansatz
    (represented as a sum of pauli terms) to be exponentiated

    :param ancilla_qubit_idx: (int) the index of the ancilla qubit

    :param Use_open_cRz: (bool) uses an open controlled Rz gate in exponentiation
    (see Fig. 11 on page 185 of Nielson and Chung's
    "Quantum Computation and Quantum Informatoin 10th Aniversary Ed.")

    :param trotter_number: (int) for an operator A with terms A_i, the trotter_number
    is the exponent (N) for to product of single term
    exponentals e^A ~ ( Product_i(e^(A_i/N)) )^N

    :param trotter_order: (int) the order of the troterization approximation, can be 1 or 2
    """

    total_phase = 1.0
    troterized_operator = qforte.QuantumCircuit()

    if (trotter_number == 1) and (trotter_order == 1):
        #loop over terms in operator
        if(Use_open_cRz):
            for term in operator.terms():
                term_generator, phase = qforte.exponentiate_single_term(factor*term[0],term[1], Use_cRz=True, ancilla_idx=ancilla_qubit_idx, Use_open_cRz=True)
                for gate in term_generator.gates():
                    troterized_operator.add_gate(gate)
                total_phase *= phase
        else:
            for term in operator.terms():
                term_generator, phase = qforte.exponentiate_single_term(factor*term[0],term[1], Use_cRz=True, ancilla_idx=ancilla_qubit_idx)
                for gate in term_generator.gates():
                    troterized_operator.add_gate(gate)
                total_phase *= phase

    else:
        if(trotter_order > 1):
            raise NotImplementedError("Higher order trotterization is not yet implemented.")
        ho_op = qforte.QuantumOperator()
        for k in range(1, trotter_number+1):
            k = float(k)
            for term in operator.terms():
                ho_op.add_term( factor*term[0] / float(trotter_number) , term[1])

        if(Use_open_cRz):
            for trot_term in ho_op.terms():
                term_generator, phase = qforte.exponentiate_single_term(trot_term[0],trot_term[1], Use_cRz=True, ancilla_idx=ancilla_qubit_idx, Use_open_cRz=True)
                for gate in term_generator.gates():
                    troterized_operator.add_gate(gate)
                total_phase *= phase
        else:
            for trot_term in ho_op.terms():
                term_generator, phase = qforte.exponentiate_single_term(trot_term[0],trot_term[1], Use_cRz=True, ancilla_idx=ancilla_qubit_idx)
                for gate in term_generator.gates():
                    troterized_operator.add_gate(gate)
                total_phase *= phase

    return (troterized_operator, total_phase)
示例#8
0
文件: qpe.py 项目: henankf223/qforte
    def get_dynamics_circ(self):
        """Generates a circuit for controlled dynamics operations used in phase
        estimation. It approximates the exponentiated hermetina operator H as e^-iHt.

            Arguments
            ---------

            H : QuantumOperator
                The hermetian operaotr whos dynamics and eigenstates are of interest,
                ususally the Hamiltonian.

            trotter_num : int
                The trotter number (m) to use for the decompostion. Exponentiation
                is exact in the m --> infinity limit.

            self._abegin : int
                The index of the begin qubit.

            n_ancilla : int
                The number of anciall qubit used for the phase estimation.
                Determintes the total number of time steps.

            t : float
                The total evolution time.

            Returns
            -------

            Udyn : QuantumCircuit
                A circuit approximating controlled application of e^-iHt.
        """
        Udyn = qforte.QuantumCircuit()
        ancilla_idx = self._abegin
        total_phase = 1.0
        for n in range(self._n_ancilla):
            tn = 2 ** n
            temp_op = qforte.QuantumOperator()
            scaler_terms = []
            for h in self._qb_ham.terms():
                c, op = h
                phase = -1.0j * self._t * c #* tn
                temp_op.add_term(phase, op)
                gates = op.gates()
                if op.size() == 0:
                    scaler_terms.append(c * self._t)


            expn_op, phase1 = trotterize_w_cRz(temp_op,
                                               ancilla_idx,
                                               trotter_number=self._trotter_number)

            # Rotation for the scaler Hamiltonian term
            Udyn.add_gate(qforte.gate('R', ancilla_idx, ancilla_idx,  -1.0 * np.sum(scaler_terms) * float(tn)))

            # NOTE: Approach uses 2^ancilla_idx blocks of the time evolution circuit
            for i in range(tn):
                for gate in expn_op.gates():
                    Udyn.add_gate(gate)

            ancilla_idx += 1

        return Udyn
示例#9
0
文件: srqk.py 项目: henankf223/qforte
    def matrix_element(self, m, n, use_op=False):
        """Returns a single matrix element M_mn based on the evolution of
        two unitary operators Um = exp(-i * m * dt * H) and Un = exp(-i * n * dt *H)
        on a reference state |Phi_o>, (optionally) with respect to an operator A.
        Specifically, M_mn is given by <Phi_o| Um^dag Un | Phi_o> or
        (optionally if A is specified) <Phi_o| Um^dag A Un | Phi_o>.

            Arguments
            ---------

            ref : list
                The the reference state |Phi_o>.

            dt : float
                The real time step value (delta t).

            m : int
                The number of time steps for the Um evolution.

            n : int
                The number of time steps for the Un evolution.

            H : QuantumOperator
                The operator to time evolove with respect to (usually the Hamiltonain).

            nqubits : int
                The number of qubits

            A : QuantumOperator
                The overal operator to measure with respect to (optional).

            trot_number : int
                The number of trotter steps (m) to perform when approximating the matrix
                exponentials (Um or Un). For the exponential of two non commuting terms
                e^(A + B), the approximate operator C(m) = (e^(A/m) * e^(B/m))^m is
                exact in the infinite m limit.

            Returns
            -------
            value : complex
                The outcome of measuring <X> and <Y> to determine <2*sigma_+>,
                ultimately the value of the matrix elemet.

        """
        value = 0.0
        ancilla_idx = self._nqb
        Uk = qforte.QuantumCircuit()
        temp_op1 = qforte.QuantumOperator()
        # TODO (opt): move to C side.
        for t in self._qb_ham.terms():
            c, op = t
            phase = -1.0j * n * self._dt * c
            temp_op1.add_term(phase, op)

        expn_op1, phase1 = trotterize_w_cRz(
            temp_op1, ancilla_idx, trotter_number=self._trotter_number)

        for gate in expn_op1.gates():
            Uk.add_gate(gate)

        Ub = qforte.QuantumCircuit()

        temp_op2 = qforte.QuantumOperator()
        for t in self._qb_ham.terms():
            c, op = t
            phase = -1.0j * m * self._dt * c
            temp_op2.add_term(phase, op)

        expn_op2, phase2 = trotterize_w_cRz(
            temp_op2,
            ancilla_idx,
            trotter_number=self._trotter_number,
            Use_open_cRz=False)

        for gate in expn_op2.gates():
            Ub.add_gate(gate)

        if not use_op:
            # TODO (opt): use Uprep
            cir = qforte.QuantumCircuit()
            for j in range(self._nqb):
                if self._ref[j] == 1:
                    cir.add_gate(qforte.gate('X', j, j))

            cir.add_gate(qforte.gate('H', ancilla_idx, ancilla_idx))

            cir.add_circuit(Uk)

            cir.add_gate(qforte.gate('X', ancilla_idx, ancilla_idx))
            cir.add_circuit(Ub)
            cir.add_gate(qforte.gate('X', ancilla_idx, ancilla_idx))

            X_op = qforte.QuantumOperator()
            x_circ = qforte.QuantumCircuit()
            Y_op = qforte.QuantumOperator()
            y_circ = qforte.QuantumCircuit()

            x_circ.add_gate(qforte.gate('X', ancilla_idx, ancilla_idx))
            y_circ.add_gate(qforte.gate('Y', ancilla_idx, ancilla_idx))

            X_op.add_term(1.0, x_circ)
            Y_op.add_term(1.0, y_circ)

            X_exp = qforte.Experiment(self._nqb + 1, cir, X_op, 100)
            Y_exp = qforte.Experiment(self._nqb + 1, cir, Y_op, 100)

            params = [1.0]
            x_value = X_exp.perfect_experimental_avg(params)
            y_value = Y_exp.perfect_experimental_avg(params)

            value = (x_value + 1.0j * y_value) * phase1 * np.conj(phase2)

        else:
            value = 0.0
            for t in self._qb_ham.terms():
                c, V_l = t

                # TODO (opt):
                cV_l = qforte.QuantumCircuit()
                for gate in V_l.gates():
                    gate_str = gate.gate_id()
                    target = gate.target()
                    control_gate_str = 'c' + gate_str
                    cV_l.add_gate(
                        qforte.gate(control_gate_str, target, ancilla_idx))

                cir = qforte.QuantumCircuit()
                # TODO (opt): use Uprep
                for j in range(self._nqb):
                    if self._ref[j] == 1:
                        cir.add_gate(qforte.gate('X', j, j))

                cir.add_gate(qforte.gate('H', ancilla_idx, ancilla_idx))

                cir.add_circuit(Uk)
                cir.add_circuit(cV_l)

                cir.add_gate(qforte.gate('X', ancilla_idx, ancilla_idx))
                cir.add_circuit(Ub)
                cir.add_gate(qforte.gate('X', ancilla_idx, ancilla_idx))

                X_op = qforte.QuantumOperator()
                x_circ = qforte.QuantumCircuit()
                Y_op = qforte.QuantumOperator()
                y_circ = qforte.QuantumCircuit()

                x_circ.add_gate(qforte.gate('X', ancilla_idx, ancilla_idx))
                y_circ.add_gate(qforte.gate('Y', ancilla_idx, ancilla_idx))

                X_op.add_term(1.0, x_circ)
                Y_op.add_term(1.0, y_circ)

                X_exp = qforte.Experiment(self._nqb + 1, cir, X_op, 100)
                Y_exp = qforte.Experiment(self._nqb + 1, cir, Y_op, 100)

                # TODO (cleanup): Remove params as required arg (Nick)
                params = [1.0]
                x_value = X_exp.perfect_experimental_avg(params)
                y_value = Y_exp.perfect_experimental_avg(params)

                element = (x_value + 1.0j * y_value) * phase1 * np.conj(phase2)
                value += c * element

        return value