def test_tapering_qubits_manual_input(self):
        """
        Test taper_off_qubits function using LiH Hamiltonian.

        Checks different qubits inputs to remove manually.

        Test the lowest eigenvalue against the full Hamiltonian,
        and the full spectrum between them.
        """
        hamiltonian, spectrum = lih_hamiltonian()
        qubit_hamiltonian = jordan_wigner(hamiltonian)
        stab1 = QubitOperator('Z0 Z2', -1.0)
        stab2 = QubitOperator('Z1 Z3', -1.0)

        tapered_ham_0_3 = taper_off_qubits(qubit_hamiltonian, [stab1, stab2],
                                           manual_input=True,
                                           fixed_positions=[0, 3])
        tapered_ham_2_1 = taper_off_qubits(qubit_hamiltonian, [stab1, stab2],
                                           manual_input=True,
                                           fixed_positions=[2, 1])

        tapered_spectrum_0_3 = eigenspectrum(tapered_ham_0_3)
        tapered_spectrum_2_1 = eigenspectrum(tapered_ham_2_1)

        self.assertAlmostEqual(spectrum[0], tapered_spectrum_0_3[0])
        self.assertAlmostEqual(spectrum[0], tapered_spectrum_2_1[0])
        self.assertTrue(
            numpy.allclose(tapered_spectrum_0_3, tapered_spectrum_2_1))
Esempio n. 2
0
def taper_hamiltonian(H: QubitOperator, n_spin_orbitals, n_electrons):
    '''
    Taper off the H with the stabilizer in the correct phase based on hf state. 
    '''
    stabs = get_bare_stabilizer(H)
    hf = hf_occ(n_spin_orbitals, n_electrons, True)
    stabs = correct_stabilizer_phase(stabs, hf)
    return taper_off_qubits(H, stabs)
    def test_tappering_stabilizer_more_qubits(self):
        """Test for stabilizer with more qubits than operator."""
        hamiltonian = QubitOperator('Y0 Y1', 1.0)
        stab = QubitOperator('X0 X1 X2', -1.0)

        num_qubits = max(count_qubits(hamiltonian), count_qubits(stab))
        tap_ham = taper_off_qubits(hamiltonian, stab)
        num_qubits_tap = count_qubits(tap_ham)

        self.assertFalse(num_qubits == num_qubits_tap)
    def test_tapering_qubits_manual_input_false(self):
        """Test taper_off_qubits function using LiH Hamiltonian."""
        hamiltonian, spectrum = lih_hamiltonian()
        qubit_hamiltonian = jordan_wigner(hamiltonian)
        stab1 = QubitOperator('Z0 Z2', -1.0)
        stab2 = QubitOperator('Z1 Z3', -1.0)

        tapered_hamiltonian = taper_off_qubits(operator=qubit_hamiltonian,
                                               stabilizers=[stab1, stab2],
                                               manual_input=False,
                                               fixed_positions=[0, 3])
        tapered_spectrum = eigenspectrum(tapered_hamiltonian)

        self.assertAlmostEqual(spectrum[0], tapered_spectrum[0])
Esempio n. 5
0
def taper_qubits(qubit_H):
    n = count_qubits(qubit_H)
    H_dict = qubit_H.terms
    terms = list(H_dict.keys())
    num_terms = len(terms)

    #create bit string representation of each term
    field = fm.PrimeField(2)
    E = fm.Matrix(num_terms, 2 * n, field)
    for i in range(num_terms):

        term = terms[i]
        spot = 0
        for j in range(n):
            try:
                if term[spot][0] == j:
                    char = term[spot][1]
                    spot += 1
                else:
                    char = 'I'
            except IndexError:
                char = 'I'

            if char == 'I':
                E.set(i, j, 0)
                E.set(i, j + n, 0)
            if char == 'X':
                E.set(i, j, 0)
                E.set(i, j + n, 1)
            if char == 'Y':
                E.set(i, j, 1)
                E.set(i, j + n, 1)
            if char == 'Z':
                E.set(i, j, 1)
                E.set(i, j + n, 0)

    E.reduced_row_echelon_form()
    E_reduced = np.empty((num_terms, 2 * n), dtype=int)
    for row in range(num_terms):
        for col in range(2 * n):
            E_reduced[row][col] = E.get(row, col)
    del E

    while (E_reduced[-1] == np.zeros(2 * n)).all():
        E_reduced = np.delete(E_reduced, len(E_reduced) - 1, axis=0)

    #determine nullspace of parity matrix
    pivots, first_entries = [], []
    E_reduced = E_reduced.transpose()
    for col in range(len(E_reduced)):
        try:
            first_entry = list(E_reduced[col]).index(1)
            isPivot = True
            for col2 in range(col):
                if E_reduced[col2][first_entry] == 1:
                    isPivot = False
            if isPivot:
                pivots += [col]
                first_entries += [first_entry]
        except ValueError:
            pass
    nonpivots = list(set(range(len(E_reduced))) - set(pivots))

    nullspace = []
    for col in nonpivots:
        col_vector = list(E_reduced[col])

        null_vector = [0] * 2 * n
        for i in range(2 * n):
            if col == i:
                null_vector[i] = 1
            elif i in pivots:
                first_entry = first_entries[pivots.index(i)]
                if col_vector[first_entry] == 1:
                    null_vector[i] = 1
        nullspace += [null_vector]
    del E_reduced

    #create symmetry generators
    generators = []
    for i in range(len(nullspace)):
        null_vector = nullspace[i]
        tau = ''
        for j in range(n):
            x = null_vector[j]
            z = null_vector[j + n]

            if x == 0 and z == 0:
                tau += 'I'
            elif x == 1 and z == 0:
                tau += 'X'
            elif x == 1 and z == 1:
                tau += 'Y'
            else:
                tau += 'Z'
        generators += [tau]

    #convert generators into QubitOperators
    for i in range(len(generators)):
        tau = generators[i]

        tau_str = ''
        for j in range(n):
            if tau[j] != 'I':
                tau_str += tau[j] + str(j) + ' '

        generators[i] = QubitOperator(tau_str)

    #use generators to create different sectors of Hamiltonian
    sectors = []
    perms = list(itertools.product([1, -1], repeat=len(generators)))
    for perm in perms:
        signed_generators = [
            perm[i] * generators[i] for i in range(len(generators))
        ]

        sector = taper_off_qubits(qubit_H, signed_generators)
        sector.compress()
        sectors += [sector]

    return sectors