We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Printing Moment containing classical control fails
**Description of the issue**

A classically controlled op causes moment printing to fail. The op itself renders correctly, and a circuit containing the moment renders correctly. Just the moment itself fails to render.

**How to reproduce the issue**

```python
op = cirq.X(cirq.NamedQubit('q')).with_classical_controls('m')
m = cirq.Moment(op)
print(op)
print(cirq.Circuit(m))
print(m)
```

```
X(q).with_classical_controls(m)


q: ───X───
      ║
m: ═══^═══


ValueError: Wanted diagram info from cirq.ClassicallyControlledOperation(cirq.X(cirq.NamedQubit('q')), [cirq.KeyCondition(cirq.MeasurementKey(name='m'))]) for [cirq.NamedQubit('q')]) but got cirq.CircuitDiagramInfo(wire_symbols=('X', '^'), exponent=1.0, connected=True, exponent_qubit_index=1, auto_exponent_parens=True)

cirq-core/cirq/protocols/circuit_diagram_info_protocol.py:345: ValueError
```

v0.15

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `cirq-core/cirq/ops/classically_controlled_operation.py`
Content:
```
1 # Copyright 2021 The Cirq Developers
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 #     https://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14 from typing import (
15     AbstractSet,
16     Any,
17     Mapping,
18     Dict,
19     FrozenSet,
20     List,
21     Optional,
22     Sequence,
23     TYPE_CHECKING,
24     Tuple,
25     Union,
26 )
27 
28 import sympy
29 
30 from cirq import protocols, value
31 from cirq.ops import raw_types
32 
33 if TYPE_CHECKING:
34     import cirq
35 
36 
37 @value.value_equality
38 class ClassicallyControlledOperation(raw_types.Operation):
39     """Augments existing operations to be conditionally executed.
40 
41     An operation that is classically controlled is executed iff all conditions
42     evaluate to True. Currently the only condition type is a measurement key.
43     A measurement key evaluates to True iff any qubit in the corresponding
44     measurement operation evaluated to a non-zero value.
45 
46     This object is typically created via
47      `operation.with_classical_controls(*conditions)`.
48     """
49 
50     def __init__(
51         self,
52         sub_operation: 'cirq.Operation',
53         conditions: Sequence[Union[str, 'cirq.MeasurementKey', 'cirq.Condition', sympy.Basic]],
54     ):
55         """Initializes a `ClassicallyControlledOperation`.
56 
57         Multiple consecutive `ClassicallyControlledOperation` layers are
58         squashed when possible, so one should not depend on a specific number
59         of layers.
60 
61         Args:
62             sub_operation: The operation to gate with a classical control
63                 condition.
64             conditions: A sequence of measurement keys, or strings that can be
65                 parsed into measurement keys.
66 
67         Raises:
68             ValueError: If an unsupported gate is being classically
69                 controlled.
70         """
71         if protocols.measurement_key_objs(sub_operation):
72             raise ValueError(
73                 f'Cannot conditionally run operations with measurements: {sub_operation}'
74             )
75         conditions = tuple(conditions)
76         if isinstance(sub_operation, ClassicallyControlledOperation):
77             conditions += sub_operation._conditions
78             sub_operation = sub_operation._sub_operation
79         conds: List['cirq.Condition'] = []
80         for c in conditions:
81             if isinstance(c, str):
82                 c = value.MeasurementKey.parse_serialized(c)
83             if isinstance(c, value.MeasurementKey):
84                 c = value.KeyCondition(c)
85             if isinstance(c, sympy.Basic):
86                 c = value.SympyCondition(c)
87             conds.append(c)
88         self._conditions: Tuple['cirq.Condition', ...] = tuple(conds)
89         self._sub_operation: 'cirq.Operation' = sub_operation
90 
91     @property
92     def classical_controls(self) -> FrozenSet['cirq.Condition']:
93         return frozenset(self._conditions).union(self._sub_operation.classical_controls)
94 
95     def without_classical_controls(self) -> 'cirq.Operation':
96         return self._sub_operation.without_classical_controls()
97 
98     @property
99     def qubits(self):
100         return self._sub_operation.qubits
101 
102     def with_qubits(self, *new_qubits):
103         return self._sub_operation.with_qubits(*new_qubits).with_classical_controls(
104             *self._conditions
105         )
106 
107     def _decompose_(self):
108         result = protocols.decompose_once(self._sub_operation, NotImplemented)
109         if result is NotImplemented:
110             return NotImplemented
111 
112         return [ClassicallyControlledOperation(op, self._conditions) for op in result]
113 
114     def _value_equality_values_(self):
115         return (frozenset(self._conditions), self._sub_operation)
116 
117     def __str__(self) -> str:
118         keys = ', '.join(map(str, self._conditions))
119         return f'{self._sub_operation}.with_classical_controls({keys})'
120 
121     def __repr__(self):
122         return (
123             f'cirq.ClassicallyControlledOperation('
124             f'{self._sub_operation!r}, {list(self._conditions)!r})'
125         )
126 
127     def _is_parameterized_(self) -> bool:
128         return protocols.is_parameterized(self._sub_operation)
129 
130     def _parameter_names_(self) -> AbstractSet[str]:
131         return protocols.parameter_names(self._sub_operation)
132 
133     def _resolve_parameters_(
134         self, resolver: 'cirq.ParamResolver', recursive: bool
135     ) -> 'ClassicallyControlledOperation':
136         new_sub_op = protocols.resolve_parameters(self._sub_operation, resolver, recursive)
137         return ClassicallyControlledOperation(new_sub_op, self._conditions)
138 
139     def _circuit_diagram_info_(
140         self, args: 'cirq.CircuitDiagramInfoArgs'
141     ) -> Optional['protocols.CircuitDiagramInfo']:
142         sub_args = protocols.CircuitDiagramInfoArgs(
143             known_qubit_count=args.known_qubit_count,
144             known_qubits=args.known_qubits,
145             use_unicode_characters=args.use_unicode_characters,
146             precision=args.precision,
147             label_map=args.label_map,
148         )
149         sub_info = protocols.circuit_diagram_info(self._sub_operation, sub_args, None)
150         if sub_info is None:
151             return NotImplemented  # coverage: ignore
152         control_count = len({k for c in self._conditions for k in c.keys})
153         wire_symbols = sub_info.wire_symbols + ('^',) * control_count
154         if any(not isinstance(c, value.KeyCondition) for c in self._conditions):
155             wire_symbols = (
156                 wire_symbols[0]
157                 + '(conditions=['
158                 + ', '.join(str(c) for c in self._conditions)
159                 + '])',
160             ) + wire_symbols[1:]
161         exponent_qubit_index = None
162         if sub_info.exponent_qubit_index is not None:
163             exponent_qubit_index = sub_info.exponent_qubit_index + control_count
164         elif sub_info.exponent is not None:
165             exponent_qubit_index = control_count
166         return protocols.CircuitDiagramInfo(
167             wire_symbols=wire_symbols,
168             exponent=sub_info.exponent,
169             exponent_qubit_index=exponent_qubit_index,
170         )
171 
172     def _json_dict_(self) -> Dict[str, Any]:
173         return {'conditions': self._conditions, 'sub_operation': self._sub_operation}
174 
175     def _act_on_(self, sim_state: 'cirq.SimulationStateBase') -> bool:
176         if all(c.resolve(sim_state.classical_data) for c in self._conditions):
177             protocols.act_on(self._sub_operation, sim_state)
178         return True
179 
180     def _with_measurement_key_mapping_(
181         self, key_map: Mapping[str, str]
182     ) -> 'ClassicallyControlledOperation':
183         conditions = [protocols.with_measurement_key_mapping(c, key_map) for c in self._conditions]
184         sub_operation = protocols.with_measurement_key_mapping(self._sub_operation, key_map)
185         sub_operation = self._sub_operation if sub_operation is NotImplemented else sub_operation
186         return sub_operation.with_classical_controls(*conditions)
187 
188     def _with_key_path_prefix_(self, prefix: Tuple[str, ...]) -> 'ClassicallyControlledOperation':
189         conditions = [protocols.with_key_path_prefix(c, prefix) for c in self._conditions]
190         sub_operation = protocols.with_key_path_prefix(self._sub_operation, prefix)
191         sub_operation = self._sub_operation if sub_operation is NotImplemented else sub_operation
192         return sub_operation.with_classical_controls(*conditions)
193 
194     def _with_rescoped_keys_(
195         self, path: Tuple[str, ...], bindable_keys: FrozenSet['cirq.MeasurementKey']
196     ) -> 'ClassicallyControlledOperation':
197         conds = [protocols.with_rescoped_keys(c, path, bindable_keys) for c in self._conditions]
198         sub_operation = protocols.with_rescoped_keys(self._sub_operation, path, bindable_keys)
199         return sub_operation.with_classical_controls(*conds)
200 
201     def _control_keys_(self) -> FrozenSet['cirq.MeasurementKey']:
202         local_keys: FrozenSet['cirq.MeasurementKey'] = frozenset(
203             k for condition in self._conditions for k in condition.keys
204         )
205         return local_keys.union(protocols.control_keys(self._sub_operation))
206 
207     def _qasm_(self, args: 'cirq.QasmArgs') -> Optional[str]:
208         args.validate_version('2.0')
209         if len(self._conditions) > 1:
210             raise ValueError('QASM does not support multiple conditions.')
211         subop_qasm = protocols.qasm(self._sub_operation, args=args)
212         if not self._conditions:
213             return subop_qasm
214         return f'if ({self._conditions[0].qasm}) {subop_qasm}'
215
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/cirq-core/cirq/ops/classically_controlled_operation.py b/cirq-core/cirq/ops/classically_controlled_operation.py
--- a/cirq-core/cirq/ops/classically_controlled_operation.py
+++ b/cirq-core/cirq/ops/classically_controlled_operation.py
@@ -149,9 +149,13 @@
         sub_info = protocols.circuit_diagram_info(self._sub_operation, sub_args, None)
         if sub_info is None:
             return NotImplemented  # coverage: ignore
-        control_count = len({k for c in self._conditions for k in c.keys})
-        wire_symbols = sub_info.wire_symbols + ('^',) * control_count
-        if any(not isinstance(c, value.KeyCondition) for c in self._conditions):
+        control_label_count = 0
+        if args.label_map is not None:
+            control_label_count = len({k for c in self._conditions for k in c.keys})
+        wire_symbols = sub_info.wire_symbols + ('^',) * control_label_count
+        if control_label_count == 0 or any(
+            not isinstance(c, value.KeyCondition) for c in self._conditions
+        ):
             wire_symbols = (
                 wire_symbols[0]
                 + '(conditions=['
@@ -160,9 +164,9 @@
             ) + wire_symbols[1:]
         exponent_qubit_index = None
         if sub_info.exponent_qubit_index is not None:
-            exponent_qubit_index = sub_info.exponent_qubit_index + control_count
+            exponent_qubit_index = sub_info.exponent_qubit_index + control_label_count
         elif sub_info.exponent is not None:
-            exponent_qubit_index = control_count
+            exponent_qubit_index = control_label_count
         return protocols.CircuitDiagramInfo(
             wire_symbols=wire_symbols,
             exponent=sub_info.exponent,

{"golden_diff": "diff --git a/cirq-core/cirq/ops/classically_controlled_operation.py b/cirq-core/cirq/ops/classically_controlled_operation.py\n--- a/cirq-core/cirq/ops/classically_controlled_operation.py\n+++ b/cirq-core/cirq/ops/classically_controlled_operation.py\n@@ -149,9 +149,13 @@\n         sub_info = protocols.circuit_diagram_info(self._sub_operation, sub_args, None)\n         if sub_info is None:\n             return NotImplemented  # coverage: ignore\n-        control_count = len({k for c in self._conditions for k in c.keys})\n-        wire_symbols = sub_info.wire_symbols + ('^',) * control_count\n-        if any(not isinstance(c, value.KeyCondition) for c in self._conditions):\n+        control_label_count = 0\n+        if args.label_map is not None:\n+            control_label_count = len({k for c in self._conditions for k in c.keys})\n+        wire_symbols = sub_info.wire_symbols + ('^',) * control_label_count\n+        if control_label_count == 0 or any(\n+            not isinstance(c, value.KeyCondition) for c in self._conditions\n+        ):\n             wire_symbols = (\n                 wire_symbols[0]\n                 + '(conditions=['\n@@ -160,9 +164,9 @@\n             ) + wire_symbols[1:]\n         exponent_qubit_index = None\n         if sub_info.exponent_qubit_index is not None:\n-            exponent_qubit_index = sub_info.exponent_qubit_index + control_count\n+            exponent_qubit_index = sub_info.exponent_qubit_index + control_label_count\n         elif sub_info.exponent is not None:\n-            exponent_qubit_index = control_count\n+            exponent_qubit_index = control_label_count\n         return protocols.CircuitDiagramInfo(\n             wire_symbols=wire_symbols,\n             exponent=sub_info.exponent,\n", "issue": "Printing Moment containing classical control fails\n**Description of the issue**\r\n\r\nA classically controlled op causes moment printing to fail. The op itself renders correctly, and a circuit containing the moment renders correctly. Just the moment itself fails to render.\r\n\r\n**How to reproduce the issue**\r\n\r\n```python\r\nop = cirq.X(cirq.NamedQubit('q')).with_classical_controls('m')\r\nm = cirq.Moment(op)\r\nprint(op)\r\nprint(cirq.Circuit(m))\r\nprint(m)\r\n```\r\n\r\n```\r\nX(q).with_classical_controls(m)\r\n\r\n\r\nq: \u2500\u2500\u2500X\u2500\u2500\u2500\r\n      \u2551\r\nm: \u2550\u2550\u2550^\u2550\u2550\u2550\r\n\r\n\r\nValueError: Wanted diagram info from cirq.ClassicallyControlledOperation(cirq.X(cirq.NamedQubit('q')), [cirq.KeyCondition(cirq.MeasurementKey(name='m'))]) for [cirq.NamedQubit('q')]) but got cirq.CircuitDiagramInfo(wire_symbols=('X', '^'), exponent=1.0, connected=True, exponent_qubit_index=1, auto_exponent_parens=True)\r\n\r\ncirq-core/cirq/protocols/circuit_diagram_info_protocol.py:345: ValueError\r\n```\r\n\r\nv0.15\n", "before_files": [{"content": "# Copyright 2021 The Cirq Developers\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom typing import (\n    AbstractSet,\n    Any,\n    Mapping,\n    Dict,\n    FrozenSet,\n    List,\n    Optional,\n    Sequence,\n    TYPE_CHECKING,\n    Tuple,\n    Union,\n)\n\nimport sympy\n\nfrom cirq import protocols, value\nfrom cirq.ops import raw_types\n\nif TYPE_CHECKING:\n    import cirq\n\n\n@value.value_equality\nclass ClassicallyControlledOperation(raw_types.Operation):\n    \"\"\"Augments existing operations to be conditionally executed.\n\n    An operation that is classically controlled is executed iff all conditions\n    evaluate to True. Currently the only condition type is a measurement key.\n    A measurement key evaluates to True iff any qubit in the corresponding\n    measurement operation evaluated to a non-zero value.\n\n    This object is typically created via\n     `operation.with_classical_controls(*conditions)`.\n    \"\"\"\n\n    def __init__(\n        self,\n        sub_operation: 'cirq.Operation',\n        conditions: Sequence[Union[str, 'cirq.MeasurementKey', 'cirq.Condition', sympy.Basic]],\n    ):\n        \"\"\"Initializes a `ClassicallyControlledOperation`.\n\n        Multiple consecutive `ClassicallyControlledOperation` layers are\n        squashed when possible, so one should not depend on a specific number\n        of layers.\n\n        Args:\n            sub_operation: The operation to gate with a classical control\n                condition.\n            conditions: A sequence of measurement keys, or strings that can be\n                parsed into measurement keys.\n\n        Raises:\n            ValueError: If an unsupported gate is being classically\n                controlled.\n        \"\"\"\n        if protocols.measurement_key_objs(sub_operation):\n            raise ValueError(\n                f'Cannot conditionally run operations with measurements: {sub_operation}'\n            )\n        conditions = tuple(conditions)\n        if isinstance(sub_operation, ClassicallyControlledOperation):\n            conditions += sub_operation._conditions\n            sub_operation = sub_operation._sub_operation\n        conds: List['cirq.Condition'] = []\n        for c in conditions:\n            if isinstance(c, str):\n                c = value.MeasurementKey.parse_serialized(c)\n            if isinstance(c, value.MeasurementKey):\n                c = value.KeyCondition(c)\n            if isinstance(c, sympy.Basic):\n                c = value.SympyCondition(c)\n            conds.append(c)\n        self._conditions: Tuple['cirq.Condition', ...] = tuple(conds)\n        self._sub_operation: 'cirq.Operation' = sub_operation\n\n    @property\n    def classical_controls(self) -> FrozenSet['cirq.Condition']:\n        return frozenset(self._conditions).union(self._sub_operation.classical_controls)\n\n    def without_classical_controls(self) -> 'cirq.Operation':\n        return self._sub_operation.without_classical_controls()\n\n    @property\n    def qubits(self):\n        return self._sub_operation.qubits\n\n    def with_qubits(self, *new_qubits):\n        return self._sub_operation.with_qubits(*new_qubits).with_classical_controls(\n            *self._conditions\n        )\n\n    def _decompose_(self):\n        result = protocols.decompose_once(self._sub_operation, NotImplemented)\n        if result is NotImplemented:\n            return NotImplemented\n\n        return [ClassicallyControlledOperation(op, self._conditions) for op in result]\n\n    def _value_equality_values_(self):\n        return (frozenset(self._conditions), self._sub_operation)\n\n    def __str__(self) -> str:\n        keys = ', '.join(map(str, self._conditions))\n        return f'{self._sub_operation}.with_classical_controls({keys})'\n\n    def __repr__(self):\n        return (\n            f'cirq.ClassicallyControlledOperation('\n            f'{self._sub_operation!r}, {list(self._conditions)!r})'\n        )\n\n    def _is_parameterized_(self) -> bool:\n        return protocols.is_parameterized(self._sub_operation)\n\n    def _parameter_names_(self) -> AbstractSet[str]:\n        return protocols.parameter_names(self._sub_operation)\n\n    def _resolve_parameters_(\n        self, resolver: 'cirq.ParamResolver', recursive: bool\n    ) -> 'ClassicallyControlledOperation':\n        new_sub_op = protocols.resolve_parameters(self._sub_operation, resolver, recursive)\n        return ClassicallyControlledOperation(new_sub_op, self._conditions)\n\n    def _circuit_diagram_info_(\n        self, args: 'cirq.CircuitDiagramInfoArgs'\n    ) -> Optional['protocols.CircuitDiagramInfo']:\n        sub_args = protocols.CircuitDiagramInfoArgs(\n            known_qubit_count=args.known_qubit_count,\n            known_qubits=args.known_qubits,\n            use_unicode_characters=args.use_unicode_characters,\n            precision=args.precision,\n            label_map=args.label_map,\n        )\n        sub_info = protocols.circuit_diagram_info(self._sub_operation, sub_args, None)\n        if sub_info is None:\n            return NotImplemented  # coverage: ignore\n        control_count = len({k for c in self._conditions for k in c.keys})\n        wire_symbols = sub_info.wire_symbols + ('^',) * control_count\n        if any(not isinstance(c, value.KeyCondition) for c in self._conditions):\n            wire_symbols = (\n                wire_symbols[0]\n                + '(conditions=['\n                + ', '.join(str(c) for c in self._conditions)\n                + '])',\n            ) + wire_symbols[1:]\n        exponent_qubit_index = None\n        if sub_info.exponent_qubit_index is not None:\n            exponent_qubit_index = sub_info.exponent_qubit_index + control_count\n        elif sub_info.exponent is not None:\n            exponent_qubit_index = control_count\n        return protocols.CircuitDiagramInfo(\n            wire_symbols=wire_symbols,\n            exponent=sub_info.exponent,\n            exponent_qubit_index=exponent_qubit_index,\n        )\n\n    def _json_dict_(self) -> Dict[str, Any]:\n        return {'conditions': self._conditions, 'sub_operation': self._sub_operation}\n\n    def _act_on_(self, sim_state: 'cirq.SimulationStateBase') -> bool:\n        if all(c.resolve(sim_state.classical_data) for c in self._conditions):\n            protocols.act_on(self._sub_operation, sim_state)\n        return True\n\n    def _with_measurement_key_mapping_(\n        self, key_map: Mapping[str, str]\n    ) -> 'ClassicallyControlledOperation':\n        conditions = [protocols.with_measurement_key_mapping(c, key_map) for c in self._conditions]\n        sub_operation = protocols.with_measurement_key_mapping(self._sub_operation, key_map)\n        sub_operation = self._sub_operation if sub_operation is NotImplemented else sub_operation\n        return sub_operation.with_classical_controls(*conditions)\n\n    def _with_key_path_prefix_(self, prefix: Tuple[str, ...]) -> 'ClassicallyControlledOperation':\n        conditions = [protocols.with_key_path_prefix(c, prefix) for c in self._conditions]\n        sub_operation = protocols.with_key_path_prefix(self._sub_operation, prefix)\n        sub_operation = self._sub_operation if sub_operation is NotImplemented else sub_operation\n        return sub_operation.with_classical_controls(*conditions)\n\n    def _with_rescoped_keys_(\n        self, path: Tuple[str, ...], bindable_keys: FrozenSet['cirq.MeasurementKey']\n    ) -> 'ClassicallyControlledOperation':\n        conds = [protocols.with_rescoped_keys(c, path, bindable_keys) for c in self._conditions]\n        sub_operation = protocols.with_rescoped_keys(self._sub_operation, path, bindable_keys)\n        return sub_operation.with_classical_controls(*conds)\n\n    def _control_keys_(self) -> FrozenSet['cirq.MeasurementKey']:\n        local_keys: FrozenSet['cirq.MeasurementKey'] = frozenset(\n            k for condition in self._conditions for k in condition.keys\n        )\n        return local_keys.union(protocols.control_keys(self._sub_operation))\n\n    def _qasm_(self, args: 'cirq.QasmArgs') -> Optional[str]:\n        args.validate_version('2.0')\n        if len(self._conditions) > 1:\n            raise ValueError('QASM does not support multiple conditions.')\n        subop_qasm = protocols.qasm(self._sub_operation, args=args)\n        if not self._conditions:\n            return subop_qasm\n        return f'if ({self._conditions[0].qasm}) {subop_qasm}'\n", "path": "cirq-core/cirq/ops/classically_controlled_operation.py"}], "after_files": [{"content": "# Copyright 2021 The Cirq Developers\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nfrom typing import (\n    AbstractSet,\n    Any,\n    Mapping,\n    Dict,\n    FrozenSet,\n    List,\n    Optional,\n    Sequence,\n    TYPE_CHECKING,\n    Tuple,\n    Union,\n)\n\nimport sympy\n\nfrom cirq import protocols, value\nfrom cirq.ops import raw_types\n\nif TYPE_CHECKING:\n    import cirq\n\n\n@value.value_equality\nclass ClassicallyControlledOperation(raw_types.Operation):\n    \"\"\"Augments existing operations to be conditionally executed.\n\n    An operation that is classically controlled is executed iff all conditions\n    evaluate to True. Currently the only condition type is a measurement key.\n    A measurement key evaluates to True iff any qubit in the corresponding\n    measurement operation evaluated to a non-zero value.\n\n    This object is typically created via\n     `operation.with_classical_controls(*conditions)`.\n    \"\"\"\n\n    def __init__(\n        self,\n        sub_operation: 'cirq.Operation',\n        conditions: Sequence[Union[str, 'cirq.MeasurementKey', 'cirq.Condition', sympy.Basic]],\n    ):\n        \"\"\"Initializes a `ClassicallyControlledOperation`.\n\n        Multiple consecutive `ClassicallyControlledOperation` layers are\n        squashed when possible, so one should not depend on a specific number\n        of layers.\n\n        Args:\n            sub_operation: The operation to gate with a classical control\n                condition.\n            conditions: A sequence of measurement keys, or strings that can be\n                parsed into measurement keys.\n\n        Raises:\n            ValueError: If an unsupported gate is being classically\n                controlled.\n        \"\"\"\n        if protocols.measurement_key_objs(sub_operation):\n            raise ValueError(\n                f'Cannot conditionally run operations with measurements: {sub_operation}'\n            )\n        conditions = tuple(conditions)\n        if isinstance(sub_operation, ClassicallyControlledOperation):\n            conditions += sub_operation._conditions\n            sub_operation = sub_operation._sub_operation\n        conds: List['cirq.Condition'] = []\n        for c in conditions:\n            if isinstance(c, str):\n                c = value.MeasurementKey.parse_serialized(c)\n            if isinstance(c, value.MeasurementKey):\n                c = value.KeyCondition(c)\n            if isinstance(c, sympy.Basic):\n                c = value.SympyCondition(c)\n            conds.append(c)\n        self._conditions: Tuple['cirq.Condition', ...] = tuple(conds)\n        self._sub_operation: 'cirq.Operation' = sub_operation\n\n    @property\n    def classical_controls(self) -> FrozenSet['cirq.Condition']:\n        return frozenset(self._conditions).union(self._sub_operation.classical_controls)\n\n    def without_classical_controls(self) -> 'cirq.Operation':\n        return self._sub_operation.without_classical_controls()\n\n    @property\n    def qubits(self):\n        return self._sub_operation.qubits\n\n    def with_qubits(self, *new_qubits):\n        return self._sub_operation.with_qubits(*new_qubits).with_classical_controls(\n            *self._conditions\n        )\n\n    def _decompose_(self):\n        result = protocols.decompose_once(self._sub_operation, NotImplemented)\n        if result is NotImplemented:\n            return NotImplemented\n\n        return [ClassicallyControlledOperation(op, self._conditions) for op in result]\n\n    def _value_equality_values_(self):\n        return (frozenset(self._conditions), self._sub_operation)\n\n    def __str__(self) -> str:\n        keys = ', '.join(map(str, self._conditions))\n        return f'{self._sub_operation}.with_classical_controls({keys})'\n\n    def __repr__(self):\n        return (\n            f'cirq.ClassicallyControlledOperation('\n            f'{self._sub_operation!r}, {list(self._conditions)!r})'\n        )\n\n    def _is_parameterized_(self) -> bool:\n        return protocols.is_parameterized(self._sub_operation)\n\n    def _parameter_names_(self) -> AbstractSet[str]:\n        return protocols.parameter_names(self._sub_operation)\n\n    def _resolve_parameters_(\n        self, resolver: 'cirq.ParamResolver', recursive: bool\n    ) -> 'ClassicallyControlledOperation':\n        new_sub_op = protocols.resolve_parameters(self._sub_operation, resolver, recursive)\n        return ClassicallyControlledOperation(new_sub_op, self._conditions)\n\n    def _circuit_diagram_info_(\n        self, args: 'cirq.CircuitDiagramInfoArgs'\n    ) -> Optional['protocols.CircuitDiagramInfo']:\n        sub_args = protocols.CircuitDiagramInfoArgs(\n            known_qubit_count=args.known_qubit_count,\n            known_qubits=args.known_qubits,\n            use_unicode_characters=args.use_unicode_characters,\n            precision=args.precision,\n            label_map=args.label_map,\n        )\n        sub_info = protocols.circuit_diagram_info(self._sub_operation, sub_args, None)\n        if sub_info is None:\n            return NotImplemented  # coverage: ignore\n        control_label_count = 0\n        if args.label_map is not None:\n            control_label_count = len({k for c in self._conditions for k in c.keys})\n        wire_symbols = sub_info.wire_symbols + ('^',) * control_label_count\n        if control_label_count == 0 or any(\n            not isinstance(c, value.KeyCondition) for c in self._conditions\n        ):\n            wire_symbols = (\n                wire_symbols[0]\n                + '(conditions=['\n                + ', '.join(str(c) for c in self._conditions)\n                + '])',\n            ) + wire_symbols[1:]\n        exponent_qubit_index = None\n        if sub_info.exponent_qubit_index is not None:\n            exponent_qubit_index = sub_info.exponent_qubit_index + control_label_count\n        elif sub_info.exponent is not None:\n            exponent_qubit_index = control_label_count\n        return protocols.CircuitDiagramInfo(\n            wire_symbols=wire_symbols,\n            exponent=sub_info.exponent,\n            exponent_qubit_index=exponent_qubit_index,\n        )\n\n    def _json_dict_(self) -> Dict[str, Any]:\n        return {'conditions': self._conditions, 'sub_operation': self._sub_operation}\n\n    def _act_on_(self, sim_state: 'cirq.SimulationStateBase') -> bool:\n        if all(c.resolve(sim_state.classical_data) for c in self._conditions):\n            protocols.act_on(self._sub_operation, sim_state)\n        return True\n\n    def _with_measurement_key_mapping_(\n        self, key_map: Mapping[str, str]\n    ) -> 'ClassicallyControlledOperation':\n        conditions = [protocols.with_measurement_key_mapping(c, key_map) for c in self._conditions]\n        sub_operation = protocols.with_measurement_key_mapping(self._sub_operation, key_map)\n        sub_operation = self._sub_operation if sub_operation is NotImplemented else sub_operation\n        return sub_operation.with_classical_controls(*conditions)\n\n    def _with_key_path_prefix_(self, prefix: Tuple[str, ...]) -> 'ClassicallyControlledOperation':\n        conditions = [protocols.with_key_path_prefix(c, prefix) for c in self._conditions]\n        sub_operation = protocols.with_key_path_prefix(self._sub_operation, prefix)\n        sub_operation = self._sub_operation if sub_operation is NotImplemented else sub_operation\n        return sub_operation.with_classical_controls(*conditions)\n\n    def _with_rescoped_keys_(\n        self, path: Tuple[str, ...], bindable_keys: FrozenSet['cirq.MeasurementKey']\n    ) -> 'ClassicallyControlledOperation':\n        conds = [protocols.with_rescoped_keys(c, path, bindable_keys) for c in self._conditions]\n        sub_operation = protocols.with_rescoped_keys(self._sub_operation, path, bindable_keys)\n        return sub_operation.with_classical_controls(*conds)\n\n    def _control_keys_(self) -> FrozenSet['cirq.MeasurementKey']:\n        local_keys: FrozenSet['cirq.MeasurementKey'] = frozenset(\n            k for condition in self._conditions for k in condition.keys\n        )\n        return local_keys.union(protocols.control_keys(self._sub_operation))\n\n    def _qasm_(self, args: 'cirq.QasmArgs') -> Optional[str]:\n        args.validate_version('2.0')\n        if len(self._conditions) > 1:\n            raise ValueError('QASM does not support multiple conditions.')\n        subop_qasm = protocols.qasm(self._sub_operation, args=args)\n        if not self._conditions:\n            return subop_qasm\n        return f'if ({self._conditions[0].qasm}) {subop_qasm}'\n", "path": "cirq-core/cirq/ops/classically_controlled_operation.py"}]}