def test_tapering_qubits_remove_positions(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, positions) = taper_off_qubits(operator=qubit_hamiltonian, stabilizers=[stab1, stab2], manual_input=True, fixed_positions=[0, 3], output_tapered_positions=True) tapered_spectrum = eigenspectrum(tapered_hamiltonian) self.assertAlmostEqual(spectrum[0], tapered_spectrum[0]) self.assertEqual(positions, [0, 3])
def full_connected_transverse_field_ising(n_qubit, field=1, spin_coupling=1): spin_coupling_hamiltonian = QubitOperator() for i in range(n_qubit): for j in range(i + 1, n_qubit): spin_coupling_hamiltonian += QubitOperator( "Z" + str(i)) * QubitOperator("Z" + str(j)) field_hamitonian = QubitOperator() for i in range(n_qubit): field_hamitonian += QubitOperator("X" + str(i)) hamiltonian = spin_coupling * spin_coupling_hamiltonian + field * field_hamitonian from .SpinChainInitBlock import get_transverse_field_init_block energy_obj = EnergyObjective( hamiltonian, n_qubit, init_block=get_transverse_field_init_block(n_qubit)) return energy_obj
def inner_product(qubit_op, state1, state2=None): qubit_op.compress() if state2 is None: state2 = state1.copy() if qubit_op == QubitOperator(): return 0 else: array_op = get_sparse_operator(qubit_op).toarray() return np.dot(state1.conj().T, np.dot(array_op, state2))[0][0]
def get_operator_nontrivial_term_weight_sum(operator: QubitOperator): coeff_sum = 0 for pauli_and_coeff in operator.get_operators(): for string_pauli in pauli_and_coeff.terms: if len(string_pauli) == 0: print(string_pauli) continue coeff_sum += abs(pauli_and_coeff.terms[string_pauli]) return coeff_sum
def test_qiskitpauli_to_qubitop(): qiskit_term = WeightedPauliOperator([ [1, Pauli.from_label("XIIIIY")], ]) op_fermion_term = QubitOperator(((0, "X"), (5, "Y"))) test_op_fermion_term = qiskitpauli_to_qubitop(qiskit_term) assert test_op_fermion_term.isclose(op_fermion_term)
def test_matvec_zx(self): """Testing with multiple factors.""" vec = numpy.array([1, 2, 3, 4]) matvec_expected = numpy.array([2, 1, -4, -3]) self.assertTrue( numpy.allclose( LinearQubitOperator(QubitOperator('Z0 X1')) * vec, matvec_expected))
def test_get_interaction_operator_identity(self): interaction_operator = InteractionOperator(-2j, self.one_body, self.two_body) qubit_operator = jordan_wigner(interaction_operator) self.assertTrue(qubit_operator == -2j * QubitOperator(())) self.assertEqual( interaction_operator, get_interaction_operator(reverse_jordan_wigner(qubit_operator), self.n_qubits))
def test_matvec_x(self): """Testing product with X.""" vec = numpy.array([1, 2, 3, 4]) matvec_expected = numpy.array([2, 1, 4, 3]) self.assertTrue( numpy.allclose( LinearQubitOperator(QubitOperator('X1')) * vec, matvec_expected))
def test_get_exact_expectation_values_empty_op(self): # Given circuit = Circuit(Program(H(0), CNOT(0, 1), CNOT(1, 2))) qubit_operator = QubitOperator() # When expectation_values = self.wf_simulator.get_exact_expectation_values( circuit, qubit_operator) # Then self.assertAlmostEqual(sum(expectation_values.values), 0.0)
def test_matvec_y(self): """Testing product with Y.""" vec = numpy.array([1, 2, 3, 4], dtype=complex) matvec_expected = 1.0j * numpy.array([-2, 1, -4, 3], dtype=complex) self.assertTrue( numpy.allclose( LinearQubitOperator(QubitOperator('Y1')) * vec, matvec_expected))
def z_term(self, p): """Returns the Z term on a single qubit as a QubitOperator Arguments: p [int] -- qubit index Returns: [QubitOperator] -- Z term on the chosen qubit. """ return QubitOperator("Z" + str(p), self.hc[p] / 2 + sum(self.hr2[:, p]) / 2)
def test_matvec_z(self): """Testing product with Z.""" vec = numpy.array([1, 2, 3, 4]) matvec_expected = numpy.array([1, 2, -3, -4]) self.assertTrue( numpy.allclose( LinearQubitOperator(QubitOperator('Z0'), 2) * vec, matvec_expected))
def test_matvec_0(self): """Testing with zero term.""" qubit_operator = QubitOperator.zero() vec = numpy.array([1, 2, 3, 4, 5, 6, 7, 8]) matvec_expected = numpy.zeros(vec.shape) self.assertTrue(numpy.allclose( LinearQubitOperator(qubit_operator, 3) * vec, matvec_expected))
def test_matvec_compare(self): """Compare LinearQubitOperator with qubit_operator_sparse.""" qubit_operator = QubitOperator('X0 Y1 Z3') mat_expected = qubit_operator_sparse(qubit_operator) self.assertTrue(numpy.allclose(numpy.transpose( numpy.array([LinearQubitOperator(qubit_operator) * v for v in numpy.identity(16)])), mat_expected.A))
def test_ccr_onsite(self): c1 = FermionOperator(((1, 1), )) a1 = hermitian_conjugated(c1) self.assertTrue( normal_ordered(c1 * a1) == FermionOperator(()) - normal_ordered(a1 * c1)) self.assertTrue( jordan_wigner(c1 * a1) == QubitOperator(()) - jordan_wigner(a1 * c1))
def test_commutator(self): operator_a = FermionOperator('') self.assertTrue(FermionOperator().isclose( commutator(operator_a, self.fermion_operator))) operator_b = QubitOperator('X1 Y2') self.assertTrue( commutator(self.qubit_operator, operator_b).isclose(self.qubit_operator * operator_b - operator_b * self.qubit_operator))
def make_hamiltonian(model, nspin, nterm): if model == "heisenberg": sx = [] sy = [] sz = [] for i in range(nspin): sx.append(QubitOperator(f"X{i}")) sy.append(QubitOperator(f"Y{i}")) sz.append(QubitOperator(f"Z{i}")) H = [] active = [] for term in range(nterm): jw_hamiltonian = 0*QubitOperator("") if term == nspin-1: i = term j = 0 active.append([i, j]) jw_hamiltonian += sx[i]*sx[j] + sy[i]*sy[j] + sz[i]*sz[j] str_jw_hamiltonian = str(jw_hamiltonian) observable = create_observable_from_openfermion_text( str_jw_hamiltonian) H.append(observable) else: i = term j = i + 1 active.append([i, j]) jw_hamiltonian += sx[i]*sx[j] + sy[i]*sy[j] + sz[i]*sz[j] str_jw_hamiltonian = str(jw_hamiltonian) observable = create_observable_from_openfermion_text( str_jw_hamiltonian) H.append(observable) jw_hamiltonian_full = 0*QubitOperator("") for i in range(nspin): if i < nspin-1: j = i + 1 else: j = 0 jw_hamiltonian_full += sx[i]*sx[j] + sy[i]*sy[j] + sz[i]*sz[j] str_jw_hamiltonian_full = str(jw_hamiltonian_full) observable_full = create_observable_from_openfermion_text( str_jw_hamiltonian_full) return H, active, observable_full
def dissolve(term): """Decomposition helper. Takes a product of binary variables and outputs the Pauli-string sum that corresponds to the decomposed multi-qubit operator. Args: term (tuple): product of binary variables, i.e.: 'w0 w2 w3' Returns (QubitOperator): superposition of Pauli-strings Raises: ValueError: if the variable in term is not integer """ prod = 2.0 for var in term: if not isinstance(var, (numpy.int32, numpy.int64, int)): raise ValueError('dissolve only works on integers') prod *= (QubitOperator((), 0.5) - QubitOperator('Z' + str(var), 0.5)) return QubitOperator((), 1.0) - prod
def test_time_evolve_type_checks(): one_pauli_term = QubitOperator('X0 Y2 Z3') with pytest.raises(TypeError): TimeEvolution('a', one_pauli_term) with pytest.raises(TypeError): TimeEvolution(-1.0 * 1j, one_pauli_term) with pytest.raises(TypeError): TimeEvolution(1.0, FermionOperator('1^'))
def test_apply_operator(self): """Tests apply_operator() since it's executed on other processors.""" vec = numpy.array([1, 2, 3, 4]) matvec_expected = numpy.array([2, 1, 4, 3]) self.assertTrue( numpy.allclose( apply_operator( (LinearQubitOperator(QubitOperator('X1')), vec)), matvec_expected))
def construct_C(n, r, p): C = QubitOperator('', 0) perms = list(itertools.product([1, -1], repeat=n)) for perm in perms: term = QubitOperator('', 0) for j in range(r): product = QubitOperator('', 1) for i in range(n): product *= QubitOperator('', 1 / 2) + QubitOperator( 'Z' + str(i + n * j), perm[i] / 2) sign = -1 if j < p else 1 term += sign * product C += term**2 return C
def get_one_DMs(get_expectation_value, wavefunction): n_qubit = len(wavefunction) one_DMs = np.array([PauliI] * n_qubit) for i in range(0, n_qubit): for ip in range(1, 4): one_DMs[i] = one_DMs[i] + get_expectation_value( QubitOperator(PauliString[ip] + str(0)), [wavefunction[i]]) * PauliMat[ip] one_DMs[i] = one_DMs[i] / 2 return one_DMs
def get_expectation_values_from_rdms( interactionrdm: InteractionRDM, qubitoperator: QubitOperator, sort_terms: bool = False, ) -> ExpectationValues: """Computes expectation values of Pauli strings in a QubitOperator given a fermionic InteractionRDM from OpenFermion. Args: interactionrdm: interaction RDM to use for the expectation values computation, as an OF InteractionRDM object qubitoperator: qubit operator to compute the expectation values for in the form of an OpenFermion QubitOperator object sort_terms: whether or not the input qubit operator needs to be sorted before calculating expectations Returns: expectation values of Pauli strings in the qubit operator as an ExpectationValues object """ if sort_terms: terms_iterator = sorted(qubitoperator.terms.items(), key=lambda x: abs(x[1]), reverse=True) else: terms_iterator = qubitoperator.terms.items() reordered_qubitoperator = QubitOperator() for term, coefficient in terms_iterator: reordered_qubitoperator += QubitOperator(term, coefficient) expectations_packed = interactionrdm.get_qubit_expectations( reordered_qubitoperator) if () in expectations_packed.terms: del expectations_packed.terms[( )] # Expectation of the constant term is excluded from expectation values expectations = np.array(list(expectations_packed.terms.values())) if np.any(np.abs(np.imag(expectations)) > 1e-3): raise RuntimeWarning( f"Expectation values extracted from rdms inside get_expectation_values_from_rdms are complex!" ) expectations = np.real(expectations) np.clip(expectations, -1, 1, out=expectations) return ExpectationValues(expectations)
def benchmark_get_linear_qubit_operator(n_qubits, n_terms): """Test speed with getting a linear operator from a Qubit Operator. Args: n_qubits: The number of qubits, implying the dimension of the operator is 2 ** n_qubits. n_terms: The number of terms in a qubit operator. Returns: runtime_operator: The time it takes to get the linear operator. runtime_matvec: The time it takes to perform matrix multiplication. """ # Generates Qubit Operator with specified number of terms. m = { 0: 'X', 1: 'Y', 2: 'Z', } qubit_operator = QubitOperator.zero() for _ in xrange(n_terms): tuples = [] for i in xrange(n_qubits): op = numpy.random.randint(4) # 3 is 'I', so just skip. if op > 2: continue tuples.append((i, m[op])) if tuples: qubit_operator += QubitOperator(tuples, 1.00) # Gets an instance of LinearOperator. start = time.time() linear_operator = get_linear_qubit_operator(qubit_operator) end = time.time() runtime_operator = end - start vec = numpy.random.rand(2**n_qubits) # Performs matrix multiplication. start = time.time() matvec = linear_operator * vec end = time.time() runtime_matvec = end - start return runtime_operator, runtime_matvec
def test_z(self): pauli_z = QubitOperator(((2, 'Z'),)) transmed_z = reverse_jordan_wigner(pauli_z) expected = (FermionOperator(()) + FermionOperator(((2, 1), (2, 0)), -2.)) self.assertTrue(transmed_z == expected) retransmed_z = jordan_wigner(transmed_z) self.assertTrue(pauli_z == retransmed_z)
def get_operator_n_qubit(operator: QubitOperator): n_qubit = -1 for pauli_and_coeff in operator.get_operators(): for string_pauli in pauli_and_coeff.terms: if len(string_pauli) == 0: continue highest_index = string_pauli[len(string_pauli) - 1][0] if highest_index > n_qubit: n_qubit = highest_index return n_qubit + 1
def test_matvec_z3(self): """Testing product with Z^n.""" vec = numpy.array( [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]) matvec_expected = numpy.array( [1, -2, 3, -4, 5, -6, 7, -8, 9, -10, 11, -12, 13, -14, 15, -16]) self.assertTrue(numpy.allclose( LinearQubitOperator(QubitOperator('Z3')) * vec, matvec_expected))
def setUp(self): self.coefficient = 0.5 self.operators = ((1, 'X'), (3, 'Y'), (8, 'Z')) self.term = QubitOperator(self.operators, self.coefficient) self.identity = QubitOperator(()) self.coefficient_a = 6.7j self.coefficient_b = -88. self.operators_a = ((3, 'Z'), (1, 'Y'), (4, 'Y')) self.operators_b = ((2, 'X'), (3, 'Y')) self.operator_a = QubitOperator(self.operators_a, self.coefficient_a) self.operator_b = QubitOperator(self.operators_b, self.coefficient_b) self.operator_ab = self.operator_a + self.operator_b self.qubit_operator = QubitOperator(((1, 'X'), (3, 'Y'), (8, 'Z')), 0.5) self.qubit_operator += QubitOperator(((1, 'Z'), (3, 'X'), (8, 'Z')), 1.2)
def test_function_errors(self): """Test main function errors.""" operator = (QubitOperator('Z0 X1', 1.0) + QubitOperator('X1', 2.0)) sector1 = [0] sector2 = [1] qbt_list = [0] with self.assertRaises(TypeError): project_onto_sector(operator=1.0, qubits=qbt_list, sectors=sector1) with self.assertRaises(TypeError): projection_error(operator=1.0, qubits=qbt_list, sectors=sector1) with self.assertRaises(TypeError): project_onto_sector(operator=operator, qubits=0.0, sectors=sector2) with self.assertRaises(TypeError): projection_error(operator=operator, qubits=0.0, sectors=sector2) with self.assertRaises(TypeError): project_onto_sector(operator=operator, qubits=qbt_list, sectors=operator) with self.assertRaises(TypeError): projection_error(operator=operator, qubits=qbt_list, sectors=operator) with self.assertRaises(ValueError): project_onto_sector(operator=operator, qubits=[0, 1], sectors=sector1) with self.assertRaises(ValueError): projection_error(operator=operator, qubits=[0, 1], sectors=sector1) with self.assertRaises(ValueError): project_onto_sector(operator=operator, qubits=qbt_list, sectors=[0, 0]) with self.assertRaises(ValueError): projection_error(operator=operator, qubits=qbt_list, sectors=[0, 0]) with self.assertRaises(ValueError): project_onto_sector(operator=operator, qubits=qbt_list, sectors=[-1]) with self.assertRaises(ValueError): projection_error(operator=operator, qubits=qbt_list, sectors=[-1])
def test_error_operator_all_diagonal(self): terms = [ QubitOperator(()), QubitOperator('Z0 Z1 Z2'), QubitOperator('Z0 Z3'), QubitOperator('Z0 Z1 Z2 Z3') ] zero = QubitOperator() self.assertTrue(zero.isclose(error_operator(terms)))