21template <
typename Time = Types::time_type>
class CircToQasm {
64 const std::unordered_map<Types::qubit_t, Types::qubit_t> &bitsMap) {
65 const auto mappedCircuit =
66 std::static_pointer_cast<Circuits::Circuit<Time>>(
67 circuit->Remap(bitsMap, bitsMap));
69 return GenerateFromCircuit(mappedCircuit,
false);
81 return GenerateFromCircuit(circuit,
true);
92 (clone ? std::static_pointer_cast<Circuits::Circuit<Time>>(
96 circ->ConvertForDistribution();
98 std::string
qasm = QasmHeader();
100 qasm += QasmGatesAndRegsDefinitions(circ);
103 for (
const auto &gate : circ->GetOperations())
104 qasm += OperationToQasm(gate);
109 static std::string OperationToQasm(
113 switch (operation->GetType()) {
115 qasm += GateToQasm(operation);
118 auto qbits = operation->AffectedQubits();
119 auto bits = operation->AffectedBits();
121 assert(qbits.size() == bits.size());
123 for (
size_t i = 0; i < qbits.size(); ++i)
124 qasm +=
"measure q[" + std::to_string(qbits[i]) +
"]->c" +
125 std::to_string(bits[i]) +
"[0];\n";
128 auto qbits = operation->AffectedQubits();
129 for (
const auto &qbit : qbits)
130 qasm +=
"reset q[" + std::to_string(qbit) +
"];\n";
139 std::static_pointer_cast<Circuits::IConditionalOperation<Time>>(
141 auto bits = condop->AffectedBits();
142 auto vals = std::static_pointer_cast<Circuits::EqualCondition>(
143 condop->GetCondition())
145 assert(bits.size() == vals.size());
147 for (
size_t i = 0; i < bits.size(); ++i)
148 qasm +=
"if(c" + std::to_string(bits[i]) +
149 "==" + std::to_string(vals[i] ? 1 : 0) +
") ";
151 const auto theop = condop->GetOperation();
152 qasm += OperationToQasm(theop);
156 qasm +=
"barrier q;\n";
163 throw std::runtime_error(
"Not supported!");
171 GateToQasm(
const std::shared_ptr<Circuits::IOperation<Time>> &operation) {
176 std::static_pointer_cast<Circuits::IQuantumGate<Time>>(operation);
180 switch (gate->GetGateType()) {
182 qasm +=
"U(0,0," + std::to_string(gate->GetParams()[0]) +
") q[" +
183 std::to_string(gate->GetQubit(0)) +
"];\n";
186 qasm +=
"x q[" + std::to_string(gate->GetQubit(0)) +
"];\n";
189 qasm +=
"y q[" + std::to_string(gate->GetQubit(0)) +
"];\n";
192 qasm +=
"z q[" + std::to_string(gate->GetQubit(0)) +
"];\n";
195 qasm +=
"h q[" + std::to_string(gate->GetQubit(0)) +
"];\n";
198 qasm +=
"s q[" + std::to_string(gate->GetQubit(0)) +
"];\n";
201 qasm +=
"sdg q[" + std::to_string(gate->GetQubit(0)) +
"];\n";
204 qasm +=
"t q[" + std::to_string(gate->GetQubit(0)) +
"];\n";
207 qasm +=
"tdg q[" + std::to_string(gate->GetQubit(0)) +
"];\n";
213 qasm +=
"sx q[" + std::to_string(gate->GetQubit(0)) +
"];\n";
216 qasm +=
"sxdg q[" + std::to_string(gate->GetQubit(0)) +
"];\n";
219 qasm +=
"k q[" + std::to_string(gate->GetQubit(0)) +
"];\n";
224 qasm +=
"rx(" + std::to_string(gate->GetParams()[0]) +
") q[" +
225 std::to_string(gate->GetQubit(0)) +
"];\n";
228 qasm +=
"ry(" + std::to_string(gate->GetParams()[0]) +
") q[" +
229 std::to_string(gate->GetQubit(0)) +
"];\n";
232 qasm +=
"rz(" + std::to_string(gate->GetParams()[0]) +
") q[" +
233 std::to_string(gate->GetQubit(0)) +
"];\n";
236 if (gate->GetParams()[3] == 0)
237 qasm +=
"U(" + std::to_string(gate->GetParams()[0]) +
"," +
238 std::to_string(gate->GetParams()[1]) +
"," +
239 std::to_string(gate->GetParams()[2]) +
") q[" +
240 std::to_string(gate->GetQubit(0)) +
"];\n";
242 throw std::runtime_error(
"U with gamma non zero not supported yet!");
247 qasm +=
"CX q[" + std::to_string(gate->GetQubit(0)) +
"],q[" +
248 std::to_string(gate->GetQubit(1)) +
"];\n";
251 qasm +=
"cy q[" + std::to_string(gate->GetQubit(0)) +
"],q[" +
252 std::to_string(gate->GetQubit(1)) +
"];\n";
255 qasm +=
"cz q[" + std::to_string(gate->GetQubit(0)) +
"],q[" +
256 std::to_string(gate->GetQubit(1)) +
"];\n";
259 qasm +=
"cu1(" + std::to_string(gate->GetParams()[0]) +
") q[" +
260 std::to_string(gate->GetQubit(0)) +
"],q[" +
261 std::to_string(gate->GetQubit(1)) +
"];\n";
267 qasm +=
"crx(" + std::to_string(gate->GetParams()[0]) +
") q[" +
268 std::to_string(gate->GetQubit(0)) +
"],q[" +
269 std::to_string(gate->GetQubit(1)) +
"];\n";
272 qasm +=
"cry(" + std::to_string(gate->GetParams()[0]) +
") q[" +
273 std::to_string(gate->GetQubit(0)) +
"],q[" +
274 std::to_string(gate->GetQubit(1)) +
"];\n";
279 qasm +=
"crz(" + std::to_string(gate->GetParams()[0]) +
") q[" +
280 std::to_string(gate->GetQubit(0)) +
"],q[" +
281 std::to_string(gate->GetQubit(1)) +
"];\n";
284 qasm +=
"ch q[" + std::to_string(gate->GetQubit(0)) +
"],q[" +
285 std::to_string(gate->GetQubit(1)) +
"];\n";
291 qasm +=
"csx q[" + std::to_string(gate->GetQubit(0)) +
"],q[" +
292 std::to_string(gate->GetQubit(1)) +
"];\n";
295 qasm +=
"csxdag q[" + std::to_string(gate->GetQubit(0)) +
"],q[" +
296 std::to_string(gate->GetQubit(1)) +
"];\n";
302 if (gate->GetParams()[3] == 0)
303 qasm +=
"cu3(" + std::to_string(gate->GetParams()[0]) +
"," +
304 std::to_string(gate->GetParams()[1]) +
"," +
305 std::to_string(gate->GetParams()[2]) +
") q[" +
306 std::to_string(gate->GetQubit(0)) +
"], q[" +
307 std::to_string(gate->GetQubit(1)) +
"];\n";
309 throw std::runtime_error(
"CU with gamma non zero not supported yet!");
315 qasm +=
"swap q[" + std::to_string(gate->GetQubit(0)) +
"],q[" +
316 std::to_string(gate->GetQubit(1)) +
"];\n";
323 throw std::runtime_error(
"Not supported!");
330 static std::string QasmHeader() {
331 std::string qasm =
"OPENQASM 2.0;\n";
339 QasmRegisters(
const std::shared_ptr<Circuits::Circuit<Time>> &circuit) {
340 const auto nrq = circuit->GetMaxQubitIndex() + 1;
342 const std::string nrq_str = std::to_string(nrq);
344 std::string qasm =
"qreg q[" + nrq_str +
"];\n";
346 std::set<size_t> measQubits;
348 for (
const auto &op : *circuit) {
349 const auto bits = op->AffectedBits();
351 for (
auto bit : bits)
352 measQubits.insert(bit);
356 for (
auto bit : measQubits) {
360 if (creg_count <
static_cast<int>(bit))
361 qasm +=
"creg c" + std::to_string(creg_count) +
"[" +
362 std::to_string(bit - creg_count) +
"];\n";
364 qasm +=
"creg c" + std::to_string(bit) +
"[1];\n";
365 creg_count = bit + 1;
371 static std::string QasmGatesAndRegsDefinitions(
372 const std::shared_ptr<Circuits::Circuit<Time>> &circuit) {
378 for (
const auto &op : circuit->GetOperations()) {
379 const auto opType = op->GetType();
383 std::static_pointer_cast<Circuits::IQuantumGate<Time>>(
385 ? std::static_pointer_cast<
386 Circuits::IConditionalOperation<Time>>(op)
390 switch (gate->GetGateType()) {
392#ifdef DONT_USE_HEADER_DEFINITIONS
399#ifdef DONT_USE_HEADER_DEFINITIONS
406#ifdef DONT_USE_HEADER_DEFINITIONS
413#ifdef DONT_USE_HEADER_DEFINITIONS
420#ifdef DONT_USE_HEADER_DEFINITIONS
427#ifdef DONT_USE_HEADER_DEFINITIONS
434#ifdef DONT_USE_HEADER_DEFINITIONS
441#ifdef DONT_USE_HEADER_DEFINITIONS
448#ifdef DONT_USE_HEADER_DEFINITIONS
459#ifndef DONT_USE_HEADER_DEFINITIONS
465#ifndef DONT_USE_HEADER_DEFINITIONS
471#ifndef DONT_USE_HEADER_DEFINITIONS
478#ifdef DONT_USE_HEADER_DEFINITIONS
485#ifdef DONT_USE_HEADER_DEFINITIONS
492#ifdef DONT_USE_HEADER_DEFINITIONS
500#ifdef DONT_USE_HEADER_DEFINITIONS
509#ifndef DONT_USE_HEADER_DEFINITIONS
514#ifdef DONT_USE_HEADER_DEFINITIONS
523#ifdef DONT_USE_HEADER_DEFINITIONS
531#ifdef DONT_USE_HEADER_DEFINITIONS
542#ifdef DONT_USE_HEADER_DEFINITIONS
550#ifdef DONT_USE_HEADER_DEFINITIONS
559#ifdef DONT_USE_HEADER_DEFINITIONS
566#ifdef DONT_USE_HEADER_DEFINITIONS
592 if (gate->GetParams()[3] == 0) {
593#ifdef DONT_USE_HEADER_DEFINITIONS
599 throw std::runtime_error(
600 "CU with gamma non zero not supported yet!");
613 throw std::runtime_error(
"Not supported!");
622 qasm +=
"include \"qelib1.inc\";\n";
624 qasm += QasmRegisters(circuit);
630 qasm += XGateDefinition();
632 qasm += YGateDefinition();
634 qasm += ZGateDefinition();
636 qasm += HGateDefinition();
638 qasm += SGateDefinition();
640 qasm += SDGGateDefinition();
643 qasm += SxGateDefinition();
645 qasm += SxDGGateDefinition();
648 qasm += KGateDefinition();
651 qasm += TGateDefinition();
653 qasm += TDGGateDefinition();
656 qasm += RxGateDefinition();
658 qasm += RyGateDefinition();
660 qasm += RzGateDefinition();
663 qasm += CZGateDefinition();
665 qasm += CYGateDefinition();
667 qasm += CHGateDefinition();
671 qasm += CRZGateDefinition();
673 qasm += CU1GateDefinition();
675 qasm += CU3GateDefinition();
677 qasm += CRXGateDefinition();
679 qasm += CRYGateDefinition();
681 qasm += SwapGateDefinition();
684 qasm += CSGateDefinition();
686 qasm += CSDAGGateDefinition();
689 qasm += CSXGateDefinition();
691 qasm += CSXDAGGateDefinition();
697 static std::string U3GateDefinition() {
698 return "gate u3(theta,phi,lambda) q { U(theta,phi,lambda) q; }\n";
701 static std::string U2GateDefinition() {
702 return "gate u2(phi,lambda) q { U(pi/2,phi,lambda) q; }\n";
705 static std::string U1GateDefinition() {
706 return "gate u1(lambda) q { U(0,0,lambda) q; }\n";
709 static std::string XGateDefinition() {
710 return "gate x a { U(pi,0,pi) a; }\n";
713 static std::string YGateDefinition() {
714 return "gate y a { U(pi,pi/2,pi/2) a; }\n";
717 static std::string ZGateDefinition() {
return "gate z a { U(0,0,pi) a; }\n"; }
719 static std::string HGateDefinition() {
720 return "gate h a { U(pi/2,0,pi) a; }\n";
723 static std::string SGateDefinition() {
724 return "gate s a { U(0,0,pi/2) a; }\n";
727 static std::string SDGGateDefinition() {
728 return "gate sdg a { U(0,0,-pi/2) a; }\n";
733 static std::string SxGateDefinition() {
734 return "gate sx a { U(pi/2,-pi/2,pi/2) a; }\n";
739 static std::string SxDGGateDefinition() {
740 return "gate sxdg a { U(-pi/2,-pi/2,pi/2) a; }\n";
743 static std::string KGateDefinition() {
744 return "gate k a { U(pi/2,pi/2,pi/2) a; }\n";
747 static std::string TGateDefinition() {
748 return "gate t a { U(0,0,pi/4) a; }\n";
751 static std::string TDGGateDefinition() {
752 return "gate tdg a { U(0,0,-pi/4) a; }\n";
755 static std::string RxGateDefinition() {
756 return "gate rx(theta) a { U(theta,-pi/2,pi/2) a; }\n";
759 static std::string RyGateDefinition() {
760 return "gate ry(theta) a { U(theta,0,0) a; }\n";
763 static std::string RzGateDefinition() {
764 return "gate rz(phi) a { U(0,0,phi) a; }\n";
767 static std::string SwapGateDefinition() {
768 return "gate swap a,b { CX a,b; CX b,a; CX a,b; }\n";
773 static std::string CZGateDefinition() {
774 return "gate cz a,b { h b; CX a,b; h b; }\n";
777 static std::string CYGateDefinition() {
778 return "gate cy a,b { sdg b; CX a,b; s b; }\n";
781 static std::string CHGateDefinition() {
782 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; "
786 static std::string CCXGateDefinition() {
787 return "gate ccx a,b,c\
793 cx a, c; t b; t c; h c;\
794 cx a, b; t a; tdg b;\
799 static std::string CU1GateDefinition() {
800 return "gate cu1(lambda) a,b { U(0,0,lambda/2) a; CX a,b; U(0,0,-lambda/2) "
801 "b; CX a,b; U(0,0,lambda/2) b; }\n";
804 static std::string CU3GateDefinition() {
805 return "gate cu3(theta,phi,lambda) c,t { U(0,0,(lambda+phi)/2) c; "
806 "U(0,0,(lambda-phi)/2) t; CX c,t; U(-theta/2,0,-(phi+lambda)/2) t; "
807 "CX c,t; U(theta/2,phi,0) t; }\n";
813 static std::string CRXGateDefinition() {
814 return "gate crx(theta) a,b { cu3(theta,-pi/2,pi/2) a,b; }\n";
817 static std::string CRYGateDefinition() {
818 return "gate cry(theta) a,b { cu3(theta,0,0) a,b; }\n";
821 static std::string CRZGateDefinition() {
822 return "gate crz(lambda) a,b { U(0,0,lambda/2) b; CX a,b; U(0,0,-lambda/2) "
826 static std::string CSGateDefinition() {
827 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) "
831 static std::string CSDAGGateDefinition() {
832 return "gate csdag c,t { CX c,t; U(0,0,pi/4) t; CX c,t; U(0,0,-pi/4) c; "
833 "U(0,0,-pi/4) t; }\n";
836 static std::string CSXGateDefinition() {
837 return "gate csx c,t { U(pi/2,0,pi) t; cs c,t; U(pi/2,0,pi) t; }\n";
840 static std::string CSXDAGGateDefinition() {
841 return "gate csxdag c,t { U(pi/2,0,pi) t; csdag c,t; U(pi/2,0,pi) t; }\n";