-
Notifications
You must be signed in to change notification settings - Fork 1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Testing] Fix types in operations for dense pauli strings #4892
[Testing] Fix types in operations for dense pauli strings #4892
Conversation
pauli_mask=mask, | ||
coefficient=self.coefficient * _vectorized_pauli_mul_phase(self.pauli_mask[i], p), | ||
) | ||
|
||
return NotImplemented | ||
|
||
def __rmul__(self, other): | ||
if isinstance(other, (sympy.Basic, numbers.Number)): | ||
def __rmul__(self: T, other: Any) -> T: # type: ignore |
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.
Why the type ignore? (here and elsewhere). Should we revert to not having type annotations in these cases instead of explicitly ignoring them?
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.
The thing here is that BaseDensePauliString
is a subclass of raw_types.Gate
. As a result, mypy expects BaseDensePauliString.__rmul__
to return an object of a subclass of cirq.LinearCombinationOfGates
. That is not the case, as the operation actually acts on the coefficient
attribute of the Pauli string. Maybe a natural fix would be for the operations in raw_types.Gate
to have Union[Gate, cirq.LinearCombinationOfGates]
as return type instead of cirq.LinearCombinationOfGates
alone. I'll commit the fix for review.
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.
I rollbacked the previous change, that is, the return type of linear operations in raw_types.py
is now back to cirq.LinearCombinationOfGates
alone. I used Gate
's method wrap_in_linear_combination
to convert the results of linear operations in dense_pauli_string.py
(I mimicked what's done in raw_types.py
).
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.
Left another round of comments. Main concern is about potential breaking changes when doing binary operations on dense pauli strings of different type types.
if isinstance(power, int): | ||
i_group = [1, +1j, -1, -1j] | ||
if self.coefficient in i_group: | ||
coef = i_group[i_group.index(self.coefficient) * power % 4] | ||
else: | ||
coef = self.coefficient ** power | ||
if power % 2 == 0: | ||
return coef * DensePauliString.eye(len(self)) | ||
return DensePauliString(coefficient=coef, pauli_mask=self.pauli_mask) | ||
return coef * self.eye(len(self)) |
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.
This should be type(self).eye
since eye
is a class method. We should also have a test to verify this works as expected.
return coef * self.eye(len(self)) | |
return coef * type(self).eye(len(self)) |
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.
self.eye
andtype(self).eye
are semantically equivalent here. Is your suggestion referring to some convention or best practice?- I'll add the test.
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.
I changed to type(self)
as suggested.
def __mul__(self: TCls, other: Union[sympy.Basic, int, float, complex, TCls]) -> TCls: | ||
cls = type(self) | ||
|
||
if isinstance(other, cls): |
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.
Does this mean multiplying a MutableDensePauliString
instance with a DensePauliString
was allowed before this change but will not be allowed anymore? This sounds like a breaking change and should not be done.
For binary operations that expect an other
argument which can be a base dense pauli string, I think we should default to returning a MutableDensePauliString
if the types of self and other are not same (but both are instances of BaseDensePauliString), else return type(self)
.
This should be done for __mul__
, __rmul__
, tensor_product
etc. Please also add corresponding tests.
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.
I added the possibility to cross operate on mutable and non-mutable dense Pauli strings.
Co-authored-by: Tanuj Khattar <tanujkhattar@google.com>
Friendly ping @alexandrebouayad: Do you have time to finish this up? I can take it on if not. |
@vtomole thanks for the reminder, it had slipped my mind. I'll do it in the coming days. |
I have made the changes as suggested, plus a few other minor ones. I'll add the remaining tests, and I'll ensure that local checks pass by the end of this week hopefully. |
@alexandrebouayad Can you please fix the remaining failing tests? Thanks! |
@alexandrebouayad Gentle reminder, do you still have time to work on this? |
Hey @alexandrebouayad , I'm pretty sure this PR has been superseded by #5624. We would love your review on that PR. |
@vtomole Actually, I did skip over some of the tricky parts of fixing mypy types in my PR #5624; for example: Adding return types annotations to operations like Fixing this would require us to modify the default return types on |
@vtomole Thanks for letting me now, I'll try and have a look at #5624. @tanujkhattar I have managed to add full return type annotations for both For the latter to work, I had to remove |
Fix #4835.
Fix operations like
__pow__
,__mul__
,__rmul__
,__abs__
,tensor_product
, etc, on abstract classBaseDensePauliString
so that the operations return compatible types when applied on the two concrete subclassesDensePauliString
andMutableDensePauliString
.Also add a few type annotations, and modify a few tests.
One noticeable implied change: multiplying a MutableDensePauliString object with a DensePauliString object (and vise versa) is not allowed anymore.