Skip to content

cirq.measure - accept list arguments#5411

Merged
CirqBot merged 13 commits into
quantumlib:masterfrom
pavoljuhas:cirq-measure-accept-list-arguments
Jun 6, 2022
Merged

cirq.measure - accept list arguments#5411
CirqBot merged 13 commits into
quantumlib:masterfrom
pavoljuhas:cirq-measure-accept-list-arguments

Conversation

@pavoljuhas

@pavoljuhas pavoljuhas commented May 26, 2022

Copy link
Copy Markdown
Collaborator

Allow passing qubits for cirq.measure and cirq.measure_each in
a single iterable argument.
Keep accepting them as variable-length arguments as before.

Fixes #2408.

ndarray docstring advises to use np.array for array creation.
Not yet ready, expecting test failure.
Allow variable-length arguments as well as iterables.

Resolve quantumlib#2408
@pavoljuhas pavoljuhas requested review from a team, cduck and vtomole as code owners May 26, 2022 22:22
@pavoljuhas pavoljuhas requested a review from dabacon May 26, 2022 22:22
@CirqBot CirqBot added the size: S 10< lines changed <50 label May 26, 2022
@maffoo

maffoo commented May 26, 2022

Copy link
Copy Markdown
Contributor

I think allowing arbitrarily nested lists of Qids is probably more flexibility than we want to allow. I'd suggest that we accept either Qids as varargs, or a single iterable arg containins Qids. It should be possible to use @overload types to express this to mypy in addition to the runtime handling of different args.

@pavoljuhas

Copy link
Copy Markdown
Collaborator Author

I think allowing arbitrarily nested lists of Qids is probably more flexibility than we want to allow. I'd suggest that we accept either Qids as varargs, or a single iterable arg containins Qids. ...

Sounds good to me, but Gate.on_each() already accepts a mix of varargs and possibly nested sequences.
The issue at hand (#2408) asks for a similar interface in cirq.measure().
If we leave it as is we'll get a consistent behavior in what those 2 functions can digest.

for target in targets:
if isinstance(target, Qid):
operations.append(self.on(target))
elif isinstance(target, Iterable) and not isinstance(target, str):
operations.extend(self.on_each(*target))
else:

@maffoo

maffoo commented May 27, 2022

Copy link
Copy Markdown
Contributor

The Gate.on_each implementation is a bit confused because how it behaves depends on the number of qubits the gate expects. For single-qubit gates, it allows combinations of varargs and arbitrarily-nested sequences, as you point out:

In [1]: a, b, c, d = cirq.LineQubit.range(4)

In [2]: cirq.H.on_each([[[[a]]]], b, [[c], [[d]]])
Out[2]: 
[cirq.H(cirq.LineQubit(0)),
 cirq.H(cirq.LineQubit(1)),
 cirq.H(cirq.LineQubit(2)),
 cirq.H(cirq.LineQubit(3))]

but for multi-qubit gates it only allows either varargs or a single sequence of sequences of qids:

n [3]: cirq.CZ.on_each((a, b), (c, d))
Out[3]: 
[cirq.CZ(cirq.LineQubit(0), cirq.LineQubit(1)),
 cirq.CZ(cirq.LineQubit(2), cirq.LineQubit(3))]

In [4]: cirq.CZ.on_each([(a, b), (c, d)])
Out[4]: 
[cirq.CZ(cirq.LineQubit(0), cirq.LineQubit(1)),
 cirq.CZ(cirq.LineQubit(2), cirq.LineQubit(3))]

In [5]: cirq.CZ.on_each([(a, b)], [(c, d)])
...
ValueError: All values in sequence should be Qids, but got [(cirq.LineQubit(0), cirq.LineQubit(1))]

I'm not sure if this behavior for single-qubit gates was intentional, but I'd be surprised if it were. I think just accepting gate.on_each(a, b, c, d) or gate.on_each([a, b, c, d]) would be sufficient, and calling with some deeply nested list is more likely an unintentional error on the part of the caller that we should flag rather than allow.

For cirq.measure I'd suggest that rather than emulating the current behavior of Gate.on_each, we should take the more conservative approach and just allow cirq.measure(a, b, c, d) or cirq.measure([a, b, c, d]), but not arbitrarily nested sequences.

Whatever we decide to do, we should probably also modify cirq.measure_each (which produces separate single-qubit measure gates for each qubit, rather than one measure gate for all of them) in the same way, so that it stays consistent with cirq.measure.

@pavoljuhas

Copy link
Copy Markdown
Collaborator Author

@maffoo - sounds good, I will adjust it that way.
Thanks for pointing out measure_each needs the same change.

Simplify arguments handling - qubits must be either passed
in a single iterable argument or as multiple scalar arguments.
Not yet ready, expecting test failure.
Accept qubits in variable-length arguments or as a single
argument which must be an iterable of qubits.
@pavoljuhas

Copy link
Copy Markdown
Collaborator Author

Ready for next review. I am not entirely sure if I got right the typing in function implementations after @overload.

@maffoo maffoo left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

One minor comment, then LGTM.

Comment thread cirq-core/cirq/ops/measure_util.py
pavoljuhas and others added 2 commits May 28, 2022 16:36
Accept exactly one argument when it is an iterable of qubits.

Co-authored-by: Matthew Neeley <mneeley@gmail.com>
Accept exactly one argument when it is an iterable of qubits.
@pavoljuhas

Copy link
Copy Markdown
Collaborator Author

nit: Could modify this slightly to accept exactly one arg

Done. Thank you for the mypy tip on double underscore!

@pavoljuhas

Copy link
Copy Markdown
Collaborator Author

@dabacon, @cduck, @vtomole - PTAL.

@dabacon dabacon left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM

@dabacon dabacon added the automerge Tells CirqBot to sync and merge this PR. (If it's running.) label Jun 6, 2022
@CirqBot CirqBot added the front_of_queue_automerge CirqBot uses this label to indicate (and remember) what's being merged next. label Jun 6, 2022
@CirqBot CirqBot merged commit 35a6b60 into quantumlib:master Jun 6, 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 Jun 6, 2022
@pavoljuhas pavoljuhas deleted the cirq-measure-accept-list-arguments branch June 6, 2022 22:40
rht pushed a commit to rht/Cirq that referenced this pull request May 1, 2023
Allow passing qubits for `cirq.measure` and `cirq.measure_each` in
a single iterable argument.  
Keep accepting them as variable-length arguments as before.

Fixes quantumlib#2408.
harry-phasecraft pushed a commit to PhaseCraft/Cirq that referenced this pull request Oct 31, 2024
Allow passing qubits for `cirq.measure` and `cirq.measure_each` in
a single iterable argument.  
Keep accepting them as variable-length arguments as before.

Fixes quantumlib#2408.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size: S 10< lines changed <50

Projects

None yet

Development

Successfully merging this pull request may close these issues.

cirq.measure should accept List[Qid] the same way "on_each" does.

5 participants