示例#1
0
    def test_build_from_openfermion(self):
        print('\n')
        trial_state = qforte.QuantumComputer(4)

        trial_prep = [None] * 5
        trial_prep[0] = qforte.gate('H', 0, 0)
        trial_prep[1] = qforte.gate('H', 1, 1)
        trial_prep[2] = qforte.gate('H', 2, 2)
        trial_prep[3] = qforte.gate('H', 3, 3)
        trial_prep[4] = qforte.gate('cX', 0, 1)

        trial_circ = qforte.QuantumCircuit()

        #prepare the circuit
        for gate in trial_prep:
            trial_circ.add_gate(gate)

        # use circuit to prepare trial state
        trial_state.apply_circuit(trial_circ)

        test_operator = QubitOperator('X2 Y1', 0.0 - 0.25j)
        test_operator += QubitOperator('Y2 Y1', 0.25)
        test_operator += QubitOperator('X2 X1', 0.25)
        test_operator += QubitOperator('Y2 X1', 0.0 + 0.25j)
        print(test_operator)

        qforte_operator = qforte.build_from_openfermion(test_operator)

        qforte.smart_print(qforte_operator)

        exp = trial_state.direct_op_exp_val(qforte_operator)
        print(exp)
        self.assertAlmostEqual(exp, 0.2499999999999999 + 0.0j)
def Fredkin(i, j, k):
    """
    builds a circuit to simulate a three-qubit Fredkin gate
    (Controled-SWAP, CSWAP gate).

    :param i: control qubit 1
    :param j: swap qubit 1
    :param k: swap qubit 2
    """

    C12 = qforte.gate('cX', j, i)
    C32 = qforte.gate('cX', j, k)
    CV23 = qforte.gate('cV', k, j)
    CV13 = qforte.gate('cV', k, i)

    F_circ = qforte.Circuit()
    F_circ.add(C32)
    F_circ.add(CV23)
    F_circ.add(CV13)
    F_circ.add(C12)
    F_circ.add(CV23.adjoint())
    F_circ.add(C32)
    F_circ.add(C12)

    return F_circ
示例#3
0
    def test_cX_gate(self):
        # test the cX/CNOT gate
        nqubits = 2
        basis0 = make_basis('00')  # basis0:|00>
        basis1 = make_basis('01')  # basis1:|10>
        basis2 = make_basis('10')  # basis2:|01>
        basis3 = make_basis('11')  # basis3:|11>
        computer = Computer(nqubits)
        CNOT = gate('CNOT', 0, 1)

        # test CNOT|00> = |00>
        computer.set_state([(basis0, 1.0)])
        computer.apply_gate(CNOT)
        coeff0 = computer.coeff(basis0)
        coeff1 = computer.coeff(basis1)
        coeff2 = computer.coeff(basis2)
        coeff3 = computer.coeff(basis3)
        assert coeff0 == approx(1.0, abs=1.0e-16)
        assert coeff1 == approx(0, abs=1.0e-16)
        assert coeff2 == approx(0, abs=1.0e-16)
        assert coeff3 == approx(0, abs=1.0e-16)

        # test CNOT|10> = |11>
        computer.set_state([(basis1, 1.0)])
        computer.apply_gate(CNOT)
        coeff0 = computer.coeff(basis0)
        coeff1 = computer.coeff(basis1)
        coeff2 = computer.coeff(basis2)
        coeff3 = computer.coeff(basis3)
        assert coeff0 == approx(0, abs=1.0e-16)
        assert coeff1 == approx(0, abs=1.0e-16)
        assert coeff2 == approx(0, abs=1.0e-16)
        assert coeff3 == approx(1, abs=1.0e-16)

        # test CNOT|01> = |01>
        computer.set_state([(basis2, 1.0)])
        computer.apply_gate(CNOT)
        coeff0 = computer.coeff(basis0)
        coeff1 = computer.coeff(basis1)
        coeff2 = computer.coeff(basis2)
        coeff3 = computer.coeff(basis3)
        assert coeff0 == approx(0, abs=1.0e-16)
        assert coeff1 == approx(0, abs=1.0e-16)
        assert coeff2 == approx(1, abs=1.0e-16)
        assert coeff3 == approx(0, abs=1.0e-16)

        # test CNOT|11> = |10>
        computer.set_state([(basis3, 1.0)])
        computer.apply_gate(CNOT)
        coeff0 = computer.coeff(basis0)
        coeff1 = computer.coeff(basis1)
        coeff2 = computer.coeff(basis2)
        coeff3 = computer.coeff(basis3)
        assert coeff0 == approx(0, abs=1.0e-16)
        assert coeff1 == approx(1, abs=1.0e-16)
        assert coeff2 == approx(0, abs=1.0e-16)
        assert coeff3 == approx(0, abs=1.0e-16)

        with pytest.raises(ValueError):
            gate('CNOT', 0, 1.0)
示例#4
0
    def test_trotterization_with_controlled_U(self):

        circ_vec = [build_circuit('Y_0 X_1'), build_circuit('X_0 Y_1')]
        coef_vec = [-1.0719145972781818j, 1.0719145972781818j]

        # the operator to be exponentiated
        minus_iH = QubitOperator()
        for i in range(len(circ_vec)):
            minus_iH.add(coef_vec[i], circ_vec[i])

        ancilla_idx = 2

        # exponentiate the operator
        Utrot, phase = trotterization.trotterize_w_cRz(minus_iH, ancilla_idx)

        # Case 1: positive control

        # initalize a quantum computer
        qc = Computer(3)

        # build HF state
        qc.apply_gate(gate('X', 0, 0))

        # put ancilla in |1> state
        qc.apply_gate(gate('X', 2, 2))

        # apply the troterized minus_iH
        qc.apply_circuit(Utrot)

        smart_print(qc)

        coeffs = qc.get_coeff_vec()

        assert coeffs[5] == approx(-0.5421829373021542, abs=1.0e-15)
        assert coeffs[6] == approx(-0.8402604730072732, abs=1.0e-15)

        # Case 2: negitive control

        # initalize a quantum computer
        qc = Computer(3)

        # build HF state
        qc.apply_gate(gate('X', 0, 0))

        # apply the troterized minus_iH
        qc.apply_circuit(Utrot)

        smart_print(qc)

        coeffs = qc.get_coeff_vec()

        assert coeffs[1] == approx(1, abs=1.0e-15)
    def test_H2_experiment_perfect(self):
        print('\n')
        #the RHF H2 energy at equilibrium bond length
        E_hf = -1.1166843870661929

        #the H2 qubit hamiltonian
        circ_vec = [
            Circuit(),
            build_circuit('Z_0'),
            build_circuit('Z_1'),
            build_circuit('Z_2'),
            build_circuit('Z_3'),
            build_circuit('Z_0 Z_1'),
            build_circuit('Y_0 X_1 X_2 Y_3'),
            build_circuit('Y_0 Y_1 X_2 X_3'),
            build_circuit('X_0 X_1 Y_2 Y_3'),
            build_circuit('X_0 Y_1 Y_2 X_3'),
            build_circuit('Z_0 Z_2'),
            build_circuit('Z_0 Z_3'),
            build_circuit('Z_1 Z_2'),
            build_circuit('Z_1 Z_3'),
            build_circuit('Z_2 Z_3')
        ]

        coef_vec = [
            -0.098863969784274, 0.1711977489805748, 0.1711977489805748,
            -0.222785930242875, -0.222785930242875, 0.1686221915724993,
            0.0453222020577776, -0.045322202057777, -0.045322202057777,
            0.0453222020577776, 0.1205448220329002, 0.1658670240906778,
            0.1658670240906778, 0.1205448220329002, 0.1743484418396386
        ]

        H2_qubit_hamiltonian = QubitOperator()
        for i in range(len(circ_vec)):
            H2_qubit_hamiltonian.add(coef_vec[i], circ_vec[i])

        # circuit for making HF state
        circ = Circuit()
        circ.add(gate('X', 0, 0))
        circ.add(gate('X', 1, 1))

        TestExperiment = Experiment(4, circ, H2_qubit_hamiltonian, 1000000)
        params2 = []
        avg_energy = TestExperiment.perfect_experimental_avg(params2)
        print('Perfectly Measured H2 Experimental Avg. Energy')
        print(avg_energy)
        print('H2 RHF Energy')
        print(E_hf)

        experimental_error = abs(avg_energy - E_hf)

        assert experimental_error == approx(0, abs=1.0e-14)
def generic_test_circ_vec_builder(qb_list, id):
    circ_vec_tc = [Circuit() for i in range(len(qb_list))]
    circ_vec_ct = [Circuit() for i in range(len(qb_list))]
    for i, pair in enumerate(ct_lst):
        t = pair[0]
        c = pair[1]
        if (id == 'cR'):
            circ_vec_ct[i].add(gate(id, t, c, 3.17 * t * c))
            circ_vec_tc[i].add(gate(id, c, t, 1.41 * t * c))

        else:
            circ_vec_ct[i].add(gate(id, t, c))
            circ_vec_tc[i].add(gate(id, c, t))

    return circ_vec_tc, circ_vec_ct
