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

Allow passing None to AbstractCircuit.from_moments #6637

Merged
merged 2 commits into from
Jun 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 13 additions & 11 deletions cirq-core/cirq/circuits/circuit.py
Original file line number Diff line number Diff line change
Expand Up @@ -145,29 +145,31 @@ class AbstractCircuit(abc.ABC):
"""

@classmethod
def from_moments(cls: Type[CIRCUIT_TYPE], *moments: 'cirq.OP_TREE') -> CIRCUIT_TYPE:
def from_moments(cls: Type[CIRCUIT_TYPE], *moments: Optional['cirq.OP_TREE']) -> CIRCUIT_TYPE:
"""Create a circuit from moment op trees.

Args:
*moments: Op tree for each moment. If an op tree is a moment, it
will be included directly in the new circuit. If an op tree is
a circuit, it will be frozen, wrapped in a CircuitOperation, and
included in its own moment in the new circuit. Otherwise, the
op tree will be passed to `cirq.Moment` to create a new moment
which is then included in the new circuit. Note that in the
latter case we have the normal restriction that operations in a
moment must be applied to disjoint sets of qubits.
*moments: Op trees for each moment, which can be one of the following:
- Moment: will be included directly in the new circuit.
- AbstractCircuit: will be frozen, wrapped in a CircuitOperation,
and included in its own moment in the new circuit.
- None: will be skipped and omitted from the circuit. This can be
used to include or skip a moment based on a conditional, for example.
- Other OP_TREE: will be passed to `cirq.Moment` to create a new moment
which is then included in the new circuit. Note that in this
case we have the normal restriction that operations in a
moment must be applied to disjoint sets of qubits.
"""
return cls._from_moments(cls._make_moments(moments))

@staticmethod
def _make_moments(moments: Iterable['cirq.OP_TREE']) -> Iterator['cirq.Moment']:
def _make_moments(moments: Iterable[Optional['cirq.OP_TREE']]) -> Iterator['cirq.Moment']:
for m in moments:
if isinstance(m, Moment):
yield m
elif isinstance(m, AbstractCircuit):
yield Moment(m.freeze().to_op())
else:
elif m is not None:
Copy link
Collaborator

Choose a reason for hiding this comment

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

Should this be elif m to encapsulate the empty [] case as well? Since None is expected to replace the [] case, I'd expect them to yield the same output. WDYT?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I didn't intend for None to replace []. The former would be skipped, while the latter would produce an empty moment in the circuit.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Thanks for clarifying!

yield Moment(m)

@classmethod
Expand Down
1 change: 1 addition & 0 deletions cirq-core/cirq/circuits/circuit_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ def test_from_moments():
[cirq.X(c)],
[],
cirq.Z(d),
None,
[cirq.measure(a, b, key='ab'), cirq.measure(c, d, key='cd')],
)
assert circuit == cirq.Circuit(
Expand Down
Loading