We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Multi-qubit conditions in DeferredMeasurementsTransformer 
Use https://github.com/quantumlib/Cirq/pull/5755 to allow control keys from multi-qubit measurements in deferred measurements transformers. That new feature allows us to express "anything but all zeros", which is the condition required.

https://github.com/quantumlib/Cirq/blob/77b61f500af3726ad4b34b06c72e21eac48d3db6/cirq-core/cirq/transformers/measurement_transformers.py#L121-L124

--- 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/transformers/measurement_transformers.py`
Content:
```
1 # Copyright 2022 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 
15 from typing import Any, Dict, List, Optional, TYPE_CHECKING, Union
16 
17 from cirq import ops, protocols, value
18 from cirq.transformers import transformer_api, transformer_primitives
19 from cirq.transformers.synchronize_terminal_measurements import find_terminal_measurements
20 
21 if TYPE_CHECKING:
22     import cirq
23 
24 
25 class _MeasurementQid(ops.Qid):
26     """A qubit that substitutes in for a deferred measurement.
27 
28     Exactly one qubit will be created per qubit in the measurement gate.
29     """
30 
31     def __init__(self, key: Union[str, 'cirq.MeasurementKey'], qid: 'cirq.Qid'):
32         """Initializes the qubit.
33 
34         Args:
35             key: The key of the measurement gate being deferred.
36             qid: One qubit that is being measured. Each deferred measurement
37                 should create one new _MeasurementQid per qubit being measured
38                 by that gate.
39         """
40         self._key = value.MeasurementKey.parse_serialized(key) if isinstance(key, str) else key
41         self._qid = qid
42 
43     @property
44     def dimension(self) -> int:
45         return self._qid.dimension
46 
47     def _comparison_key(self) -> Any:
48         return (str(self._key), self._qid._comparison_key())
49 
50     def __str__(self) -> str:
51         return f"M('{self._key}', q={self._qid})"
52 
53     def __repr__(self) -> str:
54         return f'_MeasurementQid({self._key!r}, {self._qid!r})'
55 
56 
57 @transformer_api.transformer
58 def defer_measurements(
59     circuit: 'cirq.AbstractCircuit', *, context: Optional['cirq.TransformerContext'] = None
60 ) -> 'cirq.Circuit':
61     """Implements the Deferred Measurement Principle.
62 
63     Uses the Deferred Measurement Principle to move all measurements to the
64     end of the circuit. All non-terminal measurements are changed to
65     conditional quantum gates onto ancilla qubits, and classically controlled
66     operations are transformed to quantum controls from those ancilla qubits.
67     Finally, measurements of all ancilla qubits are appended to the end of the
68     circuit.
69 
70     Optimizing deferred measurements is an area of active research, and future
71     iterations may contain optimizations that reduce the number of ancilla
72     qubits, so one should not depend on the exact shape of the output from this
73     function. Only the logical equivalence is guaranteed to remain unchanged.
74     Moment and subcircuit structure is not preserved.
75 
76     Args:
77         circuit: The circuit to transform. It will not be modified.
78         context: `cirq.TransformerContext` storing common configurable options
79             for transformers.
80     Returns:
81         A circuit with equivalent logic, but all measurements at the end of the
82         circuit.
83     Raises:
84         ValueError: If sympy-based classical conditions are used, or if
85             conditions based on multi-qubit measurements exist. (The latter of
86             these is planned to be implemented soon).
87         NotImplementedError: When attempting to defer a measurement with a
88             confusion map. (https://github.com/quantumlib/Cirq/issues/5482)
89     """
90 
91     circuit = transformer_primitives.unroll_circuit_op(circuit, deep=True, tags_to_check=None)
92     terminal_measurements = {op for _, op in find_terminal_measurements(circuit)}
93     measurement_qubits: Dict['cirq.MeasurementKey', List['_MeasurementQid']] = {}
94 
95     def defer(op: 'cirq.Operation', _) -> 'cirq.OP_TREE':
96         if op in terminal_measurements:
97             return op
98         gate = op.gate
99         if isinstance(gate, ops.MeasurementGate):
100             if gate.confusion_map:
101                 raise NotImplementedError(
102                     "Deferring confused measurement is not implemented, but found "
103                     f"measurement with key={gate.key} and non-empty confusion map."
104                 )
105             key = value.MeasurementKey.parse_serialized(gate.key)
106             targets = [_MeasurementQid(key, q) for q in op.qubits]
107             measurement_qubits[key] = targets
108             cxs = [ops.CX(q, target) for q, target in zip(op.qubits, targets)]
109             xs = [ops.X(targets[i]) for i, b in enumerate(gate.full_invert_mask()) if b]
110             return cxs + xs
111         elif protocols.is_measurement(op):
112             return [defer(op, None) for op in protocols.decompose_once(op)]
113         elif op.classical_controls:
114             controls = []
115             for c in op.classical_controls:
116                 if isinstance(c, value.KeyCondition):
117                     if c.key not in measurement_qubits:
118                         raise ValueError(f'Deferred measurement for key={c.key} not found.')
119                     qubits = measurement_qubits[c.key]
120                     if len(qubits) != 1:
121                         # TODO: Multi-qubit conditions require
122                         # https://github.com/quantumlib/Cirq/issues/4512
123                         # Remember to update docstring above once this works.
124                         raise ValueError('Only single qubit conditions are allowed.')
125                     controls.extend(qubits)
126                 else:
127                     raise ValueError('Only KeyConditions are allowed.')
128             return op.without_classical_controls().controlled_by(
129                 *controls, control_values=[tuple(range(1, q.dimension)) for q in controls]
130             )
131         return op
132 
133     circuit = transformer_primitives.map_operations_and_unroll(
134         circuit=circuit,
135         map_func=defer,
136         tags_to_ignore=context.tags_to_ignore if context else (),
137         raise_if_add_qubits=False,
138     ).unfreeze()
139     for k, qubits in measurement_qubits.items():
140         circuit.append(ops.measure(*qubits, key=k))
141     return circuit
142 
143 
144 @transformer_api.transformer
145 def dephase_measurements(
146     circuit: 'cirq.AbstractCircuit',
147     *,
148     context: Optional['cirq.TransformerContext'] = transformer_api.TransformerContext(deep=True),
149 ) -> 'cirq.Circuit':
150     """Changes all measurements to a dephase operation.
151 
152     This transformer is useful when using a density matrix simulator, when
153     wishing to calculate the final density matrix of a circuit and not simulate
154     the measurements themselves.
155 
156     Args:
157         circuit: The circuit to transform. It will not be modified.
158         context: `cirq.TransformerContext` storing common configurable options
159             for transformers. The default has `deep=True` to ensure
160             measurements at all levels are dephased.
161     Returns:
162         A copy of the circuit, with dephase operations in place of all
163         measurements.
164     Raises:
165         ValueError: If the circuit contains classical controls. In this case,
166             it is required to change these to quantum controls via
167             `cirq.defer_measurements` first. Since deferral adds ancilla qubits
168             to the circuit, this is not done automatically, to prevent
169             surprises.
170     """
171 
172     def dephase(op: 'cirq.Operation', _) -> 'cirq.OP_TREE':
173         gate = op.gate
174         if isinstance(gate, ops.MeasurementGate):
175             key = value.MeasurementKey.parse_serialized(gate.key)
176             return ops.KrausChannel.from_channel(ops.phase_damp(1), key=key).on_each(op.qubits)
177         elif isinstance(op, ops.ClassicallyControlledOperation):
178             raise ValueError('Use cirq.defer_measurements first to remove classical controls.')
179         return op
180 
181     ignored = () if context is None else context.tags_to_ignore
182     return transformer_primitives.map_operations(
183         circuit, dephase, deep=context.deep if context else True, tags_to_ignore=ignored
184     ).unfreeze()
185 
186 
187 @transformer_api.transformer
188 def drop_terminal_measurements(
189     circuit: 'cirq.AbstractCircuit',
190     *,
191     context: Optional['cirq.TransformerContext'] = transformer_api.TransformerContext(deep=True),
192 ) -> 'cirq.Circuit':
193     """Removes terminal measurements from a circuit.
194 
195     This transformer is helpful when trying to capture the final state vector
196     of a circuit with many terminal measurements, as simulating the circuit
197     with those measurements in place would otherwise collapse the final state.
198 
199     Args:
200         circuit: The circuit to transform. It will not be modified.
201         context: `cirq.TransformerContext` storing common configurable options
202             for transformers. The default has `deep=True`, as "terminal
203             measurements" is ill-defined without inspecting subcircuits;
204             passing a context with `deep=False` will return an error.
205     Returns:
206         A copy of the circuit, with identity or X gates in place of terminal
207         measurements.
208     Raises:
209         ValueError: if the circuit contains non-terminal measurements, or if
210             the provided context has`deep=False`.
211     """
212 
213     if context is None or not context.deep:
214         raise ValueError(
215             'Context has `deep=False`, but `deep=True` is required to drop terminal measurements.'
216         )
217 
218     if not circuit.are_all_measurements_terminal():
219         raise ValueError('Circuit contains a non-terminal measurement.')
220 
221     def flip_inversion(op: 'cirq.Operation', _) -> 'cirq.OP_TREE':
222         if isinstance(op.gate, ops.MeasurementGate):
223             return [
224                 ops.X(q) if b else ops.I(q) for q, b in zip(op.qubits, op.gate.full_invert_mask())
225             ]
226         return op
227 
228     ignored = () if context is None else context.tags_to_ignore
229     return transformer_primitives.map_operations(
230         circuit, flip_inversion, deep=context.deep if context else True, tags_to_ignore=ignored
231     ).unfreeze()
232
```
--- 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/transformers/measurement_transformers.py b/cirq-core/cirq/transformers/measurement_transformers.py
--- a/cirq-core/cirq/transformers/measurement_transformers.py
+++ b/cirq-core/cirq/transformers/measurement_transformers.py
@@ -12,6 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+import itertools
 from typing import Any, Dict, List, Optional, TYPE_CHECKING, Union
 
 from cirq import ops, protocols, value
@@ -81,9 +82,7 @@
         A circuit with equivalent logic, but all measurements at the end of the
         circuit.
     Raises:
-        ValueError: If sympy-based classical conditions are used, or if
-            conditions based on multi-qubit measurements exist. (The latter of
-            these is planned to be implemented soon).
+        ValueError: If sympy-based classical conditions are used.
         NotImplementedError: When attempting to defer a measurement with a
             confusion map. (https://github.com/quantumlib/Cirq/issues/5482)
     """
@@ -111,23 +110,22 @@
         elif protocols.is_measurement(op):
             return [defer(op, None) for op in protocols.decompose_once(op)]
         elif op.classical_controls:
-            controls = []
+            new_op = op.without_classical_controls()
             for c in op.classical_controls:
                 if isinstance(c, value.KeyCondition):
                     if c.key not in measurement_qubits:
                         raise ValueError(f'Deferred measurement for key={c.key} not found.')
-                    qubits = measurement_qubits[c.key]
-                    if len(qubits) != 1:
-                        # TODO: Multi-qubit conditions require
-                        # https://github.com/quantumlib/Cirq/issues/4512
-                        # Remember to update docstring above once this works.
-                        raise ValueError('Only single qubit conditions are allowed.')
-                    controls.extend(qubits)
+                    qs = measurement_qubits[c.key]
+                    if len(qs) == 1:
+                        control_values: Any = range(1, qs[0].dimension)
+                    else:
+                        all_values = itertools.product(*[range(q.dimension) for q in qs])
+                        anything_but_all_zeros = tuple(itertools.islice(all_values, 1, None))
+                        control_values = ops.SumOfProducts(anything_but_all_zeros)
+                    new_op = new_op.controlled_by(*qs, control_values=control_values)
                 else:
                     raise ValueError('Only KeyConditions are allowed.')
-            return op.without_classical_controls().controlled_by(
-                *controls, control_values=[tuple(range(1, q.dimension)) for q in controls]
-            )
+            return new_op
         return op
 
     circuit = transformer_primitives.map_operations_and_unroll(

{"golden_diff": "diff --git a/cirq-core/cirq/transformers/measurement_transformers.py b/cirq-core/cirq/transformers/measurement_transformers.py\n--- a/cirq-core/cirq/transformers/measurement_transformers.py\n+++ b/cirq-core/cirq/transformers/measurement_transformers.py\n@@ -12,6 +12,7 @@\n # See the License for the specific language governing permissions and\n # limitations under the License.\n \n+import itertools\n from typing import Any, Dict, List, Optional, TYPE_CHECKING, Union\n \n from cirq import ops, protocols, value\n@@ -81,9 +82,7 @@\n         A circuit with equivalent logic, but all measurements at the end of the\n         circuit.\n     Raises:\n-        ValueError: If sympy-based classical conditions are used, or if\n-            conditions based on multi-qubit measurements exist. (The latter of\n-            these is planned to be implemented soon).\n+        ValueError: If sympy-based classical conditions are used.\n         NotImplementedError: When attempting to defer a measurement with a\n             confusion map. (https://github.com/quantumlib/Cirq/issues/5482)\n     \"\"\"\n@@ -111,23 +110,22 @@\n         elif protocols.is_measurement(op):\n             return [defer(op, None) for op in protocols.decompose_once(op)]\n         elif op.classical_controls:\n-            controls = []\n+            new_op = op.without_classical_controls()\n             for c in op.classical_controls:\n                 if isinstance(c, value.KeyCondition):\n                     if c.key not in measurement_qubits:\n                         raise ValueError(f'Deferred measurement for key={c.key} not found.')\n-                    qubits = measurement_qubits[c.key]\n-                    if len(qubits) != 1:\n-                        # TODO: Multi-qubit conditions require\n-                        # https://github.com/quantumlib/Cirq/issues/4512\n-                        # Remember to update docstring above once this works.\n-                        raise ValueError('Only single qubit conditions are allowed.')\n-                    controls.extend(qubits)\n+                    qs = measurement_qubits[c.key]\n+                    if len(qs) == 1:\n+                        control_values: Any = range(1, qs[0].dimension)\n+                    else:\n+                        all_values = itertools.product(*[range(q.dimension) for q in qs])\n+                        anything_but_all_zeros = tuple(itertools.islice(all_values, 1, None))\n+                        control_values = ops.SumOfProducts(anything_but_all_zeros)\n+                    new_op = new_op.controlled_by(*qs, control_values=control_values)\n                 else:\n                     raise ValueError('Only KeyConditions are allowed.')\n-            return op.without_classical_controls().controlled_by(\n-                *controls, control_values=[tuple(range(1, q.dimension)) for q in controls]\n-            )\n+            return new_op\n         return op\n \n     circuit = transformer_primitives.map_operations_and_unroll(\n", "issue": "Multi-qubit conditions in DeferredMeasurementsTransformer \nUse https://github.com/quantumlib/Cirq/pull/5755 to allow control keys from multi-qubit measurements in deferred measurements transformers. That new feature allows us to express \"anything but all zeros\", which is the condition required.\r\n\r\nhttps://github.com/quantumlib/Cirq/blob/77b61f500af3726ad4b34b06c72e21eac48d3db6/cirq-core/cirq/transformers/measurement_transformers.py#L121-L124\n", "before_files": [{"content": "# Copyright 2022 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.\n\nfrom typing import Any, Dict, List, Optional, TYPE_CHECKING, Union\n\nfrom cirq import ops, protocols, value\nfrom cirq.transformers import transformer_api, transformer_primitives\nfrom cirq.transformers.synchronize_terminal_measurements import find_terminal_measurements\n\nif TYPE_CHECKING:\n    import cirq\n\n\nclass _MeasurementQid(ops.Qid):\n    \"\"\"A qubit that substitutes in for a deferred measurement.\n\n    Exactly one qubit will be created per qubit in the measurement gate.\n    \"\"\"\n\n    def __init__(self, key: Union[str, 'cirq.MeasurementKey'], qid: 'cirq.Qid'):\n        \"\"\"Initializes the qubit.\n\n        Args:\n            key: The key of the measurement gate being deferred.\n            qid: One qubit that is being measured. Each deferred measurement\n                should create one new _MeasurementQid per qubit being measured\n                by that gate.\n        \"\"\"\n        self._key = value.MeasurementKey.parse_serialized(key) if isinstance(key, str) else key\n        self._qid = qid\n\n    @property\n    def dimension(self) -> int:\n        return self._qid.dimension\n\n    def _comparison_key(self) -> Any:\n        return (str(self._key), self._qid._comparison_key())\n\n    def __str__(self) -> str:\n        return f\"M('{self._key}', q={self._qid})\"\n\n    def __repr__(self) -> str:\n        return f'_MeasurementQid({self._key!r}, {self._qid!r})'\n\n\n@transformer_api.transformer\ndef defer_measurements(\n    circuit: 'cirq.AbstractCircuit', *, context: Optional['cirq.TransformerContext'] = None\n) -> 'cirq.Circuit':\n    \"\"\"Implements the Deferred Measurement Principle.\n\n    Uses the Deferred Measurement Principle to move all measurements to the\n    end of the circuit. All non-terminal measurements are changed to\n    conditional quantum gates onto ancilla qubits, and classically controlled\n    operations are transformed to quantum controls from those ancilla qubits.\n    Finally, measurements of all ancilla qubits are appended to the end of the\n    circuit.\n\n    Optimizing deferred measurements is an area of active research, and future\n    iterations may contain optimizations that reduce the number of ancilla\n    qubits, so one should not depend on the exact shape of the output from this\n    function. Only the logical equivalence is guaranteed to remain unchanged.\n    Moment and subcircuit structure is not preserved.\n\n    Args:\n        circuit: The circuit to transform. It will not be modified.\n        context: `cirq.TransformerContext` storing common configurable options\n            for transformers.\n    Returns:\n        A circuit with equivalent logic, but all measurements at the end of the\n        circuit.\n    Raises:\n        ValueError: If sympy-based classical conditions are used, or if\n            conditions based on multi-qubit measurements exist. (The latter of\n            these is planned to be implemented soon).\n        NotImplementedError: When attempting to defer a measurement with a\n            confusion map. (https://github.com/quantumlib/Cirq/issues/5482)\n    \"\"\"\n\n    circuit = transformer_primitives.unroll_circuit_op(circuit, deep=True, tags_to_check=None)\n    terminal_measurements = {op for _, op in find_terminal_measurements(circuit)}\n    measurement_qubits: Dict['cirq.MeasurementKey', List['_MeasurementQid']] = {}\n\n    def defer(op: 'cirq.Operation', _) -> 'cirq.OP_TREE':\n        if op in terminal_measurements:\n            return op\n        gate = op.gate\n        if isinstance(gate, ops.MeasurementGate):\n            if gate.confusion_map:\n                raise NotImplementedError(\n                    \"Deferring confused measurement is not implemented, but found \"\n                    f\"measurement with key={gate.key} and non-empty confusion map.\"\n                )\n            key = value.MeasurementKey.parse_serialized(gate.key)\n            targets = [_MeasurementQid(key, q) for q in op.qubits]\n            measurement_qubits[key] = targets\n            cxs = [ops.CX(q, target) for q, target in zip(op.qubits, targets)]\n            xs = [ops.X(targets[i]) for i, b in enumerate(gate.full_invert_mask()) if b]\n            return cxs + xs\n        elif protocols.is_measurement(op):\n            return [defer(op, None) for op in protocols.decompose_once(op)]\n        elif op.classical_controls:\n            controls = []\n            for c in op.classical_controls:\n                if isinstance(c, value.KeyCondition):\n                    if c.key not in measurement_qubits:\n                        raise ValueError(f'Deferred measurement for key={c.key} not found.')\n                    qubits = measurement_qubits[c.key]\n                    if len(qubits) != 1:\n                        # TODO: Multi-qubit conditions require\n                        # https://github.com/quantumlib/Cirq/issues/4512\n                        # Remember to update docstring above once this works.\n                        raise ValueError('Only single qubit conditions are allowed.')\n                    controls.extend(qubits)\n                else:\n                    raise ValueError('Only KeyConditions are allowed.')\n            return op.without_classical_controls().controlled_by(\n                *controls, control_values=[tuple(range(1, q.dimension)) for q in controls]\n            )\n        return op\n\n    circuit = transformer_primitives.map_operations_and_unroll(\n        circuit=circuit,\n        map_func=defer,\n        tags_to_ignore=context.tags_to_ignore if context else (),\n        raise_if_add_qubits=False,\n    ).unfreeze()\n    for k, qubits in measurement_qubits.items():\n        circuit.append(ops.measure(*qubits, key=k))\n    return circuit\n\n\n@transformer_api.transformer\ndef dephase_measurements(\n    circuit: 'cirq.AbstractCircuit',\n    *,\n    context: Optional['cirq.TransformerContext'] = transformer_api.TransformerContext(deep=True),\n) -> 'cirq.Circuit':\n    \"\"\"Changes all measurements to a dephase operation.\n\n    This transformer is useful when using a density matrix simulator, when\n    wishing to calculate the final density matrix of a circuit and not simulate\n    the measurements themselves.\n\n    Args:\n        circuit: The circuit to transform. It will not be modified.\n        context: `cirq.TransformerContext` storing common configurable options\n            for transformers. The default has `deep=True` to ensure\n            measurements at all levels are dephased.\n    Returns:\n        A copy of the circuit, with dephase operations in place of all\n        measurements.\n    Raises:\n        ValueError: If the circuit contains classical controls. In this case,\n            it is required to change these to quantum controls via\n            `cirq.defer_measurements` first. Since deferral adds ancilla qubits\n            to the circuit, this is not done automatically, to prevent\n            surprises.\n    \"\"\"\n\n    def dephase(op: 'cirq.Operation', _) -> 'cirq.OP_TREE':\n        gate = op.gate\n        if isinstance(gate, ops.MeasurementGate):\n            key = value.MeasurementKey.parse_serialized(gate.key)\n            return ops.KrausChannel.from_channel(ops.phase_damp(1), key=key).on_each(op.qubits)\n        elif isinstance(op, ops.ClassicallyControlledOperation):\n            raise ValueError('Use cirq.defer_measurements first to remove classical controls.')\n        return op\n\n    ignored = () if context is None else context.tags_to_ignore\n    return transformer_primitives.map_operations(\n        circuit, dephase, deep=context.deep if context else True, tags_to_ignore=ignored\n    ).unfreeze()\n\n\n@transformer_api.transformer\ndef drop_terminal_measurements(\n    circuit: 'cirq.AbstractCircuit',\n    *,\n    context: Optional['cirq.TransformerContext'] = transformer_api.TransformerContext(deep=True),\n) -> 'cirq.Circuit':\n    \"\"\"Removes terminal measurements from a circuit.\n\n    This transformer is helpful when trying to capture the final state vector\n    of a circuit with many terminal measurements, as simulating the circuit\n    with those measurements in place would otherwise collapse the final state.\n\n    Args:\n        circuit: The circuit to transform. It will not be modified.\n        context: `cirq.TransformerContext` storing common configurable options\n            for transformers. The default has `deep=True`, as \"terminal\n            measurements\" is ill-defined without inspecting subcircuits;\n            passing a context with `deep=False` will return an error.\n    Returns:\n        A copy of the circuit, with identity or X gates in place of terminal\n        measurements.\n    Raises:\n        ValueError: if the circuit contains non-terminal measurements, or if\n            the provided context has`deep=False`.\n    \"\"\"\n\n    if context is None or not context.deep:\n        raise ValueError(\n            'Context has `deep=False`, but `deep=True` is required to drop terminal measurements.'\n        )\n\n    if not circuit.are_all_measurements_terminal():\n        raise ValueError('Circuit contains a non-terminal measurement.')\n\n    def flip_inversion(op: 'cirq.Operation', _) -> 'cirq.OP_TREE':\n        if isinstance(op.gate, ops.MeasurementGate):\n            return [\n                ops.X(q) if b else ops.I(q) for q, b in zip(op.qubits, op.gate.full_invert_mask())\n            ]\n        return op\n\n    ignored = () if context is None else context.tags_to_ignore\n    return transformer_primitives.map_operations(\n        circuit, flip_inversion, deep=context.deep if context else True, tags_to_ignore=ignored\n    ).unfreeze()\n", "path": "cirq-core/cirq/transformers/measurement_transformers.py"}], "after_files": [{"content": "# Copyright 2022 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.\n\nimport itertools\nfrom typing import Any, Dict, List, Optional, TYPE_CHECKING, Union\n\nfrom cirq import ops, protocols, value\nfrom cirq.transformers import transformer_api, transformer_primitives\nfrom cirq.transformers.synchronize_terminal_measurements import find_terminal_measurements\n\nif TYPE_CHECKING:\n    import cirq\n\n\nclass _MeasurementQid(ops.Qid):\n    \"\"\"A qubit that substitutes in for a deferred measurement.\n\n    Exactly one qubit will be created per qubit in the measurement gate.\n    \"\"\"\n\n    def __init__(self, key: Union[str, 'cirq.MeasurementKey'], qid: 'cirq.Qid'):\n        \"\"\"Initializes the qubit.\n\n        Args:\n            key: The key of the measurement gate being deferred.\n            qid: One qubit that is being measured. Each deferred measurement\n                should create one new _MeasurementQid per qubit being measured\n                by that gate.\n        \"\"\"\n        self._key = value.MeasurementKey.parse_serialized(key) if isinstance(key, str) else key\n        self._qid = qid\n\n    @property\n    def dimension(self) -> int:\n        return self._qid.dimension\n\n    def _comparison_key(self) -> Any:\n        return (str(self._key), self._qid._comparison_key())\n\n    def __str__(self) -> str:\n        return f\"M('{self._key}', q={self._qid})\"\n\n    def __repr__(self) -> str:\n        return f'_MeasurementQid({self._key!r}, {self._qid!r})'\n\n\n@transformer_api.transformer\ndef defer_measurements(\n    circuit: 'cirq.AbstractCircuit', *, context: Optional['cirq.TransformerContext'] = None\n) -> 'cirq.Circuit':\n    \"\"\"Implements the Deferred Measurement Principle.\n\n    Uses the Deferred Measurement Principle to move all measurements to the\n    end of the circuit. All non-terminal measurements are changed to\n    conditional quantum gates onto ancilla qubits, and classically controlled\n    operations are transformed to quantum controls from those ancilla qubits.\n    Finally, measurements of all ancilla qubits are appended to the end of the\n    circuit.\n\n    Optimizing deferred measurements is an area of active research, and future\n    iterations may contain optimizations that reduce the number of ancilla\n    qubits, so one should not depend on the exact shape of the output from this\n    function. Only the logical equivalence is guaranteed to remain unchanged.\n    Moment and subcircuit structure is not preserved.\n\n    Args:\n        circuit: The circuit to transform. It will not be modified.\n        context: `cirq.TransformerContext` storing common configurable options\n            for transformers.\n    Returns:\n        A circuit with equivalent logic, but all measurements at the end of the\n        circuit.\n    Raises:\n        ValueError: If sympy-based classical conditions are used.\n        NotImplementedError: When attempting to defer a measurement with a\n            confusion map. (https://github.com/quantumlib/Cirq/issues/5482)\n    \"\"\"\n\n    circuit = transformer_primitives.unroll_circuit_op(circuit, deep=True, tags_to_check=None)\n    terminal_measurements = {op for _, op in find_terminal_measurements(circuit)}\n    measurement_qubits: Dict['cirq.MeasurementKey', List['_MeasurementQid']] = {}\n\n    def defer(op: 'cirq.Operation', _) -> 'cirq.OP_TREE':\n        if op in terminal_measurements:\n            return op\n        gate = op.gate\n        if isinstance(gate, ops.MeasurementGate):\n            if gate.confusion_map:\n                raise NotImplementedError(\n                    \"Deferring confused measurement is not implemented, but found \"\n                    f\"measurement with key={gate.key} and non-empty confusion map.\"\n                )\n            key = value.MeasurementKey.parse_serialized(gate.key)\n            targets = [_MeasurementQid(key, q) for q in op.qubits]\n            measurement_qubits[key] = targets\n            cxs = [ops.CX(q, target) for q, target in zip(op.qubits, targets)]\n            xs = [ops.X(targets[i]) for i, b in enumerate(gate.full_invert_mask()) if b]\n            return cxs + xs\n        elif protocols.is_measurement(op):\n            return [defer(op, None) for op in protocols.decompose_once(op)]\n        elif op.classical_controls:\n            new_op = op.without_classical_controls()\n            for c in op.classical_controls:\n                if isinstance(c, value.KeyCondition):\n                    if c.key not in measurement_qubits:\n                        raise ValueError(f'Deferred measurement for key={c.key} not found.')\n                    qs = measurement_qubits[c.key]\n                    if len(qs) == 1:\n                        control_values: Any = range(1, qs[0].dimension)\n                    else:\n                        all_values = itertools.product(*[range(q.dimension) for q in qs])\n                        anything_but_all_zeros = tuple(itertools.islice(all_values, 1, None))\n                        control_values = ops.SumOfProducts(anything_but_all_zeros)\n                    new_op = new_op.controlled_by(*qs, control_values=control_values)\n                else:\n                    raise ValueError('Only KeyConditions are allowed.')\n            return new_op\n        return op\n\n    circuit = transformer_primitives.map_operations_and_unroll(\n        circuit=circuit,\n        map_func=defer,\n        tags_to_ignore=context.tags_to_ignore if context else (),\n        raise_if_add_qubits=False,\n    ).unfreeze()\n    for k, qubits in measurement_qubits.items():\n        circuit.append(ops.measure(*qubits, key=k))\n    return circuit\n\n\n@transformer_api.transformer\ndef dephase_measurements(\n    circuit: 'cirq.AbstractCircuit',\n    *,\n    context: Optional['cirq.TransformerContext'] = transformer_api.TransformerContext(deep=True),\n) -> 'cirq.Circuit':\n    \"\"\"Changes all measurements to a dephase operation.\n\n    This transformer is useful when using a density matrix simulator, when\n    wishing to calculate the final density matrix of a circuit and not simulate\n    the measurements themselves.\n\n    Args:\n        circuit: The circuit to transform. It will not be modified.\n        context: `cirq.TransformerContext` storing common configurable options\n            for transformers. The default has `deep=True` to ensure\n            measurements at all levels are dephased.\n    Returns:\n        A copy of the circuit, with dephase operations in place of all\n        measurements.\n    Raises:\n        ValueError: If the circuit contains classical controls. In this case,\n            it is required to change these to quantum controls via\n            `cirq.defer_measurements` first. Since deferral adds ancilla qubits\n            to the circuit, this is not done automatically, to prevent\n            surprises.\n    \"\"\"\n\n    def dephase(op: 'cirq.Operation', _) -> 'cirq.OP_TREE':\n        gate = op.gate\n        if isinstance(gate, ops.MeasurementGate):\n            key = value.MeasurementKey.parse_serialized(gate.key)\n            return ops.KrausChannel.from_channel(ops.phase_damp(1), key=key).on_each(op.qubits)\n        elif isinstance(op, ops.ClassicallyControlledOperation):\n            raise ValueError('Use cirq.defer_measurements first to remove classical controls.')\n        return op\n\n    ignored = () if context is None else context.tags_to_ignore\n    return transformer_primitives.map_operations(\n        circuit, dephase, deep=context.deep if context else True, tags_to_ignore=ignored\n    ).unfreeze()\n\n\n@transformer_api.transformer\ndef drop_terminal_measurements(\n    circuit: 'cirq.AbstractCircuit',\n    *,\n    context: Optional['cirq.TransformerContext'] = transformer_api.TransformerContext(deep=True),\n) -> 'cirq.Circuit':\n    \"\"\"Removes terminal measurements from a circuit.\n\n    This transformer is helpful when trying to capture the final state vector\n    of a circuit with many terminal measurements, as simulating the circuit\n    with those measurements in place would otherwise collapse the final state.\n\n    Args:\n        circuit: The circuit to transform. It will not be modified.\n        context: `cirq.TransformerContext` storing common configurable options\n            for transformers. The default has `deep=True`, as \"terminal\n            measurements\" is ill-defined without inspecting subcircuits;\n            passing a context with `deep=False` will return an error.\n    Returns:\n        A copy of the circuit, with identity or X gates in place of terminal\n        measurements.\n    Raises:\n        ValueError: if the circuit contains non-terminal measurements, or if\n            the provided context has`deep=False`.\n    \"\"\"\n\n    if context is None or not context.deep:\n        raise ValueError(\n            'Context has `deep=False`, but `deep=True` is required to drop terminal measurements.'\n        )\n\n    if not circuit.are_all_measurements_terminal():\n        raise ValueError('Circuit contains a non-terminal measurement.')\n\n    def flip_inversion(op: 'cirq.Operation', _) -> 'cirq.OP_TREE':\n        if isinstance(op.gate, ops.MeasurementGate):\n            return [\n                ops.X(q) if b else ops.I(q) for q, b in zip(op.qubits, op.gate.full_invert_mask())\n            ]\n        return op\n\n    ignored = () if context is None else context.tags_to_ignore\n    return transformer_primitives.map_operations(\n        circuit, flip_inversion, deep=context.deep if context else True, tags_to_ignore=ignored\n    ).unfreeze()\n", "path": "cirq-core/cirq/transformers/measurement_transformers.py"}]}