diff --git a/cirq-core/cirq/ops/clifford_gate.py b/cirq-core/cirq/ops/clifford_gate.py index c3021bf9bbc..82ce7ebe42e 100644 --- a/cirq-core/cirq/ops/clifford_gate.py +++ b/cirq-core/cirq/ops/clifford_gate.py @@ -400,7 +400,11 @@ def _has_stabilizer_effect_(self) -> Optional[bool]: # By definition, Clifford Gate should always return True. return True - def __pow__(self, exponent) -> 'CliffordGate': + def __pow__(self, exponent: float) -> 'CliffordGate': + if exponent != int(exponent): + return NotImplemented + exponent = int(exponent) + if exponent == -1: return CliffordGate.from_clifford_tableau(self.clifford_tableau.inverse()) if exponent == 0: @@ -409,18 +413,24 @@ def __pow__(self, exponent) -> 'CliffordGate': ) if exponent == 1: return self - if exponent > 0 and int(exponent) == exponent: - base_tableau = self.clifford_tableau.copy() - for _ in range(int(exponent) - 1): - base_tableau = base_tableau.then(self.clifford_tableau) - return CliffordGate.from_clifford_tableau(base_tableau) - if exponent < 0 and int(exponent) == exponent: - base_tableau = self.clifford_tableau.copy() - for _ in range(int(-exponent) - 1): - base_tableau = base_tableau.then(self.clifford_tableau) - return CliffordGate.from_clifford_tableau(base_tableau.inverse()) - return NotImplemented + base_tableau = self.clifford_tableau.copy() + if exponent < 0: + base_tableau = base_tableau.inverse() + exponent = abs(exponent) + + # https://cp-algorithms.com/algebra/binary-exp.html + aux = qis.CliffordTableau( + num_qubits=self.clifford_tableau.n + ) # this tableau collects the odd terms + while exponent > 1: + if exponent & 1: + aux = aux.then(base_tableau) + base_tableau = base_tableau.then(base_tableau) + exponent >>= 1 + + base_tableau = base_tableau.then(aux) + return CliffordGate.from_clifford_tableau(base_tableau) def __repr__(self) -> str: return f"Clifford Gate with Tableau:\n {self.clifford_tableau._str_full_()}" diff --git a/cirq-core/cirq/qis/clifford_tableau.py b/cirq-core/cirq/qis/clifford_tableau.py index e652c669043..4130436509b 100644 --- a/cirq-core/cirq/qis/clifford_tableau.py +++ b/cirq-core/cirq/qis/clifford_tableau.py @@ -129,7 +129,9 @@ def apply_global_phase(self, coefficient: linear_dict.Scalar): class CliffordTableau(StabilizerState): """Tableau representation of a stabilizer state - (based on Aaronson and Gottesman 2006). + + References: + - [Aaronson and Gottesman](https://arxiv.org/abs/quant-ph/0406196) The tableau stores the stabilizer generators of the state using three binary arrays: xs, zs, and rs.