Loading examples/adder/add_3_5.cpp +0 −1 Original line number Diff line number Diff line #include <qalloc> __qpu__ void add_3_5(qreg a, qreg b, qreg c) { using qcor::openqasm; Loading examples/unitary/ccnot.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -14,7 +14,7 @@ __qpu__ void ccnot(qreg q) { using qcor::unitary; // Create the unitary matrix qcor::UnitaryMatrix ccnot = qcor::UnitaryMatrix::Identity(8, 8); UnitaryMatrix ccnot = UnitaryMatrix::Identity(8, 8); ccnot(6, 6) = 0.0; ccnot(7, 7) = 0.0; ccnot(6, 7) = 1.0; Loading handlers/qcor_syntax_handler.cpp +5 −212 Original line number Diff line number Diff line Loading @@ -66,7 +66,11 @@ public: if (type == "class xacc::internal_compiler::qreg") { bufferNames.push_back(ident->getName().str()); type = "qreg"; } else if (type == "qcor::qreg") { bufferNames.push_back(ident->getName().str()); type = "qreg"; } program_arg_types.push_back(type); program_parameters.push_back(var); } Loading Loading @@ -260,7 +264,7 @@ public: void AddToPredefines(llvm::raw_string_ostream &OS) override { OS << "#include \"qcor.hpp\"\n"; OS << "using namespace qcor;\n"; OS << "using namespace xacc::internal_compiler;\n"; } }; Loading Loading @@ -313,217 +317,6 @@ public: } }; //// =================== COMMON CODE ==============///// // Base class of all kernels: // This will handle Adjoint() and Control() in an AUTOMATIC way, // i.e. not taking into account if it is self-adjoint. // Technically, we can define sub-classes for those special cases // and then allow users to annotate kernels as self-adjoint for instance. // class KernelBase { // public: // KernelBase(xacc::internal_compiler::qreg q, // std::shared_ptr<xacc::CompositeInstruction> bodyComposite) // : m_qreg(q), m_usedAsCallable(true), m_body(bodyComposite) {} // // Adjoint // virtual KernelBase adjoint() { // // Copy this // KernelBase adjointKernel(this, "KernelName_ADJ"); // // Reverse all instructions in m_body and replace instructions // // with their adjoint: // // T -> Tdag; Rx(theta) -> Rx(-theta), etc. // auto instructions = adjointKernel.m_body->getInstructions(); // // Assert that we don't have measurement // if (!std::all_of( // instructions.cbegin(), instructions.cend(), // [](const auto &inst) { return inst->name() != "Measure"; })) { // xacc::error( // "Unable to create Adjoint for kernels that have Measure // operations."); // } // std::reverse(instructions.begin(), instructions.end()); // for (const auto &inst : instructions) { // // Parametric gates: // if (inst->name() == "Rx" || inst->name() == "Ry" || // inst->name() == "Rz" || inst->name() == "CPHASE") { // inst->setParameter(0, -inst->getParameter(0).as<double>()); // } // // TODO: Handles T and S gates, etc... => T -> Tdg // } // adjointKernel.m_body->clear(); // adjointKernel.m_body->addInstructions(instructions); // return adjointKernel; // } // virtual KernelBase ctrl(size_t ctrlIdx) { // // Copy this // KernelBase controlledKernel(this, "KernelName_CTRL"); // // Use the controlled gate module of XACC to transform // // controlledKernel.m_body // auto ctrlKernel = quantum::controlledKernel(m_body, ctrlIdx); // // Set the body of the returned kernel instance. // controlledKernel.m_body = ctrlKernel; // return controlledKernel; // } // // Destructor: // // called right after the object invocation: // // e.g. // // Case 1: free-standing invocation: // // ... code ... // // kernelFuncClass(abc); // // -> DTor called here // // ... code ... // // Cade 2: chaining // // ... code ... // // kernelFuncClass(abc).adjoint(); // // -> DTor of the Adjoint instance called here (m_usedAsCallable = true) // // hence adding the adjoint body to the global composite. // // -> DTor of the kernelFuncClass(abc) instance called here // (m_usedAsCallable // // = false) hence having no effect. // // ... code ... // virtual ~KernelBase() { // // This is used as a CALLABLE // if (m_usedAsCallable) { // // Add all instructions to the global program. // quantum::program->addInstructions(m_body->getInstructions()); // } // } // // Default move CTor // KernelBase(KernelBase &&) = default; // protected: // // Copy ctor: // // Deep copy of the CompositeInstruction to prevent dangling references. // KernelBase(KernelBase *other, const std::string &in_optional_newName = "") // { // const auto kernelName = in_optional_newName.empty() ? // other->m_body->name() // : // in_optional_newName; // auto provider = xacc::getIRProvider("quantum"); // m_body = provider->createComposite(kernelName); // for (const auto &inst : other->m_body->getInstructions()) { // m_body->addInstruction(inst->clone()); // } // m_qreg = other->m_qreg; // m_usedAsCallable = true; // // The copied kernel becomes *INACTIVE* // other->m_usedAsCallable = false; // } // // Denote if this instance was use as a *Callable* // // i.e. // // kernelFuncClass(qubitReg); => TRUE // // kernelFuncClass(qubitReg).adjoint(); => FALSE (on the original // // kernelFuncClass instance) but TRUE for the one returned by the adjoint() // // member function. This will allow arbitrary chaining: e.g. // // kernelFuncClass(qubitReg).adjoint().ctrl(k); only the last kernel // returned // // by ctrl() will be the *Callable*; // bool m_usedAsCallable; // // The XACC composite instruction described by this kernel body: // std::shared_ptr<xacc::CompositeInstruction> m_body; // // From kernel params: // xacc::internal_compiler::qreg m_qreg; // }; // //// =================== END COMMON CODE ==============///// // // The above code can be placed in a header file which is then injected. // /// ============= ORIGINAL CODE =================== // // Assume we are rewriting this: // // __qpu__ void kernelFunc(qreg q, double angle) { // // H(q[0]); // // CNOT(q[0], q[1]); // // Rx(q[0], angle); // // } // /// ============= CODE GEN ======================//// // // kernel function: returns the class object. // KernelBase kernelFunc(xacc::internal_compiler::qreg q, double angle) { // quantum::initialize("qpp", "KERNEL_NAME"); // q.setNameAndStore("q"); // auto provider = xacc::getIRProvider("quantum"); // // Kernel name (function name) // // BODY to denote it's the original body // auto kernelBody = provider->createComposite("KernelName_BODY"); // // Rewrite from function body: // // TODO: QRT functions to take an composite instruction arg // // hence added instructions to that composite. // // HACK: for testing, swapping the *GLOBAL* program. // auto cachedGlobalProgram = quantum::program; // // Set the program to this body composite, // // hence we can listen to all the QRT instructions below. // quantum::program = kernelBody; // // ======== QRT Code =========== // // Rewrite from the __qpu__ body // quantum::h(q[0]); // Ideally, we'll do quantum::h(q[0], kernelBody); // quantum::cnot(q[0], q[1]); // quantum::rx(q[0], angle); // // ======== QRT Code =========== // // Restore the global program // quantum::program = cachedGlobalProgram; // KernelBase instance(q, kernelBody); // return instance; // } // /// ============= END CODE GEN ======================//// // // Note: The most difficult part is to *CHANGE* the function signature from // // returning *void* to returing *KernelBase*, // // i.e. we need to be able to rewrite: // // "__qpu__ void" ==> "__qpu__ KernelBase" (__qpu__ is handled by the // // pre-processor) Possibility: the *qcor* script to do that before calling // clang // // ?? // ////////////////////////////////////////////////// // // TEST kernel-in-kernel // // __qpu__ void nestedFunc(qreg q, double angle1, double angle2) { // // kernelFunc(q, angle1).adjoint(); // // Ry(q[1], angle2); // // Measure(q[0]); // // } // /// ============= CODE GEN ======================//// // KernelBase nestedFunc(xacc::internal_compiler::qreg q, double angle1, // double angle2) { // quantum::initialize("qpp", "KERNEL_NAME"); // q.setNameAndStore("q"); // auto provider = xacc::getIRProvider("quantum"); // // Kernel name (function name) // // BODY to denote it's the original body // auto kernelBody = provider->createComposite("KernelName_BODY"); // // Rewrite from function body: // auto cachedGlobalProgram = quantum::program; // // Set the program to this body composite, // // hence we can listen to all the QRT instructions below. // quantum::program = kernelBody; // // ======== QRT Code =========== // // Call other kernels (i.e. left unchanged) // // Support arbitrary chaining here as well. // kernelFunc(q, angle1).adjoint(); // // Some more gates: // quantum::ry(q[1], angle2); // quantum::mz(q[0]); // // ======== QRT Code =========== // // Restore the global program // quantum::program = cachedGlobalProgram; // KernelBase instance(q, kernelBody); // return instance; // } // /// ============= END CODE GEN ======================//// // // Classical code: // int main(int argc, char **argv) { // // Allocate 3 qubits // auto q = qalloc(3); // // Can try any of the following things: // // kernelFunc(q, 1.234); // // kernelFunc(q, 1.234).adjoint(); // // kernelFunc(q, 1.234).ctrl(2); // // I'm crazy :) // // kernelFunc(q, 1.234).adjoint().ctrl(2).adjoint(); // // Nested case: // // Note: we cannot `adjoint` or `control` the nestedFunc // // since it contains Measure (throw). // nestedFunc(q, 1.23, 4.56); // // This should include instructions from the above kernel, // // which is added when the Dtor is called. // std::cout << "Program: \n" << quantum::program->toString() << "\n"; // // dump the results // q.print(); // } } // namespace static SyntaxHandlerRegistry::Add<QCORSyntaxHandler> Loading handlers/token_collector/unitary/tests/UnitaryTokenCollectorTester.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -25,7 +25,7 @@ TEST(UnitaryTokenCollectorTester, checkSimple) { std::stringstream ss; auto xasm_tc = xacc::getService<qcor::TokenCollector>("unitary"); xasm_tc->collect(*PP.get(), cached, {"a","b","c"}, ss); xasm_tc->collect(*PP.get(), cached, {"a"}, ss); std::cout << "heres the test\n"; std::cout << ss.str() << "\n"; Loading handlers/token_collector/unitary/unitary_token_collector.cpp +3 −1 Original line number Diff line number Diff line Loading @@ -83,9 +83,11 @@ void UnitaryTokenCollector::collect(clang::Preprocessor &PP, } ss << "\n"; std::cout << "HOWDY: " << var_name << ", " << bufferNames[0] << "\n"; std::cout << ss.str() << "\n"; // Add the qfast decomp and hook up to the qrt program. ss << "auto decomposed_program = " "qcor::__internal__::decompose_unitary(\"QFAST\", " "__internal__::decompose_unitary(\"QFAST\", " << var_name << ", " << bufferNames[0] << ".name());\n"; ss << "parent_kernel->addInstruction(decomposed_program);\n"; Loading Loading
examples/adder/add_3_5.cpp +0 −1 Original line number Diff line number Diff line #include <qalloc> __qpu__ void add_3_5(qreg a, qreg b, qreg c) { using qcor::openqasm; Loading
examples/unitary/ccnot.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -14,7 +14,7 @@ __qpu__ void ccnot(qreg q) { using qcor::unitary; // Create the unitary matrix qcor::UnitaryMatrix ccnot = qcor::UnitaryMatrix::Identity(8, 8); UnitaryMatrix ccnot = UnitaryMatrix::Identity(8, 8); ccnot(6, 6) = 0.0; ccnot(7, 7) = 0.0; ccnot(6, 7) = 1.0; Loading
handlers/qcor_syntax_handler.cpp +5 −212 Original line number Diff line number Diff line Loading @@ -66,7 +66,11 @@ public: if (type == "class xacc::internal_compiler::qreg") { bufferNames.push_back(ident->getName().str()); type = "qreg"; } else if (type == "qcor::qreg") { bufferNames.push_back(ident->getName().str()); type = "qreg"; } program_arg_types.push_back(type); program_parameters.push_back(var); } Loading Loading @@ -260,7 +264,7 @@ public: void AddToPredefines(llvm::raw_string_ostream &OS) override { OS << "#include \"qcor.hpp\"\n"; OS << "using namespace qcor;\n"; OS << "using namespace xacc::internal_compiler;\n"; } }; Loading Loading @@ -313,217 +317,6 @@ public: } }; //// =================== COMMON CODE ==============///// // Base class of all kernels: // This will handle Adjoint() and Control() in an AUTOMATIC way, // i.e. not taking into account if it is self-adjoint. // Technically, we can define sub-classes for those special cases // and then allow users to annotate kernels as self-adjoint for instance. // class KernelBase { // public: // KernelBase(xacc::internal_compiler::qreg q, // std::shared_ptr<xacc::CompositeInstruction> bodyComposite) // : m_qreg(q), m_usedAsCallable(true), m_body(bodyComposite) {} // // Adjoint // virtual KernelBase adjoint() { // // Copy this // KernelBase adjointKernel(this, "KernelName_ADJ"); // // Reverse all instructions in m_body and replace instructions // // with their adjoint: // // T -> Tdag; Rx(theta) -> Rx(-theta), etc. // auto instructions = adjointKernel.m_body->getInstructions(); // // Assert that we don't have measurement // if (!std::all_of( // instructions.cbegin(), instructions.cend(), // [](const auto &inst) { return inst->name() != "Measure"; })) { // xacc::error( // "Unable to create Adjoint for kernels that have Measure // operations."); // } // std::reverse(instructions.begin(), instructions.end()); // for (const auto &inst : instructions) { // // Parametric gates: // if (inst->name() == "Rx" || inst->name() == "Ry" || // inst->name() == "Rz" || inst->name() == "CPHASE") { // inst->setParameter(0, -inst->getParameter(0).as<double>()); // } // // TODO: Handles T and S gates, etc... => T -> Tdg // } // adjointKernel.m_body->clear(); // adjointKernel.m_body->addInstructions(instructions); // return adjointKernel; // } // virtual KernelBase ctrl(size_t ctrlIdx) { // // Copy this // KernelBase controlledKernel(this, "KernelName_CTRL"); // // Use the controlled gate module of XACC to transform // // controlledKernel.m_body // auto ctrlKernel = quantum::controlledKernel(m_body, ctrlIdx); // // Set the body of the returned kernel instance. // controlledKernel.m_body = ctrlKernel; // return controlledKernel; // } // // Destructor: // // called right after the object invocation: // // e.g. // // Case 1: free-standing invocation: // // ... code ... // // kernelFuncClass(abc); // // -> DTor called here // // ... code ... // // Cade 2: chaining // // ... code ... // // kernelFuncClass(abc).adjoint(); // // -> DTor of the Adjoint instance called here (m_usedAsCallable = true) // // hence adding the adjoint body to the global composite. // // -> DTor of the kernelFuncClass(abc) instance called here // (m_usedAsCallable // // = false) hence having no effect. // // ... code ... // virtual ~KernelBase() { // // This is used as a CALLABLE // if (m_usedAsCallable) { // // Add all instructions to the global program. // quantum::program->addInstructions(m_body->getInstructions()); // } // } // // Default move CTor // KernelBase(KernelBase &&) = default; // protected: // // Copy ctor: // // Deep copy of the CompositeInstruction to prevent dangling references. // KernelBase(KernelBase *other, const std::string &in_optional_newName = "") // { // const auto kernelName = in_optional_newName.empty() ? // other->m_body->name() // : // in_optional_newName; // auto provider = xacc::getIRProvider("quantum"); // m_body = provider->createComposite(kernelName); // for (const auto &inst : other->m_body->getInstructions()) { // m_body->addInstruction(inst->clone()); // } // m_qreg = other->m_qreg; // m_usedAsCallable = true; // // The copied kernel becomes *INACTIVE* // other->m_usedAsCallable = false; // } // // Denote if this instance was use as a *Callable* // // i.e. // // kernelFuncClass(qubitReg); => TRUE // // kernelFuncClass(qubitReg).adjoint(); => FALSE (on the original // // kernelFuncClass instance) but TRUE for the one returned by the adjoint() // // member function. This will allow arbitrary chaining: e.g. // // kernelFuncClass(qubitReg).adjoint().ctrl(k); only the last kernel // returned // // by ctrl() will be the *Callable*; // bool m_usedAsCallable; // // The XACC composite instruction described by this kernel body: // std::shared_ptr<xacc::CompositeInstruction> m_body; // // From kernel params: // xacc::internal_compiler::qreg m_qreg; // }; // //// =================== END COMMON CODE ==============///// // // The above code can be placed in a header file which is then injected. // /// ============= ORIGINAL CODE =================== // // Assume we are rewriting this: // // __qpu__ void kernelFunc(qreg q, double angle) { // // H(q[0]); // // CNOT(q[0], q[1]); // // Rx(q[0], angle); // // } // /// ============= CODE GEN ======================//// // // kernel function: returns the class object. // KernelBase kernelFunc(xacc::internal_compiler::qreg q, double angle) { // quantum::initialize("qpp", "KERNEL_NAME"); // q.setNameAndStore("q"); // auto provider = xacc::getIRProvider("quantum"); // // Kernel name (function name) // // BODY to denote it's the original body // auto kernelBody = provider->createComposite("KernelName_BODY"); // // Rewrite from function body: // // TODO: QRT functions to take an composite instruction arg // // hence added instructions to that composite. // // HACK: for testing, swapping the *GLOBAL* program. // auto cachedGlobalProgram = quantum::program; // // Set the program to this body composite, // // hence we can listen to all the QRT instructions below. // quantum::program = kernelBody; // // ======== QRT Code =========== // // Rewrite from the __qpu__ body // quantum::h(q[0]); // Ideally, we'll do quantum::h(q[0], kernelBody); // quantum::cnot(q[0], q[1]); // quantum::rx(q[0], angle); // // ======== QRT Code =========== // // Restore the global program // quantum::program = cachedGlobalProgram; // KernelBase instance(q, kernelBody); // return instance; // } // /// ============= END CODE GEN ======================//// // // Note: The most difficult part is to *CHANGE* the function signature from // // returning *void* to returing *KernelBase*, // // i.e. we need to be able to rewrite: // // "__qpu__ void" ==> "__qpu__ KernelBase" (__qpu__ is handled by the // // pre-processor) Possibility: the *qcor* script to do that before calling // clang // // ?? // ////////////////////////////////////////////////// // // TEST kernel-in-kernel // // __qpu__ void nestedFunc(qreg q, double angle1, double angle2) { // // kernelFunc(q, angle1).adjoint(); // // Ry(q[1], angle2); // // Measure(q[0]); // // } // /// ============= CODE GEN ======================//// // KernelBase nestedFunc(xacc::internal_compiler::qreg q, double angle1, // double angle2) { // quantum::initialize("qpp", "KERNEL_NAME"); // q.setNameAndStore("q"); // auto provider = xacc::getIRProvider("quantum"); // // Kernel name (function name) // // BODY to denote it's the original body // auto kernelBody = provider->createComposite("KernelName_BODY"); // // Rewrite from function body: // auto cachedGlobalProgram = quantum::program; // // Set the program to this body composite, // // hence we can listen to all the QRT instructions below. // quantum::program = kernelBody; // // ======== QRT Code =========== // // Call other kernels (i.e. left unchanged) // // Support arbitrary chaining here as well. // kernelFunc(q, angle1).adjoint(); // // Some more gates: // quantum::ry(q[1], angle2); // quantum::mz(q[0]); // // ======== QRT Code =========== // // Restore the global program // quantum::program = cachedGlobalProgram; // KernelBase instance(q, kernelBody); // return instance; // } // /// ============= END CODE GEN ======================//// // // Classical code: // int main(int argc, char **argv) { // // Allocate 3 qubits // auto q = qalloc(3); // // Can try any of the following things: // // kernelFunc(q, 1.234); // // kernelFunc(q, 1.234).adjoint(); // // kernelFunc(q, 1.234).ctrl(2); // // I'm crazy :) // // kernelFunc(q, 1.234).adjoint().ctrl(2).adjoint(); // // Nested case: // // Note: we cannot `adjoint` or `control` the nestedFunc // // since it contains Measure (throw). // nestedFunc(q, 1.23, 4.56); // // This should include instructions from the above kernel, // // which is added when the Dtor is called. // std::cout << "Program: \n" << quantum::program->toString() << "\n"; // // dump the results // q.print(); // } } // namespace static SyntaxHandlerRegistry::Add<QCORSyntaxHandler> Loading
handlers/token_collector/unitary/tests/UnitaryTokenCollectorTester.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -25,7 +25,7 @@ TEST(UnitaryTokenCollectorTester, checkSimple) { std::stringstream ss; auto xasm_tc = xacc::getService<qcor::TokenCollector>("unitary"); xasm_tc->collect(*PP.get(), cached, {"a","b","c"}, ss); xasm_tc->collect(*PP.get(), cached, {"a"}, ss); std::cout << "heres the test\n"; std::cout << ss.str() << "\n"; Loading
handlers/token_collector/unitary/unitary_token_collector.cpp +3 −1 Original line number Diff line number Diff line Loading @@ -83,9 +83,11 @@ void UnitaryTokenCollector::collect(clang::Preprocessor &PP, } ss << "\n"; std::cout << "HOWDY: " << var_name << ", " << bufferNames[0] << "\n"; std::cout << ss.str() << "\n"; // Add the qfast decomp and hook up to the qrt program. ss << "auto decomposed_program = " "qcor::__internal__::decompose_unitary(\"QFAST\", " "__internal__::decompose_unitary(\"QFAST\", " << var_name << ", " << bufferNames[0] << ".name());\n"; ss << "parent_kernel->addInstruction(decomposed_program);\n"; Loading