Skip to content

Commit 69e3de1

Browse files
Optimize Clifford.__pow__ by using binary exponentiation (#6581)
1 parent 3080d93 commit 69e3de1

File tree

2 files changed

+25
-13
lines changed

2 files changed

+25
-13
lines changed

cirq-core/cirq/ops/clifford_gate.py

+22-12
Original file line numberDiff line numberDiff line change
@@ -400,7 +400,11 @@ def _has_stabilizer_effect_(self) -> Optional[bool]:
400400
# By definition, Clifford Gate should always return True.
401401
return True
402402

403-
def __pow__(self, exponent) -> 'CliffordGate':
403+
def __pow__(self, exponent: float) -> 'CliffordGate':
404+
if exponent != int(exponent):
405+
return NotImplemented
406+
exponent = int(exponent)
407+
404408
if exponent == -1:
405409
return CliffordGate.from_clifford_tableau(self.clifford_tableau.inverse())
406410
if exponent == 0:
@@ -409,18 +413,24 @@ def __pow__(self, exponent) -> 'CliffordGate':
409413
)
410414
if exponent == 1:
411415
return self
412-
if exponent > 0 and int(exponent) == exponent:
413-
base_tableau = self.clifford_tableau.copy()
414-
for _ in range(int(exponent) - 1):
415-
base_tableau = base_tableau.then(self.clifford_tableau)
416-
return CliffordGate.from_clifford_tableau(base_tableau)
417-
if exponent < 0 and int(exponent) == exponent:
418-
base_tableau = self.clifford_tableau.copy()
419-
for _ in range(int(-exponent) - 1):
420-
base_tableau = base_tableau.then(self.clifford_tableau)
421-
return CliffordGate.from_clifford_tableau(base_tableau.inverse())
422416

423-
return NotImplemented
417+
base_tableau = self.clifford_tableau.copy()
418+
if exponent < 0:
419+
base_tableau = base_tableau.inverse()
420+
exponent = abs(exponent)
421+
422+
# https://cp-algorithms.com/algebra/binary-exp.html
423+
aux = qis.CliffordTableau(
424+
num_qubits=self.clifford_tableau.n
425+
) # this tableau collects the odd terms
426+
while exponent > 1:
427+
if exponent & 1:
428+
aux = aux.then(base_tableau)
429+
base_tableau = base_tableau.then(base_tableau)
430+
exponent >>= 1
431+
432+
base_tableau = base_tableau.then(aux)
433+
return CliffordGate.from_clifford_tableau(base_tableau)
424434

425435
def __repr__(self) -> str:
426436
return f"Clifford Gate with Tableau:\n {self.clifford_tableau._str_full_()}"

cirq-core/cirq/qis/clifford_tableau.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,9 @@ def apply_global_phase(self, coefficient: linear_dict.Scalar):
129129

130130
class CliffordTableau(StabilizerState):
131131
"""Tableau representation of a stabilizer state
132-
(based on Aaronson and Gottesman 2006).
132+
133+
References:
134+
- [Aaronson and Gottesman](https://arxiv.org/abs/quant-ph/0406196)
133135
134136
The tableau stores the stabilizer generators of
135137
the state using three binary arrays: xs, zs, and rs.

0 commit comments

Comments
 (0)