示例#7
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
示例#8
0
def build_circuit(Inputstr):

    circ = qforte.QuantumCircuit()
    sepstr = Inputstr.split() #Separate string to a list by space

    for i in range(len(sepstr)):
        inputgate = sepstr[i].split('_')
        if len(inputgate) == 2:
            circ.add_gate(qforte.gate(inputgate[0], int(inputgate[1]), int(inputgate[1])))
        else:
            if 'R' in inputgate[0]:
                circ.add_gate(qforte.gate(inputgate[0], int(inputgate[1]), int(inputgate[1]), float(inputgate[2])))
            else:
                circ.add_gate(qforte.gate(inputgate[0], int(inputgate[1]), int(inputgate[2])))

    return circ
示例#9
0
    def build_classical_CI_mats(self):
        """Builds a classical configuration interaction out of single determinants.
        """
        num_tot_basis = len(self._pre_sa_ref_lst)
        h_CI = np.zeros((num_tot_basis,num_tot_basis), dtype=complex)

        omega_lst = []
        Homega_lst = []

        for i, ref in enumerate(self._pre_sa_ref_lst):
            # NOTE: do NOT use Uprep here (is determinant specific).
            Un = qforte.Circuit()
            for j in range(self._nqb):
                if ref[j] == 1:
                    Un.add(qforte.gate('X', j, j))

            QC = qforte.Computer(self._nqb)
            QC.apply_circuit(Un)
            omega_lst.append(np.asarray(QC.get_coeff_vec(), dtype=complex))

            Homega = np.zeros((2**self._nqb), dtype=complex)

            QC.apply_operator(self._qb_ham)
            Homega_lst.append(np.asarray(QC.get_coeff_vec(), dtype=complex))

            for j in range(len(omega_lst)):
                h_CI[i][j] = np.vdot(omega_lst[i], Homega_lst[j])
                h_CI[j][i] = np.conj(h_CI[i][j])

        return h_CI
示例#10
0
    def test_op_exp_val_1(self):
        # test direct expectation value measurement
        trial_state = Computer(4)

        trial_prep = [None] * 5
        trial_prep[0] = gate('H', 0, 0)
        trial_prep[1] = gate('H', 1, 1)
        trial_prep[2] = gate('H', 2, 2)
        trial_prep[3] = gate('H', 3, 3)
        trial_prep[4] = gate('cX', 0, 1)

        trial_circ = Circuit()

        #prepare the circuit
        for gate_ in trial_prep:
            trial_circ.add(gate_)

        # use circuit to prepare trial state
        trial_state.apply_circuit(trial_circ)

        # gates needed for [a1^ a2] operator
        X1 = gate('X', 1, 1)
        X2 = gate('X', 2, 2)
        Y1 = gate('Y', 1, 1)
        Y2 = gate('Y', 2, 2)

        # initialize circuits to make operator
        circ1 = Circuit()
        circ1.add(X2)
        circ1.add(Y1)
        circ2 = Circuit()
        circ2.add(Y2)
        circ2.add(Y1)
        circ3 = Circuit()
        circ3.add(X2)
        circ3.add(X1)
        circ4 = Circuit()
        circ4.add(Y2)
        circ4.add(X1)

        #build the quantum operator for [a1^ a2]
        a1_dag_a2 = QubitOperator()
        a1_dag_a2.add(0.0 - 0.25j, circ1)
        a1_dag_a2.add(0.25, circ2)
        a1_dag_a2.add(0.25, circ3)
        a1_dag_a2.add(0.0 + 0.25j, circ4)

        #get direct expectatoin value
        exp = trial_state.direct_op_exp_val(a1_dag_a2)
        assert exp == approx(0.25, abs=2.0e-16)
示例#11
0
    def test_cY_gate(self):
        # test the cY gate
        nqubits = 2
        basis0 = make_basis('00')  # basis0:|00>
        basis1 = make_basis('01')  # basis1:|10>
        basis2 = make_basis('10')  # basis2:|01>
        basis3 = make_basis('11')  # basis3:|11>
        computer = Computer(nqubits)
        cY = gate('cY', 0, 1)

        # test cY|00> = |00>
        computer.set_state([(basis0, 1.0)])
        computer.apply_gate(cY)
        coeff0 = computer.coeff(basis0)
        coeff1 = computer.coeff(basis1)
        coeff2 = computer.coeff(basis2)
        coeff3 = computer.coeff(basis3)
        assert coeff0 == approx(1, abs=1.0e-16)
        assert coeff1 == approx(0, abs=1.0e-16)
        assert coeff2 == approx(0, abs=1.0e-16)
        assert coeff3 == approx(0, abs=1.0e-16)

        # test cY|01> = |01>
        computer.set_state([(basis2, 1.0)])
        computer.apply_gate(cY)
        coeff0 = computer.coeff(basis0)
        coeff1 = computer.coeff(basis1)
        coeff2 = computer.coeff(basis2)
        coeff3 = computer.coeff(basis3)
        assert coeff0 == approx(0, abs=1.0e-16)
        assert coeff1 == approx(0, abs=1.0e-16)
        assert coeff2 == approx(1, abs=1.0e-16)
        assert coeff3 == approx(0, abs=1.0e-16)

        # test cY|10> = i|11>
        computer.set_state([(basis1, 1.0)])
        computer.apply_gate(cY)
        coeff0 = computer.coeff(basis0)
        coeff1 = computer.coeff(basis1)
        coeff2 = computer.coeff(basis2)
        coeff3 = computer.coeff(basis3)
        assert coeff0 == approx(0, abs=1.0e-16)
        assert coeff1 == approx(0, abs=1.0e-16)
        assert coeff2 == approx(0, abs=1.0e-16)
        assert coeff3.imag == approx(1, abs=1.0e-16)

        # test cY|11> = -i|10>
        computer.set_state([(basis3, 1.0)])
        computer.apply_gate(cY)
        coeff0 = computer.coeff(basis0)
        coeff1 = computer.coeff(basis1)
        coeff2 = computer.coeff(basis2)
        coeff3 = computer.coeff(basis3)
        assert coeff0 == approx(0, abs=1.0e-16)
        assert coeff1.imag == approx(-1.0, abs=1.0e-16)
        assert coeff2 == approx(0, abs=1.0e-16)
        assert coeff3 == approx(0, abs=1.0e-16)
示例#12
0
    def test_circuit(self):
        print('\n')
        num_qubits = 10

        qc1 = Computer(num_qubits)
        qc2 = Computer(num_qubits)

        prep_circ = Circuit()
        circ = Circuit()

        for i in range(num_qubits):
            prep_circ.add(gate('H', i, i))

        for i in range(num_qubits):
            prep_circ.add(gate('cR', i, i + 1, 1.116 / (i + 1.0)))

        for i in range(num_qubits - 1):
            circ.add(gate('cX', i, i + 1))
            circ.add(gate('cX', i + 1, i))
            circ.add(gate('cY', i, i + 1))
            circ.add(gate('cY', i + 1, i))
            circ.add(gate('cZ', i, i + 1))
            circ.add(gate('cZ', i + 1, i))
            circ.add(gate('cR', i, i + 1, 3.14159 / (i + 1.0)))
            circ.add(gate('cR', i + 1, i, 2.17284 / (i + 1.0)))

        qc1.apply_circuit_safe(prep_circ)
        qc2.apply_circuit_safe(prep_circ)

        qc1.apply_circuit_safe(circ)
        qc2.apply_circuit(circ)

        C1 = qc1.get_coeff_vec()
        C2 = qc2.get_coeff_vec()

        diff_vec = [(C1[i] - C2[i]) * np.conj(C1[i] - C2[i])
                    for i in range(len(C1))]
        diff_norm = np.sum(diff_vec)

        print('\nNorm of diff vec |C - Csafe|')
        print('-----------------------------')
        print('   ', diff_norm)
        assert diff_norm == approx(0, abs=1.0e-16)
示例#13
0
def build_Uprep(ref, state_prep_type):
    Uprep = qforte.Circuit()
    if state_prep_type == 'occupation_list':
        for j in range(len(ref)):
            if ref[j] == 1:
                Uprep.add(qforte.gate('X', j, j))
    else:
        raise ValueError(
            "Only 'occupation_list' supported as state preparation type")

    return Uprep
