def test_run_2qubits(self): """Test for 2-qubit cases (to check endian)""" qc = QuantumCircuit(2) qc2 = QuantumCircuit(2) qc2.x(0) op = SparsePauliOp.from_list([("II", 1)]) op2 = SparsePauliOp.from_list([("ZI", 1)]) op3 = SparsePauliOp.from_list([("IZ", 1)]) est = Estimator() result = est.run([qc], [op], [[]]).result() self.assertIsInstance(result, EstimatorResult) np.testing.assert_allclose(result.values, [1]) result = est.run([qc2], [op], [[]]).result() self.assertIsInstance(result, EstimatorResult) np.testing.assert_allclose(result.values, [1]) result = est.run([qc], [op2], [[]]).result() self.assertIsInstance(result, EstimatorResult) np.testing.assert_allclose(result.values, [1]) result = est.run([qc2], [op2], [[]]).result() self.assertIsInstance(result, EstimatorResult) np.testing.assert_allclose(result.values, [1]) result = est.run([qc], [op3], [[]]).result() self.assertIsInstance(result, EstimatorResult) np.testing.assert_allclose(result.values, [1]) result = est.run([qc2], [op3], [[]]).result() self.assertIsInstance(result, EstimatorResult) np.testing.assert_allclose(result.values, [-1])
def setUp(self): super().setUp() self.ansatz = RealAmplitudes(num_qubits=2, reps=2) self.observable = PauliSumOp.from_list([ ("II", -1.052373245772859), ("IZ", 0.39793742484318045), ("ZI", -0.39793742484318045), ("ZZ", -0.01128010425623538), ("XX", 0.18093119978423156), ]) self.expvals = -1.0284380963435145, -1.284366511861733 self.psi = (RealAmplitudes(num_qubits=2, reps=2), RealAmplitudes(num_qubits=2, reps=3)) self.params = tuple(psi.parameters for psi in self.psi) self.hamiltonian = ( SparsePauliOp.from_list([("II", 1), ("IZ", 2), ("XI", 3)]), SparsePauliOp.from_list([("IZ", 1)]), SparsePauliOp.from_list([("ZI", 1), ("ZZ", 1)]), ) self.theta = ( [0, 1, 1, 2, 3, 5], [0, 1, 1, 2, 3, 5, 8, 13], [1, 2, 3, 4, 5, 6], )
def test_run_1qubit(self): """Test for 1-qubit cases""" qc = QuantumCircuit(1) qc2 = QuantumCircuit(1) qc2.x(0) op = SparsePauliOp.from_list([("I", 1)]) op2 = SparsePauliOp.from_list([("Z", 1)]) est = Estimator() result = est.run([qc], [op], [[]]).result() self.assertIsInstance(result, EstimatorResult) np.testing.assert_allclose(result.values, [1]) result = est.run([qc], [op2], [[]]).result() self.assertIsInstance(result, EstimatorResult) np.testing.assert_allclose(result.values, [1]) result = est.run([qc2], [op], [[]]).result() self.assertIsInstance(result, EstimatorResult) np.testing.assert_allclose(result.values, [1]) result = est.run([qc2], [op2], [[]]).result() self.assertIsInstance(result, EstimatorResult) np.testing.assert_allclose(result.values, [-1])
def test_1qubit(self): """Test for 1-qubit cases""" qc = QuantumCircuit(1) qc2 = QuantumCircuit(1) qc2.x(0) op = SparsePauliOp.from_list([("I", 1)]) op2 = SparsePauliOp.from_list([("Z", 1)]) with self.assertWarns(DeprecationWarning): est = Estimator([qc, qc2], [op, op2], [[]] * 2) result = est([0], [0], [[]]) self.assertIsInstance(result, EstimatorResult) np.testing.assert_allclose(result.values, [1]) with self.assertWarns(DeprecationWarning): result = est([0], [1], [[]]) self.assertIsInstance(result, EstimatorResult) np.testing.assert_allclose(result.values, [1]) with self.assertWarns(DeprecationWarning): result = est([1], [0], [[]]) self.assertIsInstance(result, EstimatorResult) np.testing.assert_allclose(result.values, [1]) with self.assertWarns(DeprecationWarning): result = est([1], [1], [[]]) self.assertIsInstance(result, EstimatorResult) np.testing.assert_allclose(result.values, [-1])
def test_errors(self): """Test for errors""" qc = QuantumCircuit(1) qc2 = QuantumCircuit(2) op = SparsePauliOp.from_list([("I", 1)]) op2 = SparsePauliOp.from_list([("II", 1)]) with self.assertWarns(DeprecationWarning): est = Estimator([qc, qc2], [op, op2], [[]] * 2) with self.assertRaises(QiskitError), self.assertWarns( DeprecationWarning): est([0], [1], [[]]) with self.assertRaises(QiskitError), self.assertWarns( DeprecationWarning): est([1], [0], [[]]) with self.assertRaises(QiskitError), self.assertWarns( DeprecationWarning): est([0], [0], [[1e4]]) with self.assertRaises(QiskitError), self.assertWarns( DeprecationWarning): est([1], [1], [[1, 2]]) with self.assertRaises(QiskitError), self.assertWarns( DeprecationWarning): est([0, 1], [1], [[1]]) with self.assertRaises(QiskitError), self.assertWarns( DeprecationWarning): est([0], [0, 1], [[1]])
def add(self, other: OperatorBase) -> OperatorBase: if not self.num_qubits == other.num_qubits: raise ValueError( "Sum over operators with different numbers of qubits, {} and {}, is not well " "defined".format(self.num_qubits, other.num_qubits) ) if isinstance(other, PauliOp) and self.primitive == other.primitive: return PauliOp(self.primitive, coeff=self.coeff + other.coeff) # pylint: disable=cyclic-import from .pauli_sum_op import PauliSumOp if ( isinstance(other, PauliOp) and isinstance(self.coeff, (int, float, complex)) and isinstance(other.coeff, (int, float, complex)) ): return PauliSumOp( SparsePauliOp(self.primitive, coeffs=[self.coeff]) + SparsePauliOp(other.primitive, coeffs=[other.coeff]) ) if isinstance(other, PauliSumOp) and isinstance(self.coeff, (int, float, complex)): return PauliSumOp(SparsePauliOp(self.primitive, coeffs=[self.coeff])) + other return SummedOp([self, other])
def init_observable(observable: BaseOperator | PauliSumOp) -> SparsePauliOp: """Initialize observable by converting the input to a :class:`~qiskit.quantum_info.SparsePauliOp`. Args: observable: The observable. Returns: The observable as :class:`~qiskit.quantum_info.SparsePauliOp`. Raises: TypeError: If the observable is a :class:`~qiskit.opflow.PauliSumOp` and has a parameterized coefficient. """ if isinstance(observable, SparsePauliOp): return observable elif isinstance(observable, PauliSumOp): if isinstance(observable.coeff, ParameterExpression): raise TypeError( f"Observable must have numerical coefficient, not {type(observable.coeff)}." ) return observable.coeff * observable.primitive elif isinstance(observable, BasePauli): return SparsePauliOp(observable) elif isinstance(observable, BaseOperator): return SparsePauliOp.from_operator(observable) else: return SparsePauliOp(observable)
def _expval_params(operator, variance=False): # Convert O to SparsePauliOp representation if isinstance(operator, Pauli): operator = SparsePauliOp(operator) elif not isinstance(operator, SparsePauliOp): operator = SparsePauliOp.from_operator(Operator(operator)) if not isinstance(operator, SparsePauliOp): raise ExtensionError("Invalid input operator") params = {} # Add Pauli basis components of O for pauli, coeff in operator.label_iter(): if pauli in params: coeff1 = params[pauli][0] params[pauli] = (coeff1 + coeff.real, 0) else: params[pauli] = (coeff.real, 0) # Add Pauli basis components of O^2 if variance: for pauli, coeff in operator.dot(operator).label_iter(): if pauli in params: coeff1, coeff2 = params[pauli] params[pauli] = (coeff1, coeff2 + coeff.real) else: params[pauli] = (0, coeff.real) # Convert to list return list(params.items())
def _to_sparse_pauli_op(operator): """Cast the operator to a SparsePauliOp. For Opflow objects, return a global coefficient that must be multiplied to the evolution time. Since this coefficient might contain unbound parameters it cannot be absorbed into the coefficients of the SparsePauliOp. """ # pylint: disable=cyclic-import from qiskit.opflow import PauliSumOp, PauliOp if isinstance(operator, PauliSumOp): sparse_pauli = operator.primitive sparse_pauli._coeffs *= operator.coeff elif isinstance(operator, PauliOp): sparse_pauli = SparsePauliOp(operator.primitive) sparse_pauli._coeffs *= operator.coeff elif isinstance(operator, Pauli): sparse_pauli = SparsePauliOp(operator) elif isinstance(operator, SparsePauliOp): sparse_pauli = operator else: raise ValueError( f"Unsupported operator type for evolution: {type(operator)}.") return sparse_pauli
def _replace_pauli_sums(cls, operator): try: from qiskit.providers.aer.library import SaveExpectationValue except ImportError as ex: raise MissingOptionalLibraryError( libname="qiskit-aer", name="AerPauliExpectation", pip_install="pip install qiskit-aer", ) from ex # The 'expval_measurement' label on the save instruction is special - the # CircuitSampler will look for it to know that the circuit is a Expectation # measurement, and not simply a # circuit to replace with a DictStateFn if operator.__class__ == ListOp: return operator.traverse(cls._replace_pauli_sums) if isinstance(operator, PauliSumOp): save_instruction = SaveExpectationValue(operator.primitive, "expval_measurement") return CircuitStateFn(save_instruction, coeff=operator.coeff, is_measurement=True, from_operator=True) # Change to Pauli representation if necessary if {"Pauli"} != operator.primitive_strings(): logger.warning( "Measured Observable is not composed of only Paulis, converting to " "Pauli representation, which can be expensive.") # Setting massive=False because this conversion is implicit. User can perform this # action on the Observable with massive=True explicitly if they so choose. operator = operator.to_pauli_op(massive=False) if isinstance(operator, SummedOp): sparse_pauli = reduce(add, (meas.coeff * SparsePauliOp(meas.primitive) for meas in operator.oplist)) save_instruction = SaveExpectationValue(sparse_pauli, "expval_measurement") return CircuitStateFn(save_instruction, coeff=operator.coeff, is_measurement=True, from_operator=True) if isinstance(operator, PauliOp): sparse_pauli = operator.coeff * SparsePauliOp(operator.primitive) save_instruction = SaveExpectationValue(sparse_pauli, "expval_measurement") return CircuitStateFn(save_instruction, is_measurement=True, from_operator=True) raise TypeError( f"Conversion of OperatorStateFn of {operator.__class__.__name__} is not defined." )
def test_add(self): """ add test """ pauli_sum = 3 * X + Y self.assertIsInstance(pauli_sum, PauliSumOp) expected = PauliSumOp(3.0 * SparsePauliOp(Pauli("X")) + SparsePauliOp(Pauli("Y"))) self.assertEqual(pauli_sum, expected) pauli_sum = X + Y summed_op = SummedOp([X, Y]) self.assertEqual(pauli_sum, summed_op)
def test_permute(self, permutation, expected_pauli): """Test the permute method.""" pauli_sum = PauliSumOp(SparsePauliOp.from_list([("XYZ", 1)])) expected = PauliSumOp(SparsePauliOp.from_list([(expected_pauli, 1)])) permuted = pauli_sum.permute(permutation) with self.subTest(msg="test permutated object"): self.assertEqual(permuted, expected) with self.subTest(msg="test original object is unchanged"): original = PauliSumOp(SparsePauliOp.from_list([("XYZ", 1)])) self.assertEqual(pauli_sum, original)
def test_adjoint(self): """ adjoint test """ pauli_sum = PauliSumOp(SparsePauliOp(Pauli("XYZX"), coeffs=[2]), coeff=3) expected = PauliSumOp(SparsePauliOp(Pauli("XYZX")), coeff=-6) self.assertEqual(pauli_sum.adjoint(), expected) pauli_sum = PauliSumOp(SparsePauliOp(Pauli("XYZY"), coeffs=[2]), coeff=3j) expected = PauliSumOp(SparsePauliOp(Pauli("XYZY")), coeff=-6j) self.assertEqual(pauli_sum.adjoint(), expected)
def init_observable(observable: BaseOperator | PauliSumOp) -> SparsePauliOp: """Initialize observable""" if isinstance(observable, SparsePauliOp): return observable if isinstance(observable, PauliSumOp): if isinstance(observable.coeff, ParameterExpression): raise TypeError( f"observable must have numerical coefficient, not {type(observable.coeff)}" ) return observable.coeff * observable.primitive if isinstance(observable, BaseOperator): return SparsePauliOp.from_operator(observable) return SparsePauliOp(observable)
def test_coder_operators(self): """Test runtime encoder and decoder for operators.""" x = Parameter("x") y = x + 1 qc = QuantumCircuit(1) qc.h(0) coeffs = np.array([1, 2, 3, 4, 5, 6]) table = PauliTable.from_labels( ["III", "IXI", "IYY", "YIZ", "XYZ", "III"]) op = (2.0 * I ^ I) z2_symmetries = Z2Symmetries( [Pauli("IIZI"), Pauli("ZIII")], [Pauli("IIXI"), Pauli("XIII")], [1, 3], [-1, 1]) isqrt2 = 1 / np.sqrt(2) sparse = scipy.sparse.csr_matrix([[0, isqrt2, 0, isqrt2]]) subtests = ( PauliSumOp(SparsePauliOp(Pauli("XYZX"), coeffs=[2]), coeff=3), PauliSumOp(SparsePauliOp(Pauli("XYZX"), coeffs=[1]), coeff=y), PauliSumOp(SparsePauliOp(Pauli("XYZX"), coeffs=[1 + 2j]), coeff=3 - 2j), PauliSumOp.from_list([("II", -1.052373245772859), ("IZ", 0.39793742484318045)]), PauliSumOp(SparsePauliOp(table, coeffs), coeff=10), MatrixOp(primitive=np.array([[0, -1j], [1j, 0]]), coeff=x), PauliOp(primitive=Pauli("Y"), coeff=x), CircuitOp(qc, coeff=x), EvolvedOp(op, coeff=x), TaperedPauliSumOp(SparsePauliOp(Pauli("XYZX"), coeffs=[2]), z2_symmetries), StateFn(qc, coeff=x), CircuitStateFn(qc, is_measurement=True), DictStateFn("1" * 3, is_measurement=True), VectorStateFn(np.ones(2**3, dtype=complex)), OperatorStateFn(CircuitOp(QuantumCircuit(1))), SparseVectorStateFn(sparse), Statevector([1, 0]), CVaRMeasurement(Z, 0.2), ComposedOp([(X ^ Y ^ Z), (Z ^ X ^ Y ^ Z).to_matrix_op()]), SummedOp([X ^ X * 2, Y ^ Y], 2), TensoredOp([(X ^ Y), (Z ^ I)]), (Z ^ Z) ^ (I ^ 2), ) for op in subtests: with self.subTest(op=op): encoded = json.dumps(op, cls=RuntimeEncoder) self.assertIsInstance(encoded, str) decoded = json.loads(encoded, cls=RuntimeDecoder) self.assertEqual(op, decoded)
def __init__(self, operator, label="expectation_value_variance", unnormalized=False, pershot=False, conditional=False): r"""Instruction to save the expectation value and variance of a Hermitian operator. The expectation value of a Hermitian operator :math:`H` for a simulator in quantum state :math`\rho`is given by :math:`\langle H\rangle = \mbox{Tr}[H.\rho]`. The variance is given by :math:`\sigma^2 = \langle H^2 \rangle - \langle H \rangle>^2`. Args: operator (Pauli or SparsePauliOp or Operator): a Hermitian operator. label (str): the key for retrieving saved data from results. unnormalized (bool): If True return save the unnormalized accumulated or conditional accumulated expectation value over all shot [Default: False]. pershot (bool): if True save a list of expectation values for each shot of the simulation rather than the average over all shots [Default: False]. conditional (bool): if True save the average or pershot data conditional on the current classical register values [Default: False]. Raises: ExtensionError: if the input operator is invalid or not Hermitian. .. note:: This instruction can be directly appended to a circuit using the :func:`save_expectation_value` circuit method. """ # Convert O to SparsePauliOp representation if isinstance(operator, Pauli): operator = SparsePauliOp(operator) elif not isinstance(operator, SparsePauliOp): operator = SparsePauliOp.from_operator(Operator(operator)) if not allclose(operator.coeffs.imag, 0): raise ExtensionError("Input operator is not Hermitian.") params = _expval_params(operator, variance=True) super().__init__('save_expval_var', operator.num_qubits, label, unnormalized=unnormalized, pershot=pershot, conditional=conditional, params=params)
def test_equals(self): """ equality test """ self.assertNotEqual((X ^ X) + (Y ^ Y), X + Y) self.assertEqual((X ^ X) + (Y ^ Y), (Y ^ Y) + (X ^ X)) theta = ParameterVector("theta", 2) pauli_sum0 = theta[0] * (X + Z) pauli_sum1 = theta[1] * (X + Z) expected = PauliSumOp( SparsePauliOp(Pauli("X")) + SparsePauliOp(Pauli("Z")), coeff=1.0 * theta[0], ) self.assertEqual(pauli_sum0, expected) self.assertNotEqual(pauli_sum1, expected)
def test_grouped_pauli_statefn(self): """grouped pauli test with statefn""" grouped_pauli = PauliSumOp(SparsePauliOp(["Y"]), grouping_type="TPB") observable = OperatorStateFn(grouped_pauli, is_measurement=True) converter = PauliBasisChange( replacement_fn=PauliBasisChange.measurement_replacement_fn) cob = converter.convert(observable) expected = PauliSumOp(SparsePauliOp(["Z"]), grouping_type="TPB") self.assertEqual(cob[0].primitive, expected) circuit = QuantumCircuit(1) circuit.sdg(0) circuit.h(0) self.assertEqual(cob[1].primitive, circuit)
def to_pauli_op(self, massive: bool = False) -> OperatorBase: """ Returns a sum of ``PauliOp`` s equivalent to this Operator. """ # pylint: disable=import-outside-toplevel,cyclic-import from ..list_ops.summed_op import SummedOp mat_op = self.to_matrix_op(massive=massive) sparse_pauli = SparsePauliOp.from_operator( mat_op.primitive) # type: ignore if not sparse_pauli.to_list(): # pylint: disable=import-outside-toplevel from ..operator_globals import I return (I ^ self.num_qubits) * 0.0 if len(sparse_pauli) == 1: label, coeff = sparse_pauli.to_list()[0] coeff = coeff.real if np.isreal(coeff) else coeff return PrimitiveOp(Pauli(label), coeff * self.coeff) return SummedOp( [ PrimitiveOp( Pauli(label), coeff.real if coeff == coeff.real else coeff, ) for (label, coeff) in sparse_pauli.to_list() ], self.coeff, )
def _sort_simplify(sparse_pauli): sparse_pauli = sparse_pauli.simplify() indices = sparse_pauli.paulis.argsort() table = sparse_pauli.paulis[indices] coeffs = sparse_pauli.coeffs[indices] sparse_pauli = SparsePauliOp(table, coeffs) return sparse_pauli
def test_permute(self): """permute test""" pauli_sum = PauliSumOp(SparsePauliOp((X ^ Y ^ Z).primitive)) expected = PauliSumOp(SparsePauliOp((X ^ I ^ Y ^ Z ^ I).primitive)) self.assertEqual(pauli_sum.permute([1, 2, 4]), expected) pauli_sum = PauliSumOp(SparsePauliOp((X ^ Y ^ Z).primitive)) expected = PauliSumOp(SparsePauliOp((Z ^ Y ^ X).primitive)) self.assertEqual(pauli_sum.permute([2, 1, 0]), expected) with self.assertRaises(OpflowError): pauli_sum.permute([1, 2, 1]) with self.assertRaises(OpflowError): pauli_sum.permute([1, 2, -1])
def _expand_dim(self, num_qubits: int) -> "PauliSumOp": return PauliSumOp( self.primitive.tensor( # type:ignore SparsePauliOp(Pauli("I" * num_qubits)) ), coeff=self.coeff, )
def test_decoder_import(self): """Test runtime decoder importing modules.""" script = """ import sys import json from qiskit.providers.ibmq.runtime import RuntimeDecoder if __name__ == '__main__': obj = json.loads(sys.argv[1], cls=RuntimeDecoder) print(obj.__class__.__name__) """ temp_fp = tempfile.NamedTemporaryFile(mode='w', delete=False) self.addCleanup(os.remove, temp_fp.name) temp_fp.write(script) temp_fp.close() subtests = ( PauliSumOp(SparsePauliOp(Pauli("XYZX"), coeffs=[2]), coeff=3), DictStateFn("1" * 3, is_measurement=True), Statevector([1, 0]), ) for op in subtests: with self.subTest(op=op): encoded = json.dumps(op, cls=RuntimeEncoder) self.assertIsInstance(encoded, str) cmd = ["python", temp_fp.name, encoded] proc = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, check=True) self.assertIn(op.__class__.__name__, proc.stdout)
def test_find_Z2_symmetries(self): """test for find_Z2_symmetries""" qubit_op = PauliSumOp.from_list([ ("II", -1.0537076071291125), ("IZ", 0.393983679438514), ("ZI", -0.39398367943851387), ("ZZ", -0.01123658523318205), ("XX", 0.1812888082114961), ]) z2_symmetries = Z2Symmetries.find_Z2_symmetries(qubit_op) self.assertEqual(z2_symmetries.symmetries, [Pauli("ZZ")]) self.assertEqual(z2_symmetries.sq_paulis, [Pauli("IX")]) self.assertEqual(z2_symmetries.sq_list, [0]) self.assertEqual(z2_symmetries.tapering_values, None) tapered_op = z2_symmetries.taper(qubit_op)[1] self.assertEqual(tapered_op.z2_symmetries.symmetries, [Pauli("ZZ")]) self.assertEqual(tapered_op.z2_symmetries.sq_paulis, [Pauli("IX")]) self.assertEqual(tapered_op.z2_symmetries.sq_list, [0]) self.assertEqual(tapered_op.z2_symmetries.tapering_values, [-1]) z2_symmetries.tapering_values = [-1] primitive = SparsePauliOp.from_list([ ("I", -1.0424710218959303), ("Z", -0.7879673588770277), ("X", -0.18128880821149604), ]) expected_op = TaperedPauliSumOp(primitive, z2_symmetries) self.assertEqual(tapered_op, expected_op)
def permute(self, permutation: List[int]) -> "PauliSumOp": """Permutes the sequence of ``PauliSumOp``. Args: permutation: A list defining where each Pauli should be permuted. The Pauli at index j of the primitive should be permuted to position permutation[j]. Returns: A new PauliSumOp representing the permuted operator. For operator (X ^ Y ^ Z) and indices=[1,2,4], it returns (X ^ I ^ Y ^ Z ^ I). Raises: OpflowError: if indices do not define a new index for each qubit. """ if len(permutation) != self.num_qubits: raise OpflowError( "List of indices to permute must have the same size as Pauli Operator" ) length = max(permutation) + 1 spop = self.primitive.tensor( SparsePauliOp(Pauli("I" * (length - self.num_qubits)))) permutation = [i for i in range(length) if i not in permutation ] + permutation permu_arr = np.arange(length)[np.argsort(permutation)] spop.paulis.x = spop.paulis.x[:, permu_arr] spop.paulis.z = spop.paulis.z[:, permu_arr] return PauliSumOp(spop, self.coeff)
def compose( self, other: OperatorBase, permutation: Optional[List[int]] = None, front: bool = False ) -> OperatorBase: new_self, other = self._expand_shorter_operator_and_permute(other, permutation) new_self = cast(PauliOp, new_self) if front: return other.compose(new_self) # If self is identity, just return other. if not any(new_self.primitive.x + new_self.primitive.z): return other * new_self.coeff # Both Paulis if isinstance(other, PauliOp): product = new_self.primitive.dot(other.primitive) return PrimitiveOp(product, coeff=new_self.coeff * other.coeff) # pylint: disable=cyclic-import from .pauli_sum_op import PauliSumOp if isinstance(other, PauliSumOp): return PauliSumOp( SparsePauliOp(new_self.primitive).dot(other.primitive), coeff=new_self.coeff * other.coeff, ) # pylint: disable=cyclic-import from ..state_fns.circuit_state_fn import CircuitStateFn from .circuit_op import CircuitOp if isinstance(other, (CircuitOp, CircuitStateFn)): return new_self.to_circuit_op().compose(other) return super(PauliOp, new_self).compose(other)
def save_expval_params(pauli=False): """Dictionary of labels and params, qubits for exp val snapshots.""" if pauli: X_wpo = Pauli('X') Y_wpo = Pauli('Y') Z_wpo = Pauli('Z') H_wpo = np.sqrt(0.5) * (SparsePauliOp('X') + SparsePauliOp('Z')) IX_wpo = Pauli('IX') IY_wpo = Pauli('IY') IZ_wpo = Pauli('IZ') IH_wpo = np.sqrt(0.5) * (SparsePauliOp('IX') + SparsePauliOp('IZ')) XX_wpo = Pauli('XX') YY_wpo = Pauli('YY') ZZ_wpo = Pauli('ZZ') else: X_wpo = np.array([[0, 1], [1, 0]], dtype=complex) Y_wpo = np.array([[0, -1j], [1j, 0]], dtype=complex) Z_wpo = np.array([[1, 0], [0, -1]], dtype=complex) H_wpo = np.array([[1, 1], [1, -1]], dtype=complex) / np.sqrt(2) IX_wpo = np.kron(np.eye(2), X_wpo) IY_wpo = np.kron(np.eye(2), Y_wpo) IZ_wpo = np.kron(np.eye(2), Z_wpo) IH_wpo = np.kron(np.eye(2), H_wpo) XX_wpo = np.kron(X_wpo, X_wpo) YY_wpo = np.kron(Y_wpo, Y_wpo) ZZ_wpo = np.kron(Z_wpo, Z_wpo) return { "<H[0]>": (H_wpo, [0]), "<H[1]>": (H_wpo, [1]), "<X[0]>": (X_wpo, [0]), "<X[1]>": (X_wpo, [1]), "<Y[1]>": (Y_wpo, [0]), "<Y[1]>": (Y_wpo, [1]), "<Z[0]>": (Z_wpo, [0]), "<Z[1]>": (Z_wpo, [1]), "<H[0], I[1]>": (IH_wpo, [0, 1]), "<I[0], H[1]>": (IH_wpo, [1, 0]), "<X[0], I[1]>": (IX_wpo, [0, 1]), "<I[0], X[1]>": (IX_wpo, [1, 0]), "<Y[0], I[1]>": (IY_wpo, [0, 1]), "<I[0], Y[1]>": (IY_wpo, [1, 0]), "<Z[0], I[1]>": (IZ_wpo, [0, 1]), "<I[0], Z[1]>": (IZ_wpo, [1, 0]), "<X[0], X[1]>": (XX_wpo, [0, 1]), "<Y[0], Y[1]>": (YY_wpo, [0, 1]), "<Z[0], Z[1]>": (ZZ_wpo, [0, 1]), }
def test_construct(self): """ constructor test """ sparse_pauli = SparsePauliOp(Pauli("XYZX"), coeffs=[2.0]) coeff = 3.0 pauli_sum = PauliSumOp(sparse_pauli, coeff=coeff) self.assertIsInstance(pauli_sum, PauliSumOp) self.assertEqual(pauli_sum.primitive, sparse_pauli) self.assertEqual(pauli_sum.coeff, coeff) self.assertEqual(pauli_sum.num_qubits, 4)
def test_matrix_iter(self): """Test PauliSumOp dense matrix_iter method.""" labels = ["III", "IXI", "IYY", "YIZ", "XYZ", "III"] coeffs = np.array([1, 2, 3, 4, 5, 6]) table = PauliTable.from_labels(labels) coeff = 10 op = PauliSumOp(SparsePauliOp(table, coeffs), coeff) for idx, i in enumerate(op.matrix_iter()): self.assertTrue(np.array_equal(i, coeff * coeffs[idx] * Pauli(labels[idx]).to_matrix()))
def test_add(self): """add test""" pauli_sum = 3 * X + Y self.assertIsInstance(pauli_sum, PauliSumOp) expected = PauliSumOp(3.0 * SparsePauliOp(Pauli("X")) + SparsePauliOp(Pauli("Y"))) self.assertEqual(pauli_sum, expected) pauli_sum = X + Y summed_op = SummedOp([X, Y]) self.assertEqual(pauli_sum, summed_op) a = Parameter("a") b = Parameter("b") actual = a * PauliSumOp.from_list([("X", 2)]) + b * PauliSumOp.from_list([("Y", 1)]) expected = SummedOp( [PauliSumOp.from_list([("X", 2)], a), PauliSumOp.from_list([("Y", 1)], b)] ) self.assertEqual(actual, expected)