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

Created ControlValues for controlled gates/operations, fix for #4512 #4714

Closed
wants to merge 4 commits into from

Conversation

NoureldinYosri
Copy link
Collaborator

@NoureldinYosri NoureldinYosri commented Nov 30, 2021

  • created control_values.py which contains the ControlValues class.
  • FreeVars and ConstrainedVars classes are provided for ease of use.
  • while the basic idea of ControlValues integrating it inside the code base was challening
  • the old way of using control_values assumed it's a tuple of tuples of ints and was used as thus (comparasion, hashing, slicing, fomatting, conditioning, and loops), the ControlValues class had to provide these functionalities
  • the trickiest part to get right was the support for formatting!
  • fixes Controlled gate construction cannot construct some cases #4512

@NoureldinYosri NoureldinYosri requested review from cduck, vtomole and a team as code owners November 30, 2021 19:47
@google-cla google-cla bot added the cla: yes Makes googlebot stop complaining. label Nov 30, 2021
@CirqBot CirqBot added the size: M 50< lines changed <250 label Nov 30, 2021
NoureldinYosri added a commit to NoureldinYosri/Cirq that referenced this pull request Dec 1, 2021
…mlib#4512 quantumlib#4714

- created control_values.py which contains the ControlValues class.
- FreeVars and ConstrainedVars classes are provided for ease of use.
- while the basic idea of ControlValues integrating it inside the code base was challening
- the old way of using control_values assumed it's a tuple of tuples of ints and was used as thus (comparasion, hashing, slicing, fomatting, conditioning, and loops), the ControlValues class had to provide these functionalities
- the trickiest part to get right was the support for formatting!
- I'll create a follow up PR for unit tests for control_values.py
@NoureldinYosri NoureldinYosri force-pushed the control_vals branch 11 times, most recently from 194915a to 0c6f81e Compare December 1, 2021 01:42
@tanujkhattar
Copy link
Collaborator

Thanks @NoureldinYosri for opening up the PR. Unit tests need to be added for every new code / modification or else the coverage check won't pass and we can't approve any PRs with failing tests. Please add the unit tests (and fix other failing tests) and then we can do a review for the PR.

You can look at https://github.com/quantumlib/Cirq/blob/master/docs/dev/development.md#continuous-integration-and-local-testing to learn more about how to run the integration tests locally.

@tanujkhattar tanujkhattar self-assigned this Dec 2, 2021
@NoureldinYosri NoureldinYosri force-pushed the control_vals branch 9 times, most recently from 2763fdd to 26ec3b7 Compare December 2, 2021 21:02
@NoureldinYosri
Copy link
Collaborator Author

@tanujkhattar can you check this PR?, all checks pass now :)

Copy link
Collaborator

@dabacon dabacon left a comment

Choose a reason for hiding this comment

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

Some initial comments.

cirq-core/cirq/ops/control_values.py Outdated Show resolved Hide resolved
cirq-core/cirq/ops/control_values.py Outdated Show resolved Hide resolved
cirq-core/cirq/ops/controlled_gate.py Show resolved Hide resolved
cirq-core/cirq/ops/controlled_gate.py Outdated Show resolved Hide resolved
cirq-core/cirq/ops/control_values.py Outdated Show resolved Hide resolved
cirq-core/cirq/ops/control_values_test.py Show resolved Hide resolved
cirq-core/cirq/ops/control_values.py Outdated Show resolved Hide resolved
cirq-core/cirq/ops/control_values_test.py Outdated Show resolved Hide resolved
cirq-core/cirq/ops/control_values.py Outdated Show resolved Hide resolved
cirq-core/cirq/ops/controlled_gate_test.py Show resolved Hide resolved
…mlib#4512

created control_values.py which contains the ControlValues class.
FreeVars and ConstrainedVars classes are provided for ease of use.
while the basic idea of ControlValues integrating it inside the code base was challening
the old way of using control_values assumed it's a tuple of tuples of ints and was used as thus (comparasion, hashing, slicing, fomatting, conditioning, and loops), the ControlValues class had to provide these functionalities
the trickiest part to get right was the support for formatting!
@NoureldinYosri
Copy link
Collaborator Author

@daxfohl @dabacon this PR has been waiting for sometime, can we get it reviewed :)

Copy link
Contributor

@daxfohl daxfohl left a comment

Choose a reason for hiding this comment

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

Some quick comments from my phone.