示例#14
0
    def test_computer(self):
        print('\n')
        # test that 1 - 1 = 0

        # print('\n'.join(qc.str()))
        X = gate('X', 0, 0)
        print(X)
        Y = gate('Y', 0, 0)
        print(Y)
        Z = gate('Z', 0, 0)
        print(Z)
        H = gate('H', 0, 0)
        print(H)
        R = gate('R', 0, 0, 0.1)
        print(R)
        S = gate('S', 0, 0)
        print(S)
        T = gate('T', 0, 0)
        print(T)
        cX = gate('cX', 0, 1)
        print(cX)
        cY = gate('cY', 0, 1)
        print(cY)
        cZ = gate('cZ', 0, 1)
        print(cZ)
        # qcircuit = Circuit()
        # qcircuit.add(qg)
        # qcircuit.add(Gate(GateType.Hgate,1,1));
        # print('\n'.join(qcircuit.str()))
        # self.assertEqual(subtract(1, 1), 0)

        computer = Computer(16)
        # print(repr(computer))
        # circuit = Circuit()
        # circuit.add(X)
        for i in range(3000):
            computer.apply_gate(X)
            computer.apply_gate(Y)
            computer.apply_gate(Z)
            computer.apply_gate(H)
示例#15
0
文件: qpe.py 项目: henankf223/qforte
    def get_qft_circuit(self, direct):
        """Generates a circuit for Quantum Fourier Transformation with no swaping
        of bit positions.

            Arguments
            ---------

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

            self._aend : int
                The index of the end qubit.

            direct : string
                The direction of the Fourier Transform can be 'forward' or 'reverse.'

            Returns
            -------

            qft_circ : QuantumCircuit
                A circuit representing the Quantum Fourier Transform.
        """

        qft_circ = qforte.QuantumCircuit()
        lens = self._aend - self._abegin + 1
        for j in range(lens):
            qft_circ.add_gate(qforte.gate('H', j+self._abegin, j+self._abegin))
            for k in range(2, lens+1-j):
                phase = 2.0*np.pi/(2**k)
                qft_circ.add_gate(qforte.gate('cR', j+self._abegin, j+k-1+self._abegin, phase))

        if direct == 'forward':
            return qft_circ
        elif direct == 'reverse':
            return qft_circ.adjoint()
        else:
            raise ValueError('QFT directions can only be "forward" or "reverse"')

        return qft_circ
示例#16
0
def qft_circuit(na, nb, direct):
    """
    generates a circuit for Quantum Fourier Transformation

    :param na: (int) the begin qubit
    :param nb: (int) the end qubit

    :param direct: (string) the direction of the Fourier Transform
    can be 'forward' or 'reverse'
    """

    # Build qft circuit
    qft_circ = qforte.Circuit()
    lens = nb - na + 1
    for j in range(lens):
        qft_circ.add(qforte.gate('H', j + na, j + na))
        for k in range(2, lens + 1 - j):
            phase = 2.0 * numpy.pi / (2**k)
            qft_circ.add(qforte.gate('cR', j + na, j + k - 1 + na, phase))

    # Build reversing circuit
    if lens % 2 == 0:
        for i in range(int(lens / 2)):
            qft_circ.add(qforte.gate('SWAP', i + na, lens - 1 - i + na))
    else:
        for i in range(int((lens - 1) / 2)):
            qft_circ.add(qforte.gate('SWAP', i + na, lens - 1 - i + na))

    if direct == 'forward':
        return qft_circ
    elif direct == 'reverse':
        return qft_circ.adjoint()
    else:
        raise ValueError('QFT directions can only be "forward" or "reverse"')

    return qft_circ
示例#17
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())
示例#18
0
 def test_X_gate(self):
     # test the Pauli X gate
     nqubits = 1
     basis0 = make_basis('0')
     basis1 = make_basis('1')
     computer = Computer(nqubits)
     X = gate('X', 0)
     # test X|0> = |1>
     computer.apply_gate(X)
     coeff0 = computer.coeff(basis0)
     coeff1 = computer.coeff(basis1)
     assert coeff0 == approx(0, abs=1.0e-16)
     assert coeff1 == approx(1, abs=1.0e-16)
     # test X|1> = |0>
     computer.set_state([(basis1, 1.0)])
     computer.apply_gate(X)
     coeff0 = computer.coeff(basis0)
     coeff1 = computer.coeff(basis1)
     assert coeff0 == approx(1, abs=1.0e-16)
     assert coeff1 == approx(0, abs=1.0e-16)
