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