@@ -60,6 +60,11 @@ def __init__(
6060 ``max_singular_values`` and ``max_truncation_err``.
6161 :type split: Optional[Dict[str, Any]]
6262 """
63+ super ().__init__ (
64+ nqubits = nqubits , inputs = inputs , mps_inputs = mps_inputs , split = split
65+ )
66+ self .calibrations = []
67+
6368 self .inputs = inputs
6469 self .mps_inputs = mps_inputs
6570 self .split = split
@@ -111,6 +116,43 @@ def __init__(
111116 # self._qcode += str(self._nqubits) + "\n"
112117 self ._qir : List [Dict [str , Any ]] = []
113118 self ._extra_qir : List [Dict [str , Any ]] = []
119+
120+ def add_calibration (
121+ self , name : str , parameters : List [str ], instructions : List [Dict ]
122+ ) -> None :
123+ self .calibrations .append ({
124+ "name" : name ,
125+ "parameters" : parameters ,
126+ "instructions" : instructions
127+ })
128+
129+
130+ def to_tqasm (self ) -> str :
131+ qasm_lines = []
132+ qasm_lines .append ("OPENQASM 3;" )
133+ qasm_lines .append (f"qubit[{ self ._nqubits } ] q;" )
134+
135+ for gate in self ._qir :
136+ gname = gate ["name" ]
137+ targets = ", " .join (f"q[{ i } ]" for i in gate ["target" ])
138+ qasm_lines .append (f"{ gname } { targets } ;" )
139+
140+ for cal in getattr (self , "calibrations" , []):
141+ pname = ", " .join (cal ["parameters" ])
142+ qasm_lines .append (f"\n defcal { cal ['name' ]} ({ pname } ) {{" )
143+ for inst in cal ["instructions" ]:
144+ if inst ["type" ] == "frame" :
145+ qasm_lines .append (f" frame { inst ['frame' ]} = newframe({ inst ['qubit' ]} );" )
146+ elif inst ["type" ] == "play" :
147+ args_str = ", " .join (str (x ) for x in inst ["args" ])
148+ wf_type = inst ["waveform_type" ]
149+ qasm_lines .append (f" play({ inst ['frame' ]} , { wf_type } ({ args_str } ));" )
150+ qasm_lines .append ("}" )
151+
152+ return "\n " .join (qasm_lines )
153+
154+ def calibrate (self , name : str , parameters : List ["Param" ]) -> "DefcalBuilder" :
155+ return DefcalBuilder (self , name , parameters )
114156
115157 def replace_mps_inputs (self , mps_inputs : QuOperator ) -> None :
116158 """
@@ -998,3 +1040,46 @@ def expectation(
9981040 else :
9991041 den = 1.0
10001042 return num / den
1043+
1044+ class Param :
1045+ def __init__ (self , name : str ):
1046+ self .name = name
1047+
1048+ class DefcalBuilder :
1049+ def __init__ (self , circuit , name : str , parameters : List ["Param" ]):
1050+ self .circuit = circuit
1051+ self .name = name
1052+ self .parameters = parameters
1053+ self .instructions = []
1054+
1055+ def new_frame (self , frame_name : str , param : "Param" ):
1056+ self .instructions .append ({
1057+ "type" : "frame" ,
1058+ "frame" : frame_name ,
1059+ "qubit" : param .name ,
1060+ })
1061+ return self
1062+
1063+ def play (self , frame_name : str , waveform : Any , start_time : int = None ):
1064+ if not hasattr (waveform , "__dataclass_fields__" ):
1065+ raise TypeError ("Unsupported waveform type" )
1066+
1067+ waveform_type = waveform .qasm_name ()
1068+ args = list (waveform .__dict__ .values ())
1069+ if start_time is not None :
1070+ args = [start_time ] + args
1071+
1072+ self .instructions .append ({
1073+ "type" : "play" ,
1074+ "frame" : frame_name ,
1075+ "waveform_type" : waveform_type ,
1076+ "args" : args ,
1077+ })
1078+ return self
1079+
1080+ def build (self ):
1081+ self .circuit .add_calibration (
1082+ name = self .name ,
1083+ parameters = [p .name for p in self .parameters ],
1084+ instructions = self .instructions ,
1085+ )
0 commit comments