示例#19
0
 def test_Y_gate(self):
     # test the Pauli Y gate
     nqubits = 1
     basis0 = make_basis('0')
     basis1 = make_basis('1')
     computer = Computer(nqubits)
     Y = gate('Y', 0, 0)
     # test Y|0> = i|1>
     computer.apply_gate(Y)
     coeff0 = computer.coeff(basis0)
     coeff1 = computer.coeff(basis1)
     assert coeff0 == approx(0, abs=1.0e-16)
     assert coeff1.imag == approx(1.0, abs=1.0 - 16)
     # test Y|1> = -i|0>
     computer.set_state([(basis1, 1.0)])
     computer.apply_gate(Y)
     coeff0 = computer.coeff(basis0)
     coeff1 = computer.coeff(basis1)
     assert coeff0.imag == approx(-1, abs=1.0e-16)
     assert coeff1 == approx(0, abs=1.0e-16)
示例#20
0
 def test_Z_gate(self):
     # test the Pauli Y gate
     nqubits = 1
     basis0 = make_basis('0')
     basis1 = make_basis('1')
     computer = Computer(nqubits)
     Z = gate('Z', 0, 0)
     # test Z|0> = |0>
     computer.apply_gate(Z)
     coeff0 = computer.coeff(basis0)
     coeff1 = computer.coeff(basis1)
     assert coeff0 == approx(1, abs=1.0e-16)
     assert coeff1 == approx(0, abs=1.0e-16)
     # test Z|1> = -|1>
     computer.set_state([(basis1, 1.0)])
     computer.apply_gate(Z)
     coeff0 = computer.coeff(basis0)
     coeff1 = computer.coeff(basis1)
     assert coeff0 == approx(0, abs=1.0e-16)
     assert coeff1 == approx(-1.0, abs=1.0e-16)
示例#21
0
    def build_orb_energies(self):
        self._orb_e = []

        print('\nBuilding single particle energies list:')
        print('---------------------------------------')
        qc = qforte.QuantumComputer(self._nqb)
        qc.apply_circuit(build_Uprep(self._ref, 'reference'))
        E0 = qc.direct_op_exp_val(self._qb_ham)

        for i in range(self._nqb):
            qc = qforte.QuantumComputer(self._nqb)
            qc.apply_circuit(build_Uprep(self._ref, 'reference'))
            qc.apply_gate(qforte.gate('X', i, i))
            Ei = qc.direct_op_exp_val(self._qb_ham)

            if (i < sum(self._ref)):
                ei = E0 - Ei
            else:
                ei = Ei - E0

            print(f'  {i:3}     {ei:+16.12f}')
            self._orb_e.append(ei)
示例#22
0
    def get_dynamics_circ(self):
        """Generates controlled unitaries. Ancilla qubit n controls a Trotter
        approximation to exp(-iHt*2^n).

        Returns
        -------
        U : Circuit
            A circuit approximating controlled application of e^-iHt.
        """
        U = qforte.Circuit()
        ancilla_idx = self._abegin

        temp_op = qforte.QubitOperator()
        scalar_terms = []
        for scalar, operator in self._qb_ham.terms():
            phase = -1.0j * scalar * self._t
            if operator.size() == 0:
                scalar_terms.append(scalar * self._t)
            else:
                # Strangely, the code seems to work even if this line is outside the else clause.
                # TODO: Figure out how.
                temp_op.add(phase, operator)

        for n in range(self._n_ancilla):
            tn = 2 ** n
            expn_op, _ = trotterize_w_cRz(temp_op, ancilla_idx,
                                               trotter_number=self._trotter_number)

            # Rotation for the scalar Hamiltonian term
            U.add(qforte.gate('R', ancilla_idx, ancilla_idx, -1.0 * np.sum(scalar_terms) * float(tn)))

            for i in range(tn):
                U.add_circuit(expn_op)

            ancilla_idx += 1

        return U
示例#23
0
def organizer_to_circuit(op_organizer):
    """Builds a Circuit from a operator orgainizer.

    Parameters
    ----------
    op_organizer : list
        An object to organize what the coefficient and Pauli operators in terms
        of the QubitOperator 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 QubitOperator.
    """
    operator = qforte.QubitOperator()
    for coeff, word in op_organizer:
        circ = qforte.Circuit()
        for letter in word:
            circ.add(qforte.gate(letter[0], letter[1], letter[1]))

        operator.add(coeff, circ)

    return operator
