"""Data validator command classes."""from__future__importannotationsimportdataclassesimportenumimportsysfromenumimportEnumfromtypingimportClassVar,Literal,Unionimportnumpyasnpfromgraphiximportutilsfromgraphix.cliffordimportCliffordfromgraphix.fundamentalsimportPlane,Signfromgraphix.measurementsimportDomains# Ruff suggests to move this import to a type-checking block, but dataclass requires it herefromgraphix.parameterimportExpressionOrFloat# noqa: TC001fromgraphix.pauliimportPaulifromgraphix.statesimportBasicStates,StateNode=int
[docs]classCommandKind(Enum):"""Tag for command kind."""N=enum.auto()M=enum.auto()E=enum.auto()C=enum.auto()X=enum.auto()Z=enum.auto()S=enum.auto()T=enum.auto()
class_KindChecker:"""Enforce tag field declaration."""def__init_subclass__(cls)->None:super().__init_subclass__()utils.check_kind(cls,{"CommandKind":CommandKind,"Clifford":Clifford})
[docs]@dataclasses.dataclassclassM(_KindChecker):"""Measurement command. By default the plane is set to 'XY', the angle to 0, empty domains and identity vop."""node:Nodeplane:Plane=Plane.XYangle:ExpressionOrFloat=0.0s_domain:set[Node]=dataclasses.field(default_factory=set)t_domain:set[Node]=dataclasses.field(default_factory=set)kind:ClassVar[Literal[CommandKind.M]]=dataclasses.field(default=CommandKind.M,init=False)defclifford(self,clifford_gate:Clifford)->M:"""Apply a Clifford gate to the measure command. The returned `M` command is equivalent to the pattern `MC`. """domains=clifford_gate.commute_domains(Domains(self.s_domain,self.t_domain))update=MeasureUpdate.compute(self.plane,False,False,clifford_gate)returnM(self.node,update.new_plane,self.angle*update.coeff+update.add_term/np.pi,domains.s_domain,domains.t_domain,)
[docs]@dataclasses.dataclassclassMeasureUpdate:"""Describe how a measure is changed by the signals and/or a vertex operator."""new_plane:Planecoeff:intadd_term:float@staticmethoddefcompute(plane:Plane,s:bool,t:bool,clifford_gate:Clifford)->MeasureUpdate:"""Compute the update for a given plane, signals and vertex operator."""gates=list(map(Pauli.from_axis,plane.axes))ifs:clifford_gate=Clifford.X@clifford_gateift:clifford_gate=Clifford.Z@clifford_gategates=list(map(clifford_gate.measure,gates))new_plane=Plane.from_axes(*(gate.axisforgateingates))cos_pauli=clifford_gate.measure(Pauli.from_axis(plane.cos))sin_pauli=clifford_gate.measure(Pauli.from_axis(plane.sin))exchange=cos_pauli.axis!=new_plane.coscoeff=-1ifexchange==(cos_pauli.unit.sign==sin_pauli.unit.sign)else1add_term:float=0ifcos_pauli.unit.sign==Sign.MINUS:add_term+=np.piifexchange:add_term=np.pi/2-add_termreturnMeasureUpdate(new_plane,coeff,add_term)