Loading examples/CMakeLists.txt +20 −7 Original line number Diff line number Diff line Loading @@ -10,6 +10,17 @@ function(add_qcor_compile_and_exe_test test_name relative_source_location) ) endfunction() # Compile with FTQC runtime and execute function(add_qcor_ftqc_compile_and_exe_test test_name relative_source_location) add_test( NAME ${test_name} COMMAND bash -c "${CMAKE_BINARY_DIR}/qcor -qrt ftqc ${CMAKE_CURRENT_SOURCE_DIR}/${relative_source_location} -o ${test_name}; \ ${CMAKE_CURRENT_BINARY_DIR}/${test_name}" ) endfunction() add_qcor_compile_and_exe_test(qrt_bell_multi bell/bell_multi_qreg.cpp) add_test(NAME qrt_add_3_5 COMMAND ${CMAKE_BINARY_DIR}/qcor -v -c ${CMAKE_CURRENT_SOURCE_DIR}/adder/add_3_5.cpp WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/adder) add_qcor_compile_and_exe_test(qrt_mixed_language simple/mixed_language.cpp) Loading @@ -21,13 +32,15 @@ add_qcor_compile_and_exe_test(qrt_qpe_example qpe/qpe_example_qrt.cpp) add_qcor_compile_and_exe_test(qrt_kernel_include simple/multiple_kernels.cpp) add_qcor_compile_and_exe_test(qrt_grover grover/grover.cpp) add_qcor_compile_and_exe_test(qrt_adapt hybrid/adapt_h2.cpp) add_test(NAME qrt_ftqc_simple COMMAND ${CMAKE_BINARY_DIR}/qcor -c -qrt ftqc ${CMAKE_CURRENT_SOURCE_DIR}/ftqc_qrt/simple-demo.cpp) add_test(NAME qrt_ftqc_rus COMMAND ${CMAKE_BINARY_DIR}/qcor -c -qrt ftqc ${CMAKE_CURRENT_SOURCE_DIR}/ftqc_qrt/repeat-until-success.cpp) add_test(NAME qrt_ftqc_qec COMMAND ${CMAKE_BINARY_DIR}/qcor -c -qrt ftqc ${CMAKE_CURRENT_SOURCE_DIR}/ftqc_qrt/bit-flip-code.cpp) add_test(NAME qrt_ftqc_deuteron COMMAND ${CMAKE_BINARY_DIR}/qcor -c -qrt ftqc ${CMAKE_CURRENT_SOURCE_DIR}/ftqc_qrt/deuteron.cpp) add_test(NAME qrt_ftqc_bit_flip_qec_std_lib COMMAND ${CMAKE_BINARY_DIR}/qcor -c -qrt ftqc ${CMAKE_CURRENT_SOURCE_DIR}/ftqc_qrt/error_correcting_code.cpp) add_test(NAME qrt_ftqc_five_qubit_qec_std_lib COMMAND ${CMAKE_BINARY_DIR}/qcor -c -qrt ftqc ${CMAKE_CURRENT_SOURCE_DIR}/ftqc_qrt/five_qubit_qec_code.cpp) add_test(NAME qrt_ftqc_steane_qec_std_lib COMMAND ${CMAKE_BINARY_DIR}/qcor -c -qrt ftqc ${CMAKE_CURRENT_SOURCE_DIR}/ftqc_qrt/steane_qec_code.cpp) add_qcor_ftqc_compile_and_exe_test(qrt_ftqc_simple ftqc_qrt/simple-demo.cpp) add_qcor_ftqc_compile_and_exe_test(qrt_ftqc_rus ftqc_qrt/repeat-until-success.cpp) add_qcor_ftqc_compile_and_exe_test(qrt_ftqc_qec ftqc_qrt/bit-flip-code.cpp) add_qcor_ftqc_compile_and_exe_test(qrt_ftqc_deuteron ftqc_qrt/deuteron.cpp) add_qcor_ftqc_compile_and_exe_test(qrt_ftqc_bit_flip_qec_std_lib ftqc_qrt/error_correcting_code.cpp) add_qcor_ftqc_compile_and_exe_test(qrt_ftqc_five_qubit_qec_std_lib ftqc_qrt/five_qubit_qec_code.cpp) add_qcor_ftqc_compile_and_exe_test(qrt_ftqc_steane_qec_std_lib ftqc_qrt/steane_qec_code.cpp) add_qcor_ftqc_compile_and_exe_test(qrt_ftqc_qalloc ftqc_qrt/qalloc_ftqc.cpp) add_qcor_ftqc_compile_and_exe_test(qrt_ftqc_arithmetic ftqc_qrt/integer_add.cpp) add_qcor_compile_and_exe_test(quasimo_vqe quasimo/VqeWithAnsatzCircuit.cpp) add_qcor_compile_and_exe_test(quasimo_trotter quasimo/TrotterTdWorkflow.cpp) add_qcor_compile_and_exe_test(quasimo_iqpe_vqe quasimo/IterativeQpeVqe.cpp) Loading examples/ftqc_qrt/integer_add.cpp 0 → 100644 +32 −0 Original line number Diff line number Diff line #include <qcor_arithmetic> __qpu__ void test_mul_integer_inline(qreg x, int a, int N, int &result) { // x = |1> + |3> X(x[0]); H(x[1]); // ==> |a*x> inline (save in x) // Note that this kernel will allocate qubits... mul_integer_mod_in_place(x, a, N); result = 0; for (int bitIdx = 0; bitIdx < x.size(); ++bitIdx) { if (Measure(x[bitIdx])) { result = result + (1 << bitIdx); X(x[bitIdx]); } } } int main(int argc, char **argv) { // Test in-place modular multiplication: // |x> ==> |ax mod N> on the same register. // x = |1> + |3>; a = 2 // --> |2> + |6> // Simple test: int a_val = 2; int N_val = 8; auto x_reg2 = qalloc(3); int result = 0; test_mul_integer_inline(x_reg2, a_val, N_val, result); std::cout << "Result = " << result << "\n"; return 0; } No newline at end of file runtime/qrt/impls/ftqc/ftqc_qrt.cpp +21 −80 Original line number Diff line number Diff line Loading @@ -13,54 +13,8 @@ using namespace cppmicroservices; namespace { class FtqcQubitAllocator : public AllocEventListener, public QubitAllocator { class FtqcQubitAllocator : public qcor::AncQubitAllocator { public: static inline const std::string ANC_BUFFER_NAME = "ftqc_temp_buffer"; virtual void onAllocate(qubit *in_qubit) override { // std::cout << "Allocate: " << (void *)in_qubit << "\n"; } // On deallocate: don't try to deref the qubit since it may have been gone. virtual void onDealloc(qubit *in_qubit) override { // std::cout << "Deallocate: " << (void *)in_qubit << "\n"; // If this qubit was allocated from this pool: if (xacc::container::contains(m_allocatedQubits, in_qubit)) { const auto qIndex = std::find(m_allocatedQubits.begin(), m_allocatedQubits.end(), in_qubit) - m_allocatedQubits.begin(); // Strategy: create a storage copy of the returned qubit: // i.e. with the same index w.r.t. this global anc. buffer // but store it in the pool vector -> will stay alive // until giving out at the next allocate() qubit archive_qubit(ANC_BUFFER_NAME, qIndex, m_buffer.get()); m_allocatedQubits[qIndex] = &archive_qubit; m_qubitPool.emplace_back(archive_qubit); } } virtual qubit allocate() override { if (!m_qubitPool.empty()) { auto recycled_qubit = m_qubitPool.back(); m_qubitPool.pop_back(); return recycled_qubit; } if (!m_buffer) { // This must be the first call. assert(m_allocatedQubits.empty()); m_buffer = xacc::qalloc(1); m_buffer->setName(ANC_BUFFER_NAME); } // Need to allocate new qubit: // Each new qubit will have an incrementing index. const auto newIdx = m_allocatedQubits.size(); qubit new_qubit(ANC_BUFFER_NAME, newIdx, m_buffer.get()); // Just track that we allocated this qubit m_allocatedQubits.emplace_back(&new_qubit); m_buffer->setSize(m_allocatedQubits.size()); return new_qubit; } static FtqcQubitAllocator *getInstance() { if (!g_instance) { g_instance = new FtqcQubitAllocator(); Loading @@ -68,15 +22,6 @@ public: return g_instance; } static FtqcQubitAllocator *g_instance; std::shared_ptr<xacc::AcceleratorBuffer> get_buffer() { return m_buffer; } private: std::vector<qubit> m_qubitPool; // Track the list of qubit pointers for those // that was allocated by this Allocator. std::vector<qubit *> m_allocatedQubits; std::shared_ptr<xacc::AcceleratorBuffer> m_buffer; }; FtqcQubitAllocator *FtqcQubitAllocator::g_instance = nullptr; Loading @@ -103,13 +48,9 @@ class FTQC : public quantum::QuantumRuntime { virtual void y(const qubit &qidx) override { applyGate("Y", {qidx}); } virtual void z(const qubit &qidx) override { applyGate("Z", {qidx}); } virtual void t(const qubit &qidx) override { applyGate("T", {qidx}); } virtual void tdg(const qubit &qidx) override { applyGate("Tdg", {qidx}); } virtual void tdg(const qubit &qidx) override { applyGate("Tdg", {qidx}); } virtual void s(const qubit &qidx) override { applyGate("S", {qidx}); } virtual void sdg(const qubit &qidx) override { applyGate("Sdg", {qidx}); } virtual void sdg(const qubit &qidx) override { applyGate("Sdg", {qidx}); } // Common single-qubit, parameterized instructions virtual void rx(const qubit &qidx, const double theta) override { Loading @@ -130,9 +71,7 @@ class FTQC : public quantum::QuantumRuntime { applyGate("U", {qidx}, {theta, phi, lambda}); } virtual void reset(const qubit &qidx) override { applyGate("Reset", {qidx}); } virtual void reset(const qubit &qidx) override { applyGate("Reset", {qidx}); } // Measure-Z virtual bool mz(const qubit &qidx) override { Loading Loading @@ -198,21 +137,23 @@ class FTQC : public quantum::QuantumRuntime { } // Some getters for the qcor runtime library. virtual void set_current_program( std::shared_ptr<xacc::CompositeInstruction> p) override { virtual void set_current_program(std::shared_ptr<xacc::CompositeInstruction> p) override { // Nothing to do } virtual std::shared_ptr<xacc::CompositeInstruction> get_current_program() override { virtual std::shared_ptr<xacc::CompositeInstruction> get_current_program() override { return nullptr; } void set_current_buffer(xacc::AcceleratorBuffer *buffer) override { if (!qReg) { qReg = xacc::as_shared_ptr(buffer); qubitIdToGlobalIdx.clear(); // The base qreg will always have exact address in the global register. for (size_t i = 0; i < qReg->size(); ++i) { qubitIdToGlobalIdx[std::make_pair(qReg->name(), i)] = i; for (size_t i = 0; i < buffer->size(); ++i) { qubitIdToGlobalIdx[std::make_pair(buffer->name(), i)] = i; } } } Loading runtime/qrt/impls/nisq/nisq_qrt.cpp +1 −56 Original line number Diff line number Diff line Loading @@ -18,54 +18,8 @@ using namespace cppmicroservices; using namespace xacc; namespace { class NisqQubitAllocator : public AllocEventListener, public QubitAllocator { class NisqQubitAllocator : public qcor::AncQubitAllocator { public: static inline const std::string ANC_BUFFER_NAME = "nisq_temp_buffer"; virtual void onAllocate(qubit *in_qubit) override { // std::cout << "Allocate: " << (void *)in_qubit << "\n"; } // On deallocate: don't try to deref the qubit since it may have been gone. virtual void onDealloc(qubit *in_qubit) override { // std::cout << "Deallocate: " << (void *)in_qubit << "\n"; // If this qubit was allocated from this pool: if (xacc::container::contains(m_allocatedQubits, in_qubit)) { const auto qIndex = std::find(m_allocatedQubits.begin(), m_allocatedQubits.end(), in_qubit) - m_allocatedQubits.begin(); // Strategy: create a storage copy of the returned qubit: // i.e. with the same index w.r.t. this global anc. buffer // but store it in the pool vector -> will stay alive // until giving out at the next allocate() qubit archive_qubit(ANC_BUFFER_NAME, qIndex, m_buffer.get()); m_allocatedQubits[qIndex] = &archive_qubit; m_qubitPool.emplace_back(archive_qubit); } } virtual qubit allocate() override { if (!m_qubitPool.empty()) { auto recycled_qubit = m_qubitPool.back(); m_qubitPool.pop_back(); return recycled_qubit; } if (!m_buffer) { // This must be the first call. assert(m_allocatedQubits.empty()); m_buffer = xacc::qalloc(1); m_buffer->setName(ANC_BUFFER_NAME); } // Need to allocate new qubit: // Each new qubit will have an incrementing index. const auto newIdx = m_allocatedQubits.size(); qubit new_qubit(ANC_BUFFER_NAME, newIdx, m_buffer.get()); // Just track that we allocated this qubit m_allocatedQubits.emplace_back(&new_qubit); m_buffer->setSize(m_allocatedQubits.size()); return new_qubit; } static NisqQubitAllocator *getInstance() { if (!g_instance) { g_instance = new NisqQubitAllocator(); Loading @@ -73,15 +27,6 @@ public: return g_instance; } static NisqQubitAllocator *g_instance; std::shared_ptr<xacc::AcceleratorBuffer> get_buffer() { return m_buffer; } private: std::vector<qubit> m_qubitPool; // Track the list of qubit pointers for those // that was allocated by this Allocator. std::vector<qubit *> m_allocatedQubits; std::shared_ptr<xacc::AcceleratorBuffer> m_buffer; }; NisqQubitAllocator *NisqQubitAllocator::g_instance = nullptr; Loading runtime/qrt/qrt.cpp +43 −1 Original line number Diff line number Diff line Loading @@ -342,3 +342,45 @@ QubitAllocator *getAncillaQubitAllocator() { return qrt_impl->get_anc_qubit_allocator(); } } // namespace quantum namespace qcor { void AncQubitAllocator::onDealloc(xacc::internal_compiler::qubit *in_qubit) { // std::cout << "Deallocate: " << (void *)in_qubit << "\n"; // If this qubit was allocated from this pool: if (xacc::container::contains(m_allocatedQubits, in_qubit)) { const auto qIndex = std::find(m_allocatedQubits.begin(), m_allocatedQubits.end(), in_qubit) - m_allocatedQubits.begin(); // Strategy: create a storage copy of the returned qubit: // i.e. with the same index w.r.t. this global anc. buffer // but store it in the pool vector -> will stay alive // until giving out at the next allocate() qubit archive_qubit(ANC_BUFFER_NAME, qIndex, m_buffer.get()); m_allocatedQubits[qIndex] = &archive_qubit; m_qubitPool.emplace_back(archive_qubit); } } xacc::internal_compiler::qubit AncQubitAllocator::allocate() { if (!m_qubitPool.empty()) { auto recycled_qubit = m_qubitPool.back(); m_qubitPool.pop_back(); return recycled_qubit; } if (!m_buffer) { // This must be the first call. assert(m_allocatedQubits.empty()); m_buffer = xacc::qalloc(1); m_buffer->setName(ANC_BUFFER_NAME); } // Need to allocate new qubit: // Each new qubit will have an incrementing index. const auto newIdx = m_allocatedQubits.size(); qubit new_qubit(ANC_BUFFER_NAME, newIdx, m_buffer.get()); // Just track that we allocated this qubit m_allocatedQubits.emplace_back(&new_qubit); m_buffer->setSize(m_allocatedQubits.size()); return new_qubit; } } // namespace qcor No newline at end of file Loading
examples/CMakeLists.txt +20 −7 Original line number Diff line number Diff line Loading @@ -10,6 +10,17 @@ function(add_qcor_compile_and_exe_test test_name relative_source_location) ) endfunction() # Compile with FTQC runtime and execute function(add_qcor_ftqc_compile_and_exe_test test_name relative_source_location) add_test( NAME ${test_name} COMMAND bash -c "${CMAKE_BINARY_DIR}/qcor -qrt ftqc ${CMAKE_CURRENT_SOURCE_DIR}/${relative_source_location} -o ${test_name}; \ ${CMAKE_CURRENT_BINARY_DIR}/${test_name}" ) endfunction() add_qcor_compile_and_exe_test(qrt_bell_multi bell/bell_multi_qreg.cpp) add_test(NAME qrt_add_3_5 COMMAND ${CMAKE_BINARY_DIR}/qcor -v -c ${CMAKE_CURRENT_SOURCE_DIR}/adder/add_3_5.cpp WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/adder) add_qcor_compile_and_exe_test(qrt_mixed_language simple/mixed_language.cpp) Loading @@ -21,13 +32,15 @@ add_qcor_compile_and_exe_test(qrt_qpe_example qpe/qpe_example_qrt.cpp) add_qcor_compile_and_exe_test(qrt_kernel_include simple/multiple_kernels.cpp) add_qcor_compile_and_exe_test(qrt_grover grover/grover.cpp) add_qcor_compile_and_exe_test(qrt_adapt hybrid/adapt_h2.cpp) add_test(NAME qrt_ftqc_simple COMMAND ${CMAKE_BINARY_DIR}/qcor -c -qrt ftqc ${CMAKE_CURRENT_SOURCE_DIR}/ftqc_qrt/simple-demo.cpp) add_test(NAME qrt_ftqc_rus COMMAND ${CMAKE_BINARY_DIR}/qcor -c -qrt ftqc ${CMAKE_CURRENT_SOURCE_DIR}/ftqc_qrt/repeat-until-success.cpp) add_test(NAME qrt_ftqc_qec COMMAND ${CMAKE_BINARY_DIR}/qcor -c -qrt ftqc ${CMAKE_CURRENT_SOURCE_DIR}/ftqc_qrt/bit-flip-code.cpp) add_test(NAME qrt_ftqc_deuteron COMMAND ${CMAKE_BINARY_DIR}/qcor -c -qrt ftqc ${CMAKE_CURRENT_SOURCE_DIR}/ftqc_qrt/deuteron.cpp) add_test(NAME qrt_ftqc_bit_flip_qec_std_lib COMMAND ${CMAKE_BINARY_DIR}/qcor -c -qrt ftqc ${CMAKE_CURRENT_SOURCE_DIR}/ftqc_qrt/error_correcting_code.cpp) add_test(NAME qrt_ftqc_five_qubit_qec_std_lib COMMAND ${CMAKE_BINARY_DIR}/qcor -c -qrt ftqc ${CMAKE_CURRENT_SOURCE_DIR}/ftqc_qrt/five_qubit_qec_code.cpp) add_test(NAME qrt_ftqc_steane_qec_std_lib COMMAND ${CMAKE_BINARY_DIR}/qcor -c -qrt ftqc ${CMAKE_CURRENT_SOURCE_DIR}/ftqc_qrt/steane_qec_code.cpp) add_qcor_ftqc_compile_and_exe_test(qrt_ftqc_simple ftqc_qrt/simple-demo.cpp) add_qcor_ftqc_compile_and_exe_test(qrt_ftqc_rus ftqc_qrt/repeat-until-success.cpp) add_qcor_ftqc_compile_and_exe_test(qrt_ftqc_qec ftqc_qrt/bit-flip-code.cpp) add_qcor_ftqc_compile_and_exe_test(qrt_ftqc_deuteron ftqc_qrt/deuteron.cpp) add_qcor_ftqc_compile_and_exe_test(qrt_ftqc_bit_flip_qec_std_lib ftqc_qrt/error_correcting_code.cpp) add_qcor_ftqc_compile_and_exe_test(qrt_ftqc_five_qubit_qec_std_lib ftqc_qrt/five_qubit_qec_code.cpp) add_qcor_ftqc_compile_and_exe_test(qrt_ftqc_steane_qec_std_lib ftqc_qrt/steane_qec_code.cpp) add_qcor_ftqc_compile_and_exe_test(qrt_ftqc_qalloc ftqc_qrt/qalloc_ftqc.cpp) add_qcor_ftqc_compile_and_exe_test(qrt_ftqc_arithmetic ftqc_qrt/integer_add.cpp) add_qcor_compile_and_exe_test(quasimo_vqe quasimo/VqeWithAnsatzCircuit.cpp) add_qcor_compile_and_exe_test(quasimo_trotter quasimo/TrotterTdWorkflow.cpp) add_qcor_compile_and_exe_test(quasimo_iqpe_vqe quasimo/IterativeQpeVqe.cpp) Loading
examples/ftqc_qrt/integer_add.cpp 0 → 100644 +32 −0 Original line number Diff line number Diff line #include <qcor_arithmetic> __qpu__ void test_mul_integer_inline(qreg x, int a, int N, int &result) { // x = |1> + |3> X(x[0]); H(x[1]); // ==> |a*x> inline (save in x) // Note that this kernel will allocate qubits... mul_integer_mod_in_place(x, a, N); result = 0; for (int bitIdx = 0; bitIdx < x.size(); ++bitIdx) { if (Measure(x[bitIdx])) { result = result + (1 << bitIdx); X(x[bitIdx]); } } } int main(int argc, char **argv) { // Test in-place modular multiplication: // |x> ==> |ax mod N> on the same register. // x = |1> + |3>; a = 2 // --> |2> + |6> // Simple test: int a_val = 2; int N_val = 8; auto x_reg2 = qalloc(3); int result = 0; test_mul_integer_inline(x_reg2, a_val, N_val, result); std::cout << "Result = " << result << "\n"; return 0; } No newline at end of file
runtime/qrt/impls/ftqc/ftqc_qrt.cpp +21 −80 Original line number Diff line number Diff line Loading @@ -13,54 +13,8 @@ using namespace cppmicroservices; namespace { class FtqcQubitAllocator : public AllocEventListener, public QubitAllocator { class FtqcQubitAllocator : public qcor::AncQubitAllocator { public: static inline const std::string ANC_BUFFER_NAME = "ftqc_temp_buffer"; virtual void onAllocate(qubit *in_qubit) override { // std::cout << "Allocate: " << (void *)in_qubit << "\n"; } // On deallocate: don't try to deref the qubit since it may have been gone. virtual void onDealloc(qubit *in_qubit) override { // std::cout << "Deallocate: " << (void *)in_qubit << "\n"; // If this qubit was allocated from this pool: if (xacc::container::contains(m_allocatedQubits, in_qubit)) { const auto qIndex = std::find(m_allocatedQubits.begin(), m_allocatedQubits.end(), in_qubit) - m_allocatedQubits.begin(); // Strategy: create a storage copy of the returned qubit: // i.e. with the same index w.r.t. this global anc. buffer // but store it in the pool vector -> will stay alive // until giving out at the next allocate() qubit archive_qubit(ANC_BUFFER_NAME, qIndex, m_buffer.get()); m_allocatedQubits[qIndex] = &archive_qubit; m_qubitPool.emplace_back(archive_qubit); } } virtual qubit allocate() override { if (!m_qubitPool.empty()) { auto recycled_qubit = m_qubitPool.back(); m_qubitPool.pop_back(); return recycled_qubit; } if (!m_buffer) { // This must be the first call. assert(m_allocatedQubits.empty()); m_buffer = xacc::qalloc(1); m_buffer->setName(ANC_BUFFER_NAME); } // Need to allocate new qubit: // Each new qubit will have an incrementing index. const auto newIdx = m_allocatedQubits.size(); qubit new_qubit(ANC_BUFFER_NAME, newIdx, m_buffer.get()); // Just track that we allocated this qubit m_allocatedQubits.emplace_back(&new_qubit); m_buffer->setSize(m_allocatedQubits.size()); return new_qubit; } static FtqcQubitAllocator *getInstance() { if (!g_instance) { g_instance = new FtqcQubitAllocator(); Loading @@ -68,15 +22,6 @@ public: return g_instance; } static FtqcQubitAllocator *g_instance; std::shared_ptr<xacc::AcceleratorBuffer> get_buffer() { return m_buffer; } private: std::vector<qubit> m_qubitPool; // Track the list of qubit pointers for those // that was allocated by this Allocator. std::vector<qubit *> m_allocatedQubits; std::shared_ptr<xacc::AcceleratorBuffer> m_buffer; }; FtqcQubitAllocator *FtqcQubitAllocator::g_instance = nullptr; Loading @@ -103,13 +48,9 @@ class FTQC : public quantum::QuantumRuntime { virtual void y(const qubit &qidx) override { applyGate("Y", {qidx}); } virtual void z(const qubit &qidx) override { applyGate("Z", {qidx}); } virtual void t(const qubit &qidx) override { applyGate("T", {qidx}); } virtual void tdg(const qubit &qidx) override { applyGate("Tdg", {qidx}); } virtual void tdg(const qubit &qidx) override { applyGate("Tdg", {qidx}); } virtual void s(const qubit &qidx) override { applyGate("S", {qidx}); } virtual void sdg(const qubit &qidx) override { applyGate("Sdg", {qidx}); } virtual void sdg(const qubit &qidx) override { applyGate("Sdg", {qidx}); } // Common single-qubit, parameterized instructions virtual void rx(const qubit &qidx, const double theta) override { Loading @@ -130,9 +71,7 @@ class FTQC : public quantum::QuantumRuntime { applyGate("U", {qidx}, {theta, phi, lambda}); } virtual void reset(const qubit &qidx) override { applyGate("Reset", {qidx}); } virtual void reset(const qubit &qidx) override { applyGate("Reset", {qidx}); } // Measure-Z virtual bool mz(const qubit &qidx) override { Loading Loading @@ -198,21 +137,23 @@ class FTQC : public quantum::QuantumRuntime { } // Some getters for the qcor runtime library. virtual void set_current_program( std::shared_ptr<xacc::CompositeInstruction> p) override { virtual void set_current_program(std::shared_ptr<xacc::CompositeInstruction> p) override { // Nothing to do } virtual std::shared_ptr<xacc::CompositeInstruction> get_current_program() override { virtual std::shared_ptr<xacc::CompositeInstruction> get_current_program() override { return nullptr; } void set_current_buffer(xacc::AcceleratorBuffer *buffer) override { if (!qReg) { qReg = xacc::as_shared_ptr(buffer); qubitIdToGlobalIdx.clear(); // The base qreg will always have exact address in the global register. for (size_t i = 0; i < qReg->size(); ++i) { qubitIdToGlobalIdx[std::make_pair(qReg->name(), i)] = i; for (size_t i = 0; i < buffer->size(); ++i) { qubitIdToGlobalIdx[std::make_pair(buffer->name(), i)] = i; } } } Loading
runtime/qrt/impls/nisq/nisq_qrt.cpp +1 −56 Original line number Diff line number Diff line Loading @@ -18,54 +18,8 @@ using namespace cppmicroservices; using namespace xacc; namespace { class NisqQubitAllocator : public AllocEventListener, public QubitAllocator { class NisqQubitAllocator : public qcor::AncQubitAllocator { public: static inline const std::string ANC_BUFFER_NAME = "nisq_temp_buffer"; virtual void onAllocate(qubit *in_qubit) override { // std::cout << "Allocate: " << (void *)in_qubit << "\n"; } // On deallocate: don't try to deref the qubit since it may have been gone. virtual void onDealloc(qubit *in_qubit) override { // std::cout << "Deallocate: " << (void *)in_qubit << "\n"; // If this qubit was allocated from this pool: if (xacc::container::contains(m_allocatedQubits, in_qubit)) { const auto qIndex = std::find(m_allocatedQubits.begin(), m_allocatedQubits.end(), in_qubit) - m_allocatedQubits.begin(); // Strategy: create a storage copy of the returned qubit: // i.e. with the same index w.r.t. this global anc. buffer // but store it in the pool vector -> will stay alive // until giving out at the next allocate() qubit archive_qubit(ANC_BUFFER_NAME, qIndex, m_buffer.get()); m_allocatedQubits[qIndex] = &archive_qubit; m_qubitPool.emplace_back(archive_qubit); } } virtual qubit allocate() override { if (!m_qubitPool.empty()) { auto recycled_qubit = m_qubitPool.back(); m_qubitPool.pop_back(); return recycled_qubit; } if (!m_buffer) { // This must be the first call. assert(m_allocatedQubits.empty()); m_buffer = xacc::qalloc(1); m_buffer->setName(ANC_BUFFER_NAME); } // Need to allocate new qubit: // Each new qubit will have an incrementing index. const auto newIdx = m_allocatedQubits.size(); qubit new_qubit(ANC_BUFFER_NAME, newIdx, m_buffer.get()); // Just track that we allocated this qubit m_allocatedQubits.emplace_back(&new_qubit); m_buffer->setSize(m_allocatedQubits.size()); return new_qubit; } static NisqQubitAllocator *getInstance() { if (!g_instance) { g_instance = new NisqQubitAllocator(); Loading @@ -73,15 +27,6 @@ public: return g_instance; } static NisqQubitAllocator *g_instance; std::shared_ptr<xacc::AcceleratorBuffer> get_buffer() { return m_buffer; } private: std::vector<qubit> m_qubitPool; // Track the list of qubit pointers for those // that was allocated by this Allocator. std::vector<qubit *> m_allocatedQubits; std::shared_ptr<xacc::AcceleratorBuffer> m_buffer; }; NisqQubitAllocator *NisqQubitAllocator::g_instance = nullptr; Loading
runtime/qrt/qrt.cpp +43 −1 Original line number Diff line number Diff line Loading @@ -342,3 +342,45 @@ QubitAllocator *getAncillaQubitAllocator() { return qrt_impl->get_anc_qubit_allocator(); } } // namespace quantum namespace qcor { void AncQubitAllocator::onDealloc(xacc::internal_compiler::qubit *in_qubit) { // std::cout << "Deallocate: " << (void *)in_qubit << "\n"; // If this qubit was allocated from this pool: if (xacc::container::contains(m_allocatedQubits, in_qubit)) { const auto qIndex = std::find(m_allocatedQubits.begin(), m_allocatedQubits.end(), in_qubit) - m_allocatedQubits.begin(); // Strategy: create a storage copy of the returned qubit: // i.e. with the same index w.r.t. this global anc. buffer // but store it in the pool vector -> will stay alive // until giving out at the next allocate() qubit archive_qubit(ANC_BUFFER_NAME, qIndex, m_buffer.get()); m_allocatedQubits[qIndex] = &archive_qubit; m_qubitPool.emplace_back(archive_qubit); } } xacc::internal_compiler::qubit AncQubitAllocator::allocate() { if (!m_qubitPool.empty()) { auto recycled_qubit = m_qubitPool.back(); m_qubitPool.pop_back(); return recycled_qubit; } if (!m_buffer) { // This must be the first call. assert(m_allocatedQubits.empty()); m_buffer = xacc::qalloc(1); m_buffer->setName(ANC_BUFFER_NAME); } // Need to allocate new qubit: // Each new qubit will have an incrementing index. const auto newIdx = m_allocatedQubits.size(); qubit new_qubit(ANC_BUFFER_NAME, newIdx, m_buffer.get()); // Just track that we allocated this qubit m_allocatedQubits.emplace_back(&new_qubit); m_buffer->setSize(m_allocatedQubits.size()); return new_qubit; } } // namespace qcor No newline at end of file