-
Notifications
You must be signed in to change notification settings - Fork 18
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
Port PennyLane-Cirq to QubitDevice #19
Conversation
Codecov Report
@@ Coverage Diff @@
## master #19 +/- ##
==========================================
- Coverage 98.73% 98.67% -0.06%
==========================================
Files 6 6
Lines 158 151 -7
==========================================
- Hits 156 149 -7
Misses 2 2
Continue to review full report at Codecov.
|
# be calculated later | ||
w, U = np.linalg.eigh(Hmat) | ||
self._eigs[Hkey] = {"eigval": w, "eigvec": U} | ||
# TODO: get pre rotated state 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.
?
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.
Actually I'm a little confused with the handling of pre-rotation state and rotated state. In the implementation of default.qubit
, the probability is given for the rotated state but the state is given for the pre_rotated_state. I think this is somewhat inconsistent, isn't it?
Here in Cirq I have the additional problem that I can't really extract the pre_rotated_state without much hassle so that currently, state is the rotated state.
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.
What is your opinion on this, @antalszava ?
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.
And @josh146
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 is slightly intentional. Now that there is qml.prob
, we no longer want the user to access dev.probability
, so for consistency this should always represent the actual device probability.
For state, however, we are still in an awkward position where there is no equivalent to extract it from the qnode yet
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.
So what do you think of me keeping the post-rotation state as dev.state
? It is possible to extract the pre-rotation state, but it will not make the code clearer...
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 think it is fine for now. dev.state
should only ever be used for debugging, and we can attach caveats to it that depend on the device (e.g. a lot of hardware simulators don't even store any state)
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 a docstring that explains this
pennylane_cirq/simulator_device.py
Outdated
def pre_measure(self): | ||
super().pre_measure() | ||
def apply(self, operations, rotations=None, **kwargs): | ||
super().apply(operations, rotations, **kwargs) |
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.
super().apply(operations, rotations, **kwargs) | |
super().apply(operations, rotations=rotations, **kwargs) |
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 would be in case kwargs=={}
is True
and apply
being called only with passing operations
to it, since then I think rotations
would default to None
and there might be an error arising from passing too many positional arguments (None
is going to be passed as the second argument). Might be wrong though.
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 removed the argument rotations
entirely now to be consistent with the signature of apply
from the QubitDevice
class.
) | ||
else: | ||
return self.sample(observable, wires, par).var() | ||
return super().generate_samples() |
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.
How about the case of analytic==True
and returning qml.sample
?
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 see no problem with that? The logic of deciding when to call generate_samples
is implemented in QubitDevice
, so I just have to assure that samples are properly generated when it is called. And for analytic mode I can safely piggyback onto the default implementation.
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 is the part of the device.execute()
:
if (not self.analytic) or circuit.is_sampled:
self._samples = self.generate_samples()
for self.analytic==True and circuit.is_sampled
SimulatorDevice.generate_samples()
will be called and since self.analytic==True
the if statement evaluates to True
on line 158, and QubitDevice.generate_samples()
will be called.
Whereas, if self.analytic==False and circuit.is_sampled
, SimulatorDevice.generate_samples()
still gets called, but the if statement on line 158 evaluates to False
and the code block below gets executed.
If this is so (and I didn't confuse myself or mess up something here 😅 ), then how come that there is a different logic for these two cases?
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.
All you say is totally correct. There is a different logic for the analytic==False
case because in that case I don't generate the samples myself but I use Cirq's own measurement scheme. I did this because I wanted to use as much of Cirq's inbuilt API as possible
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 is the difference between simulator.run
(analytic==False
) and simulator.simulate
(analytic==True
)
("RX", [2], [cirq.Rx(2)]), | ||
("RX.inv", [1.4], [cirq.Rx(-1.4)]), | ||
("RX.inv", [-1.2], [cirq.Rx(1.2)]), | ||
("RX.inv", [2], [cirq.Rx(-2)]), |
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.
Perhaps keeping 1-1 rotations tests (e.g. RX, Rot and their inverses) could be nice
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.
They are still there, it is just misaligned due to the blacking
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.
Looks good @johannesjmeyer 😊 Once the comments are addressed, should be merge-ready
Co-Authored-By: Josh Izaac <josh146@gmail.com>
…ennylane-cirq into qubit_device_port
This reverts commit d4a4933.
…ce port has taken place
@@ -1,3 +1,3 @@ | |||
pennylane>=0.7 | |||
pennylane>=0.8 |
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 was extending the functionality of #21 with QubitDevice
being used in this plugin.
PennyLane introduces the
QubitDevice
baseclass for plugins in the next release (0.8.0). AsQubitDevice
eases the implementation drastically, this PR ports the PennyLane-Cirq plugin to this base device class.As a side effect, PennyLane-Cirq now supports tensor observables.
This PR also adresses some changes in Cirq that resulted in depreceation warnings.