@@ -49,6 +49,13 @@ def __init__(
4949 self ._extra_qir : List [Dict [str , Any ]] = []
5050 self .is_mps = False
5151
52+ self .circuit_param = {
53+ "nqubits" : nqubits ,
54+ "k" : k ,
55+ "filled" : filled ,
56+ "inputs" : inputs ,
57+ }
58+
5259 # Mapping helpers
5360 # TC uses qubit 0 as the leftmost (highest) bit
5461 # So qubit i corresponds to bit position (n-1-i) in the state integer
@@ -192,32 +199,6 @@ def _apply_iswap(self, i: int, j: int, theta: Any) -> None:
192199 cos_t * self ._state + isin_t * swapped_state
193200 )
194201
195- def _apply_fsim (self , i : int , j : int , theta : Any , phi : Any ) -> None :
196- """Apply fSim(theta, phi): fermionic simulation gate."""
197- bpi , bpj = self ._bit_position (i ), self ._bit_position (j )
198- mask_i = 1 << bpi
199- mask_j = 1 << bpj
200- bi = backend .right_shift (backend .bitwise_and (self ._basis_tensor , mask_i ), bpi )
201- bj = backend .right_shift (backend .bitwise_and (self ._basis_tensor , mask_j ), bpj )
202- diff = backend .bitwise_xor (bi , bj )
203- mask_swap = (1 << bpi ) | (1 << bpj )
204- new_basis = backend .bitwise_xor (self ._basis_tensor , diff * mask_swap )
205- indices = backend .searchsorted (self ._basis_tensor , new_basis )
206-
207- theta_c = backend .cast (backend .convert_to_tensor (theta ), dtypestr )
208- phi_c = backend .cast (backend .convert_to_tensor (phi ), dtypestr )
209- both_on = backend .cast (backend .bitwise_and (bi , bj ), dtypestr )
210- phi_factor = 1.0 + (backend .exp (- 1j * phi_c ) - 1.0 ) * both_on
211-
212- cos_theta = backend .cos (theta_c )
213- isin_theta = 1j * backend .sin (theta_c )
214- diff_f = backend .cast (diff , dtypestr )
215- swapped_state = backend .gather1d (self ._state , indices )
216-
217- self ._state = (1.0 - diff_f ) * self ._state * phi_factor + diff_f * (
218- cos_theta * self ._state - isin_theta * swapped_state
219- )
220-
221202 # -------------------------------------------------------------------------
222203 # Public gate methods (delegate to internal implementations)
223204 # -------------------------------------------------------------------------
@@ -227,16 +208,24 @@ def apply_general_gate(
227208 gate : Any ,
228209 * index : int ,
229210 name : Optional [str ] = None ,
211+ split : Optional [Dict [str , Any ]] = None ,
212+ mpo : bool = False ,
213+ ir_dict : Optional [Dict [str , Any ]] = None ,
230214 ** kwargs : Any ,
231215 ) -> None :
232216 """
233217 Apply a gate by name. Called by _meta_apply generated methods.
234218
235219 :param gate: Gate tensor (ignored, dispatch is by name)
236220 :param index: Qubit indices
237- :param name: Gate name (rz, rzz, cz, cphase, swap, iswap, fsim)
238- :param kwargs: May contain ir_dict with parameters from _meta_apply
221+ :param name: Gate name (rz, rzz, cz, cphase, swap, iswap)
222+ :param split: Split configuration (ignored in U1Circuit)
223+ :param mpo: MPO flag (ignored in U1Circuit)
224+ :param ir_dict: QIR dictionary for recording
225+ :param kwargs: Extra parameters
239226 """
227+ if name is None :
228+ name = ""
240229 non_u1 = {"x" , "y" , "h" , "t" , "s" , "td" , "sd" , "rx" , "ry" }
241230 if name and name .lower () in non_u1 :
242231 raise ValueError (
@@ -246,7 +235,28 @@ def apply_general_gate(
246235 gate_name = name .lower () if name else None
247236
248237 # Extract parameters: _meta_apply puts them in ir_dict['parameters']
249- params = kwargs .get ("ir_dict" , {}).get ("parameters" , kwargs )
238+ # Also check kwargs for direct calls
239+ params = {}
240+ if ir_dict is not None and "parameters" in ir_dict :
241+ params .update (ir_dict ["parameters" ])
242+ params .update (kwargs )
243+
244+ # Record gate in QIR
245+ gate_dict = {
246+ "gate" : gate ,
247+ "index" : index ,
248+ "name" : name ,
249+ "split" : split ,
250+ "mpo" : mpo ,
251+ }
252+ if params :
253+ gate_dict ["parameters" ] = params
254+
255+ if ir_dict is not None :
256+ ir_dict .update (gate_dict )
257+ else :
258+ ir_dict = gate_dict
259+ self ._qir .append (ir_dict )
250260
251261 if gate_name == "rz" :
252262 self ._apply_rz (index [0 ], params .get ("theta" , 0 ))
@@ -260,23 +270,16 @@ def apply_general_gate(
260270 self ._apply_swap (index [0 ], index [1 ])
261271 elif gate_name == "iswap" :
262272 self ._apply_iswap (index [0 ], index [1 ], params .get ("theta" , 1.0 ))
263- elif gate_name == "fsim" :
264- self ._apply_fsim (
265- index [0 ], index [1 ], params .get ("theta" , 0 ), params .get ("phi" , 0 )
266- )
273+ elif gate_name == "cphase" :
274+ self ._apply_cphase (index [0 ], index [1 ], params .get ("theta" , 0 ))
267275 else :
268276 raise ValueError (
269277 f"Gate { name } not implemented in U1Circuit. "
270- "Supported: rz, rzz, cz, cphase, swap, iswap, fsim ."
278+ "Supported: rz, rzz, cz, cphase, swap, iswap."
271279 )
272280
273281 # Note: Most gate methods (rz, rzz, cz, swap, iswap, cphase, etc.) are
274282 # auto-generated by _meta_apply() which calls apply_general_gate.
275- # fsim is not in the standard gate list, so we define it explicitly.
276-
277- def fsim (self , i : int , j : int , theta : Any = 0 , phi : Any = 0 , ** kwargs : Any ) -> None :
278- """Apply fSim gate on qubits i and j."""
279- self ._apply_fsim (i , j , theta , phi )
280283
281284 # -------------------------------------------------------------------------
282285 # State and expectation methods
@@ -585,5 +588,3 @@ def measure(
585588
586589# Register gates via _meta_apply
587590U1Circuit ._meta_apply ()
588-
589- # TODO(@refraction-ray): qir support
0 commit comments