23template <
typename Time = Types::time_type>
class CircToQasm
78 const auto mappedCircuit = std::static_pointer_cast<Circuits::Circuit<Time>>(circuit->Remap(bitsMap, bitsMap));
80 return GenerateFromCircuit(mappedCircuit,
false, version);
92 return GenerateFromCircuit(circuit,
true, version);
101 const auto circ = (clone ? std::static_pointer_cast<Circuits::Circuit<Time>>(circuit->Clone()) : circuit);
103 circ->ConvertForDistribution();
105 std::string
qasm = QasmHeader(version);
107 qasm += QasmGatesAndRegsDefinitions(circ, version);
110 for (
const auto &gate : circ->GetOperations())
111 qasm += OperationToQasm(gate, version);
120 switch (operation->GetType())
123 qasm += GateToQasm(operation, version);
126 auto qbits = operation->AffectedQubits();
127 auto bits = operation->AffectedBits();
129 assert(qbits.size() == bits.size());
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";
137 auto qbits = operation->AffectedQubits();
138 for (
const auto &qbit : qbits)
139 qasm +=
"reset q[" + std::to_string(qbit) +
"];\n";
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());
153 const auto theop = condop->GetOperation();
157 for (
size_t i = 0; i < bits.size(); ++i)
163 qasm +=
"c" + std::to_string(bits[i]) +
"[0]";
167 const std::string body = OperationToQasm(theop, version);
168 size_t lineStart = 0;
169 while (lineStart < body.size())
171 const size_t lineEnd = body.find(
'\n', lineStart);
172 qasm +=
" " + body.substr(lineStart, lineEnd - lineStart) +
"\n";
173 if (lineEnd == std::string::npos)
175 lineStart = lineEnd + 1;
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);
188 qasm +=
"barrier q;\n";
191 auto delayOp = std::static_pointer_cast<Circuits::Delay<Time>>(operation);
192 auto qbit = delayOp->GetQubit();
193 auto dur = delayOp->GetDuration();
196 qasm +=
"delay[" + std::to_string(dur) +
"s] q[" + std::to_string(qbit) +
"];\n";
200 qasm +=
"delay(" + std::to_string(dur) +
") q[" + std::to_string(qbit) +
"];\n";
211 throw std::runtime_error(
"Not supported!");
218 static std::string GateToQasm(
const std::shared_ptr<Circuits::IOperation<Time>> &operation,
QasmVersion version =
QasmVersion::V2)
223 const auto gate = std::static_pointer_cast<Circuits::IQuantumGate<Time>>(operation);
227 switch (gate->GetGateType())
230 qasm +=
"U(0,0," + std::to_string(gate->GetParams()[0]) +
") q[" + std::to_string(gate->GetQubit(0)) +
"];\n";
233 qasm +=
"x q[" + std::to_string(gate->GetQubit(0)) +
"];\n";
236 qasm +=
"y q[" + std::to_string(gate->GetQubit(0)) +
"];\n";
239 qasm +=
"z q[" + std::to_string(gate->GetQubit(0)) +
"];\n";
242 qasm +=
"h q[" + std::to_string(gate->GetQubit(0)) +
"];\n";
245 qasm +=
"s q[" + std::to_string(gate->GetQubit(0)) +
"];\n";
248 qasm +=
"sdg q[" + std::to_string(gate->GetQubit(0)) +
"];\n";
251 qasm +=
"t q[" + std::to_string(gate->GetQubit(0)) +
"];\n";
254 qasm +=
"tdg q[" + std::to_string(gate->GetQubit(0)) +
"];\n";
260 qasm +=
"sx q[" + std::to_string(gate->GetQubit(0)) +
"];\n";
263 qasm +=
"sxdg q[" + std::to_string(gate->GetQubit(0)) +
"];\n";
266 qasm +=
"k q[" + std::to_string(gate->GetQubit(0)) +
"];\n";
271 qasm +=
"rx(" + std::to_string(gate->GetParams()[0]) +
") q[" + std::to_string(gate->GetQubit(0)) +
"];\n";
274 qasm +=
"ry(" + std::to_string(gate->GetParams()[0]) +
") q[" + std::to_string(gate->GetQubit(0)) +
"];\n";
277 qasm +=
"rz(" + std::to_string(gate->GetParams()[0]) +
") q[" + std::to_string(gate->GetQubit(0)) +
"];\n";
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";
284 throw std::runtime_error(
"U with gamma non zero not supported yet!");
289 qasm +=
"CX q[" + std::to_string(gate->GetQubit(0)) +
"],q[" + std::to_string(gate->GetQubit(1)) +
"];\n";
292 qasm +=
"cy q[" + std::to_string(gate->GetQubit(0)) +
"],q[" + std::to_string(gate->GetQubit(1)) +
"];\n";
295 qasm +=
"cz q[" + std::to_string(gate->GetQubit(0)) +
"],q[" + std::to_string(gate->GetQubit(1)) +
"];\n";
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";
305 qasm +=
"crx(" + std::to_string(gate->GetParams()[0]) +
") q[" + std::to_string(gate->GetQubit(0)) +
"],q[" + std::to_string(gate->GetQubit(1)) +
309 qasm +=
"cry(" + std::to_string(gate->GetParams()[0]) +
") q[" + std::to_string(gate->GetQubit(0)) +
"],q[" + std::to_string(gate->GetQubit(1)) +
315 qasm +=
"crz(" + std::to_string(gate->GetParams()[0]) +
") q[" + std::to_string(gate->GetQubit(0)) +
"],q[" + std::to_string(gate->GetQubit(1)) +
319 qasm +=
"ch q[" + std::to_string(gate->GetQubit(0)) +
"],q[" + std::to_string(gate->GetQubit(1)) +
"];\n";
325 qasm +=
"csx q[" + std::to_string(gate->GetQubit(0)) +
"],q[" + std::to_string(gate->GetQubit(1)) +
"];\n";
328 qasm +=
"csxdag q[" + std::to_string(gate->GetQubit(0)) +
"],q[" + std::to_string(gate->GetQubit(1)) +
"];\n";
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)) +
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)) +
343 throw std::runtime_error(
"CU with gamma non zero not supported yet!");
349 qasm +=
"swap q[" + std::to_string(gate->GetQubit(0)) +
"],q[" + std::to_string(gate->GetQubit(1)) +
"];\n";
356 throw std::runtime_error(
"Not supported!");
367 std::string qasm = (version ==
QasmVersion::V3) ?
"OPENQASM 3.0;\n" :
"OPENQASM 2.0;\n";
374 static std::string QasmRegisters(
const std::shared_ptr<Circuits::Circuit<Time>> &circuit,
QasmVersion version =
QasmVersion::V2)
376 const auto nrq = circuit->GetMaxQubitIndex() + 1;
378 const std::string nrq_str = std::to_string(nrq);
380 std::string qasm = (version ==
QasmVersion::V3) ?
"qubit[" + nrq_str +
"] q;\n" :
"qreg q[" + nrq_str +
"];\n";
382 std::set<size_t> measQubits;
384 for (
const auto &op : *circuit)
386 std::vector<std::shared_ptr<Circuits::IOperation<Time>>> pending{op};
387 while (!pending.empty())
389 const auto current = pending.back();
392 for (
const auto bit : current->AffectedBits())
393 measQubits.insert(bit);
397 pending.push_back(std::static_pointer_cast<Circuits::IConditionalOperation<Time>>(current)->GetOperation());
403 for (
auto bit : measQubits)
408 if (creg_count <
static_cast<int>(bit))
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";
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;
422 static std::string QasmGatesAndRegsDefinitions(
const std::shared_ptr<Circuits::Circuit<Time>> &circuit,
QasmVersion version =
QasmVersion::V2)
428 for (
const auto &op : circuit->GetOperations())
430 const auto opType = op->GetType();
433 const auto &gate = std::static_pointer_cast<Circuits::IQuantumGate<Time>>(
437 switch (gate->GetGateType())
440#ifdef DONT_USE_HEADER_DEFINITIONS
447#ifdef DONT_USE_HEADER_DEFINITIONS
454#ifdef DONT_USE_HEADER_DEFINITIONS
461#ifdef DONT_USE_HEADER_DEFINITIONS
468#ifdef DONT_USE_HEADER_DEFINITIONS
475#ifdef DONT_USE_HEADER_DEFINITIONS
482#ifdef DONT_USE_HEADER_DEFINITIONS
489#ifdef DONT_USE_HEADER_DEFINITIONS
496#ifdef DONT_USE_HEADER_DEFINITIONS
506#ifdef DONT_USE_HEADER_DEFINITIONS
517#ifndef DONT_USE_HEADER_DEFINITIONS
523#ifndef DONT_USE_HEADER_DEFINITIONS
530#ifdef DONT_USE_HEADER_DEFINITIONS
537#ifdef DONT_USE_HEADER_DEFINITIONS
544#ifdef DONT_USE_HEADER_DEFINITIONS
552#ifdef DONT_USE_HEADER_DEFINITIONS
561#ifndef DONT_USE_HEADER_DEFINITIONS
566#ifdef DONT_USE_HEADER_DEFINITIONS
575#ifdef DONT_USE_HEADER_DEFINITIONS
583#ifdef DONT_USE_HEADER_DEFINITIONS
593#ifdef DONT_USE_HEADER_DEFINITIONS
603#ifdef DONT_USE_HEADER_DEFINITIONS
615#ifdef DONT_USE_HEADER_DEFINITIONS
622#ifdef DONT_USE_HEADER_DEFINITIONS
652 else if (gate->GetParams()[3] == 0)
654#ifdef DONT_USE_HEADER_DEFINITIONS
661 throw std::runtime_error(
"CU with gamma non zero not supported yet!");
674 throw std::runtime_error(
"Not supported!");
685 qasm += (version ==
QasmVersion::V3) ?
"include \"stdgates.inc\";\n" :
"include \"qelib1.inc\";\n";
687 qasm += QasmRegisters(circuit, version);
693 qasm += XGateDefinition();
695 qasm += YGateDefinition();
697 qasm += ZGateDefinition();
699 qasm += HGateDefinition();
701 qasm += SGateDefinition();
703 qasm += SDGGateDefinition();
706 qasm += SxGateDefinition();
708 qasm += SxDGGateDefinition();
711 qasm += KGateDefinition();
714 qasm += TGateDefinition();
716 qasm += TDGGateDefinition();
719 qasm += RxGateDefinition();
721 qasm += RyGateDefinition();
723 qasm += RzGateDefinition();
726 qasm += CZGateDefinition();
728 qasm += CYGateDefinition();
730 qasm += CHGateDefinition();
734 qasm += CRZGateDefinition();
736 qasm += CU1GateDefinition();
738 qasm += CU3GateDefinition();
740 qasm += CRXGateDefinition();
742 qasm += CRYGateDefinition();
744 qasm += SwapGateDefinition();
747 qasm += CSGateDefinition();
749 qasm += CSDAGGateDefinition();
752 qasm += CSXGateDefinition();
754 qasm += CSXDAGGateDefinition();
760 static std::string U3GateDefinition()
762 return "gate u3(theta,phi,lambda) q { U(theta,phi,lambda) q; }\n";
765 static std::string U2GateDefinition()
767 return "gate u2(phi,lambda) q { U(pi/2,phi,lambda) q; }\n";
770 static std::string U1GateDefinition()
772 return "gate u1(lambda) q { U(0,0,lambda) q; }\n";
775 static std::string XGateDefinition()
777 return "gate x a { U(pi,0,pi) a; }\n";
780 static std::string YGateDefinition()
782 return "gate y a { U(pi,pi/2,pi/2) a; }\n";
785 static std::string ZGateDefinition()
787 return "gate z a { U(0,0,pi) a; }\n";
790 static std::string HGateDefinition()
792 return "gate h a { U(pi/2,0,pi) a; }\n";
795 static std::string SGateDefinition()
797 return "gate s a { U(0,0,pi/2) a; }\n";
800 static std::string SDGGateDefinition()
802 return "gate sdg a { U(0,0,-pi/2) a; }\n";
807 static std::string SxGateDefinition()
809 return "gate sx a { U(pi/2,-pi/2,pi/2) a; }\n";
814 static std::string SxDGGateDefinition()
816 return "gate sxdg a { U(-pi/2,-pi/2,pi/2) a; }\n";
819 static std::string KGateDefinition()
821 return "gate k a { U(pi/2,pi/2,pi/2) a; }\n";
824 static std::string TGateDefinition()
826 return "gate t a { U(0,0,pi/4) a; }\n";
829 static std::string TDGGateDefinition()
831 return "gate tdg a { U(0,0,-pi/4) a; }\n";
834 static std::string RxGateDefinition()
836 return "gate rx(theta) a { U(theta,-pi/2,pi/2) a; }\n";
839 static std::string RyGateDefinition()
841 return "gate ry(theta) a { U(theta,0,0) a; }\n";
844 static std::string RzGateDefinition()
846 return "gate rz(phi) a { U(0,0,phi) a; }\n";
849 static std::string SwapGateDefinition()
851 return "gate swap a,b { CX a,b; CX b,a; CX a,b; }\n";
856 static std::string CZGateDefinition()
858 return "gate cz a,b { h b; CX a,b; h b; }\n";
861 static std::string CYGateDefinition()
863 return "gate cy a,b { sdg b; CX a,b; s b; }\n";
866 static std::string CHGateDefinition()
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; "
872 static std::string CCXGateDefinition()
874 return "gate ccx a,b,c\
880 cx a, c; t b; t c; h c;\
881 cx a, b; t a; tdg b;\
886 static std::string CU1GateDefinition()
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";
892 static std::string CU3GateDefinition()
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";
902 static std::string CRXGateDefinition()
904 return "gate crx(theta) a,b { cu3(theta,-pi/2,pi/2) a,b; }\n";
907 static std::string CRYGateDefinition()
909 return "gate cry(theta) a,b { cu3(theta,0,0) a,b; }\n";
912 static std::string CRZGateDefinition()
914 return "gate crz(lambda) a,b { U(0,0,lambda/2) b; CX a,b; U(0,0,-lambda/2) "
918 static std::string CSGateDefinition()
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) "
924 static std::string CSDAGGateDefinition()
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";
930 static std::string CSXGateDefinition()
932 return "gate csx c,t { U(pi/2,0,pi) t; cs c,t; U(pi/2,0,pi) t; }\n";
935 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";