|
37 | 37 | from cirq import protocols, value |
38 | 38 | from cirq._compat import proper_repr |
39 | 39 | from cirq._doc import document |
40 | | -from cirq.ops import control_values as cv, controlled_gate, eigen_gate, gate_features, raw_types |
| 40 | +from cirq.ops import ( |
| 41 | + control_values as cv, |
| 42 | + controlled_gate, |
| 43 | + eigen_gate, |
| 44 | + gate_features, |
| 45 | + global_phase_op, |
| 46 | + raw_types, |
| 47 | +) |
41 | 48 | from cirq.ops.measurement_gate import MeasurementGate |
42 | 49 | from cirq.ops.swap_gates import ISWAP, ISwapPowGate, SWAP, SwapPowGate |
43 | 50 |
|
@@ -235,6 +242,11 @@ def controlled( |
235 | 242 | return cirq.CCXPowGate(exponent=self._exponent) |
236 | 243 | return result |
237 | 244 |
|
| 245 | + def _decompose_with_context_( |
| 246 | + self, qubits: tuple[cirq.Qid, ...], context: cirq.DecompositionContext |
| 247 | + ) -> list[cirq.Operation] | NotImplementedType: |
| 248 | + return _extract_phase(self, XPowGate, qubits, context) |
| 249 | + |
238 | 250 | def _pauli_expansion_(self) -> value.LinearDict[str]: |
239 | 251 | if self._dimension != 2: |
240 | 252 | return NotImplemented # pragma: no cover |
@@ -487,6 +499,11 @@ def __repr__(self) -> str: |
487 | 499 | f'global_shift={self._global_shift!r})' |
488 | 500 | ) |
489 | 501 |
|
| 502 | + def _decompose_with_context_( |
| 503 | + self, qubits: tuple[cirq.Qid, ...], context: cirq.DecompositionContext |
| 504 | + ) -> list[cirq.Operation] | NotImplementedType: |
| 505 | + return _extract_phase(self, YPowGate, qubits, context) |
| 506 | + |
490 | 507 |
|
491 | 508 | class Ry(YPowGate): |
492 | 509 | r"""A gate with matrix $e^{-i Y t/2}$ that rotates around the Y axis of the Bloch sphere by $t$. |
@@ -699,6 +716,11 @@ def controlled( |
699 | 716 | return cirq.CCZPowGate(exponent=self._exponent) |
700 | 717 | return result |
701 | 718 |
|
| 719 | + def _decompose_with_context_( |
| 720 | + self, qubits: tuple[cirq.Qid, ...], context: cirq.DecompositionContext |
| 721 | + ) -> list[cirq.Operation] | NotImplementedType: |
| 722 | + return _extract_phase(self, ZPowGate, qubits, context) |
| 723 | + |
702 | 724 | def _qid_shape_(self) -> tuple[int, ...]: |
703 | 725 | return (self._dimension,) |
704 | 726 |
|
@@ -1131,6 +1153,11 @@ def controlled( |
1131 | 1153 | control_qid_shape=result.control_qid_shape + (2,), |
1132 | 1154 | ) |
1133 | 1155 |
|
| 1156 | + def _decompose_with_context_( |
| 1157 | + self, qubits: tuple[cirq.Qid, ...], context: cirq.DecompositionContext |
| 1158 | + ) -> list[cirq.Operation] | NotImplementedType: |
| 1159 | + return _extract_phase(self, CZPowGate, qubits, context) |
| 1160 | + |
1134 | 1161 | def _circuit_diagram_info_(self, args: cirq.CircuitDiagramInfoArgs) -> cirq.CircuitDiagramInfo: |
1135 | 1162 | return protocols.CircuitDiagramInfo( |
1136 | 1163 | wire_symbols=('@', '@'), exponent=self._diagram_exponent(args) |
@@ -1486,3 +1513,25 @@ def _phased_x_or_pauli_gate( |
1486 | 1513 | case 0.5: |
1487 | 1514 | return YPowGate(exponent=exponent) |
1488 | 1515 | return cirq.ops.PhasedXPowGate(exponent=exponent, phase_exponent=phase_exponent) |
| 1516 | + |
| 1517 | + |
| 1518 | +def _extract_phase( |
| 1519 | + gate: cirq.EigenGate, |
| 1520 | + gate_class: type, |
| 1521 | + qubits: tuple[cirq.Qid, ...], |
| 1522 | + context: cirq.DecompositionContext, |
| 1523 | +) -> list[cirq.Operation] | NotImplementedType: |
| 1524 | + """Extracts the global phase field to its own gate, or absorbs it if it has no effect. |
| 1525 | +
|
| 1526 | + This is for use within the decompose handlers, and will return `NotImplemented` if there is no |
| 1527 | + global phase, implying it is already in its simplest form. It will return a list, with the |
| 1528 | + original op minus any global phase first, and the global phase op second. If the resulting |
| 1529 | + global phase is empty (can happen for example in `XPowGate(global_phase=2/3)**3`), then it is |
| 1530 | + excluded from the return value.""" |
| 1531 | + if not context.extract_global_phases or gate.global_shift == 0: |
| 1532 | + return NotImplemented |
| 1533 | + result = [gate_class(exponent=gate.exponent).on(*qubits)] |
| 1534 | + phase_gate = global_phase_op.from_phase_and_exponent(gate.global_shift, gate.exponent) |
| 1535 | + if not phase_gate.is_identity(): |
| 1536 | + result.append(phase_gate()) |
| 1537 | + return result |
0 commit comments