def compose(self, other: OperatorBase) -> OperatorBase: if not self.is_measurement: raise ValueError( 'Composition with a Statefunctions in the first operand is not defined.') new_self, other = self._check_zero_for_composition_and_expand(other) # pylint: disable=cyclic-import,import-outside-toplevel from ..primitive_ops.circuit_op import CircuitOp from ..primitive_ops.pauli_op import PauliOp from ..primitive_ops.matrix_op import MatrixOp if isinstance(other, (PauliOp, CircuitOp, MatrixOp)): op_circuit_self = CircuitOp(self.primitive) # Avoid reimplementing compose logic composed_op_circs = op_circuit_self.compose(other.to_circuit_op()) # Returning CircuitStateFn return CircuitStateFn(composed_op_circs.primitive, is_measurement=self.is_measurement, coeff=self.coeff * other.coeff) if isinstance(other, CircuitStateFn) and self.is_measurement: from .. import Zero return self.compose(CircuitOp(other.primitive, other.coeff)).compose(Zero ^ self.num_qubits) from qiskit.aqua.operators import ComposedOp return ComposedOp([new_self, other])
def compose(self, other: OperatorBase) -> OperatorBase: r""" Composition (Linear algebra-style: A@B(x) = A(B(x))) is not well defined for states in the binary function model, but is well defined for measurements. Args: other: The Operator to compose with self. Returns: An Operator equivalent to the function composition of self and other. Raises: ValueError: If self is not a measurement, it cannot be composed from the right. """ # TODO maybe allow outers later to produce density operators or projectors, but not yet. if not self.is_measurement: raise ValueError( 'Composition with a Statefunction in the first operand is not defined.') new_self, other = self._check_zero_for_composition_and_expand(other) # TODO maybe include some reduction here in the subclasses - vector and Op, op and Op, etc. # pylint: disable=import-outside-toplevel from qiskit.aqua.operators import CircuitOp if self.primitive == {'0' * self.num_qubits: 1.0} and isinstance(other, CircuitOp): # Returning CircuitStateFn return StateFn(other.primitive, is_measurement=self.is_measurement, coeff=self.coeff * other.coeff) from qiskit.aqua.operators import ComposedOp return ComposedOp([new_self, other])
def test_expand_on_list_op(self): """ Test if expanded ListOp has expected num_qubits. """ add_qubits = 3 # ComposedOp composed_op = ComposedOp([(X ^ Y ^ Z), (H ^ T), (Z ^ X ^ Y ^ Z).to_matrix_op()]) expanded = composed_op._expand_dim(add_qubits) self.assertEqual(composed_op.num_qubits + add_qubits, expanded.num_qubits) # TensoredOp tensored_op = TensoredOp([(X ^ Y), (Z ^ I)]) expanded = tensored_op._expand_dim(add_qubits) self.assertEqual(tensored_op.num_qubits + add_qubits, expanded.num_qubits) # SummedOp summed_op = SummedOp([(X ^ Y), (Z ^ I ^ Z)]) expanded = summed_op._expand_dim(add_qubits) self.assertEqual(summed_op.num_qubits + add_qubits, expanded.num_qubits)
def test_compose_consistency(self): """Test if PrimitiveOp @ ComposedOp is consistent with ComposedOp @ PrimitiveOp.""" # PauliOp op1 = (X ^ Y ^ Z) op2 = (X ^ Y ^ Z) op3 = (X ^ Y ^ Z).to_circuit_op() comp1 = op1 @ ComposedOp([op2, op3]) comp2 = ComposedOp([op3, op2]) @ op1 self.assertListEqual(comp1.oplist, list(reversed(comp2.oplist))) # CircitOp op1 = op1.to_circuit_op() op2 = op2.to_circuit_op() op3 = op3.to_matrix_op() comp1 = op1 @ ComposedOp([op2, op3]) comp2 = ComposedOp([op3, op2]) @ op1 self.assertListEqual(comp1.oplist, list(reversed(comp2.oplist))) # MatrixOp op1 = op1.to_matrix_op() op2 = op2.to_matrix_op() op3 = op3.to_pauli_op() comp1 = op1 @ ComposedOp([op2, op3]) comp2 = ComposedOp([op3, op2]) @ op1 self.assertListEqual(comp1.oplist, list(reversed(comp2.oplist)))
def compose(self, other: OperatorBase, permutation: Optional[List[int]] = None, front: bool = False) -> OperatorBase: if not self.is_measurement and not front: raise ValueError( 'Composition with a Statefunctions in the first operand is not defined.' ) # type: ignore new_self, other = self._expand_shorter_operator_and_permute( other, permutation) if front: return other.compose(new_self) # pylint: disable=cyclic-import,import-outside-toplevel from ..primitive_ops.circuit_op import CircuitOp from ..primitive_ops.pauli_op import PauliOp from ..primitive_ops.matrix_op import MatrixOp if isinstance(other, (PauliOp, CircuitOp, MatrixOp)): op_circuit_self = CircuitOp(self.primitive) # Avoid reimplementing compose logic composed_op_circs = op_circuit_self.compose(other.to_circuit_op()) # Returning CircuitStateFn return CircuitStateFn( composed_op_circs.primitive, # type: ignore is_measurement=self.is_measurement, coeff=self.coeff * other.coeff) if isinstance(other, CircuitStateFn) and self.is_measurement: from .. import Zero return self.compose(CircuitOp( other.primitive, other.coeff)).compose(Zero ^ self.num_qubits) from qiskit.aqua.operators import ComposedOp return ComposedOp([new_self, other])
assert indented_str_content == initial_str.split("\n") assert "\t\tString\n\t\tto indent\n" == ListOp._indent( "String\nto indent\n", indentation="\t\t") print( ComposedOp([ SummedOp([ ComposedOp([ OperatorStateFn(SummedOp( [0.18093119978423136 * Z, -1.052373245772859 * I], abelian=True), is_measurement=True), PrimitiveOp(HGate()) ]), ComposedOp([ OperatorStateFn(SummedOp([ 0.18093119978423136 * Z, -1.052373245772859 * I - 1.052373245772859 * I ], abelian=True), is_measurement=True), I ]) ]), PrimitiveOp(HGate()) ])) print(ComposedOp([SummedOp([X, Z])])) # https://github.com/Qiskit/qiskit-aqua/pull/1111 -> Matrix multiplicative factor (z + z == 2 * z) z = MatrixOp([[1, 0], [0, -1]]) a = Z + z
def test_composed_op_immutable_under_eval(self): """Test ``ComposedOp.eval`` does not change the operator instance.""" op = 2 * ComposedOp([X]) _ = op.eval() # previous bug: after op.eval(), op was 2 * ComposedOp([2 * X]) self.assertEqual(op, 2 * ComposedOp([X]))