'Control values <{!r}> outside of range for control qubit '
'number <{!r}>.'.format(val, i)
if not isinstance(control_values, cv.ControlValues):
self.control_values = cv.ControlValues(
Copy link
Contributor

Choose a reason for hiding this comment

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

This needs to be marked as a breaking change since it changes the data type of a public field. @tanujkhattar

cirq-core/cirq/ops/controlled_gate.py Outdated Show resolved Hide resolved
return tuple(tuple(product) for product in vals)


class ControlValues:
Copy link
Contributor

Choose a reason for hiding this comment

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

All public functions need docstrings. Also this class needs to be available in the Cirq root namespace.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

what is the root namespace?

Copy link
Contributor

Choose a reason for hiding this comment

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

The root __init__.py file, so users can do cirq.ControlValues. (Once you do this you'll find it triggers some additional tests that check for serializability etc. These tasks need to be completed too, or else the control won't be able to run on real machines).

cirq-core/cirq/ops/control_values.py Outdated Show resolved Hide resolved
cirq-core/cirq/ops/control_values.py Outdated Show resolved Hide resolved
cirq-core/cirq/ops/control_values.py Outdated Show resolved Hide resolved
@daxfohl
Copy link
Contributor

daxfohl commented Jan 17, 2022

Can you add "fixes #4512" to the description so they are linked?

Copy link
Contributor

@daxfohl daxfohl left a comment

Choose a reason for hiding this comment

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

One more thing

cirq-core/cirq/ops/control_values.py Outdated Show resolved Hide resolved
…mlib#4512

created control_values.py which contains the ControlValues class.
FreeVars and ConstrainedVars classes are provided for ease of use.
while the basic idea of ControlValues integrating it inside the code base was challening
the old way of using control_values assumed it's a tuple of tuples of ints and was used as thus (comparasion, hashing, slicing, fomatting, conditioning, and loops), the ControlValues class had to provide these functionalities
the trickiest part to get right was the support for formatting!
@NoureldinYosri
Copy link
Collaborator Author

NoureldinYosri commented Jan 28, 2022

@daxfohl I addressed most of the comments, I have a couple of questions which I put in the comments.

cirq-core/cirq/ops/control_values.py Outdated Show resolved Hide resolved
cirq-core/cirq/ops/control_values.py Outdated Show resolved Hide resolved
cirq-core/cirq/ops/control_values.py Outdated Show resolved Hide resolved
cirq-core/cirq/ops/control_values.py Outdated Show resolved Hide resolved
@daxfohl
Copy link
Contributor

daxfohl commented Jan 29, 2022

@NoureldinYosri consider using @dataclass(frozen=True) on this to help ensure immutability. We use that elsewhere in cirq, you can just search for examples. It provides nice default implementation of equality, hash, etc as well. Just an option--if it gets in the way then don't worry about it.

…plementations, SimpleControlValues which represents the old format of control_values, ConstrainedControlValues which can be used to represent more complex expressions (e.g. xor), this allows us to later add concrete implementations that support other formats (e.g. sympy expressions), I also added a builder class to facilitate the creation of ControlValues.
@NoureldinYosri
Copy link
Collaborator Author

@daxfohl @dabacon @tanujkhattar ptal

@daxfohl
Copy link
Contributor

daxfohl commented Feb 24, 2022

The changes resolve my concerns about mutability. Still need to add these classes to the root namespace in cirq-core/cirq/__init__.py. Also the classes' top level docstrings need some more detailed explanation and examples suitable for end users. Beyond that, I think I'll pass this along to the maintainers at this point.

@MichaelBroughton
Copy link
Collaborator

There are some concerns here re: qsim compatability @95-martin-orion , this has implications for TFQ as well and our goals for decompose always returning X,Y,Z,C*Z. Have you looked into this Orion ?

Copy link
Collaborator

@95-martin-orion 95-martin-orion left a comment

Choose a reason for hiding this comment

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

Quick review pass + follow up to Mike's question

cirq-core/cirq/ops/controlled_gate.py Outdated Show resolved Hide resolved
tuple((val,) if isinstance(val, int) else tuple(sorted(val)) for val in control_values),
)
print('building from', control_values)
self.control_values = cv.ControlValuesBuilder().append(control_values).build()
Copy link
Collaborator

Choose a reason for hiding this comment

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

RE @MichaelBroughton's comment: my concern is how this completely replaces existing control behavior. qsim has optimizations for simple controls (|0> or |1>), but I'd need to check with Sergei on whether they're generalizable to arbitrary controls.

Outside of that concern, though, qsim is happy as long as the gate can be expressed as a unitary on at most 6 qubits total (the optimization allows 6 target qubits + any number of controls).

Comment on lines +28 to +29
_combinations: Any
_nxt: Optional['ControlValues'] = None
Copy link
Collaborator

Choose a reason for hiding this comment

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

What is the motivation behind this linked-list structure, instead of e.g. a list-of-lists? It seems to me that something like this would be more manageable:

[[comb1, comb2, ...], [nxt_comb1, nxt_comb2, ...], ...]

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

this assumes that lists of combinations are the only way that wil be used to define control_values, there was a previous comment on this PR about possibly supporting other ways like tensors or sympy expressions in the future.

the linked-list structure allows defining using different ways at the same time e.g. CV1(a table) -> CV2(a sympy expression) -> ... etc

each of those object will inheret from the ControlValues base class so that wil work perfectly.

Copy link
Contributor

Choose a reason for hiding this comment

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

The comment referred to above is on the linked issue. #4512 (comment)

Copy link
Contributor

Choose a reason for hiding this comment

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

Another thought, have you considered making a separate ControlValuesProduct class that merges two (or maybe N) ControlValues objects into a product? That approach would allow for a smaller base class and adhere more to the single responsibility pattern.

