Skip to content
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

Adding PasqalDevice #40

Merged
merged 31 commits into from
Oct 8, 2020
Merged

Adding PasqalDevice #40

merged 31 commits into from
Oct 8, 2020

Conversation

co9olguy
Copy link
Member

No description provided.

co9olguy and others added 11 commits July 8, 2020 13:11
* adding basic pasqal device

* using base simulator and removing qubit worries

* adding tests

* changes

* merge master and fix travis issue

* linting

* change version

* Update pennylane_cirq/pasqal_device.py

Co-authored-by: Josh Izaac <josh146@gmail.com>

* Update pennylane_cirq/pasqal_device.py

Co-authored-by: Josh Izaac <josh146@gmail.com>

* Update pennylane_cirq/pasqal_device.py

Co-authored-by: Josh Izaac <josh146@gmail.com>

Co-authored-by: Josh Izaac <josh146@gmail.com>
* Update requirements.txt

* Update requirements.txt

* Update requirements.txt

* Update pasqal_device.py

* Update test_pasqal_device.py

Co-authored-by: Josh Izaac <josh146@gmail.com>
# For consistency, this plugin uses that same total order
self.qubits = sorted(qubits)

super().__init__(wires, shots, analytic)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had to move down the superclass initialization here, since it is the thing that creates the wire_map, but the wire_map can't be determined until the cirq qubits have been assigned

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mariaschuld might have some ideas on how to improve Wire/cirq qubit integration (there was an allusion to it in #39 and #37)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I now I understand the following PR cherry picked from this one.

@@ -149,7 +157,10 @@ def reset(self):
# pylint: disable=missing-function-docstring
super().reset()

self.circuit = cirq.Circuit()
if self.cirq_device:
self.circuit = cirq.Circuit(self.cirq_device)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needed in order to use a non-default Cirq device (PasqalVirtualDevice)

requirements.txt Outdated
@@ -1,3 +1,4 @@
pennylane>=0.9
cirq>=0.7
google-api-core[grpc]<=1.14.0
git+https://github.com/quantumlib/Cirq.git@master
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pasqal functionality now merged into Cirq master, but not released

assert dev.qubits[3] == cirq.GridQubit(1, 1)
assert dev.qubits == qubits

def test_outer_init_of_qubits_unordered(self):
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was never being tested properly before

@@ -226,3 +244,10 @@ def apply(self, operations, **kwargs):
# Diagonalize the given observables
for operation in rotations:
self._apply_operation(operation)

def define_wire_map(self, wires):
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Trying to get ThreeDQubits to work uncovered a lot of uncovered edge cases at the interaction point between PennyLane's wires and Cirq's qubits

``q1>q2``, then the wire indices 0 and 1 are mapped to q2 and q1, respectively.
If the user provides their own wire labels, e.g., ``wires=["alice", "bob"]``, and the
qubits are the same as the previous example, then "alice" would map to qubit q2
and "bob" would map to qubit q1.
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: this has a big possibility to confuse users, but I'm not sure there's any better way to deal with it

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is super confusing 🤔

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

spent most of a day trying to figure this out, the alternative is even more confusing :(

# wires that are not acted upon
self.circuit.append(cirq.IdentityGate(len(self.qubits))(*self.qubits))
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line broke the PasqalDevice, since it has restrictions about how close qubits must be in order to have multi-qubit gates. Note that it would break any other cirq device in the future which also had topology restrictions

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm wondering if applying identity gates to unused qubits is the right approach. It sounds like Cirq is being somewhat smart here, and simply just discarding qubits from the simulation that are not involved in the computation. Pyquil does this same; we should be able to simply take into account these ignored qubits when returning the samples/probabilities.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, but I think this requires a change to how the devices work, doesn't it?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think so, the Forest simulators also act like this, and we take it into account in the PL plugin. We simply keep track of the inactive wires, and 'expand_dim' the probability before returning it.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, then it makes sense to do that here. I think the previous solution (identity on all wires) was a quick hack.

But it might also make sense to provide helper functions for keeping track of such things in the base Device class?

pennylane_cirq/cirq_device.py Outdated Show resolved Hide resolved
``q1>q2``, then the wire indices 0 and 1 are mapped to q2 and q1, respectively.
If the user provides their own wire labels, e.g., ``wires=["alice", "bob"]``, and the
qubits are the same as the previous example, then "alice" would map to qubit q2
and "bob" would map to qubit q1.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is super confusing 🤔

# For consistency, this plugin uses that same total order
self.qubits = sorted(qubits)

super().__init__(wires, shots, analytic)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mariaschuld might have some ideas on how to improve Wire/cirq qubit integration (there was an allusion to it in #39 and #37)

# wires that are not acted upon
self.circuit.append(cirq.IdentityGate(len(self.qubits))(*self.qubits))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm wondering if applying identity gates to unused qubits is the right approach. It sounds like Cirq is being somewhat smart here, and simply just discarding qubits from the simulation that are not involved in the computation. Pyquil does this same; we should be able to simply take into account these ignored qubits when returning the samples/probabilities.

@co9olguy
Copy link
Member Author

co9olguy commented Oct 8, 2020

@josh146 Not sure why CodeFactor is complaining about Iterable, it imports fine when I run locally 🤔

@josh146
Copy link
Member

josh146 commented Oct 8, 2020

@josh146 Not sure why CodeFactor is complaining about Iterable, it imports fine when I run locally 🤔

This is a known bug that is safe to ignore for now. The issue stems from the fact that collections.Iterable is deprecated, and the new home is collections.abc.Iterable -- this will be breaking in Python 3.9. Until then, the way Python makes this work from both import locations confuses pylint.

@co9olguy
Copy link
Member Author

co9olguy commented Oct 8, 2020

docker build for black check erroring as well, but I think it's an external issue 🤔

Copy link
Member

@josh146 josh146 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good @co9olguy! A couple of high level comments before merging:

  • the permissions changes on the doc/xanadu_theme folder should be reverted (git checkout master doc/xanadu_theme).

  • The Pasqal device hasn't been added to the docs --- a card should be added on the doc/index.rst page, and a new page added in the doc/devices/ directory. The information in the class docstring is not very user accessible (they would need to dig through the API to find it).

  • We should update the setup.py requirements.

pennylane_cirq/cirq_device.py Outdated Show resolved Hide resolved
requirements.txt Show resolved Hide resolved
Co-authored-by: Josh Izaac <josh146@gmail.com>
@josh146
Copy link
Member

josh146 commented Oct 8, 2020

docker build for black check erroring as well, but I think it's an external issue 🤔

This is now fixed, it's failing still though because Black is complaining on an unformatted file :)

@co9olguy
Copy link
Member Author

co9olguy commented Oct 8, 2020

docker build for black check erroring as well, but I think it's an external issue thinking

This is now fixed, it's failing still though because Black is complaining on an unformatted file :)

That is easy enough to deal with :)

Copy link
Member

@josh146 josh146 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💯

doc/devices/pasqal.rst Outdated Show resolved Hide resolved
@codecov
Copy link

codecov bot commented Oct 8, 2020

Codecov Report

❗ No coverage uploaded for pull request base (master@e985c4b). Click here to learn what that means.
The diff coverage is 100.00%.

Impacted file tree graph

@@            Coverage Diff            @@
##             master      #40   +/-   ##
=========================================
  Coverage          ?   99.60%           
=========================================
  Files             ?        7           
  Lines             ?      253           
  Branches          ?        0           
=========================================
  Hits              ?      252           
  Misses            ?        1           
  Partials          ?        0           
Impacted Files Coverage Δ
pennylane_cirq/cirq_device.py 98.75% <ø> (ø)
pennylane_cirq/cirq_operation.py 100.00% <ø> (ø)
pennylane_cirq/__init__.py 100.00% <100.00%> (ø)
pennylane_cirq/pasqal_device.py 100.00% <100.00%> (ø)
pennylane_cirq/_version.py 100.00% <0.00%> (ø)
pennylane_cirq/ops.py 100.00% <0.00%> (ø)
pennylane_cirq/simulator_device.py 100.00% <0.00%> (ø)
... and 1 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update e985c4b...c3973ff. Read the comment docs.

@co9olguy co9olguy merged commit f3dc1ff into master Oct 8, 2020
@co9olguy co9olguy deleted the pasqal-holding branch October 8, 2020 17:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants