diff --git a/src/circuit/quantumcircuit_impl.hpp b/src/circuit/quantumcircuit_impl.hpp index 55d7dc6..9f9fca2 100644 --- a/src/circuit/quantumcircuit_impl.hpp +++ b/src/circuit/quantumcircuit_impl.hpp @@ -1506,16 +1506,29 @@ std::string QuantumCircuit::to_qasm3(void) } qk_opcounts_clear(&opcounts); - // registers - std::string creg_name = "c"; - std::string qreg_name = "q"; - qasm3 << "bit[" << num_clbits() << "] " << creg_name << ";" << std::endl; - qasm3 << "qubit[" << num_qubits() << "] " << qreg_name << ";" << std::endl; - // save ops uint_t nops; nops = qk_circuit_num_instructions(rust_circuit_.get()); + // Declare registers + // After transpilation, qubit registers will be mapped to physical registers, + // so we need to combined them in a single quantum register "q"; + const std::string qreg_name = "q"; + qasm3 << "qubit[" << num_qubits() << "] " << qreg_name << ";" << std::endl; + for(const auto& creg : cregs_) + { + qasm3 << "bit[" << creg.size() << "] " << creg.name() << ";" << std::endl; + } + + auto recover_reg_data = [this](uint_t index) -> std::pair + { + auto it = std::upper_bound(cregs_.begin(), cregs_.end(), index, + [](uint_t v, const ClassicalRegister& reg) { return v < reg.base_index(); }); + assert(it != cregs_.begin()); + it = std::prev(it); + return std::make_pair(it->name(), index - it->base_index()); + }; + for (uint_t i = 0; i < nops; i++) { QkCircuitInstruction *op = new QkCircuitInstruction; @@ -1526,7 +1539,8 @@ std::string QuantumCircuit::to_qasm3(void) { for (uint_t j = 0; j < op->num_qubits; j++) { - qasm3 << creg_name << "[" << op->clbits[j] << "] = " << op->name << " " << qreg_name << "[" << op->qubits[j] << "];" << std::endl; + const auto creg_data = recover_reg_data(op->clbits[j]); + qasm3 << creg_data.first << "[" << creg_data.second << "] = " << op->name << " " << qreg_name << "[" << op->qubits[j] << "];" << std::endl; } } } diff --git a/src/circuit/register.hpp b/src/circuit/register.hpp index 3189e9d..b0b2b92 100644 --- a/src/circuit/register.hpp +++ b/src/circuit/register.hpp @@ -146,7 +146,7 @@ class Register /// @brief Return the size of this register /// @return the size of this register - uint_t size(void) { return size_; } + uint_t size(void) const { return size_; } /// @brief Return the name of this register /// @return the name of this register @@ -157,6 +157,10 @@ class Register base_index_ = base; } + /// @brief Return the base index of this register + /// @return the base index of this register + uint_t base_index() const { return base_index_; } + Bit &operator[](const uint_t i) { return bits_[i]; } protected: diff --git a/test/test_circuit.cpp b/test/test_circuit.cpp index 53182e2..8f402de 100644 --- a/test/test_circuit.cpp +++ b/test/test_circuit.cpp @@ -614,6 +614,35 @@ static int test_compose(void) { return Ok; } +static int test_to_qasm3_multi_regs(void) { + auto qreg1 = QuantumRegister(2, std::string("q1")); + auto qreg2 = QuantumRegister(1, std::string("q2")); + auto creg1 = ClassicalRegister(2, std::string("c1")); + auto creg2 = ClassicalRegister(1, std::string("c2")); + QuantumCircuit circ(std::vector({qreg1, qreg2}), std::vector({creg1, creg2})); + + circ.measure(qreg2, creg2); + circ.measure(qreg1, creg1); + + const auto actual = circ.to_qasm3(); + const std::string expected = + "OPENQASM 3.0;\n" + "include \"stdgates.inc\";\n" + "qubit[3] q;\n" + "bit[2] c1;\n" + "bit[1] c2;\n" + "c2[0] = measure q[2];\n" + "c1[0] = measure q[0];\n" + "c1[1] = measure q[1];\n"; + if (actual != expected) { + std::cerr << " to_qasm3_multi_regs test : \n expected:\n" << expected + << "\n actual:\n" << actual << std::endl; + return EqualityError; + } + + return Ok; +} + extern "C" int test_circuit(void) { int num_failed = 0; @@ -621,6 +650,7 @@ extern "C" int test_circuit(void) { num_failed += RUN_TEST(test_measure); num_failed += RUN_TEST(test_append); num_failed += RUN_TEST(test_compose); + num_failed += RUN_TEST(test_to_qasm3_multi_regs); std::cerr << "=== Number of failed subtests: " << num_failed << std::endl; return num_failed;