-
Notifications
You must be signed in to change notification settings - Fork 50
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
noncliff: add copy, == for GeneralizedStabilizer, UnitaryPauliChannel #419
Conversation
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.
That is very useful, thank you! I have a minor worry about the use of deepcopy, explained below.
src/nonclifford.jl
Outdated
@@ -342,6 +347,8 @@ struct UnitaryPauliChannel{T,S,P} <: AbstractPauliChannel | |||
end | |||
|
|||
PauliChannel(p::UnitaryPauliChannel) = p.paulichannel | |||
Base.copy(p::UnitaryPauliChannel) = deepcopy(p) |
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.
using deepcopy
as an implementation of copy
is a bit dangerous. It frequently works fine, but if you have views into some other memory it can produce unexpected results. The more boilerplate-heavy "Constructor on copied slot entries" is much safer here.
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.
My bad...
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.
Since tuples are immutable, I used p.weights
or p.paulis
instead of copy(p.weights)
, copy(p.paulis)
etc.
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.
You encountered an interesting quirk of julia when you were trying to copy a tuple. See the comment I added below.
@@ -342,6 +347,8 @@ struct UnitaryPauliChannel{T,S,P} <: AbstractPauliChannel | |||
end | |||
|
|||
PauliChannel(p::UnitaryPauliChannel) = p.paulichannel | |||
Base.copy(p::UnitaryPauliChannel) = UnitaryPauliChannel(p.paulis, p.weights) | |||
Base.:(==)(p₁::UnitaryPauliChannel, p₂::UnitaryPauliChannel) = p₁.paulis==p₂.paulis && p₁.weights==p₂.weights |
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 tuples might be immutable, but the objects they contain are not-necessarily immutable. E.g. if I do something stupid like mul_left!(p.paulis, some_other_pauli)
on a copied p
, the original p
would also be modified. I am stupid to do that to begin with, but nonetheless I would be right to be surprised that modifying the copy modified the original as well.
More generally, let the compiler worry about immutability unless you know for a fact that the compiler is doing a bad job. The compiler can figure out when immutability guarantees let it reuse memory:
Lastly, you are probably doing this because Tuple
does not have a copy
method. That is a frustration I have with julia -- the story behind it can be found starting in this discussion: https://discourse.julialang.org/t/why-can-i-deepcopy-nothing-but-not-copy-nothing/112429 (in particular see the links by stevengj).
Anyway, to make sure this is an actual copy, the clunky but necessary map(copy, p.paulis)
can be used.
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.
Thank you for these insights! I avoided using copy(p.paulis)
so it wouldn’t look stupid.
thank you! |
This PR is inspired from this comment: #355 (comment)