-
Notifications
You must be signed in to change notification settings - Fork 376
Operator.compose should allow indices #1144
Operator.compose should allow indices #1144
Conversation
merge qiskit-aqua to my fork
…at it expands shorter operator with identity 2) implemented OperatorBase.expand 3) defined abstract method OperatorBase.identity, and implemented in child classes of OperatorBase (TODO check if implementation makes sense for every class) 4) created tests for composing Operators of different dimensions
…ays default to False), even if tensored instances were is_measurement=True
Thanks for the commitment @molar-volume! I think we need to clarify what #1088 should do and how we could do it. The idea was that you could pass concrete indices (not only ops of different sizes) and e.g. do op = (X ^ 5)
op.compose( Z ^ Y, qubits=[0, 3], inplace=True)
print(op) # ComposedOp( [X ^ X ^ X ^ X ^ X], [Z ^ I ^ I ^ Y ^ I] ) So it is closer to the same method of the quantum circuit, see The approach in here does only allow for consecutive qubit indices (e.g.
A possible approach would be to add a def pad_with_identities(self, new_dim, qargs=None):
"""Extend this operator to ``new_dim`` where this operator acts on ``qargs``.
Args:
new_dim: The new dimension, must be larger equal than ``self.num_qubits``.
qargs: The qubit indices this operator acts on, must be a list of length ``self.num_qubits``.
""" And then in |
Hi @Cryoris thank you for the feedback ! Now I think it has some advantages, for example you can define def expand_to_dim(self, num_qubits: int) -> OperatorBase:
return self.tensor(self.identity_operator(num_qubits)) I understand that we need a more general method with indices, just like you defined def pad_with_identities(self, new_dim, qargs=None) For the circ_op = (X ^ Y).to_circuit_op().permute([0,2]) @ (X ^ Y ^ Z ^ X).to_circuit_op()
print(circ_op.to_circuit())
┌───┐
q_0: ┤ X ├─────
├───┤┌───┐
q_1: ┤ Z ├┤ Y ├
├───┤└───┘
q_2: ┤ Y ├─────
├───┤┌───┐
q_3: ┤ X ├┤ X ├
└───┘└───┘ I think I know how to implement |
2) test_permute_on_primitive_op implemented. It checks correctness and consistency of permute implementations.
2) added testcase for MatrixOp permute, to check consistency with PauliOp.permute and CircuitOp.permute
Permute implemented for PauliOp and MatrixOp as well. import numpy as np
from qiskit.aqua.operators import MatrixOp, X, Y, Z, I, CircuitOp
pauli_op = (X ^ Z).permute([0, 2]) @ (X ^ Y ^ Z ^ X)
matrix_op = (X ^ Z).to_matrix_op().permute([0, 2]) @ (X ^ Y ^ Z ^ X).to_matrix_op()
circuit_op = (X ^ Z).to_circuit_op().permute([0, 2]) @ (X ^ Y ^ Z ^ X).to_circuit_op()
print(circuit_op.to_circuit())
circ_eq_pauli = np.allclose(circuit_op.to_matrix(), pauli_op.to_matrix()) # circ_eq_pauli: True
circ_eq_matrix = np.allclose(circuit_op.to_matrix(), matrix_op.to_matrix()) # circ_eq_matrix: True
┌───┐┌───┐
q_0: ┤ X ├┤ I ├
├───┤├───┤
q_1: ┤ Z ├┤ Z ├
├───┤└───┘
q_2: ┤ Y ├─────
├───┤┌───┐
q_3: ┤ X ├┤ X ├
└───┘└───┘ Do you want to provide compose with indices (or |
Is there are good reason for the rename of |
@woodsp-ibm |
after reading #1086 I note that |
Ah ok, identity is a new method that was added by this PR. so you just renamed your new method. From my perspective I am not sure that the name change does so much for me since they are all operators according to OperatorBase. Maybe the method anyway should be some class or even module level function to return a specific operator of said type i.e. an identity in this case. I do not know why it would be an instance method since it has no real need of self (or am I mistaken again) - unless it were an identity spanning the same number of qubits as the operator in self in which case I could somehow see it. |
@woodsp-ibm |
Yes, I see some implementations of identity_operator do use self (when they need to copy across a property like is_measurement) while some do not. Do you see this as function that would be called in general by a user of the API - I guess you can if you want an instance that is an identity across that number of qubits - but of course with it being tied to self one needs to do that off an existing object which just seems weird. Otherwise its just a really some helper method to facilitate the one expand_to_dim implementation in the base class rather than have it implemented in each of the classes. |
Co-authored-by: Julien Gacon <gaconju@gmail.com>
…different num_qubit
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM thanks for all the work!
I should add thanks for all your hard work and persistence to see this through. It has been a while, with a lot of discussion, so thanks again for your patience and perseverance in making this happen! |
My pleasure @woodsp-ibm ! I know the discussion was necessary and helped me a lot, so thanks for all your comments. Thanks @Cryoris ! |
) * 1) modified PrimitiveOp._check_zero_for_composition_and_expand, so that it expands shorter operator with identity 2) implemented OperatorBase.expand 3) defined abstract method OperatorBase.identity, and implemented in child classes of OperatorBase (TODO check if implementation makes sense for every class) 4) created tests for composing Operators of different dimensions * CircuitStateFn.tensor did not set is_measurement parameter (hence always default to False), even if tensored instances were is_measurement=True * Added test for expand method on StateFn subclasses * 1) PauliOp.permute implemented 2) test_permute_on_primitive_op implemented. It checks correctness and consistency of permute implementations. * 1) permute implemented for MatrixOp 2) added testcase for MatrixOp permute, to check consistency with PauliOp.permute and CircuitOp.permute * identity renamed to identity_operator in OperatorBase * OperatorBase.expand renamed to expand_to_dim * expand_to_dim overridden for PrimitiveOps * 1) expand_to_dim implemented for each subclass of OperatorBase 2) removed identity_operator * OperatorStateFn permute implemented * 1) permute for TensoredOp 2) extended documentation * 1) TensoredOp.permute moved to ListOp.permute 2) ListOp.permute uses CircuitOps instead of MatrixOps for permutations * permute defined abstract in OperatorBase * composition of PrimitiveOp with ComposedOp prepends the ComposedOp.oplist with PrimitiveOp * Revert "composition of PrimitiveOp with ComposedOp prepends the ComposedOp.oplist with PrimitiveOp" * 1) compose in MatrixOp, PauliOp and CircuitOp enhanced, to be consistent with ComposedOp.compose 2) test_compose_consistency added to verify the consistency * DRY applied * Test if ListOp.permute is consistent with PrimitiveOp permute methods * test for expand_to_dim on ListOps * 1) changed signature of compose to allow permutations on operators 2) permutation on operators included in compose method * refactoring * unit test for compose with indices * refactoring and fixed linting * 1) StateFn.compose expands the shorter operators with identity 2) refactored _check_zero_for_composition_and_expand 3) unit test for new composition features of StateFns 4) fixing style * 1) expand_to_dim renamed to expand_with_identities (expand_to_dim was misleading, because its parameter is not the target dimension, but the number or qubits to add to operator) 2) documentation for the new features improved * permute implemented for DictStateFn * 1) VectorStateFn.to_dict_fn and DictStateFn.to_vector_state_fn implemented 2) VectorStateFn permute implemented 3) unit tests for the new functionality * implemented custom function to decompose permutations into transpositions, to avoid import of sympy * explaining comment for CircuitStateFn.expand_with_identity * expand_with_identity made private and renamed to _expand_dim (expand_with_identity is misleading for implementations in DictStateFn and VectorStateFn, where zeros are used for expansion) * 1) Compose method has only one set of permutation indices (for other operator). 2) Added new argument front=False in compose method. If front==True, return other.compose(self), but only after expansion and permutation is performed. * 1) modified test_op_construction because of changes in compose signature 2) fix in CircuitOp.compose * _check_zero_for_composition_and_expand renamed to _expand_shorter_operator_and_permute, to be more self-explanatory * VectorStateFn.permute reimplemented for better performance * removed duplicate method to_vector_state_fn (to_matrix_op was already defined) * new_self instead of self in EvolvedOp * test_op_construction refactored * raise AquaError in ListOp.permute, if ListOp contains operators with different num_qubit Co-authored-by: Manoel Marques <manoelmrqs@gmail.com> Co-authored-by: Julien Gacon <gaconju@gmail.com> Co-authored-by: Manoel Marques <Manoel.Marques@ibm.com> Co-authored-by: Steve Wood <40241007+woodsp-ibm@users.noreply.github.com>
) * 1) modified PrimitiveOp._check_zero_for_composition_and_expand, so that it expands shorter operator with identity 2) implemented OperatorBase.expand 3) defined abstract method OperatorBase.identity, and implemented in child classes of OperatorBase (TODO check if implementation makes sense for every class) 4) created tests for composing Operators of different dimensions * CircuitStateFn.tensor did not set is_measurement parameter (hence always default to False), even if tensored instances were is_measurement=True * Added test for expand method on StateFn subclasses * 1) PauliOp.permute implemented 2) test_permute_on_primitive_op implemented. It checks correctness and consistency of permute implementations. * 1) permute implemented for MatrixOp 2) added testcase for MatrixOp permute, to check consistency with PauliOp.permute and CircuitOp.permute * identity renamed to identity_operator in OperatorBase * OperatorBase.expand renamed to expand_to_dim * expand_to_dim overridden for PrimitiveOps * 1) expand_to_dim implemented for each subclass of OperatorBase 2) removed identity_operator * OperatorStateFn permute implemented * 1) permute for TensoredOp 2) extended documentation * 1) TensoredOp.permute moved to ListOp.permute 2) ListOp.permute uses CircuitOps instead of MatrixOps for permutations * permute defined abstract in OperatorBase * composition of PrimitiveOp with ComposedOp prepends the ComposedOp.oplist with PrimitiveOp * Revert "composition of PrimitiveOp with ComposedOp prepends the ComposedOp.oplist with PrimitiveOp" * 1) compose in MatrixOp, PauliOp and CircuitOp enhanced, to be consistent with ComposedOp.compose 2) test_compose_consistency added to verify the consistency * DRY applied * Test if ListOp.permute is consistent with PrimitiveOp permute methods * test for expand_to_dim on ListOps * 1) changed signature of compose to allow permutations on operators 2) permutation on operators included in compose method * refactoring * unit test for compose with indices * refactoring and fixed linting * 1) StateFn.compose expands the shorter operators with identity 2) refactored _check_zero_for_composition_and_expand 3) unit test for new composition features of StateFns 4) fixing style * 1) expand_to_dim renamed to expand_with_identities (expand_to_dim was misleading, because its parameter is not the target dimension, but the number or qubits to add to operator) 2) documentation for the new features improved * permute implemented for DictStateFn * 1) VectorStateFn.to_dict_fn and DictStateFn.to_vector_state_fn implemented 2) VectorStateFn permute implemented 3) unit tests for the new functionality * implemented custom function to decompose permutations into transpositions, to avoid import of sympy * explaining comment for CircuitStateFn.expand_with_identity * expand_with_identity made private and renamed to _expand_dim (expand_with_identity is misleading for implementations in DictStateFn and VectorStateFn, where zeros are used for expansion) * 1) Compose method has only one set of permutation indices (for other operator). 2) Added new argument front=False in compose method. If front==True, return other.compose(self), but only after expansion and permutation is performed. * 1) modified test_op_construction because of changes in compose signature 2) fix in CircuitOp.compose * _check_zero_for_composition_and_expand renamed to _expand_shorter_operator_and_permute, to be more self-explanatory * VectorStateFn.permute reimplemented for better performance * removed duplicate method to_vector_state_fn (to_matrix_op was already defined) * new_self instead of self in EvolvedOp * test_op_construction refactored * raise AquaError in ListOp.permute, if ListOp contains operators with different num_qubit Co-authored-by: Manoel Marques <manoelmrqs@gmail.com> Co-authored-by: Julien Gacon <gaconju@gmail.com> Co-authored-by: Manoel Marques <Manoel.Marques@ibm.com> Co-authored-by: Steve Wood <40241007+woodsp-ibm@users.noreply.github.com>
) * 1) modified PrimitiveOp._check_zero_for_composition_and_expand, so that it expands shorter operator with identity 2) implemented OperatorBase.expand 3) defined abstract method OperatorBase.identity, and implemented in child classes of OperatorBase (TODO check if implementation makes sense for every class) 4) created tests for composing Operators of different dimensions * CircuitStateFn.tensor did not set is_measurement parameter (hence always default to False), even if tensored instances were is_measurement=True * Added test for expand method on StateFn subclasses * 1) PauliOp.permute implemented 2) test_permute_on_primitive_op implemented. It checks correctness and consistency of permute implementations. * 1) permute implemented for MatrixOp 2) added testcase for MatrixOp permute, to check consistency with PauliOp.permute and CircuitOp.permute * identity renamed to identity_operator in OperatorBase * OperatorBase.expand renamed to expand_to_dim * expand_to_dim overridden for PrimitiveOps * 1) expand_to_dim implemented for each subclass of OperatorBase 2) removed identity_operator * OperatorStateFn permute implemented * 1) permute for TensoredOp 2) extended documentation * 1) TensoredOp.permute moved to ListOp.permute 2) ListOp.permute uses CircuitOps instead of MatrixOps for permutations * permute defined abstract in OperatorBase * composition of PrimitiveOp with ComposedOp prepends the ComposedOp.oplist with PrimitiveOp * Revert "composition of PrimitiveOp with ComposedOp prepends the ComposedOp.oplist with PrimitiveOp" * 1) compose in MatrixOp, PauliOp and CircuitOp enhanced, to be consistent with ComposedOp.compose 2) test_compose_consistency added to verify the consistency * DRY applied * Test if ListOp.permute is consistent with PrimitiveOp permute methods * test for expand_to_dim on ListOps * 1) changed signature of compose to allow permutations on operators 2) permutation on operators included in compose method * refactoring * unit test for compose with indices * refactoring and fixed linting * 1) StateFn.compose expands the shorter operators with identity 2) refactored _check_zero_for_composition_and_expand 3) unit test for new composition features of StateFns 4) fixing style * 1) expand_to_dim renamed to expand_with_identities (expand_to_dim was misleading, because its parameter is not the target dimension, but the number or qubits to add to operator) 2) documentation for the new features improved * permute implemented for DictStateFn * 1) VectorStateFn.to_dict_fn and DictStateFn.to_vector_state_fn implemented 2) VectorStateFn permute implemented 3) unit tests for the new functionality * implemented custom function to decompose permutations into transpositions, to avoid import of sympy * explaining comment for CircuitStateFn.expand_with_identity * expand_with_identity made private and renamed to _expand_dim (expand_with_identity is misleading for implementations in DictStateFn and VectorStateFn, where zeros are used for expansion) * 1) Compose method has only one set of permutation indices (for other operator). 2) Added new argument front=False in compose method. If front==True, return other.compose(self), but only after expansion and permutation is performed. * 1) modified test_op_construction because of changes in compose signature 2) fix in CircuitOp.compose * _check_zero_for_composition_and_expand renamed to _expand_shorter_operator_and_permute, to be more self-explanatory * VectorStateFn.permute reimplemented for better performance * removed duplicate method to_vector_state_fn (to_matrix_op was already defined) * new_self instead of self in EvolvedOp * test_op_construction refactored * raise AquaError in ListOp.permute, if ListOp contains operators with different num_qubit Co-authored-by: Manoel Marques <manoelmrqs@gmail.com> Co-authored-by: Julien Gacon <gaconju@gmail.com> Co-authored-by: Manoel Marques <Manoel.Marques@ibm.com> Co-authored-by: Steve Wood <40241007+woodsp-ibm@users.noreply.github.com>
) * 1) modified PrimitiveOp._check_zero_for_composition_and_expand, so that it expands shorter operator with identity 2) implemented OperatorBase.expand 3) defined abstract method OperatorBase.identity, and implemented in child classes of OperatorBase (TODO check if implementation makes sense for every class) 4) created tests for composing Operators of different dimensions * CircuitStateFn.tensor did not set is_measurement parameter (hence always default to False), even if tensored instances were is_measurement=True * Added test for expand method on StateFn subclasses * 1) PauliOp.permute implemented 2) test_permute_on_primitive_op implemented. It checks correctness and consistency of permute implementations. * 1) permute implemented for MatrixOp 2) added testcase for MatrixOp permute, to check consistency with PauliOp.permute and CircuitOp.permute * identity renamed to identity_operator in OperatorBase * OperatorBase.expand renamed to expand_to_dim * expand_to_dim overridden for PrimitiveOps * 1) expand_to_dim implemented for each subclass of OperatorBase 2) removed identity_operator * OperatorStateFn permute implemented * 1) permute for TensoredOp 2) extended documentation * 1) TensoredOp.permute moved to ListOp.permute 2) ListOp.permute uses CircuitOps instead of MatrixOps for permutations * permute defined abstract in OperatorBase * composition of PrimitiveOp with ComposedOp prepends the ComposedOp.oplist with PrimitiveOp * Revert "composition of PrimitiveOp with ComposedOp prepends the ComposedOp.oplist with PrimitiveOp" * 1) compose in MatrixOp, PauliOp and CircuitOp enhanced, to be consistent with ComposedOp.compose 2) test_compose_consistency added to verify the consistency * DRY applied * Test if ListOp.permute is consistent with PrimitiveOp permute methods * test for expand_to_dim on ListOps * 1) changed signature of compose to allow permutations on operators 2) permutation on operators included in compose method * refactoring * unit test for compose with indices * refactoring and fixed linting * 1) StateFn.compose expands the shorter operators with identity 2) refactored _check_zero_for_composition_and_expand 3) unit test for new composition features of StateFns 4) fixing style * 1) expand_to_dim renamed to expand_with_identities (expand_to_dim was misleading, because its parameter is not the target dimension, but the number or qubits to add to operator) 2) documentation for the new features improved * permute implemented for DictStateFn * 1) VectorStateFn.to_dict_fn and DictStateFn.to_vector_state_fn implemented 2) VectorStateFn permute implemented 3) unit tests for the new functionality * implemented custom function to decompose permutations into transpositions, to avoid import of sympy * explaining comment for CircuitStateFn.expand_with_identity * expand_with_identity made private and renamed to _expand_dim (expand_with_identity is misleading for implementations in DictStateFn and VectorStateFn, where zeros are used for expansion) * 1) Compose method has only one set of permutation indices (for other operator). 2) Added new argument front=False in compose method. If front==True, return other.compose(self), but only after expansion and permutation is performed. * 1) modified test_op_construction because of changes in compose signature 2) fix in CircuitOp.compose * _check_zero_for_composition_and_expand renamed to _expand_shorter_operator_and_permute, to be more self-explanatory * VectorStateFn.permute reimplemented for better performance * removed duplicate method to_vector_state_fn (to_matrix_op was already defined) * new_self instead of self in EvolvedOp * test_op_construction refactored * raise AquaError in ListOp.permute, if ListOp contains operators with different num_qubit Co-authored-by: Manoel Marques <manoelmrqs@gmail.com> Co-authored-by: Julien Gacon <gaconju@gmail.com> Co-authored-by: Manoel Marques <Manoel.Marques@ibm.com> Co-authored-by: Steve Wood <40241007+woodsp-ibm@users.noreply.github.com>
resolves #1088
resolves #1143
This PR is created to verify the solution for expanding operator in #1088 (permute part of issue is not addressed yet)
The method
expand
for expanding the operator withidentity
is defined in OperatorBase,because it enhances
compose
(defined for OperatorBase),and uses
tensor
(defined for OperatorBase), and new methodidentity
(abstract in OperatorBase).identity
is implemented for each subclass of 'OperatorBase',but I am unsure of implementation for DictStateFn and VectorStateFn (instead of identity,
zeros
are used).The new features are demonstrated in
test_expand_on_state_fn
andtest_compose_op_of_different_dim
Summary
Progress for #1088 and solution for #1143
Details and comments