Skip to content

Commit

Permalink
Add ActOnCliffordTableauArgs. Support it in _act_on_ for common gates…
Browse files Browse the repository at this point in the history
… and measurements. (#3063)

#2948 #2423
  • Loading branch information
smitsanghavi committed Jul 14, 2020
1 parent adc8964 commit fb9fbac
Show file tree
Hide file tree
Showing 16 changed files with 823 additions and 35 deletions.
1 change: 1 addition & 0 deletions cirq/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,7 @@
)

from cirq.sim import (
ActOnCliffordTableauArgs,
ActOnStateVectorArgs,
StabilizerStateChForm,
CIRCUIT_LIKE,
Expand Down
128 changes: 126 additions & 2 deletions cirq/ops/common_gates.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,27 @@ def _apply_unitary_(self, args: 'protocols.ApplyUnitaryArgs'
args.available_buffer *= p
return args.available_buffer

def _act_on_(self, args: Any):
from cirq.sim import clifford

if isinstance(args, clifford.ActOnCliffordTableauArgs):
if protocols.is_parameterized(self) or self.exponent % 0.5 != 0:
return NotImplemented
tableau = args.tableau
q = args.axes[0]
effective_exponent = self._exponent % 2
if effective_exponent == 0.5:
tableau.xs[:, q] ^= tableau.zs[:, q]
tableau.rs[:] ^= (tableau.xs[:, q] & tableau.zs[:, q])
elif effective_exponent == 1:
tableau.rs[:] ^= tableau.zs[:, q]
elif effective_exponent == 1.5:
tableau.rs[:] ^= tableau.xs[:, q] & tableau.zs[:, q]
tableau.xs[:, q] ^= tableau.zs[:, q]
return True

return NotImplemented

def in_su2(self) -> 'XPowGate':
"""Returns an equal-up-global-phase gate from the group SU2."""
return XPowGate(exponent=self._exponent, global_shift=-0.5)
Expand Down Expand Up @@ -279,6 +300,29 @@ def _apply_unitary_(self, args: 'protocols.ApplyUnitaryArgs'
args.available_buffer *= p
return args.available_buffer

def _act_on_(self, args: Any):
from cirq.sim import clifford

if isinstance(args, clifford.ActOnCliffordTableauArgs):
if protocols.is_parameterized(self) or self.exponent % 0.5 != 0:
return NotImplemented
tableau = args.tableau
q = args.axes[0]
effective_exponent = self._exponent % 2
if effective_exponent == 0.5:
tableau.rs[:] ^= (tableau.xs[:, q] & (~tableau.zs[:, q]))
(tableau.xs[:, q], tableau.zs[:, q]) = (tableau.zs[:, q].copy(),
tableau.xs[:, q].copy())
elif effective_exponent == 1:
tableau.rs[:] ^= tableau.xs[:, q] ^ tableau.zs[:, q]
elif effective_exponent == 1.5:
tableau.rs[:] ^= (~(tableau.xs[:, q]) & tableau.zs[:, q])
(tableau.xs[:, q], tableau.zs[:, q]) = (tableau.zs[:, q].copy(),
tableau.xs[:, q].copy())
return True

return NotImplemented

def in_su2(self) -> 'YPowGate':
"""Returns an equal-up-global-phase gate from the group SU2."""
return YPowGate(exponent=self._exponent, global_shift=-0.5)
Expand Down Expand Up @@ -425,6 +469,27 @@ def _apply_unitary_(self, args: 'protocols.ApplyUnitaryArgs'
args.target_tensor *= p
return args.target_tensor

def _act_on_(self, args: Any):
from cirq.sim import clifford

if isinstance(args, clifford.ActOnCliffordTableauArgs):
if protocols.is_parameterized(self) or self.exponent % 0.5 != 0:
return NotImplemented
tableau = args.tableau
q = args.axes[0]
effective_exponent = self._exponent % 2
if effective_exponent == 0.5:
tableau.rs[:] ^= (tableau.xs[:, q] & tableau.zs[:, q])
tableau.zs[:, q] ^= tableau.xs[:, q]
elif effective_exponent == 1:
tableau.rs[:] ^= tableau.xs[:, q]
elif effective_exponent == 1.5:
tableau.rs[:] ^= tableau.xs[:, q] & (~tableau.zs[:, q])
tableau.zs[:, q] ^= tableau.xs[:, q]
return True

return NotImplemented

def _decompose_into_clifford_with_qubits_(self, qubits):
from cirq.ops.clifford_gate import SingleQubitCliffordGate
if self.exponent % 2 == 0:
Expand Down Expand Up @@ -685,6 +750,24 @@ def _apply_unitary_(self, args: 'protocols.ApplyUnitaryArgs'
args.target_tensor *= np.sqrt(2) * p
return args.target_tensor

def _act_on_(self, args: Any):
from cirq.sim import clifford

if isinstance(args, clifford.ActOnCliffordTableauArgs):
if protocols.is_parameterized(self) or self.exponent % 0.5 != 0:
return NotImplemented
tableau = args.tableau
q = args.axes[0]
if self._exponent % 1 != 0:
return NotImplemented
if self._exponent % 2 == 1:
(tableau.xs[:, q], tableau.zs[:, q]) = (tableau.zs[:, q].copy(),
tableau.xs[:, q].copy())
tableau.rs[:] ^= (tableau.xs[:, q] & tableau.zs[:, q])
return True

return NotImplemented

def _decompose_(self, qubits):
q = qubits[0]

Expand Down Expand Up @@ -792,6 +875,30 @@ def _apply_unitary_(self, args: 'protocols.ApplyUnitaryArgs'
args.target_tensor *= p
return args.target_tensor

def _act_on_(self, args: Any):
from cirq.sim import clifford

if isinstance(args, clifford.ActOnCliffordTableauArgs):
if protocols.is_parameterized(self) or self.exponent % 1 != 0:
return NotImplemented
tableau = args.tableau
q1 = args.axes[0]
q2 = args.axes[1]
if self._exponent % 2 == 1:
(tableau.xs[:, q2], tableau.zs[:, q2]) = \
(tableau.zs[:, q2].copy(), tableau.xs[:, q2].copy())
tableau.rs[:] ^= tableau.xs[:,q1] & tableau.zs[:,q2] & \
(tableau.xs[:,q2] ^ tableau.zs[:,q1])
tableau.xs[:, q2] ^= tableau.xs[:, q1]
tableau.zs[:, q1] ^= tableau.zs[:, q2]
(tableau.xs[:, q2],
tableau.zs[:, q2]) = (tableau.zs[:, q2].copy(),
tableau.xs[:, q2].copy())
tableau.rs[:] ^= (tableau.xs[:, q2] & tableau.zs[:, q2])
return True

return NotImplemented

def _pauli_expansion_(self) -> value.LinearDict[str]:
if protocols.is_parameterized(self):
return NotImplemented
Expand Down Expand Up @@ -858,8 +965,7 @@ def controlled(self,
def _circuit_diagram_info_(self, args: 'cirq.CircuitDiagramInfoArgs'
) -> 'cirq.CircuitDiagramInfo':
return protocols.CircuitDiagramInfo(
wire_symbols=('@', '@'),
exponent=self._diagram_exponent(args))
wire_symbols=('@', '@'), exponent=self._diagram_exponent(args))

def _qasm_(self, args: 'cirq.QasmArgs',
qubits: Tuple['cirq.Qid', ...]) -> Optional[str]:
Expand Down Expand Up @@ -973,6 +1079,24 @@ def _apply_unitary_(self, args: 'protocols.ApplyUnitaryArgs'
args.target_tensor *= p
return args.target_tensor

def _act_on_(self, args: Any):
from cirq.sim import clifford

if isinstance(args, clifford.ActOnCliffordTableauArgs):
if protocols.is_parameterized(self) or self.exponent % 1 != 0:
return NotImplemented
tableau = args.tableau
q1 = args.axes[0]
q2 = args.axes[1]
if self._exponent % 2 == 1:
tableau.rs[:] ^= (tableau.xs[:, q1] & tableau.zs[:, q2] &
(~(tableau.xs[:, q2] ^ tableau.zs[:, q1])))
tableau.xs[:, q2] ^= tableau.xs[:, q1]
tableau.zs[:, q1] ^= tableau.zs[:, q2]
return True

return NotImplemented

def _pauli_expansion_(self) -> value.LinearDict[str]:
if protocols.is_parameterized(self):
return NotImplemented
Expand Down

0 comments on commit fb9fbac

Please sign in to comment.