@@ -31,14 +31,18 @@ class StabilizerCircuit(AbstractCircuit):
3131 "sd" : "S_DAG" ,
3232 }
3333
34- def __init__ (self , nqubits : int , inputs : Tensor = None ) -> None :
34+ def __init__ (
35+ self , nqubits : int , inputs : Tensor = None , tableau_inputs : Tensor = None
36+ ) -> None :
3537 """
3638 ``StabilizerCircuit`` class based on stim package
3739
3840 :param nqubits: Number of qubits
3941 :type nqubits: int
4042 :param inputs: initial state by stabilizers, defaults to None
4143 :type inputs: Tensor, optional
44+ :param tableau_inputs: initial state by **inverse** tableau, defaults to None
45+ :type tableau_inputs: Tensor, optional
4246 """
4347 self ._nqubits = nqubits
4448 self ._stim_circuit = stim .Circuit ()
@@ -49,6 +53,8 @@ def __init__(self, nqubits: int, inputs: Tensor = None) -> None:
4953 self .current_sim = stim .TableauSimulator ()
5054 if inputs :
5155 self .current_sim .set_state_from_stabilizers (inputs )
56+ if tableau_inputs :
57+ self .current_sim .set_inverse_tableau (tableau_inputs )
5258
5359 def apply_general_gate (
5460 self ,
@@ -123,6 +129,22 @@ def random_gate(self, *index: int, recorded: bool = False) -> None:
123129 if recorded :
124130 self ._stim_circuit += t .to_circuit ()
125131
132+ def tableau_gate (self , * index : int , tableau : Any , recorded : bool = False ) -> None :
133+ """
134+ Apply a gate indicated by tableau to the circuit.
135+ This operation will not record in qir
136+
137+ :param index: Qubit indices to apply the gate to
138+ :type index: int
139+ :param tableau: stim.Tableau representation of the gate
140+ :type tableau: Any
141+ :param recorded: Whether the gate is recorded in ``stim.Circuit``, defaults to False
142+ :type recorded: bool, optional
143+ """
144+ self .current_sim .do_tableau (tableau , index )
145+ if recorded :
146+ self ._stim_circuit += tableau .to_circuit ()
147+
126148 def measure (self , * index : int , with_prob : bool = False ) -> Tensor :
127149 """
128150 Measure qubits in Z basis.
@@ -167,6 +189,27 @@ def cond_measurement(self, index: int) -> Tensor:
167189
168190 cond_measure = cond_measurement
169191
192+ def cond_measure_many (self , * index : int ) -> Tensor :
193+ """
194+ Measure qubits in Z basis with state collapse.
195+
196+ :param index: Index of qubit to measure
197+ :type index: int
198+ :return: Measurement results and probability (if with_prob=True)
199+ :rtype: Union[np.ndarray, Tuple[np.ndarray, float]]
200+ """
201+ # Convert negative indices
202+
203+ # Add measurement instructions
204+ self ._stim_circuit .append_from_stim_program_text (
205+ "M " + " " .join (map (str , index ))
206+ )
207+ # self.current_sim = None
208+ m = self .current_simulator ().measure_many (* index )
209+ # Sample once from the circuit using sampler
210+
211+ return m
212+
170213 def sample (
171214 self ,
172215 batch : Optional [int ] = None ,
@@ -346,6 +389,12 @@ def current_tableau(self) -> stim.Tableau:
346389 """
347390 return self .current_simulator ().current_inverse_tableau () ** - 1
348391
392+ def current_inverse_tableau (self ) -> stim .Tableau :
393+ """
394+ Return the current inverse tableau of the circuit.
395+ """
396+ return self .current_simulator ().current_inverse_tableau ()
397+
349398 def entanglement_entropy (self , cut : Sequence [int ]) -> float :
350399 """
351400 Calculate the entanglement entropy for a subset of qubits using stabilizer formalism.
0 commit comments