def test_get_context_selection_circuit_for_group(self): group = QubitOperator(((0, "X"), (1, "Y"))) - 0.5 * QubitOperator( ((1, "Y"), )) circuit, ising_operator = get_context_selection_circuit_for_group( group) # Need to convert to QubitOperator in order to get matrix representation qubit_operator = QubitOperator() for ising_term in ising_operator.terms: qubit_operator += QubitOperator(ising_term, ising_operator.terms[ising_term]) target_unitary = qubit_operator_sparse(group) transformed_unitary = ( circuit.to_unitary().conj().T @ qubit_operator_sparse(qubit_operator) @ circuit.to_unitary()) self.assertTrue( np.allclose(target_unitary.todense(), transformed_unitary))
def test_group_greedily_all_comeasureable(self): target_operator = 10.0 * QubitOperator("Y0") target_operator -= 3.0 * QubitOperator("Y0 Y1") target_operator += 1.0 * QubitOperator("Y1") target_operator += 20.0 * QubitOperator("Y0 Y1 Y2") circuit = Circuit([X(0), X(1), X(2)]) estimation_tasks = [EstimationTask(target_operator, circuit, None)] grouped_tasks = group_greedily(estimation_tasks) assert len(grouped_tasks) == 1 assert grouped_tasks[0].operator == target_operator for initial_task, modified_task in zip(estimation_tasks, grouped_tasks): assert modified_task.circuit == initial_task.circuit assert modified_task.number_of_shots == initial_task.number_of_shots
def generate_qubitop(P): #Converts Pauli representation used in gradient grouping algorithm to QubitOperator. pauli_str = '' for c in range(0, len(P)): if P[c] != 'e': pauli_str += P[c].upper() + str(c) + ' ' return QubitOperator(pauli_str)
def test_build_qaoa_circuit(self): # Given hamiltonian_1 = QubitOperator('Z0') hamiltonian_2 = QubitOperator('X0') hamiltonians = [hamiltonian_1, hamiltonian_2] params = np.array([1, 1]) pyquil_prog = pyquil.quil.Program().inst(pyquil.gates.H(0), pyquil.gates.RZ(2.0, 0), pyquil.gates.H(0), pyquil.gates.RZ(2.0, 0), pyquil.gates.H(0)) correct_circuit = Circuit(pyquil_prog) # When circuit = build_qaoa_circuit(params, hamiltonians) # Then self.assertEqual(circuit, correct_circuit)
def test_qubitop_to_paulisum_identity_operator(self): # Given qubit_operator = QubitOperator("", 4) # When paulisum = qubitop_to_paulisum(qubit_operator) # Then self.assertEqual(paulisum.qubits, ()) self.assertEqual(paulisum, PauliSum() + 4)
def test_qubit_operator_io(self): # Given qubit_op = QubitOperator(((0, "Y"), (3, "X"), (8, "Z"), (11, "X")), 3.0j) # When save_qubit_operator(qubit_op, "qubit_op.json") loaded_op = load_qubit_operator("qubit_op.json") # Then self.assertEqual(qubit_op, loaded_op)
def test_get_estimated_expectation_values_with_constant(self): for estimator in self.estimators: # Given coefficient = -2 constant_qubit_operator = QubitOperator( (), coefficient) + QubitOperator((0, "X")) # When values = estimator.get_estimated_expectation_values( self.backend, self.circuit, constant_qubit_operator, n_samples=self.n_samples, epsilon=self.epsilon, delta=self.delta, ).values value = values[1] # Then self.assertTrue(len(values) == 2) self.assertEqual(coefficient, value)
def test_single_mode_projection(self): """Find the coeffcient of a wavefunction generated from a single qubit. """ n_qubits = 1 qubits = cirq.LineQubit.range(n_qubits) ops = QubitOperator('X0', 1.0) init_state = numpy.zeros(2**n_qubits, dtype=numpy.complex128) init_state[1] = 1.0 + 0.0j cof = numpy.zeros(n_qubits, dtype=numpy.complex128) cirq_utils.qubit_projection(ops, qubits, init_state, cof) self.assertEqual(cof[0], 1.0 + 0.0j)
def test_build_qubitoperator_from_coeffs_and_labels(self): # Given test_op = QubitOperator(((0, "Y"), (1, "X"), (2, "Z"), (4, "X")), 3.0j) coeffs = [3.0j] labels = [[2, 1, 3, 0, 1]] # When build_op = get_qubitop_from_coeffs_and_labels(coeffs, labels) # Then self.assertEqual(test_op, build_op)
def test_get_exact_expectation_values_empty_op(self, wf_simulator): # Given circuit = Circuit(Program(H(0), CNOT(0, 1), CNOT(1, 2))) qubit_operator = QubitOperator() target_value = 0.0 # When expectation_values = wf_simulator.get_exact_expectation_values( circuit, qubit_operator ) # Then assert sum(expectation_values.values) == pytest.approx(target_value, abs=1e-7)
def test_types_consistency(): r"""Test the type consistency of the qubit Hamiltonian constructed by 'convert_observable' from an OpenFermion QubitOperator with respect to the same observable built directly using PennyLane operations""" # Reference PL operator pl_ref = 1 * qml.Identity(0) + 2 * qml.PauliZ(0) @ qml.PauliX(1) # Corresponding OpenFermion QubitOperator of = QubitOperator("", 1) + QubitOperator("Z0 X1", 2) # Build PL operator using 'convert_observable' pl = qchem.convert_observable(of) ops = pl.terms[1] ops_ref = pl_ref.terms[1] for i, op in enumerate(ops): assert op.name == ops_ref[i].name assert type(op) == type(ops_ref[i])
def test_qubitop_io(self): # Given qubit_op = QubitOperator(((0, 'Y'), (1, 'X'), (2, 'Z'), (4, 'X')), 3.j) # When save_qubit_operator(qubit_op, 'qubit_op.json') loaded_op = load_qubit_operator('qubit_op.json') # Then self.assertEqual(qubit_op, loaded_op) os.remove('qubit_op.json')
def test_qubitop_to_dict_io(self): # Given qubit_op = QubitOperator(((0, 'Y'), (1, 'X'), (2, 'Z'), (4, 'X')), 3.j) qubit_op += hermitian_conjugated(qubit_op) # When qubitop_dict = convert_qubitop_to_dict(qubit_op) recreated_qubit_op = convert_dict_to_qubitop(qubitop_dict) # Then self.assertEqual(recreated_qubit_op, qubit_op)
def test_listupCSFs(self): from openfermion import QubitOperator, commutator ZZZZ = QubitOperator('Z0 Z1 Z2 Z3') ZZZZ2 = QubitOperator('Z0 Z1 Z4 Z6') from freqerica.op.symm import SymmRemover norb = 4 n_qubit = norb * 2 remover = SymmRemover(n_qubit, [ZZZZ, ZZZZ2]) print(remover) remover.set_eigvals([-1, +1]) print(remover) wfs = freqerica.op.util.listupCSFs(norb, mult=1, na=2, nb=2, remover=remover) #print(wfs) assert True
def __init__(self, qubit_operator: typing.Union[QubitOperator, str, numbers.Number] = None): """ Initialize from string or from a preexisting OpenFermion QubitOperator instance :param qubit_operator: string or openfermion.QubitOperator if string: Same conventions as openfermion if None: The Hamiltonian is initialized as identity operator if Number: initialized as scaled unit operator """ if isinstance(qubit_operator, str): self._qubit_operator = self.from_string( string=qubit_operator)._qubit_operator elif qubit_operator is None: self._qubit_operator = QubitOperator.zero() elif isinstance(qubit_operator, numbers.Number): self._qubit_operator = qubit_operator * QubitOperator.identity() else: self._qubit_operator = qubit_operator assert (isinstance(self._qubit_operator, QubitOperator))
def test_get_context_selection_circuit_offdiagonal(self): term = QubitOperator("X0 Y1") circuit, ising_operator = get_context_selection_circuit(term) # Need to convert to QubitOperator in order to get matrix representation qubit_operator = change_operator_type(ising_operator, QubitOperator) target_unitary = qubit_operator_sparse(term) transformed_unitary = ( circuit.to_unitary().conj().T @ qubit_operator_sparse(qubit_operator) @ circuit.to_unitary()) assert np.allclose(target_unitary.todense(), transformed_unitary)
def test_get_exact_expectation_values_empty_op(self): # Given circuit = Circuit(Program(H(0), CNOT(0, 1), CNOT(1, 2))) qubit_operator = QubitOperator() target_value = 0.0 # When for simulator in self.wf_simulators: expectation_values = simulator.get_exact_expectation_values( circuit, qubit_operator) # Then self.assertAlmostEqual(sum(expectation_values.values), target_value)
def get_maxcut_hamiltonian(graph, scaling=1.0, shifted=False, l1_normalized=False): """Converts a MAXCUT instance, as described by a weighted graph, to an Ising Hamiltonian. It allows for different convention in the choice of the Hamiltonian. Args: graph (networkx.Graph): undirected weighted graph describing the MAXCUT instance. scaling (float): scaling of the terms of the Hamiltonian shifted (bool): if True include a shift. Default: False l1_normalized (bool): normalize the operator using the l1_norm = \sum |w| Returns: zquantum.core.qubitoperator.QubitOperator object describing the Hamiltonian H = \sum_{<i,j>} w_{i,j} * scaling * (Z_i Z_j - shifted * I) or H_norm = H / l1_norm if l1_normalized is True. """ output = QubitOperator() nodes_dict = generate_graph_node_dict(graph) l1_norm = 0 for edge in graph.edges: coeff = graph.edges[edge[0], edge[1]]["weight"] * scaling l1_norm += np.abs(coeff) node_index1 = nodes_dict[edge[0]] node_index2 = nodes_dict[edge[1]] ZZ_term_str = "Z" + str(node_index1) + " Z" + str(node_index2) output += QubitOperator(ZZ_term_str, coeff) if shifted: output += QubitOperator("", -coeff) # constant term, i.e I if l1_normalized and (l1_norm > 0): output /= l1_norm return output
def symmetry_pauli_string(orbprop, operation_list): operation_paulistr_table = {} na = QubitOperator(()) nb = QubitOperator(()) for i in range(orbprop.ncas): na *= QubitOperator((i * 2, 'Z')) nb *= QubitOperator((i * 2 + 1, 'Z')) if 'na' in operation_list: operation_paulistr_table['na'] = na if 'nb' in operation_list: operation_paulistr_table['nb'] = nb ncore, ncas = orbprop.ncore, orbprop.ncas for op in operation_list: if op == 'na' or op == 'nb': continue qop_paulistr = QubitOperator(()) for i, iorb in enumerate(range(ncore, ncore + ncas)): irrep = orbprop.irreps[iorb] char = symmtable[irrep][op] if char == -1: qop_paulistr *= QubitOperator([(i * 2, 'Z'), (i * 2 + 1, 'Z')]) if char == NA: qop_paulistr = None break if qop_paulistr is not None: operation_paulistr_table[op] = qop_paulistr return operation_paulistr_table
def get_qubitop_from_coeffs_and_labels( coeffs: List[float], labels: List[List[int]] ) -> QubitOperator: """Generates a QubitOperator based on a coefficient vector and a label matrix. Args: coeffs: a list of floats representing the coefficients for the terms in the Hamiltonian labels: a list of lists (a matrix) where each list is a vector of integers representing the Pauli string. See pauliutil.py for details. Example: The Hamiltonian H = 0.1 X1 X2 - 0.4 Y1 Y2 Z3 Z4 can be initiated by calling H = QubitOperator([0.1, -0.4],\ # coefficients [[1 1 0 0],\ # label matrix [2 2 3 3]]) """ output = QubitOperator() for i in range(0, len(labels)): string_term = "" for ind, elem in enumerate(labels[i]): pauli_symbol = "" if elem == 1: pauli_symbol = "X" + str(ind) + " " if elem == 2: pauli_symbol = "Y" + str(ind) + " " if elem == 3: pauli_symbol = "Z" + str(ind) + " " string_term += pauli_symbol output += coeffs[i] * QubitOperator(string_term) return output
def ansatz_based_cost_function(): target_operator = QubitOperator("Z0") ansatz = MockAnsatz(number_of_layers=1, problem_size=1) backend = MockQuantumSimulator() estimation_method = estimate_expectation_values_by_averaging estimation_preprocessors = [partial(allocate_shots_uniformly, number_of_shots=1)] return AnsatzBasedCostFunction( target_operator, ansatz, backend, estimation_method=estimation_method, estimation_preprocessors=estimation_preprocessors, )
def test_one_qubit_parametric_gates_using_expectation_values( self, backend_for_gates_test, initial_gate, tested_gate, params, target_values): if backend_for_gates_test.n_samples is None: pytest.xfail( "This test won't work for simulators without sampling, it's covered by " "a test in QuantumSimulatorTests.") # Given qubit_list = [Qubit(0)] gate_1 = Gate(initial_gate, qubits=qubit_list) gate_2 = Gate(tested_gate, params=params, qubits=qubit_list) circuit = Circuit() circuit.qubits = qubit_list circuit.gates = [gate_1, gate_2] operators = [ QubitOperator("[]"), QubitOperator("[X0]"), QubitOperator("[Y0]"), QubitOperator("[Z0]"), ] sigma = 1 / np.sqrt(backend_for_gates_test.n_samples) for i, operator in enumerate(operators): # When estimation_tasks = [ EstimationTask(operator, circuit, backend_for_gates_test.n_samples) ] expectation_values = estimate_expectation_values_by_averaging( backend_for_gates_test, estimation_tasks) calculated_value = expectation_values.values[0] # Then assert calculated_value == pytest.approx(target_values[i], abs=sigma * 3)
def noisy_ansatz(): target_operator = QubitOperator("Z0") ansatz = MockAnsatz(number_of_layers=2, problem_size=1) backend = MockQuantumSimulator() estimator = MockEstimator() ansatz.get_executable_circuit = mock.Mock( wraps=ansatz.get_executable_circuit) return AnsatzBasedCostFunction(target_operator, ansatz, backend, estimator=estimator, parameter_precision=1e-4, parameter_precision_seed=1234)
def test_compute_group_variances_without_ref(groups, expecval): test_variances = compute_group_variances(groups, expecval) test_ham_variance = np.sum(test_variances) # Assemble H and compute its variances independently ham = QubitOperator() for g in groups: ham += g ham_coeff = np.array(list(ham.terms.values())) pauli_var = 1.0 - expecval.values**2 ref_ham_variance = np.sum(ham_coeff**2 * pauli_var) assert math.isclose( test_ham_variance, ref_ham_variance) # this is true as long as the groups do not overlap
def test_get_exact_expectation_values(self): # Given circuit = Circuit(Program(H(0), CNOT(0, 1), CNOT(1, 2))) qubit_operator = QubitOperator('2[] - [Z0 Z1] + [X0 X2]') target_values = np.array([2., -1., 0.]) # When for simulator in self.wf_simulators: expectation_values = simulator.get_exact_expectation_values( circuit, qubit_operator) # Then np.testing.assert_array_almost_equal(expectation_values.values, target_values)
def test_qubit_wavefunction_from_vacuum(self): """Build a wavefunction given a group of qubit operations. """ test_val = 1.0 + 2.0 + 3.0 + 5.0 + 7.0 + 11.0 + 13.0 + 0.j n_qubits = 1 qubits = cirq.LineQubit.range(n_qubits) ops = QubitOperator('X0', 1.0) + QubitOperator('X0', 2.0) \ + QubitOperator('X0', 3.0) + QubitOperator('X0', 5.0) \ + QubitOperator('X0', 7.0) + QubitOperator('X0', 11.0) \ + QubitOperator('X0', 13.0) state = cirq_utils.qubit_wavefunction_from_vacuum(ops, qubits) self.assertEqual(state[1], test_val)
def test_one_qubit_non_parametric_gates_using_expectation_values( self, backend_for_gates_test, initial_gate, tested_gate, target_values): if backend_for_gates_test.n_samples is None: pytest.xfail( "This test won't work for simulators without sampling, it should be covered by a test in QuantumSimulatorTests." ) # Given qubit_list = [Qubit(0)] gate_1 = Gate(initial_gate, qubits=qubit_list) gate_2 = Gate(tested_gate, qubits=qubit_list) circuit = Circuit() circuit.qubits = qubit_list circuit.gates = [gate_1, gate_2] operators = [ QubitOperator("[]"), QubitOperator("[X0]"), QubitOperator("[Y0]"), QubitOperator("[Z0]"), ] sigma = 1 / np.sqrt(backend_for_gates_test.n_samples) for i, operator in enumerate(operators): # When estimator = BasicEstimator() expectation_value = estimator.get_estimated_expectation_values( backend_for_gates_test, circuit, operator, ).values[0] # Then assert expectation_value == pytest.approx(target_values[i], abs=sigma * 3)
def test_qubitop_to_paulisum_setting_qubits(self): # Given qubit_operator = QubitOperator("Z0 Z1", -1.5) expected_qubits = (LineQubit(0), LineQubit(5)) expected_paulisum = (PauliSum() + PauliString(Z.on(expected_qubits[0])) * PauliString(Z.on(expected_qubits[1])) * -1.5) # When paulisum = qubitop_to_paulisum(qubit_operator, qubits=expected_qubits) # Then self.assertEqual(paulisum.qubits, expected_qubits) self.assertEqual(paulisum, expected_paulisum)
def test_qubitop_to_paulisum_z0z1_operator(self): # Given qubit_operator = QubitOperator("Z0 Z1", -1.5) expected_qubits = (GridQubit(0, 0), GridQubit(1, 0)) expected_paulisum = (PauliSum() + PauliString(Z.on(expected_qubits[0])) * PauliString(Z.on(expected_qubits[1])) * -1.5) # When paulisum = qubitop_to_paulisum(qubit_operator) # Then self.assertEqual(paulisum.qubits, expected_qubits) self.assertEqual(paulisum, expected_paulisum)
def taper_qubits_off(self, qop): indices_targetpauli = { util.paulistr(qop_tgtpauli)[0][0] for qop_tgtpauli in self.targetpauli_qop_list } index_pack_map = [] index_new = 0 for index_old in range(self.n_qubit): if index_old in indices_targetpauli: index_pack_map.append(None) else: index_pack_map.append(index_new) index_new += 1 qop_tapered = QubitOperator() for pauli_string, coeff in qop.terms.items(): pauli_string_new = [] for index_old, axis in pauli_string: index_new = index_pack_map[index_old] pauli_string_new.append((index_new, axis)) qop_tapered += QubitOperator(pauli_string_new, coeff) return qop_tapered