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 SumOfProducts subclass of ControlValues #5755

Merged
merged 10 commits into from
Jul 15, 2022

Conversation

NoureldinYosri
Copy link
Collaborator

This class allows the creation of control values that can't be factored into simple products hence solving #4512

This class allows the creation of control values that can't be factored into simple products hence solving quantumlib#4512
@NoureldinYosri NoureldinYosri requested review from a team, vtomole and cduck as code owners July 13, 2022 16:01
@CirqBot CirqBot added the size: M 50< lines changed <250 label Jul 13, 2022
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.

Looks good, left a couple questions.

cirq-core/cirq/ops/control_values.py Show resolved Hide resolved
cirq-core/cirq/ops/control_values.py Show resolved Hide resolved
cirq-core/cirq/ops/control_values.py Show resolved Hide resolved
cirq-core/cirq/ops/control_values.py Outdated Show resolved Hide resolved
nand = SumOfProducts(((0, 0), (0, 1), (1, 0))) # nand of two bits
"""

_internal_representation: Tuple[Tuple[int, ...], ...]
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can we add a post init method which verifies that length of all nested tuples in self._internal_representation is the same? This is assumed to be true in the implementation of methods like _number_variables below

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

added, I also test for the uniqueness of products in it

return frozenset(self._internal_representation) == {(1,) * self._number_variables()}

def diagram_repr(self) -> str:
return NotImplemented
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why is the diagram_repr not implemented?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

the most basic implementation is problematic since the strings will be quite large since they have size num_products x num_qubits => O(num_qubits x 2^num_qubits), this is why I'm hestiant to implement it, however I added it anyway :)

def __getitem__(
self, key: Union[int, slice]
) -> Union['AbstractControlValues', Tuple[int, ...]]:
return NotImplemented
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why is this NotImplemented? Also, I don't like the pattern of
a) Declaring abstract methods in the API, telling the users that all implementations will implement these abstract methods.
b) Returning NotImplemented in the implementation of the abstract methods.

If we want to allow implementations to return NotImplemented; then these shouldn't be abstract methods in the first place.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

the reason that I'm hesitant to implement it is that it will have a different meaning from that of ProductOfSums, where in ProductOfSums we get valide values of qubit, here we get a product

Comment on lines +251 to +254
if not isinstance(other, SumOfProducts):
raise TypeError(
f'And operation not supported between types SumOfProducts and {type(other)}'
)
Copy link
Collaborator

Choose a reason for hiding this comment

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

We are not doing the the linked-list style concatenation discussed earlier? Will that come in a follow-up PR?

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 would wait until next PR, I want to introduct the SumOfProducts class before Cirq 1.0, because it has full expressive power (i.e. fixes the original issue), the linked structure can be introducted later without affecting users

the difference between the current state and what will happen when the linked structure is introduced is expressions like this ((x xor y) and (z and w)) and can now be represented by a SumOfProducts objects that has 8 products, while when we introduce the linked structure then we will only need to store 5 products (2 for the first and 3 for the second) and similarly for larger expressions where we would could in some cases store an exponenetial number of products in pseudopolynomial space.

Copy link
Collaborator

@tanujkhattar tanujkhattar left a comment

Choose a reason for hiding this comment

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

The doctests are failing because they run the python expression in docstrings written within ">>>" code blocks and compare the expected ouptut with received output.

I've suggested changes that should fix the failing tests. See https://docs.python.org/3/library/doctest.html for more details.

This can be constructed as
>>> xor_control_values = cirq.SumOfProducts(((0, 0), (1, 1)))
>>> q0, q1, q2 = cirq.LineQubit.range(3)
>>> cirq.X(q2).controlled_by(q0, q1, control_values=xor_control_values)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
>>> cirq.X(q2).controlled_by(q0, q1, control_values=xor_control_values)
>>> xor_cop = cirq.X(q2).controlled_by(q0, q1, control_values=xor_control_values)


>>> nand_control_values = cirq.SumOfProducts(((0, 0), (0, 1), (1, 0)))
>>> q0, q1, q2 = cirq.LineQubit.range(3)
>>> cirq.X(q2).controlled_by(q0, q1, control_values=nand_control_values)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
>>> cirq.X(q2).controlled_by(q0, q1, control_values=nand_control_values)
>>> nand_cop = cirq.X(q2).controlled_by(q0, q1, control_values=nand_control_values)

@NoureldinYosri
Copy link
Collaborator Author

@tanujkhattar I fixed the docstring and added the optional argument to diagram_repr that we discussed offline

@NoureldinYosri
Copy link
Collaborator Author

@tanujkhattar I added the changes we discussed offline namely and now works between ProductOfSums and SumOfProducts, and I removed the indexing requirement from the abstrat class and from SumOfProducts, fixed the issues that appeared

I did't get to testing ControlledOperations/Gates with SumOfProducts, however it should work fine, however I know of a line that will break (and worse silently) with SumOfProducts and that is this one https://github.com/quantumlib/Cirq/blob/master/cirq-core/cirq/ops/controlled_operation.py#L170 the comparison logic will break I tried a quick fix but it didn't work, I think in a follow up in which we add the tests we discussed we will also need to fix this line

@tanujkhattar
Copy link
Collaborator

@NoureldinYosri Thanks for the changes; I'll merge this PR and implement the additional fixes. Have a safe trip!

@tanujkhattar tanujkhattar added the automerge Tells CirqBot to sync and merge this PR. (If it's running.) label Jul 15, 2022
@CirqBot CirqBot added the front_of_queue_automerge CirqBot uses this label to indicate (and remember) what's being merged next. label Jul 15, 2022
@CirqBot CirqBot merged commit d75dfd0 into quantumlib:master Jul 15, 2022
@CirqBot CirqBot removed automerge Tells CirqBot to sync and merge this PR. (If it's running.) front_of_queue_automerge CirqBot uses this label to indicate (and remember) what's being merged next. labels Jul 15, 2022
rht pushed a commit to rht/Cirq that referenced this pull request May 1, 2023
This class allows the creation of control values that can't be factored into simple products hence solving quantumlib#4512
harry-phasecraft pushed a commit to PhaseCraft/Cirq that referenced this pull request Oct 31, 2024
This class allows the creation of control values that can't be factored into simple products hence solving quantumlib#4512
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
size: M 50< lines changed <250
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants