"""24 Unique single-qubit Clifford gates and their multiplications, conjugations and Pauli conjugations."""from__future__importannotationsimportcopyimportmathfromenumimportEnumfromtypingimportTYPE_CHECKING,Anyimportnumpyasnpimporttyping_extensionsfromgraphix._dbimport(CLIFFORD,CLIFFORD_CONJ,CLIFFORD_HSZ_DECOMPOSITION,CLIFFORD_LABEL,CLIFFORD_MEASURE,CLIFFORD_MUL,CLIFFORD_TO_QASM3,)fromgraphix.fundamentalsimportIXYZ,ComplexUnitfromgraphix.measurementsimportDomainsfromgraphix.pauliimportPauliifTYPE_CHECKING:importnumpy.typingasnpt
[docs]classClifford(Enum):"""Clifford gate."""# MEMO: Cannot use ClassVar hereI:CliffordX:CliffordY:CliffordZ:CliffordS:CliffordSDG:CliffordH:Clifford_0=0_1=1_2=2_3=3_4=4_5=5_6=6_7=7_8=8_9=9_10=10_11=11_12=12_13=13_14=14_15=15_16=16_17=17_18=18_19=19_20=20_21=21_22=22_23=23@propertydefmatrix(self)->npt.NDArray[np.complex128]:"""Return the matrix of the Clifford gate."""returnCLIFFORD[self.value]@staticmethoddeftry_from_matrix(mat:npt.NDArray[Any])->Clifford|None:"""Find the Clifford gate from the matrix. Return `None` if not found. Notes ----- Global phase is ignored. """ifmat.shape!=(2,2):returnNoneforciinClifford:mi=ci.matrixforpiv,piv_inzip(mat.flat,mi.flat):ifmath.isclose(abs(piv),0):continueifmath.isclose(abs(piv_),0):continueifnp.allclose(mat/piv,mi/piv_):returncireturnNonedef__repr__(self)->str:"""Return the Clifford expression on the form of HSZ decomposition."""formula=" @ ".join([f"Clifford.{gate}"forgateinself.hsz])iflen(self.hsz)==1:returnformulareturnf"({formula})"def__str__(self)->str:"""Return the name of the Clifford gate."""returnCLIFFORD_LABEL[self.value]@propertydefconj(self)->Clifford:"""Return the conjugate of the Clifford gate."""returnClifford(CLIFFORD_CONJ[self.value])@propertydefhsz(self)->list[Clifford]:"""Return a decomposition of the Clifford gate with the gates `H`, `S`, `Z`."""return[Clifford(i)foriinCLIFFORD_HSZ_DECOMPOSITION[self.value]]@propertydefqasm3(self)->tuple[str,...]:"""Return a decomposition of the Clifford gate as qasm3 gates."""returnCLIFFORD_TO_QASM3[self.value]def__matmul__(self,other:Clifford)->Clifford:"""Multiplication within the Clifford group (modulo unit factor)."""ifisinstance(other,Clifford):returnClifford(CLIFFORD_MUL[self.value][other.value])returnNotImplementeddefmeasure(self,pauli:Pauli)->Pauli:"""Compute C† P C."""ifpauli.symbol==IXYZ.I:returncopy.deepcopy(pauli)table=CLIFFORD_MEASURE[self.value]ifpauli.symbol==IXYZ.X:symbol,sign=table.xelifpauli.symbol==IXYZ.Y:symbol,sign=table.yelifpauli.symbol==IXYZ.Z:symbol,sign=table.zelse:typing_extensions.assert_never(pauli.symbol)returnpauli.unit*Pauli(symbol,ComplexUnit.from_properties(sign=sign))defcommute_domains(self,domains:Domains)->Domains:""" Commute `X^sZ^t` with `C`. Given `X^sZ^t`, return `X^s'Z^t'` such that `X^sZ^tC = CX^s'Z^t'`. Note that applying the method to `self.conj` computes the reverse commutation: indeed, `C†X^sZ^t = (X^sZ^tC)† = (CX^s'Z^t')† = X^s'Z^t'C†`. """s_domain=domains.s_domain.copy()t_domain=domains.t_domain.copy()forgateinself.hsz:ifgate==Clifford.I:passelifgate==Clifford.H:t_domain,s_domain=s_domain,t_domainelifgate==Clifford.S:t_domain^=s_domainelifgate==Clifford.Z:passelse:# pragma: no coverraiseRuntimeError(f"{gate} should be either I, H, S or Z.")returnDomains(s_domain,t_domain)