Maestro 0.3.11
Unified interface for quantum circuit simulation
Loading...
Searching...
No Matches
CircQasm.h
Go to the documentation of this file.
1
12
13#pragma once
14
15#ifndef _CIRCQASM_H_
16#define _CIRCQASM_H_
17
18#include "../Circuit/Circuit.h"
19
20namespace qasm
21{
22
23template <typename Time = Types::time_type> class CircToQasm
24{
25 public:
26 // selects which OpenQASM dialect Generate/GenerateWithMapping emit; only
27 // the version line, include, register declarations and measurement syntax
28 // differ between the two, see QasmHeader/QasmRegisters/OperationToQasm
29 enum class QasmVersion
30 {
33 };
34
35 enum class QasmGateType : size_t
36 {
37 X, // XGate
38 Y, // YGate
39 Z, // ZGate
40 H, // HadamardGate
41 S, // SGate
42 SDG, // SdgGate
43 Sx, // SxGate
44 SxDG, // SxDagGate
45 K, // KGate
46 T, // TGate
47 TDG, // TdgGate
48 Rx, // RxGate
49 Ry, // RyGate
50 Rz, // RzGate
51 U, // UGate
52 CZ, // CZGate
53 CY, // CYGate
54 CH, // CHGate
55 CRZ, // CRzGate
56 CU1, // CPGate
57 CU3, // CUGate
58 CRX, // CRxGate
59 CRY, // CRyGate
62 CSX, // CSxGate
63 CSXDAG, // CSxDagGate
67 };
68
69 // still need to be defined additionally:
70
71 /*
72 kCUGateType
73 */
74
75 static std::string GenerateWithMapping(const std::shared_ptr<Circuits::Circuit<Time>> &circuit,
76 const std::unordered_map<Types::qubit_t, Types::qubit_t> &bitsMap, QasmVersion version = QasmVersion::V2)
77 {
78 const auto mappedCircuit = std::static_pointer_cast<Circuits::Circuit<Time>>(circuit->Remap(bitsMap, bitsMap));
79
80 return GenerateFromCircuit(mappedCircuit, false, version);
81 }
82
83 // look over the circuit and convert it to qasm
84 // identify which gates are used, generate gate definitions only for those
85 // (that do not exist in the qasm standard) the standard ones are U3 and CX
86 // attention: the definitions depend on other ones, so the order is important,
87 // also some gates that are not used in the circuit still need to be defined
88 // if they are used in the definitions of the gates that are used
89
90 static std::string Generate(const std::shared_ptr<Circuits::Circuit<Time>> &circuit, QasmVersion version = QasmVersion::V2)
91 {
92 return GenerateFromCircuit(circuit, true, version);
93 }
94
95 private:
96 static std::string GenerateFromCircuit(const std::shared_ptr<Circuits::Circuit<Time>> &circuit, bool clone, QasmVersion version = QasmVersion::V2)
97 {
98 if (circuit->empty())
99 return "";
100
101 const auto circ = (clone ? std::static_pointer_cast<Circuits::Circuit<Time>>(circuit->Clone()) : circuit);
102
103 circ->ConvertForDistribution(); // get rid of swap and 3 qubit gates
104
105 std::string qasm = QasmHeader(version);
106
107 qasm += QasmGatesAndRegsDefinitions(circ, version);
108
109 // iterate over the circuit and generate the qasm
110 for (const auto &gate : circ->GetOperations())
111 qasm += OperationToQasm(gate, version);
112
113 return qasm;
114 }
115
116 static std::string OperationToQasm(const std::shared_ptr<Circuits::IOperation<Time>> &operation, QasmVersion version = QasmVersion::V2)
117 {
118 std::string qasm;
119
120 switch (operation->GetType())
121 {
123 qasm += GateToQasm(operation, version);
124 break;
126 auto qbits = operation->AffectedQubits();
127 auto bits = operation->AffectedBits();
128
129 assert(qbits.size() == bits.size());
130
131 for (size_t i = 0; i < qbits.size(); ++i)
132 qasm += (version == QasmVersion::V3) ? "c" + std::to_string(bits[i]) + "[0] = measure q[" + std::to_string(qbits[i]) + "];\n"
133 : "measure q[" + std::to_string(qbits[i]) + "]->c" + std::to_string(bits[i]) + "[0];\n";
134 }
135 break;
137 auto qbits = operation->AffectedQubits();
138 for (const auto &qbit : qbits)
139 qasm += "reset q[" + std::to_string(qbit) + "];\n";
140 }
141 break;
143 [[fallthrough]];
145 // conditionals are similar, generate an if and then call again for the
146 // conditioned operations
147 {
148 auto condop = std::static_pointer_cast<Circuits::IConditionalOperation<Time>>(operation);
149 auto bits = condop->AffectedBits();
150 auto vals = std::static_pointer_cast<Circuits::EqualCondition>(condop->GetCondition())->GetAllBits();
151 assert(bits.size() == vals.size());
152
153 const auto theop = condop->GetOperation();
154 if (version == QasmVersion::V3)
155 {
156 qasm += "if (";
157 for (size_t i = 0; i < bits.size(); ++i)
158 {
159 if (i != 0)
160 qasm += " && ";
161 if (!vals[i])
162 qasm += "!";
163 qasm += "c" + std::to_string(bits[i]) + "[0]";
164 }
165 qasm += ") {\n";
166
167 const std::string body = OperationToQasm(theop, version);
168 size_t lineStart = 0;
169 while (lineStart < body.size())
170 {
171 const size_t lineEnd = body.find('\n', lineStart);
172 qasm += " " + body.substr(lineStart, lineEnd - lineStart) + "\n";
173 if (lineEnd == std::string::npos)
174 break;
175 lineStart = lineEnd + 1;
176 }
177 qasm += "}\n";
178 }
179 else
180 {
181 for (size_t i = 0; i < bits.size(); ++i)
182 qasm += "if(c" + std::to_string(bits[i]) + "==" + std::to_string(vals[i] ? 1 : 0) + ") ";
183 qasm += OperationToQasm(theop, version);
184 }
185 }
186 break;
188 qasm += "barrier q;\n";
189 break;
191 auto delayOp = std::static_pointer_cast<Circuits::Delay<Time>>(operation);
192 auto qbit = delayOp->GetQubit();
193 auto dur = delayOp->GetDuration();
194 if (version == QasmVersion::V3)
195 {
196 qasm += "delay[" + std::to_string(dur) + "s] q[" + std::to_string(qbit) + "];\n";
197 }
198 else
199 {
200 qasm += "delay(" + std::to_string(dur) + ") q[" + std::to_string(qbit) + "];\n";
201 }
202 }
203 break;
205 [[fallthrough]];
207 [[fallthrough]];
209 [[fallthrough]];
211 throw std::runtime_error("Not supported!");
212 break;
213 }
214
215 return qasm;
216 }
217
218 static std::string GateToQasm(const std::shared_ptr<Circuits::IOperation<Time>> &operation, QasmVersion version = QasmVersion::V2)
219 {
220 if (!operation || operation->GetType() != Circuits::OperationType::kGate)
221 return "";
222
223 const auto gate = std::static_pointer_cast<Circuits::IQuantumGate<Time>>(operation);
224
225 std::string qasm;
226
227 switch (gate->GetGateType())
228 {
230 qasm += "U(0,0," + std::to_string(gate->GetParams()[0]) + ") q[" + std::to_string(gate->GetQubit(0)) + "];\n";
231 break;
233 qasm += "x q[" + std::to_string(gate->GetQubit(0)) + "];\n";
234 break;
236 qasm += "y q[" + std::to_string(gate->GetQubit(0)) + "];\n";
237 break;
239 qasm += "z q[" + std::to_string(gate->GetQubit(0)) + "];\n";
240 break;
242 qasm += "h q[" + std::to_string(gate->GetQubit(0)) + "];\n";
243 break;
245 qasm += "s q[" + std::to_string(gate->GetQubit(0)) + "];\n";
246 break;
248 qasm += "sdg q[" + std::to_string(gate->GetQubit(0)) + "];\n";
249 break;
251 qasm += "t q[" + std::to_string(gate->GetQubit(0)) + "];\n";
252 break;
254 qasm += "tdg q[" + std::to_string(gate->GetQubit(0)) + "];\n";
255 break;
256
257 //*************************************************************************************************
258 // Defined locally for QASM2; provided by stdgates.inc for QASM3.
260 qasm += "sx q[" + std::to_string(gate->GetQubit(0)) + "];\n";
261 break;
263 qasm += "sxdg q[" + std::to_string(gate->GetQubit(0)) + "];\n";
264 break;
266 qasm += "k q[" + std::to_string(gate->GetQubit(0)) + "];\n";
267 break;
268 //*************************************************************************************************
269
271 qasm += "rx(" + std::to_string(gate->GetParams()[0]) + ") q[" + std::to_string(gate->GetQubit(0)) + "];\n";
272 break;
274 qasm += "ry(" + std::to_string(gate->GetParams()[0]) + ") q[" + std::to_string(gate->GetQubit(0)) + "];\n";
275 break;
277 qasm += "rz(" + std::to_string(gate->GetParams()[0]) + ") q[" + std::to_string(gate->GetQubit(0)) + "];\n";
278 break;
280 if (gate->GetParams()[3] == 0)
281 qasm += "U(" + std::to_string(gate->GetParams()[0]) + "," + std::to_string(gate->GetParams()[1]) + "," + std::to_string(gate->GetParams()[2]) +
282 ") q[" + std::to_string(gate->GetQubit(0)) + "];\n";
283 else
284 throw std::runtime_error("U with gamma non zero not supported yet!");
285 break;
286
288 // first is the control qubit!
289 qasm += "CX q[" + std::to_string(gate->GetQubit(0)) + "],q[" + std::to_string(gate->GetQubit(1)) + "];\n";
290 break;
292 qasm += "cy q[" + std::to_string(gate->GetQubit(0)) + "],q[" + std::to_string(gate->GetQubit(1)) + "];\n";
293 break;
295 qasm += "cz q[" + std::to_string(gate->GetQubit(0)) + "],q[" + std::to_string(gate->GetQubit(1)) + "];\n";
296 break;
298 qasm += (version == QasmVersion::V3 ? "cp(" : "cu1(") + std::to_string(gate->GetParams()[0]) + ") q[" + std::to_string(gate->GetQubit(0)) + "],q[" +
299 std::to_string(gate->GetQubit(1)) + "];\n";
300 break;
301
302 //*************************************************************************************************
303 // defined here, not in the 'standard' header
305 qasm += "crx(" + std::to_string(gate->GetParams()[0]) + ") q[" + std::to_string(gate->GetQubit(0)) + "],q[" + std::to_string(gate->GetQubit(1)) +
306 "];\n";
307 break;
309 qasm += "cry(" + std::to_string(gate->GetParams()[0]) + ") q[" + std::to_string(gate->GetQubit(0)) + "],q[" + std::to_string(gate->GetQubit(1)) +
310 "];\n";
311 break;
312 //*************************************************************************************************
313
315 qasm += "crz(" + std::to_string(gate->GetParams()[0]) + ") q[" + std::to_string(gate->GetQubit(0)) + "],q[" + std::to_string(gate->GetQubit(1)) +
316 "];\n";
317 break;
319 qasm += "ch q[" + std::to_string(gate->GetQubit(0)) + "],q[" + std::to_string(gate->GetQubit(1)) + "];\n";
320 break;
321
322 //*************************************************************************************************
323 // defined here, not in the 'standard' header
325 qasm += "csx q[" + std::to_string(gate->GetQubit(0)) + "],q[" + std::to_string(gate->GetQubit(1)) + "];\n";
326 break;
328 qasm += "csxdag q[" + std::to_string(gate->GetQubit(0)) + "],q[" + std::to_string(gate->GetQubit(1)) + "];\n";
329 break;
330
331 // we have a problem with this, our CU is with 4 parameters, so not fully
332 // converted if the 4th parameter is not zero!
334 if (version == QasmVersion::V3)
335 qasm += "cu(" + std::to_string(gate->GetParams()[0]) + "," + std::to_string(gate->GetParams()[1]) + "," + std::to_string(gate->GetParams()[2]) +
336 "," + std::to_string(gate->GetParams()[3]) + ") q[" + std::to_string(gate->GetQubit(0)) + "], q[" + std::to_string(gate->GetQubit(1)) +
337 "];\n";
338 else if (gate->GetParams()[3] == 0)
339 qasm += "cu3(" + std::to_string(gate->GetParams()[0]) + "," + std::to_string(gate->GetParams()[1]) + "," +
340 std::to_string(gate->GetParams()[2]) + ") q[" + std::to_string(gate->GetQubit(0)) + "], q[" + std::to_string(gate->GetQubit(1)) +
341 "];\n";
342 else
343 throw std::runtime_error("CU with gamma non zero not supported yet!");
344 break;
345 //*************************************************************************************************
346
347 // swap is converted to three CX gates
349 qasm += "swap q[" + std::to_string(gate->GetQubit(0)) + "],q[" + std::to_string(gate->GetQubit(1)) + "];\n";
350 break;
351 // three qubit gates, do not need to be converted as they are converted to
352 // two qubit gates already
354 [[fallthrough]];
356 throw std::runtime_error("Not supported!");
357 break;
359 break;
360 }
361
362 return qasm;
363 }
364
365 static std::string QasmHeader(QasmVersion version = QasmVersion::V2)
366 {
367 std::string qasm = (version == QasmVersion::V3) ? "OPENQASM 3.0;\n" : "OPENQASM 2.0;\n";
368
369 return qasm;
370 }
371
372 // assume qubits and cbits starting from 0, map the circuit to that if not
373 // already like that
374 static std::string QasmRegisters(const std::shared_ptr<Circuits::Circuit<Time>> &circuit, QasmVersion version = QasmVersion::V2)
375 {
376 const auto nrq = circuit->GetMaxQubitIndex() + 1;
377
378 const std::string nrq_str = std::to_string(nrq);
379
380 std::string qasm = (version == QasmVersion::V3) ? "qubit[" + nrq_str + "] q;\n" : "qreg q[" + nrq_str + "];\n";
381
382 std::set<size_t> measQubits;
383
384 for (const auto &op : *circuit)
385 {
386 std::vector<std::shared_ptr<Circuits::IOperation<Time>>> pending{op};
387 while (!pending.empty())
388 {
389 const auto current = pending.back();
390 pending.pop_back();
391
392 for (const auto bit : current->AffectedBits())
393 measQubits.insert(bit);
394
396 {
397 pending.push_back(std::static_pointer_cast<Circuits::IConditionalOperation<Time>>(current)->GetOperation());
398 }
399 }
400 }
401
402 int creg_count = 0;
403 for (auto bit : measQubits)
404 {
405 // this completion is needed to have a proper total cregister definition
406 // we need this to be able to address the bits properly, otherwise
407 // conversion circuit -> qasm -> circuit would not work properly
408 if (creg_count < static_cast<int>(bit))
409 {
410 const std::string fillerSize = std::to_string(bit - creg_count);
411 qasm += (version == QasmVersion::V3) ? "bit[" + fillerSize + "] c" + std::to_string(creg_count) + ";\n"
412 : "creg c" + std::to_string(creg_count) + "[" + fillerSize + "];\n";
413 }
414
415 qasm += (version == QasmVersion::V3) ? "bit[1] c" + std::to_string(bit) + ";\n" : "creg c" + std::to_string(bit) + "[1];\n";
416 creg_count = static_cast<int>(bit) + 1;
417 }
418
419 return qasm;
420 }
421
422 static std::string QasmGatesAndRegsDefinitions(const std::shared_ptr<Circuits::Circuit<Time>> &circuit, QasmVersion version = QasmVersion::V2)
423 {
424 std::vector<bool> neededGates(static_cast<size_t>(QasmGateType::NoGate), false);
425
426 // #define DONT_USE_HEADER_DEFINITIONS 1
427
428 for (const auto &op : circuit->GetOperations())
429 {
430 const auto opType = op->GetType();
432 {
433 const auto &gate = std::static_pointer_cast<Circuits::IQuantumGate<Time>>(
434 opType == Circuits::OperationType::kConditionalGate ? std::static_pointer_cast<Circuits::IConditionalOperation<Time>>(op)->GetOperation()
435 : op);
436
437 switch (gate->GetGateType())
438 {
440#ifdef DONT_USE_HEADER_DEFINITIONS
441 neededGates[static_cast<size_t>(QasmGateType::U)] = true;
442#else
443 neededGates[static_cast<size_t>(QasmGateType::IncludedGate)] = true;
444#endif
445 break;
447#ifdef DONT_USE_HEADER_DEFINITIONS
448 neededGates[static_cast<size_t>(QasmGateType::X)] = true;
449#else
450 neededGates[static_cast<size_t>(QasmGateType::IncludedGate)] = true;
451#endif
452 break;
454#ifdef DONT_USE_HEADER_DEFINITIONS
455 neededGates[static_cast<size_t>(QasmGateType::Y)] = true;
456#else
457 neededGates[static_cast<size_t>(QasmGateType::IncludedGate)] = true;
458#endif
459 break;
461#ifdef DONT_USE_HEADER_DEFINITIONS
462 neededGates[static_cast<size_t>(QasmGateType::Z)] = true;
463#else
464 neededGates[static_cast<size_t>(QasmGateType::IncludedGate)] = true;
465#endif
466 break;
468#ifdef DONT_USE_HEADER_DEFINITIONS
469 neededGates[static_cast<size_t>(QasmGateType::H)] = true;
470#else
471 neededGates[static_cast<size_t>(QasmGateType::IncludedGate)] = true;
472#endif
473 break;
475#ifdef DONT_USE_HEADER_DEFINITIONS
476 neededGates[static_cast<size_t>(QasmGateType::S)] = true;
477#else
478 neededGates[static_cast<size_t>(QasmGateType::IncludedGate)] = true;
479#endif
480 break;
482#ifdef DONT_USE_HEADER_DEFINITIONS
483 neededGates[static_cast<size_t>(QasmGateType::SDG)] = true;
484#else
485 neededGates[static_cast<size_t>(QasmGateType::IncludedGate)] = true;
486#endif
487 break;
489#ifdef DONT_USE_HEADER_DEFINITIONS
490 neededGates[static_cast<size_t>(QasmGateType::T)] = true;
491#else
492 neededGates[static_cast<size_t>(QasmGateType::IncludedGate)] = true;
493#endif
494 break;
496#ifdef DONT_USE_HEADER_DEFINITIONS
497 neededGates[static_cast<size_t>(QasmGateType::TDG)] = true;
498#else
499 neededGates[static_cast<size_t>(QasmGateType::IncludedGate)] = true;
500#endif
501 break;
502
503 //*************************************************************************************************
504 // Defined locally for QASM2; provided by stdgates.inc for QASM3.
506#ifdef DONT_USE_HEADER_DEFINITIONS
507 neededGates[static_cast<size_t>(QasmGateType::Sx)] = true;
508#else
509 neededGates[static_cast<size_t>(QasmGateType::IncludedGate)] = true;
510 // stdgates.inc defines sx, qelib1.inc does not.
511 if (version == QasmVersion::V2)
512 neededGates[static_cast<size_t>(QasmGateType::Sx)] = true;
513#endif
514 break;
516 neededGates[static_cast<size_t>(QasmGateType::SxDG)] = true;
517#ifndef DONT_USE_HEADER_DEFINITIONS
518 neededGates[static_cast<size_t>(QasmGateType::IncludedGate)] = true;
519#endif
520 break;
522 neededGates[static_cast<size_t>(QasmGateType::K)] = true;
523#ifndef DONT_USE_HEADER_DEFINITIONS
524 neededGates[static_cast<size_t>(QasmGateType::IncludedGate)] = true;
525#endif
526 break;
527 //*************************************************************************************************
528
530#ifdef DONT_USE_HEADER_DEFINITIONS
531 neededGates[static_cast<size_t>(QasmGateType::Rx)] = true;
532#else
533 neededGates[static_cast<size_t>(QasmGateType::IncludedGate)] = true;
534#endif
535 break;
537#ifdef DONT_USE_HEADER_DEFINITIONS
538 neededGates[static_cast<size_t>(QasmGateType::Ry)] = true;
539#else
540 neededGates[static_cast<size_t>(QasmGateType::IncludedGate)] = true;
541#endif
542 break;
544#ifdef DONT_USE_HEADER_DEFINITIONS
545 neededGates[static_cast<size_t>(QasmGateType::Rz)] = true;
546#else
547 neededGates[static_cast<size_t>(QasmGateType::IncludedGate)] = true;
548#endif
549 break;
550
552#ifdef DONT_USE_HEADER_DEFINITIONS
553 neededGates[static_cast<size_t>(QasmGateType::U)] = true;
554#else
555 neededGates[static_cast<size_t>(QasmGateType::IncludedGate)] = true;
556#endif
557 break;
558
560 // standard gate
561#ifndef DONT_USE_HEADER_DEFINITIONS
562 neededGates[static_cast<size_t>(QasmGateType::IncludedGate)] = true;
563#endif
564 break;
566#ifdef DONT_USE_HEADER_DEFINITIONS
567 neededGates[static_cast<size_t>(QasmGateType::CY)] = true;
568 neededGates[static_cast<size_t>(QasmGateType::SDG)] = true;
569 neededGates[static_cast<size_t>(QasmGateType::S)] = true;
570#else
571 neededGates[static_cast<size_t>(QasmGateType::IncludedGate)] = true;
572#endif
573 break;
575#ifdef DONT_USE_HEADER_DEFINITIONS
576 neededGates[static_cast<size_t>(QasmGateType::CZ)] = true;
577 neededGates[static_cast<size_t>(QasmGateType::H)] = true;
578#else
579 neededGates[static_cast<size_t>(QasmGateType::IncludedGate)] = true;
580#endif
581 break;
583#ifdef DONT_USE_HEADER_DEFINITIONS
584 neededGates[static_cast<size_t>(QasmGateType::CU1)] = true;
585#else
586 neededGates[static_cast<size_t>(QasmGateType::IncludedGate)] = true;
587#endif
588 break;
589
590 //*************************************************************************************************
591 // defined here, not in the 'standard' header
593#ifdef DONT_USE_HEADER_DEFINITIONS
594 neededGates[static_cast<size_t>(QasmGateType::CRX)] = true;
595 neededGates[static_cast<size_t>(QasmGateType::CU3)] = true;
596#else
597 neededGates[static_cast<size_t>(QasmGateType::IncludedGate)] = true;
598 if (version == QasmVersion::V2)
599 neededGates[static_cast<size_t>(QasmGateType::CRX)] = true;
600#endif
601 break;
603#ifdef DONT_USE_HEADER_DEFINITIONS
604 neededGates[static_cast<size_t>(QasmGateType::CRY)] = true;
605 neededGates[static_cast<size_t>(QasmGateType::CU3)] = true;
606#else
607 neededGates[static_cast<size_t>(QasmGateType::IncludedGate)] = true;
608 if (version == QasmVersion::V2)
609 neededGates[static_cast<size_t>(QasmGateType::CRY)] = true;
610#endif
611 break;
612 //*************************************************************************************************
613
615#ifdef DONT_USE_HEADER_DEFINITIONS
616 neededGates[static_cast<size_t>(QasmGateType::CRZ)] = true;
617#else
618 neededGates[static_cast<size_t>(QasmGateType::IncludedGate)] = true;
619#endif
620 break;
622#ifdef DONT_USE_HEADER_DEFINITIONS
623 neededGates[static_cast<size_t>(QasmGateType::CH)] = true;
624 neededGates[static_cast<size_t>(QasmGateType::H)] = true;
625 neededGates[static_cast<size_t>(QasmGateType::SDG)] = true;
626 neededGates[static_cast<size_t>(QasmGateType::T)] = true;
627 neededGates[static_cast<size_t>(QasmGateType::S)] = true;
628 neededGates[static_cast<size_t>(QasmGateType::X)] = true;
629#else
630 neededGates[static_cast<size_t>(QasmGateType::IncludedGate)] = true;
631#endif
632 break;
633
634 //*************************************************************************************************
635 // defined here, not in the 'standard' header
637 neededGates[static_cast<size_t>(QasmGateType::CSX)] = true;
638 neededGates[static_cast<size_t>(QasmGateType::CS)] = true;
639 break;
641 neededGates[static_cast<size_t>(QasmGateType::CSXDAG)] = true;
642 neededGates[static_cast<size_t>(QasmGateType::CSDAG)] = true;
643 break;
644
645 // we have a problem with this, our CU is with 4 parameters, so not
646 // fully converted if the 4th parameter is not zero!
648 if (version == QasmVersion::V3)
649 {
650 neededGates[static_cast<size_t>(QasmGateType::IncludedGate)] = true;
651 }
652 else if (gate->GetParams()[3] == 0)
653 {
654#ifdef DONT_USE_HEADER_DEFINITIONS
655 neededGates[static_cast<size_t>(QasmGateType::CU3)] = true;
656#else
657 neededGates[static_cast<size_t>(QasmGateType::IncludedGate)] = true;
658#endif
659 }
660 else
661 throw std::runtime_error("CU with gamma non zero not supported yet!");
662 break;
663 //*************************************************************************************************
664
665 // swap is converted to three CX gates
667 neededGates[static_cast<size_t>(QasmGateType::SWAP)] = true;
668 break;
669 // three qubit gates, do not need to be converted as they are
670 // converted to two qubit gates already
672 [[fallthrough]];
674 throw std::runtime_error("Not supported!");
675 break;
677 break;
678 }
679 }
680 }
681
682 std::string qasm;
683
684 if (neededGates[static_cast<size_t>(QasmGateType::IncludedGate)])
685 qasm += (version == QasmVersion::V3) ? "include \"stdgates.inc\";\n" : "include \"qelib1.inc\";\n";
686
687 qasm += QasmRegisters(circuit, version);
688
689 // WARNING: order matters, so be sure you won't define gates based on gates
690 // that are defined later here
691
692 if (neededGates[static_cast<size_t>(QasmGateType::X)])
693 qasm += XGateDefinition();
694 if (neededGates[static_cast<size_t>(QasmGateType::Y)])
695 qasm += YGateDefinition();
696 if (neededGates[static_cast<size_t>(QasmGateType::Z)])
697 qasm += ZGateDefinition();
698 if (neededGates[static_cast<size_t>(QasmGateType::H)])
699 qasm += HGateDefinition();
700 if (neededGates[static_cast<size_t>(QasmGateType::S)])
701 qasm += SGateDefinition();
702 if (neededGates[static_cast<size_t>(QasmGateType::SDG)])
703 qasm += SDGGateDefinition();
704
705 if (neededGates[static_cast<size_t>(QasmGateType::Sx)])
706 qasm += SxGateDefinition();
707 if (neededGates[static_cast<size_t>(QasmGateType::SxDG)])
708 qasm += SxDGGateDefinition();
709
710 if (neededGates[static_cast<size_t>(QasmGateType::K)])
711 qasm += KGateDefinition();
712
713 if (neededGates[static_cast<size_t>(QasmGateType::T)])
714 qasm += TGateDefinition();
715 if (neededGates[static_cast<size_t>(QasmGateType::TDG)])
716 qasm += TDGGateDefinition();
717
718 if (neededGates[static_cast<size_t>(QasmGateType::Rx)])
719 qasm += RxGateDefinition();
720 if (neededGates[static_cast<size_t>(QasmGateType::Ry)])
721 qasm += RyGateDefinition();
722 if (neededGates[static_cast<size_t>(QasmGateType::Rz)])
723 qasm += RzGateDefinition();
724
725 if (neededGates[static_cast<size_t>(QasmGateType::CZ)])
726 qasm += CZGateDefinition();
727 if (neededGates[static_cast<size_t>(QasmGateType::CY)])
728 qasm += CYGateDefinition();
729 if (neededGates[static_cast<size_t>(QasmGateType::CH)])
730 qasm += CHGateDefinition();
731 // qasm += CCXGateDefinition();
732
733 if (neededGates[static_cast<size_t>(QasmGateType::CRZ)])
734 qasm += CRZGateDefinition();
735 if (neededGates[static_cast<size_t>(QasmGateType::CU1)])
736 qasm += CU1GateDefinition();
737 if (neededGates[static_cast<size_t>(QasmGateType::CU3)])
738 qasm += CU3GateDefinition();
739 if (neededGates[static_cast<size_t>(QasmGateType::CRX)])
740 qasm += CRXGateDefinition();
741 if (neededGates[static_cast<size_t>(QasmGateType::CRY)])
742 qasm += CRYGateDefinition();
743 if (neededGates[static_cast<size_t>(QasmGateType::SWAP)])
744 qasm += SwapGateDefinition();
745
746 if (neededGates[static_cast<size_t>(QasmGateType::CS)])
747 qasm += CSGateDefinition();
748 if (neededGates[static_cast<size_t>(QasmGateType::CSDAG)])
749 qasm += CSDAGGateDefinition();
750
751 if (neededGates[static_cast<size_t>(QasmGateType::CSX)])
752 qasm += CSXGateDefinition();
753 if (neededGates[static_cast<size_t>(QasmGateType::CSXDAG)])
754 qasm += CSXDAGGateDefinition();
755
756 return qasm;
757 }
758
759 // gates definitions
760 static std::string U3GateDefinition()
761 {
762 return "gate u3(theta,phi,lambda) q { U(theta,phi,lambda) q; }\n";
763 }
764
765 static std::string U2GateDefinition()
766 {
767 return "gate u2(phi,lambda) q { U(pi/2,phi,lambda) q; }\n";
768 }
769
770 static std::string U1GateDefinition()
771 {
772 return "gate u1(lambda) q { U(0,0,lambda) q; }\n";
773 }
774
775 static std::string XGateDefinition()
776 {
777 return "gate x a { U(pi,0,pi) a; }\n";
778 }
779
780 static std::string YGateDefinition()
781 {
782 return "gate y a { U(pi,pi/2,pi/2) a; }\n";
783 }
784
785 static std::string ZGateDefinition()
786 {
787 return "gate z a { U(0,0,pi) a; }\n";
788 }
789
790 static std::string HGateDefinition()
791 {
792 return "gate h a { U(pi/2,0,pi) a; }\n";
793 }
794
795 static std::string SGateDefinition()
796 {
797 return "gate s a { U(0,0,pi/2) a; }\n";
798 }
799
800 static std::string SDGGateDefinition()
801 {
802 return "gate sdg a { U(0,0,-pi/2) a; }\n";
803 }
804
805 // the following two introduce a global phase compared with the operators for
806 // sx and sxdg, but that should be ok
807 static std::string SxGateDefinition()
808 {
809 return "gate sx a { U(pi/2,-pi/2,pi/2) a; }\n"; // this is a rotation,
810 // equivalent up to a
811 // global phase
812 }
813
814 static std::string SxDGGateDefinition()
815 {
816 return "gate sxdg a { U(-pi/2,-pi/2,pi/2) a; }\n";
817 }
818
819 static std::string KGateDefinition()
820 {
821 return "gate k a { U(pi/2,pi/2,pi/2) a; }\n";
822 }
823
824 static std::string TGateDefinition()
825 {
826 return "gate t a { U(0,0,pi/4) a; }\n";
827 }
828
829 static std::string TDGGateDefinition()
830 {
831 return "gate tdg a { U(0,0,-pi/4) a; }\n";
832 }
833
834 static std::string RxGateDefinition()
835 {
836 return "gate rx(theta) a { U(theta,-pi/2,pi/2) a; }\n";
837 }
838
839 static std::string RyGateDefinition()
840 {
841 return "gate ry(theta) a { U(theta,0,0) a; }\n";
842 }
843
844 static std::string RzGateDefinition()
845 {
846 return "gate rz(phi) a { U(0,0,phi) a; }\n";
847 }
848
849 static std::string SwapGateDefinition()
850 {
851 return "gate swap a,b { CX a,b; CX b,a; CX a,b; }\n";
852 }
853
854 // with hadamard it's going to the x basis... then after cx, back to the z
855 // basis, applying hadamard again
856 static std::string CZGateDefinition()
857 {
858 return "gate cz a,b { h b; CX a,b; h b; }\n";
859 }
860
861 static std::string CYGateDefinition()
862 {
863 return "gate cy a,b { sdg b; CX a,b; s b; }\n";
864 }
865
866 static std::string CHGateDefinition()
867 {
868 return "gate ch a,b { h b; sdg b; CX a,b; h b; t b; CX a,b; t b; h b; s b; "
869 "x b; s a; }\n";
870 }
871
872 static std::string CCXGateDefinition()
873 {
874 return "gate ccx a,b,c\
875 {\
876 h c;\
877 cx b, c; tdg c;\
878 cx a, c; t c;\
879 cx b, c; tdg c;\
880 cx a, c; t b; t c; h c;\
881 cx a, b; t a; tdg b;\
882 cx a, b;\
883 }\n";
884 }
885
886 static std::string CU1GateDefinition()
887 {
888 return "gate cu1(lambda) a,b { U(0,0,lambda/2) a; CX a,b; U(0,0,-lambda/2) "
889 "b; CX a,b; U(0,0,lambda/2) b; }\n";
890 }
891
892 static std::string CU3GateDefinition()
893 {
894 return "gate cu3(theta,phi,lambda) c,t { U(0,0,(lambda+phi)/2) c; "
895 "U(0,0,(lambda-phi)/2) t; CX c,t; U(-theta/2,0,-(phi+lambda)/2) t; "
896 "CX c,t; U(theta/2,phi,0) t; }\n";
897 }
898
899 //*************************************************************************************************
900 // defined here, not in the 'standard' header
901
902 static std::string CRXGateDefinition()
903 {
904 return "gate crx(theta) a,b { cu3(theta,-pi/2,pi/2) a,b; }\n";
905 }
906
907 static std::string CRYGateDefinition()
908 {
909 return "gate cry(theta) a,b { cu3(theta,0,0) a,b; }\n";
910 }
911
912 static std::string CRZGateDefinition()
913 {
914 return "gate crz(lambda) a,b { U(0,0,lambda/2) b; CX a,b; U(0,0,-lambda/2) "
915 "b; CX a,b; }\n";
916 }
917
918 static std::string CSGateDefinition()
919 {
920 return "gate cs c,t { U(0,0,pi/4) c; U(0,0,pi/4) t; CX c,t; U(0,0,-pi/4) "
921 "t; CX c,t; }\n";
922 }
923
924 static std::string CSDAGGateDefinition()
925 {
926 return "gate csdag c,t { CX c,t; U(0,0,pi/4) t; CX c,t; U(0,0,-pi/4) c; "
927 "U(0,0,-pi/4) t; }\n";
928 }
929
930 static std::string CSXGateDefinition()
931 {
932 return "gate csx c,t { U(pi/2,0,pi) t; cs c,t; U(pi/2,0,pi) t; }\n";
933 }
934
935 static std::string CSXDAGGateDefinition()
936 {
937 return "gate csxdag c,t { U(pi/2,0,pi) t; csdag c,t; U(pi/2,0,pi) t; }\n";
938 }
939};
940
941} // namespace qasm
942
943#endif
Circuit class for holding the sequence of operations.
Definition Circuit.h:51
The operation interface.
Definition Operations.h:402
static std::string Generate(const std::shared_ptr< Circuits::Circuit< Time > > &circuit, QasmVersion version=QasmVersion::V2)
Definition CircQasm.h:90
static std::string GenerateWithMapping(const std::shared_ptr< Circuits::Circuit< Time > > &circuit, const std::unordered_map< Types::qubit_t, Types::qubit_t > &bitsMap, QasmVersion version=QasmVersion::V2)
Definition CircQasm.h:75
@ kConditionalGate
conditional gate, similar with gate, but conditioned on something from 'OperationState'
Definition Operations.h:33
@ kDelay
a delay or idle period on one or more qubits
Definition Operations.h:50
@ kNoOp
no operation, just a placeholder, could be used to erase some operation from a circuit
Definition Operations.h:44
@ kComposite
a composite operation, contains other operations - should not be used in the beginning,...
Definition Operations.h:46
@ kRandomGen
random classical bit generator, result in 'OperationState'
Definition Operations.h:32
@ kConditionalRandomGen
conditional random generator, similar with random gen, but conditioned on something from 'OperationSt...
Definition Operations.h:38
@ kConditionalMeasurement
conditional measurement, similar with measurement, but conditioned on something from 'OperationState'
Definition Operations.h:35
@ kMeasurement
measurement, result in 'OperationState'
Definition Operations.h:31
@ kGate
the usual quantum gate, result stays in simulator's state
Definition Operations.h:30
@ kReset
reset, no result in 'state', just apply measurement, then apply not on all qubits that were measured ...
Definition Operations.h:41
@ kQuantumChannel
a non-unitary CPTP operation on the simulator state
Definition Operations.h:49