示例#24
0
    def build_orb_energies(self):
        """Calculates single qubit energies. Used in quasi-Newton updates.
        """
        self._orb_e = []

        print('\nBuilding single particle energies list:')
        print('---------------------------------------', flush=True)
        qc = qf.Computer(self._nqb)
        qc.apply_circuit(build_Uprep(self._ref, 'occupation_list'))
        E0 = qc.direct_op_exp_val(self._qb_ham)

        for i in range(self._nqb):
            qc = qf.Computer(self._nqb)
            qc.apply_circuit(build_Uprep(self._ref, 'occupation_list'))
            qc.apply_gate(qf.gate('X', i, i))
            Ei = qc.direct_op_exp_val(self._qb_ham)

            if(i<sum(self._ref)):
                ei = E0 - Ei
            else:
                ei = Ei - E0

            print(f'  {i:3}     {ei:+16.12f}', flush=True)
            self._orb_e.append(ei)
示例#25
0
文件: qpe.py 项目: henankf223/qforte
    def get_z_circuit(self):
        """Generates a circuit of Z gates for each quibit in the ancilla register.

            Arguments
            ---------

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

            self._aend : int
                The index of the end qubit.

            Returns
            -------

            z_circ : QuantumCircuit
                A circuit representing the the Z gates to be measured.
        """

        Z_circ = qforte.QuantumCircuit()
        for j in range(self._abegin, self._aend + 1):
            Z_circ.add_gate(qforte.gate('Z', j, j))

        return Z_circ
示例#26
0
文件: qpe.py 项目: henankf223/qforte
    def get_Uhad(self):
        """Generates a circuit which to puts all of the ancilla regester in
        superpostion.

            Arguments
            ---------

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

            self._aend : int
                The index of the end qubit.

            Returns
            -------

            qft_circ : QuantumCircuit
                A circuit of consecutive Hadamard gates.
        """
        Uhad = qforte.QuantumCircuit()
        for j in range(self._abegin, self._aend + 1):
            Uhad.add_gate(qforte.gate('H', j, j))

        return Uhad
def Toffoli(i, j, k):
    """
    builds a circuit to simulate a three-qubit Toffoli gate
    (Control-Control-NOT, CCNOT gate).

    :param i: control qubit 1
    :param j: control qubit 2
    :param k: target qubit
    """

    T1 = qforte.gate('T', i, i)
    T2 = qforte.gate('T', j, j)
    T3 = qforte.gate('T', k, k)
    C12 = qforte.gate('cX', j, i)
    C13 = qforte.gate('cX', k, i)
    C23 = qforte.gate('cX', k, j)
    H3 = qforte.gate('H', k, k)

    T_circ = qforte.Circuit()
    T_circ.add(H3)
    T_circ.add(C23)
    T_circ.add(T3.adjoint())
    T_circ.add(C13)
    T_circ.add(T3)
    T_circ.add(C23)
    T_circ.add(T3.adjoint())
    T_circ.add(C13)
    T_circ.add(T2)
    T_circ.add(T3)
    T_circ.add(C12)
    T_circ.add(H3)
    T_circ.add(T1)
    T_circ.add(T2.adjoint())
    T_circ.add(C12)

    return T_circ
示例#28
0
def exponentiate_single_term(coefficient,
                             term,
                             Use_cRz=False,
                             ancilla_idx=None,
                             Use_open_cRz=False):
    """
    returns the exponential of an string of Pauli operators multiplied by an imaginary coefficient

        exp(coefficient * term)

    Parameters
    ----------
    :param coefficient: float
        an imaginary coefficient that multiplies the Pauli string
    :param term: QuantumCircuit
        a Pauli string to be exponentiated
    """
    # This function assumes that the factor is imaginary. The following tests for it.
    if np.abs(np.real(coefficient)) > 1.0e-16:
        print("exp factor: ", coefficient)
        raise ValueError(
            'exponentiate_single_term() called with a real coefficient')

    # If the Pauli string has no terms this is just a phase factor
    if term.size() == 0:
        return (qforte.QuantumCircuit(), np.exp(coefficient))

    exponential = qforte.QuantumCircuit()
    to_z = qforte.QuantumCircuit()
    to_original = qforte.QuantumCircuit()
    cX_circ = qforte.QuantumCircuit()

    prev_target = None
    max_target = None

    for gate in term.gates():
        id = gate.gate_id()
        target = gate.target()
        control = gate.control()

        if (id == 'X'):
            to_z.add_gate(qforte.gate('H', target, control))
            to_original.add_gate(qforte.gate('H', target, control))
        elif (id == 'Y'):
            to_z.add_gate(qforte.gate('Rzy', target, control))
            to_original.add_gate(qforte.gate('Rzy', target, control))
        elif (id == 'I'):
            continue

        if (prev_target is not None):
            cX_circ.add_gate(qforte.gate('cX', target, prev_target))

        prev_target = target
        max_target = target

    # Gate that actually contains the parameterization for the term
    # TODO(Nick): investigate real/imaginary usage of 'factor' in below expression

    if (Use_cRz):
        z_rot = qforte.gate('cRz', max_target, ancilla_idx,
                            -2.0 * np.imag(coefficient))
    else:
        z_rot = qforte.gate('Rz', max_target, max_target,
                            -2.0 * np.imag(coefficient))

    # Assemble the actual exponential
    exponential.add_circuit(to_z)
    exponential.add_circuit(cX_circ)

    if (Use_open_cRz):
        exponential.add_gate(qforte.gate('X', ancilla_idx, ancilla_idx))

    exponential.add_gate(z_rot)

    if (Use_open_cRz):
        exponential.add_gate(qforte.gate('X', ancilla_idx, ancilla_idx))

    adj_cX_circ = cX_circ.adjoint()
    exponential.add_circuit(adj_cX_circ)
    adj_to_z = to_z.adjoint()
    exponential.add_circuit(adj_to_z)

    return (exponential, 1.0)
示例#29
0
    def build_qk_mats(self):
        num_tot_basis = len(self._single_det_refs) * self._nstates_per_ref

        h_mat = np.zeros((num_tot_basis,num_tot_basis), dtype=complex)
        s_mat = np.zeros((num_tot_basis,num_tot_basis), dtype=complex)

        # TODO (opt): make numpy arrays.
        omega_lst = []
        Homega_lst = []

        for i, ref in enumerate(self._single_det_refs):
            for m in range(self._nstates_per_ref):
                # NOTE: do NOT use Uprep here (is determinant specific).
                Um = qforte.Circuit()
                for j in range(self._nqb):
                    if ref[j] == 1:
                        Um.add(qforte.gate('X', j, j))
                        phase1 = 1.0

                if(m>0):
                    fact = (0.0-1.0j) * m * self._mr_dt
                    expn_op1, phase1 = trotterize(self._qb_ham, factor=fact, trotter_number=self._trotter_number)
                    Um.add(expn_op1)

                QC = qforte.Computer(self._nqb)
                QC.apply_circuit(Um)
                QC.apply_constant(phase1)
                omega_lst.append(np.asarray(QC.get_coeff_vec(), dtype=complex))

                QC.apply_operator(self._qb_ham)
                Homega_lst.append(np.asarray(QC.get_coeff_vec(), dtype=complex))

        if(self._diagonalize_each_step):
            print('\n\n')
            print(f"{'k(S)':>7}{'E(Npar)':>19}{'N(params)':>14}{'N(CNOT)':>18}{'N(measure)':>20}")
            print('-------------------------------------------------------------------------------')

        for p in range(num_tot_basis):
            for q in range(p, num_tot_basis):
                h_mat[p][q] = np.vdot(omega_lst[p], Homega_lst[q])
                h_mat[q][p] = np.conj(h_mat[p][q])
                s_mat[p][q] = np.vdot(omega_lst[p], omega_lst[q])
                s_mat[q][p] = np.conj(s_mat[p][q])

            if (self._diagonalize_each_step):
                # TODO (cleanup): have this print to a separate file
                evals, evecs = canonical_geig_solve(s_mat[0:p+1, 0:p+1],
                                   h_mat[0:p+1, 0:p+1],
                                   print_mats=False,
                                   sort_ret_vals=True)

                scond = np.linalg.cond(s_mat[0:p+1, 0:p+1])
                cs_str = '{:.2e}'.format(scond)

                k = p+1
                self._n_classical_params = k
                if(k==1):
                    self._n_cnot = self._srqk._n_cnot
                else:
                    self._n_cnot = 2 * Um.get_num_cnots()
                self._n_pauli_trm_measures  = k * self._Nl + self._srqk._n_pauli_trm_measures
                self._n_pauli_trm_measures += k * (k-1) * self._Nl
                self._n_pauli_trm_measures += k * (k-1)

                print(f' {scond:7.2e}    {np.real(evals[self._target_root]):+15.9f}    {self._n_classical_params:8}        {self._n_cnot:10}        {self._n_pauli_trm_measures:12}')

        return s_mat, h_mat
示例#30
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