Loading examples/qrt/qpe_example_qrt.cpp +12 −2 Original line number Diff line number Diff line Loading @@ -2,6 +2,15 @@ // Use the pre-defined IQFT kernel #include "qft.hpp" using namespace qcor; // The Oracle: T gate __qpu__ void compositeOp(qreg q) { // T gate on the last qubit int bitIdx = q.size() - 1; T(q[bitIdx]); } // Example of Quantum Phase Estimation circuit using QCOR runtime. // Compile with: // qcor -o qpe -qpu qpp -shots 1024 -qrt qpe_example_qrt.cpp Loading @@ -28,9 +37,10 @@ __qpu__ void QuantumPhaseEstimation(qreg q) { const auto bitPrecision = nQubits - 1; for (int32_t i = 0; i < bitPrecision; ++i) { const int nbCalls = 1 << i; // Ctrl(T) = CPhase(pi/4) for (int j = 0; j < nbCalls; ++j) { CPhase(q[i], q[nQubits - 1], M_PI_4); int ctlBit = i; // Controlled-Oracle Controlled::Apply(ctlBit, compositeOp, q); } } Loading runtime/qcor.hpp +21 −0 Original line number Diff line number Diff line Loading @@ -384,6 +384,27 @@ Handle taskInitiate(std::shared_ptr<ObjectiveFunction> objective, }, nParameters); } #ifdef QCOR_USE_QRT // Controlled-Op transform: // Usage: Controlled::Apply(controlBit, QuantumKernel, Args...) // where Args... are arguments that will be passed to the kernel. // Note: we use a class with a static member function to enforce // that the invocation is Controlled::Apply(...) (with the '::' separator), // hence the XASM compiler cannot mistakenly parse this as a XASM call. class Controlled { public: template <typename FunctorType, typename... ArgumentTypes> static void Apply(int ctrlIdx, FunctorType functor, ArgumentTypes... args) { __controlledIdx = { ctrlIdx }; const auto __cached_execute_flag = __execute; __execute = false; functor(args...); __controlledIdx.clear(); __execute = __cached_execute_flag; } }; #endif } // namespace qcor #endif runtime/qrt/qrt.cpp +35 −2 Original line number Diff line number Diff line Loading @@ -2,10 +2,13 @@ #include "Instruction.hpp" #include "PauliOperator.hpp" #include "xacc.hpp" #include "xacc_service.hpp" #include "xacc_internal_compiler.hpp" #include <Eigen/Dense> #include <Utils.hpp> std::vector<int> xacc::internal_compiler::__controlledIdx = {}; namespace quantum { std::shared_ptr<xacc::CompositeInstruction> program = nullptr; std::shared_ptr<xacc::IRProvider> provider = nullptr; Loading @@ -31,6 +34,21 @@ void set_shots(int shots) { {std::make_pair("shots", shots)}); } // Add a controlled instruction: void add_controlled_inst(xacc::InstPtr &inst, int ctrlIdx) { auto tempKernel = provider->createComposite("temp_control"); tempKernel->addInstruction(inst); auto ctrlKernel = std::dynamic_pointer_cast<xacc::CompositeInstruction>(xacc::getService<xacc::Instruction>("C-U")); ctrlKernel->expand({ std::make_pair("U", tempKernel), std::make_pair("control-idx", ctrlIdx), }); for (int instId = 0; instId < ctrlKernel->nInstructions(); ++instId) { program->addInstruction(ctrlKernel->getInstruction(instId)->clone()); } } void one_qubit_inst(const std::string &name, const qubit &qidx, std::vector<double> parameters) { auto inst = Loading @@ -39,8 +57,16 @@ void one_qubit_inst(const std::string &name, const qubit &qidx, for (int i = 0; i < parameters.size(); i++) { inst->setParameter(i, parameters[i]); } // Not in a controlled-block if (xacc::internal_compiler::__controlledIdx.empty()){ // Add the instruction program->addInstruction(inst); } else { // In a controlled block: add_controlled_inst(inst, __controlledIdx[0]); } } void two_qubit_inst(const std::string &name, const qubit &qidx1, const qubit &qidx2, std::vector<double> parameters) { Loading @@ -50,8 +76,15 @@ void two_qubit_inst(const std::string &name, const qubit &qidx1, const qubit &qi for (int i = 0; i < parameters.size(); i++) { inst->setParameter(i, parameters[i]); } // Not in a controlled-block if (xacc::internal_compiler::__controlledIdx.empty()) { program->addInstruction(inst); } else { // In a controlled block: add_controlled_inst(inst, __controlledIdx[0]); } } void h(const qubit &qidx) { one_qubit_inst("H", qidx); } void x(const qubit &qidx) { one_qubit_inst("X", qidx); } Loading runtime/qrt/qrt.hpp +6 −0 Original line number Diff line number Diff line Loading @@ -12,6 +12,12 @@ class AcceleratorBuffer; class CompositeInstruction; class IRProvider; class Observable; namespace internal_compiler { // Current runtime controlled bit indices // (if the current kernel is wrapped in a Controlled block) extern std::vector<int> __controlledIdx; } } // namespace xacc namespace quantum { Loading Loading
examples/qrt/qpe_example_qrt.cpp +12 −2 Original line number Diff line number Diff line Loading @@ -2,6 +2,15 @@ // Use the pre-defined IQFT kernel #include "qft.hpp" using namespace qcor; // The Oracle: T gate __qpu__ void compositeOp(qreg q) { // T gate on the last qubit int bitIdx = q.size() - 1; T(q[bitIdx]); } // Example of Quantum Phase Estimation circuit using QCOR runtime. // Compile with: // qcor -o qpe -qpu qpp -shots 1024 -qrt qpe_example_qrt.cpp Loading @@ -28,9 +37,10 @@ __qpu__ void QuantumPhaseEstimation(qreg q) { const auto bitPrecision = nQubits - 1; for (int32_t i = 0; i < bitPrecision; ++i) { const int nbCalls = 1 << i; // Ctrl(T) = CPhase(pi/4) for (int j = 0; j < nbCalls; ++j) { CPhase(q[i], q[nQubits - 1], M_PI_4); int ctlBit = i; // Controlled-Oracle Controlled::Apply(ctlBit, compositeOp, q); } } Loading
runtime/qcor.hpp +21 −0 Original line number Diff line number Diff line Loading @@ -384,6 +384,27 @@ Handle taskInitiate(std::shared_ptr<ObjectiveFunction> objective, }, nParameters); } #ifdef QCOR_USE_QRT // Controlled-Op transform: // Usage: Controlled::Apply(controlBit, QuantumKernel, Args...) // where Args... are arguments that will be passed to the kernel. // Note: we use a class with a static member function to enforce // that the invocation is Controlled::Apply(...) (with the '::' separator), // hence the XASM compiler cannot mistakenly parse this as a XASM call. class Controlled { public: template <typename FunctorType, typename... ArgumentTypes> static void Apply(int ctrlIdx, FunctorType functor, ArgumentTypes... args) { __controlledIdx = { ctrlIdx }; const auto __cached_execute_flag = __execute; __execute = false; functor(args...); __controlledIdx.clear(); __execute = __cached_execute_flag; } }; #endif } // namespace qcor #endif
runtime/qrt/qrt.cpp +35 −2 Original line number Diff line number Diff line Loading @@ -2,10 +2,13 @@ #include "Instruction.hpp" #include "PauliOperator.hpp" #include "xacc.hpp" #include "xacc_service.hpp" #include "xacc_internal_compiler.hpp" #include <Eigen/Dense> #include <Utils.hpp> std::vector<int> xacc::internal_compiler::__controlledIdx = {}; namespace quantum { std::shared_ptr<xacc::CompositeInstruction> program = nullptr; std::shared_ptr<xacc::IRProvider> provider = nullptr; Loading @@ -31,6 +34,21 @@ void set_shots(int shots) { {std::make_pair("shots", shots)}); } // Add a controlled instruction: void add_controlled_inst(xacc::InstPtr &inst, int ctrlIdx) { auto tempKernel = provider->createComposite("temp_control"); tempKernel->addInstruction(inst); auto ctrlKernel = std::dynamic_pointer_cast<xacc::CompositeInstruction>(xacc::getService<xacc::Instruction>("C-U")); ctrlKernel->expand({ std::make_pair("U", tempKernel), std::make_pair("control-idx", ctrlIdx), }); for (int instId = 0; instId < ctrlKernel->nInstructions(); ++instId) { program->addInstruction(ctrlKernel->getInstruction(instId)->clone()); } } void one_qubit_inst(const std::string &name, const qubit &qidx, std::vector<double> parameters) { auto inst = Loading @@ -39,8 +57,16 @@ void one_qubit_inst(const std::string &name, const qubit &qidx, for (int i = 0; i < parameters.size(); i++) { inst->setParameter(i, parameters[i]); } // Not in a controlled-block if (xacc::internal_compiler::__controlledIdx.empty()){ // Add the instruction program->addInstruction(inst); } else { // In a controlled block: add_controlled_inst(inst, __controlledIdx[0]); } } void two_qubit_inst(const std::string &name, const qubit &qidx1, const qubit &qidx2, std::vector<double> parameters) { Loading @@ -50,8 +76,15 @@ void two_qubit_inst(const std::string &name, const qubit &qidx1, const qubit &qi for (int i = 0; i < parameters.size(); i++) { inst->setParameter(i, parameters[i]); } // Not in a controlled-block if (xacc::internal_compiler::__controlledIdx.empty()) { program->addInstruction(inst); } else { // In a controlled block: add_controlled_inst(inst, __controlledIdx[0]); } } void h(const qubit &qidx) { one_qubit_inst("H", qidx); } void x(const qubit &qidx) { one_qubit_inst("X", qidx); } Loading
runtime/qrt/qrt.hpp +6 −0 Original line number Diff line number Diff line Loading @@ -12,6 +12,12 @@ class AcceleratorBuffer; class CompositeInstruction; class IRProvider; class Observable; namespace internal_compiler { // Current runtime controlled bit indices // (if the current kernel is wrapped in a Controlled block) extern std::vector<int> __controlledIdx; } } // namespace xacc namespace quantum { Loading