Comment on lines +144 to +145
for control_vals in self.control_values:
control_vals = cv.ControlValues.flatten(control_vals)
Copy link
Collaborator

Choose a reason for hiding this comment

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

At a glance, this doesn't appear to add functionality - for a control like |00><00| + |11><11| I would expect some extra handling to be needed (sum over tensors?), and tests to be added to cover it.

Is this being added in a future PR?

Copy link
Collaborator Author

@NoureldinYosri NoureldinYosri Mar 3, 2022

Choose a reason for hiding this comment

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

the |00><00| + |11><11| combination can be added in the same way that the xor combination |01><01| + |10><10| which was not supported in the old way but is supported now as can be seen in the tests

Copy link
Contributor

Choose a reason for hiding this comment

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

Did we ever have a design review on this one? I provided the initial code reviews assuming a design was approved, but I still kind of stand by what I originally said on the linked issue, that this could be done more simply by just adding a bool flag to the ControlledGate constructor. That flag would control whether to interpret the 2D input array vertically as allowed states by qubit (which is how it currently works, but is limited), or horizontally as a full set of allowed states (which allows full control).

That this question came up during code review makes me think end users are going to have trouble understanding how to use these classes.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I introduced the idea in #4512 (comment) and talked about it ina cirq meeting #4512 (comment), wrote a prototype in #4512 (comment) and got a review in #4512 (comment)


the boolean idea has some issues

  1. it doesn't address your previous comment Controlled gate construction cannot construct some cases #4512 (comment), it fact it will make it harder to add those new ways lalter.
  2. there is no way of getting around computing products, what a boolean will do is to force the users to compute them before passing them to the constructor, a work around would be passing an array of booleans but that has its own issues.
  3. any work around will make the constructors for controlledGate and controlledOperation execture complex logic which is not a good idea in general, introduce tech debt and make it harder change or support new types later,

lets discuss this in the next cirq meeting.

Copy link
Contributor

Choose a reason for hiding this comment

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

Sounds good. I have limited availability for cynqs these days, but I think a reprise with the rest of the team on Wed would be great just to get the ball rolling on this PR, since it seems to keep going stagnant. I'm looking forward to the functionality.

Copy link
Collaborator Author

@NoureldinYosri NoureldinYosri left a comment

Choose a reason for hiding this comment

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

I'll remove the debug line and add the classes to the root namespace ASAP.

the main point of the link-list structure is all for different ways of creating control_values (e.g. the old way, the new way, using tensors, using generators, using sympy expressions ..etc) to be used together.

@95-martin-orion
Copy link
Collaborator

Bump: the checks appear to have gotten stuck 😖 . @NoureldinYosri, you may need to push a change (maybe resolving the conflicts marked) to get it moving again.

Copy link
Contributor

@daxfohl daxfohl left a comment

Choose a reason for hiding this comment

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

Added a couple of thoughts that we could go over during cynq.

Comment on lines +28 to +29
_combinations: Any
_nxt: Optional['ControlValues'] = None
Copy link
Contributor

Choose a reason for hiding this comment

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

Another thought, have you considered making a separate ControlValuesProduct class that merges two (or maybe N) ControlValues objects into a product? That approach would allow for a smaller base class and adhere more to the single responsibility pattern.



@ControlValues.register
class SimpleControlValues(ControlValues):
Copy link
Contributor

Choose a reason for hiding this comment

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

Let's bikeshed this during synq. I don't think users will find the name intuitive. Perhaps PerQubitControlValues? Also the docstring could use some examples to make it clear.

Copy link
Contributor

@daxfohl daxfohl left a comment

Choose a reason for hiding this comment

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

One more question

return (
f'cirq.ControlledGate(sub_gate={self.sub_gate!r}, '
f'num_controls={self.num_controls()!r})'
)
return (
f'cirq.ControlledGate(sub_gate={self.sub_gate!r}, '
f'control_values={self.control_values!r},'
f'control_values={self.control_values.arrangements()!r},'
Copy link
Contributor

Choose a reason for hiding this comment

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

Does this still round-trip? Given there's no type information about which subclass of ControlValues it uses, I'm not seeing how it could.

@NoureldinYosri
Copy link
Collaborator Author

NoureldinYosri commented Mar 21, 2022

@daxfohl @95-martin-orion I have a simple way of implementing this which I think addresses all the comments/concerns, I will present it during the cirq meeting for discussion.

@daxfohl
Copy link
Contributor

daxfohl commented Mar 21, 2022 via email

@95-martin-orion
Copy link
Collaborator

Discussed on Cirq sync: @NoureldinYosri will write a document capturing the overarching design of this change, we'll discuss and reach a consensus there, then any changes can be reflected here.

@NoureldinYosri
Copy link
Collaborator Author

As discussed in the cirq-sync meeting I wrote a design descriping the current approach.

@tanujkhattar @95-martin-orion @daxfohl @dabacon

@tanujkhattar
Copy link
Collaborator

This can now be closed after #5788

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cla: yes Makes googlebot stop complaining. size: M 50< lines changed <250
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Controlled gate construction cannot construct some cases
7 participants