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))
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])
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