1+
2+ std::string to_qasm3 (void ) {
3+ add_pending_control_flow_op ();
4+
5+ std::stringstream qasm3;
6+ qasm3 << std::setprecision (18 );
7+ qasm3 << " OPENQASM 3.0;" << std::endl;
8+ qasm3 << " include \" stdgates.inc\" ;" << std::endl;
9+
10+ auto name_map = get_standard_gate_name_mapping ();
11+ // add header for non-standard gates
12+ bool cs = false ;
13+ bool sxdg = false ;
14+ QkOpCounts opcounts = qk_circuit_count_ops (rust_circuit_.get ());
15+ for (int i = 0 ; i < opcounts.len ; i++) {
16+ if (opcounts.data [i].count != 0 ) {
17+ auto op = name_map[opcounts.data [i].name ].gate_map ();
18+ switch (op) {
19+ case QkGate_R:
20+ qasm3 << " gate r(p0, p1) _gate_q_0 {" << std::endl;
21+ qasm3 << " U(p0, -pi/2 + p1, pi/2 - p1) _gate_q_0;" << std::endl;
22+ qasm3 << " }" << std::endl;
23+ break ;
24+ case QkGate_SXdg:
25+ case QkGate_RYY:
26+ case QkGate_XXPlusYY:
27+ case QkGate_XXMinusYY:
28+ if (!sxdg) {
29+ qasm3 << " gate sxdg _gate_q_0 {" << std::endl;
30+ qasm3 << " s _gate_q_0;" << std::endl;
31+ qasm3 << " h _gate_q_0;" << std::endl;
32+ qasm3 << " s _gate_q_0;" << std::endl;
33+ qasm3 << " }" << std::endl;
34+ sxdg = true ;
35+ }
36+ if (op == QkGate_RYY) {
37+ qasm3 << " gate ryy(p0) _gate_q_0, _gate_q_1 {" << std::endl;
38+ qasm3 << " sxdg _gate_q_0;" << std::endl;
39+ qasm3 << " sxdg _gate_q_1;" << std::endl;
40+ qasm3 << " cx _gate_q_0, _gate_q_1;" << std::endl;
41+ qasm3 << " rz(p0) _gate_q_1;" << std::endl;
42+ qasm3 << " cx _gate_q_0, _gate_q_1;" << std::endl;
43+ qasm3 << " sx _gate_q_0;" << std::endl;
44+ qasm3 << " sx _gate_q_1;" << std::endl;
45+ qasm3 << " }" << std::endl;
46+ }
47+ if (op == QkGate_XXPlusYY) {
48+ qasm3 << " gate xx_plus_yy(p0, p1) _gate_q_0, _gate_q_1 {"
49+ << std::endl;
50+ qasm3 << " rz(p1) _gate_q_0;" << std::endl;
51+ qasm3 << " sdg _gate_q_1;" << std::endl;
52+ qasm3 << " sx _gate_q_1;" << std::endl;
53+ qasm3 << " s _gate_q_1;" << std::endl;
54+ qasm3 << " s _gate_q_0;" << std::endl;
55+ qasm3 << " cx _gate_q_1, _gate_q_0;" << std::endl;
56+ qasm3 << " ry((-0.5)*p0) _gate_q_1;" << std::endl;
57+ qasm3 << " ry((-0.5)*p0) _gate_q_0;" << std::endl;
58+ qasm3 << " cx _gate_q_1, _gate_q_0;" << std::endl;
59+ qasm3 << " sdg _gate_q_0;" << std::endl;
60+ qasm3 << " sdg _gate_q_1;" << std::endl;
61+ qasm3 << " sxdg _gate_q_1;" << std::endl;
62+ qasm3 << " s _gate_q_1;" << std::endl;
63+ qasm3 << " rz(-p1) _gate_q_0;" << std::endl;
64+ qasm3 << " }" << std::endl;
65+ }
66+ if (op == QkGate_XXMinusYY) {
67+ qasm3 << " gate xx_minus_yy(p0, p1) _gate_q_0, _gate_q_1 {"
68+ << std::endl;
69+ qasm3 << " rz(-p1) _gate_q_1;" << std::endl;
70+ qasm3 << " sdg _gate_q_0;" << std::endl;
71+ qasm3 << " sx _gate_q_0;" << std::endl;
72+ qasm3 << " s _gate_q_0;" << std::endl;
73+ qasm3 << " s _gate_q_1;" << std::endl;
74+ qasm3 << " cx _gate_q_0, _gate_q_1;" << std::endl;
75+ qasm3 << " ry(0.5*p0) _gate_q_0;" << std::endl;
76+ qasm3 << " ry((-0.5)*p0) _gate_q_1;" << std::endl;
77+ qasm3 << " cx _gate_q_0, _gate_q_1;" << std::endl;
78+ qasm3 << " sdg _gate_q_1;" << std::endl;
79+ qasm3 << " sdg _gate_q_0;" << std::endl;
80+ qasm3 << " sxdg _gate_q_0;" << std::endl;
81+ qasm3 << " s _gate_q_0;" << std::endl;
82+ qasm3 << " rz(p1) _gate_q_1;" << std::endl;
83+ qasm3 << " }" << std::endl;
84+ }
85+ break ;
86+ case QkGate_DCX:
87+ qasm3 << " gate dcx _gate_q_0, _gate_q_1 {" << std::endl;
88+ qasm3 << " cx _gate_q_0, _gate_q_1;" << std::endl;
89+ qasm3 << " cx _gate_q_1, _gate_q_0;" << std::endl;
90+ qasm3 << " }" << std::endl;
91+ break ;
92+ case QkGate_ECR:
93+ qasm3 << " gate ecr _gate_q_0, _gate_q_1 {" << std::endl;
94+ qasm3 << " s _gate_q_0;" << std::endl;
95+ qasm3 << " sx _gate_q_1;" << std::endl;
96+ qasm3 << " cx _gate_q_0, _gate_q_1;" << std::endl;
97+ qasm3 << " x _gate_q_0;" << std::endl;
98+ qasm3 << " }" << std::endl;
99+ break ;
100+ case QkGate_ISwap:
101+ qasm3 << " gate iswap _gate_q_0, _gate_q_1 {" << std::endl;
102+ qasm3 << " s _gate_q_0;" << std::endl;
103+ qasm3 << " s _gate_q_1;" << std::endl;
104+ qasm3 << " h _gate_q_0;" << std::endl;
105+ qasm3 << " cx _gate_q_0, _gate_q_1;" << std::endl;
106+ qasm3 << " cx _gate_q_1, _gate_q_0;" << std::endl;
107+ qasm3 << " h _gate_q_1;" << std::endl;
108+ qasm3 << " }" << std::endl;
109+ break ;
110+ case QkGate_CSX:
111+ case QkGate_CS:
112+ if (!cs) {
113+ qasm3 << " gate cs _gate_q_0, _gate_q_1 {" << std::endl;
114+ qasm3 << " t _gate_q_0;" << std::endl;
115+ qasm3 << " cx _gate_q_0, _gate_q_1;" << std::endl;
116+ qasm3 << " tdg _gate_q_1;" << std::endl;
117+ qasm3 << " cx _gate_q_0, _gate_q_1;" << std::endl;
118+ qasm3 << " t _gate_q_1;" << std::endl;
119+ qasm3 << " }" << std::endl;
120+ cs = true ;
121+ }
122+ if (op == QkGate_CSX) {
123+ qasm3 << " gate csx _gate_q_0, _gate_q_1 {" << std::endl;
124+ qasm3 << " h _gate_q_1;" << std::endl;
125+ qasm3 << " cs _gate_q_0, _gate_q_1;" << std::endl;
126+ qasm3 << " h _gate_q_1;" << std::endl;
127+ qasm3 << " }" << std::endl;
128+ }
129+ break ;
130+ case QkGate_CSdg:
131+ qasm3 << " gate csdg _gate_q_0, _gate_q_1 {" << std::endl;
132+ qasm3 << " tdg _gate_q_0;" << std::endl;
133+ qasm3 << " cx _gate_q_0, _gate_q_1;" << std::endl;
134+ qasm3 << " t _gate_q_1;" << std::endl;
135+ qasm3 << " cx _gate_q_0, _gate_q_1;" << std::endl;
136+ qasm3 << " tdg _gate_q_1;" << std::endl;
137+ qasm3 << " }" << std::endl;
138+ break ;
139+ case QkGate_CCZ:
140+ qasm3 << " gate ccz _gate_q_0, _gate_q_1, _gate_q_2 {" << std::endl;
141+ qasm3 << " h _gate_q_2;" << std::endl;
142+ qasm3 << " ccx _gate_q_0, _gate_q_1, _gate_q_2;" << std::endl;
143+ qasm3 << " h _gate_q_2;" << std::endl;
144+ qasm3 << " }" << std::endl;
145+ break ;
146+ case QkGate_RXX:
147+ qasm3 << " gate rxx(p0) _gate_q_0, _gate_q_1 {" << std::endl;
148+ qasm3 << " h _gate_q_0;" << std::endl;
149+ qasm3 << " h _gate_q_1;" << std::endl;
150+ qasm3 << " cx _gate_q_0, _gate_q_1;" << std::endl;
151+ qasm3 << " rz(p0) _gate_q_1;" << std::endl;
152+ qasm3 << " cx _gate_q_0, _gate_q_1;" << std::endl;
153+ qasm3 << " h _gate_q_1;" << std::endl;
154+ qasm3 << " h _gate_q_0;" << std::endl;
155+ qasm3 << " }" << std::endl;
156+ break ;
157+ case QkGate_RZX:
158+ qasm3 << " gate rzx(p0) _gate_q_0, _gate_q_1 {" << std::endl;
159+ qasm3 << " h _gate_q_1;" << std::endl;
160+ qasm3 << " cx _gate_q_0, _gate_q_1;" << std::endl;
161+ qasm3 << " rz(p0) _gate_q_1;" << std::endl;
162+ qasm3 << " cx _gate_q_0, _gate_q_1;" << std::endl;
163+ qasm3 << " h _gate_q_1;" << std::endl;
164+ qasm3 << " }" << std::endl;
165+ break ;
166+ case QkGate_RZZ:
167+ qasm3 << " gate rzz(p0) _gate_q_0, _gate_q_1 {" << std::endl;
168+ qasm3 << " cx _gate_q_0, _gate_q_1;" << std::endl;
169+ qasm3 << " rz(p0) _gate_q_1;" << std::endl;
170+ qasm3 << " cx _gate_q_0, _gate_q_1;" << std::endl;
171+ qasm3 << " }" << std::endl;
172+ break ;
173+ case QkGate_RCCX:
174+ qasm3 << " gate rccx _gate_q_0, _gate_q_1, _gate_q_2 {" << std::endl;
175+ qasm3 << " h _gate_q_2;" << std::endl;
176+ qasm3 << " t _gate_q_2;" << std::endl;
177+ qasm3 << " cx _gate_q_1, _gate_q_2;" << std::endl;
178+ qasm3 << " tdg _gate_q_2;" << std::endl;
179+ qasm3 << " cx _gate_q_0, _gate_q_2;" << std::endl;
180+ qasm3 << " t _gate_q_2;" << std::endl;
181+ qasm3 << " cx _gate_q_1, _gate_q_2;" << std::endl;
182+ qasm3 << " tdg _gate_q_2;" << std::endl;
183+ qasm3 << " h _gate_q_2;" << std::endl;
184+ qasm3 << " }" << std::endl;
185+ break ;
186+ case QkGate_C3X:
187+ qasm3 << " gate mcx _gate_q_0, _gate_q_1, _gate_q_2, _gate_q_3 {"
188+ << std::endl;
189+ qasm3 << " h _gate_q_3;" << std::endl;
190+ qasm3 << " p(pi/8) _gate_q_0;" << std::endl;
191+ qasm3 << " p(pi/8) _gate_q_1;" << std::endl;
192+ qasm3 << " p(pi/8) _gate_q_2;" << std::endl;
193+ qasm3 << " p(pi/8) _gate_q_3;" << std::endl;
194+ qasm3 << " cx _gate_q_0, _gate_q_1;" << std::endl;
195+ qasm3 << " p(-pi/8) _gate_q_1;" << std::endl;
196+ qasm3 << " cx _gate_q_0, _gate_q_1;" << std::endl;
197+ qasm3 << " cx _gate_q_1, _gate_q_2;" << std::endl;
198+ qasm3 << " p(-pi/8) _gate_q_2;" << std::endl;
199+ qasm3 << " cx _gate_q_0, _gate_q_2;" << std::endl;
200+ qasm3 << " p(pi/8) _gate_q_2;" << std::endl;
201+ qasm3 << " cx _gate_q_1, _gate_q_2;" << std::endl;
202+ qasm3 << " p(-pi/8) _gate_q_2;" << std::endl;
203+ qasm3 << " cx _gate_q_0, _gate_q_2;" << std::endl;
204+ qasm3 << " cx _gate_q_2, _gate_q_3;" << std::endl;
205+ qasm3 << " p(-pi/8) _gate_q_3;" << std::endl;
206+ qasm3 << " cx _gate_q_1, _gate_q_3;" << std::endl;
207+ qasm3 << " p(pi/8) _gate_q_3;" << std::endl;
208+ qasm3 << " cx _gate_q_2, _gate_q_3;" << std::endl;
209+ qasm3 << " p(-pi/8) _gate_q_3;" << std::endl;
210+ qasm3 << " cx _gate_q_0, _gate_q_3;" << std::endl;
211+ qasm3 << " p(pi/8) _gate_q_3;" << std::endl;
212+ qasm3 << " cx _gate_q_2, _gate_q_3;" << std::endl;
213+ qasm3 << " p(-pi/8) _gate_q_3;" << std::endl;
214+ qasm3 << " cx _gate_q_1, _gate_q_3;" << std::endl;
215+ qasm3 << " p(pi/8) _gate_q_3;" << std::endl;
216+ qasm3 << " cx _gate_q_2, _gate_q_3;" << std::endl;
217+ qasm3 << " p(-pi/8) _gate_q_3;" << std::endl;
218+ qasm3 << " cx _gate_q_0, _gate_q_3;" << std::endl;
219+ qasm3 << " h _gate_q_3;" << std::endl;
220+ qasm3 << " }" << std::endl;
221+ break ;
222+ case QkGate_C3SX:
223+ qasm3 << " gate c3sx _gate_q_0, _gate_q_1, _gate_q_2, _gate_q_3 {"
224+ << std::endl;
225+ qasm3 << " h _gate_q_3;" << std::endl;
226+ qasm3 << " cp(pi/8) _gate_q_0, _gate_q_3;" << std::endl;
227+ qasm3 << " h _gate_q_3;" << std::endl;
228+ qasm3 << " cx _gate_q_0, _gate_q_1;" << std::endl;
229+ qasm3 << " h _gate_q_3;" << std::endl;
230+ qasm3 << " cp(-pi/8) _gate_q_1, _gate_q_3;" << std::endl;
231+ qasm3 << " h _gate_q_3;" << std::endl;
232+ qasm3 << " cx _gate_q_0, _gate_q_1;" << std::endl;
233+ qasm3 << " h _gate_q_3;" << std::endl;
234+ qasm3 << " cp(pi/8) _gate_q_1, _gate_q_3;" << std::endl;
235+ qasm3 << " h _gate_q_3;" << std::endl;
236+ qasm3 << " cx _gate_q_1, _gate_q_2;" << std::endl;
237+ qasm3 << " h _gate_q_3;" << std::endl;
238+ qasm3 << " cp(-pi/8) _gate_q_2, _gate_q_3;" << std::endl;
239+ qasm3 << " h _gate_q_3;" << std::endl;
240+ qasm3 << " cx _gate_q_0, _gate_q_2;" << std::endl;
241+ qasm3 << " h _gate_q_3;" << std::endl;
242+ qasm3 << " cp(pi/8) _gate_q_2, _gate_q_3;" << std::endl;
243+ qasm3 << " h _gate_q_3;" << std::endl;
244+ qasm3 << " cx _gate_q_1, _gate_q_2;" << std::endl;
245+ qasm3 << " h _gate_q_3;" << std::endl;
246+ qasm3 << " cp(-pi/8) _gate_q_2, _gate_q_3;" << std::endl;
247+ qasm3 << " h _gate_q_3;" << std::endl;
248+ qasm3 << " cx _gate_q_0, _gate_q_2;" << std::endl;
249+ qasm3 << " h _gate_q_3;" << std::endl;
250+ qasm3 << " cp(pi/8) _gate_q_2, _gate_q_3;" << std::endl;
251+ qasm3 << " h _gate_q_3;" << std::endl;
252+ qasm3 << " }" << std::endl;
253+ break ;
254+ case QkGate_RC3X:
255+ qasm3 << " gate rcccx _gate_q_0, _gate_q_1, _gate_q_2, _gate_q_3 {"
256+ << std::endl;
257+ qasm3 << " h _gate_q_3;" << std::endl;
258+ qasm3 << " t _gate_q_3;" << std::endl;
259+ qasm3 << " cx _gate_q_2, _gate_q_3;" << std::endl;
260+ qasm3 << " tdg _gate_q_3;" << std::endl;
261+ qasm3 << " h _gate_q_3;" << std::endl;
262+ qasm3 << " cx _gate_q_0, _gate_q_3;" << std::endl;
263+ qasm3 << " t _gate_q_3;" << std::endl;
264+ qasm3 << " cx _gate_q_1, _gate_q_3;" << std::endl;
265+ qasm3 << " tdg _gate_q_3;" << std::endl;
266+ qasm3 << " cx _gate_q_0, _gate_q_3;" << std::endl;
267+ qasm3 << " t _gate_q_3;" << std::endl;
268+ qasm3 << " cx _gate_q_1, _gate_q_3;" << std::endl;
269+ qasm3 << " tdg _gate_q_3;" << std::endl;
270+ qasm3 << " h _gate_q_3;" << std::endl;
271+ qasm3 << " t _gate_q_3;" << std::endl;
272+ qasm3 << " cx _gate_q_2, _gate_q_3;" << std::endl;
273+ qasm3 << " tdg _gate_q_3;" << std::endl;
274+ qasm3 << " h _gate_q_3;" << std::endl;
275+ qasm3 << " }" << std::endl;
276+ break ;
277+ case QkGate_CU1:
278+ qasm3 << " gate cu1(p0) _gate_q_0, _gate_q_1 {" << std::endl;
279+ qasm3 << " cp(p0) _gate_q_0 _gate_q_1;" << std::endl;
280+ qasm3 << " }" << std::endl;
281+ break ;
282+ case QkGate_CU3:
283+ qasm3 << " gate cu3(p0, p1, p2) _gate_q_0, _gate_q_1 {" << std::endl;
284+ qasm3 << " cu(p0, p1, p2, 0) _gate_q_0 _gate_q_1;" << std::endl;
285+ qasm3 << " }" << std::endl;
286+ break ;
287+ default :
288+ break ;
289+ }
290+ }
291+ }
292+ qk_opcounts_clear (&opcounts);
293+
294+ // save ops
295+ uint_t nops;
296+ nops = qk_circuit_num_instructions (rust_circuit_.get ());
297+
298+ // Declare registers
299+ // After transpilation, qubit registers will be mapped to physical registers,
300+ // so we need to combined them in a single quantum register "q";
301+ const std::string qreg_name = " q" ;
302+ qasm3 << " qubit[" << num_qubits () << " ] " << qreg_name << " ;" << std::endl;
303+ for (const auto &creg : cregs_) {
304+ qasm3 << " bit[" << creg.size () << " ] " << creg.name () << " ;" << std::endl;
305+ }
306+
307+ auto recover_reg_data =
308+ [this ](uint_t index) -> std::pair<std::string, uint_t > {
309+ auto it = std::upper_bound (cregs_.begin (), cregs_.end (), index,
310+ [](uint_t v, const ClassicalRegister ®) {
311+ return v < reg.base_index ();
312+ });
313+ assert (it != cregs_.begin ());
314+ it = std::prev (it);
315+ return std::make_pair (it->name (), index - it->base_index ());
316+ };
317+
318+ for (uint_t i = 0 ; i < nops; i++) {
319+ QkCircuitInstruction *op = new QkCircuitInstruction;
320+ qk_circuit_get_instruction (rust_circuit_.get (), i, op);
321+ if (op->num_clbits > 0 ) {
322+ if (op->num_qubits == op->num_clbits ) {
323+ for (uint_t j = 0 ; j < op->num_qubits ; j++) {
324+ const auto creg_data = recover_reg_data (op->clbits [j]);
325+ qasm3 << creg_data.first << " [" << creg_data.second
326+ << " ] = " << op->name << " " << qreg_name << " ["
327+ << op->qubits [j] << " ];" << std::endl;
328+ }
329+ }
330+ } else {
331+ if (strcmp (op->name , " u" ) == 0 ) {
332+ qasm3 << " U" ;
333+ } else {
334+ qasm3 << op->name ;
335+ }
336+ if (op->num_params > 0 ) {
337+ qasm3 << " (" ;
338+ for (uint_t j = 0 ; j < op->num_params ; j++) {
339+ char *param = qk_param_str (op->params [j]);
340+ qasm3 << param;
341+ qk_str_free (param);
342+ if (j != op->num_params - 1 )
343+ qasm3 << " , " ;
344+ }
345+ qasm3 << " )" ;
346+ }
347+ if (op->num_qubits > 0 ) {
348+ qasm3 << " " ;
349+ for (uint_t j = 0 ; j < op->num_qubits ; j++) {
350+ qasm3 << qreg_name << " [" << op->qubits [j] << " ]" ;
351+ if (j != op->num_qubits - 1 )
352+ qasm3 << " , " ;
353+ }
354+ }
355+ qasm3 << " ;" << std::endl;
356+ }
357+ qk_circuit_instruction_clear (op);
358+ }
359+
360+ return qasm3.str ();
361+ }
0 commit comments