Loading examples/grover/general_grover.cpp +14 −20 Original line number Diff line number Diff line Loading @@ -5,26 +5,27 @@ __qpu__ void reflect_about_uniform(qreg q) { H(q); X(q); } action { std::vector<qubit> ctrl_qubits; for (int i = 0; i < q.size() - 1; i++) { std::cout << "adding qubit " << q[i].second << "\n"; ctrl_qubits.push_back(q[i]); } auto last_qubit = q[2]; // we have N qubits, get the first N-1 as the // ctrl qubits, and the last one for the // ctrl-ctrl-...-ctrl-z operation qubit auto ctrl_qubits = q.head(q.size()-1); auto last_qubit = q.tail(); Z::ctrl(ctrl_qubits, last_qubit); } return; } __qpu__ void run_grover(qreg q, GroverPhaseOracle oracle, const int iterations) { // Put them all in a superposition H(q); // Iteratively apply the oracle then reflect for (int i = 0; i < iterations; i++) { oracle(q); reflect_about_uniform(q); } // Measure all qubits Measure(q); } Loading @@ -33,17 +34,10 @@ __qpu__ void oracle(qreg q) { CZ(q[1], q[2]); } __qpu__ void ccz(qreg q) { Z::ctrl({q[0], q[1]}, q[2]); } int main() { int main(int argc, char** argv) { auto q = qalloc(3); run_grover(q, oracle, 1); q.print(); run_grover::print_kernel(q, oracle, 1); auto m = ccz::as_unitary_matrix(q); std::cout << m << "\n"; std::cout << run_grover::openqasm(q, oracle, 1) << "\n"; for (auto [bits, count] : q.counts()) { print(bits, ":", count); } } runtime/kernel/quantum_kernel.hpp +36 −23 Original line number Diff line number Diff line Loading @@ -98,6 +98,8 @@ class QuantumKernel { // Create the Adjoint of this quantum kernel static void adjoint(std::shared_ptr<CompositeInstruction> parent_kernel, Args... args) { auto provider = qcor::__internal__::get_provider(); // instantiate and don't let it call the destructor Derived derived(args...); derived.disable_destructor = true; Loading @@ -117,7 +119,6 @@ class QuantumKernel { "Unable to create Adjoint for kernels that have Measure operations."); } auto provider = qcor::__internal__::get_provider(); for (int i = 0; i < instructions.size(); i++) { auto inst = derived.parent_kernel->getInstruction(i); // Parametric gates: Loading @@ -144,6 +145,8 @@ class QuantumKernel { // add the instructions to the current parent kernel parent_kernel->addInstructions(new_instructions); quantum::set_current_program(parent_kernel); // no measures, so no execute } Loading Loading @@ -183,6 +186,15 @@ class QuantumKernel { ctrl(parent_kernel, {ctrlIdx}, args...); } static void ctrl(std::shared_ptr<CompositeInstruction> parent_kernel, qreg ctrl_qbits, Args... args) { std::vector<qubit> ctrl_qubit_vec; for (int i = 0; i < ctrl_qbits.size(); i++) ctrl_qubit_vec.push_back(ctrl_qbits[i]); ctrl(parent_kernel, ctrl_qubit_vec, args...); } static void ctrl(std::shared_ptr<CompositeInstruction> parent_kernel, const std::vector<qubit> &ctrl_qbits, Args... args) { const auto buffer_name = ctrl_qbits[0].first; Loading Loading @@ -412,21 +424,23 @@ class KernelSignature { } }; // We use the following to enable ctrl operations on our single // qubit gates, X::ctrl(), Z::ctrl(), H::ctrl(), etc.... template <typename Derived> using OneQubitKernel = QuantumKernel<Derived, qubit>; template <typename Derived> using TwoQubitKernel = QuantumKernel<Derived, qubit, qubit>; #define ONE_QUBIT_KERNEL_CTRL_ENABLER(CLASSNAME, QRTNAME) \ class CLASSNAME : public OneQubitKernel<class CLASSNAME> { \ public: \ CLASSNAME(qubit q) : OneQubitKernel<CLASSNAME>(q) {} \ CLASSNAME(std::shared_ptr<qcor::CompositeInstruction> _parent_kernel, qubit q) \ : OneQubitKernel<CLASSNAME>(_parent_kernel, q) { throw std::runtime_error("you cannot call this.");} \ CLASSNAME(std::shared_ptr<qcor::CompositeInstruction> _parent_kernel, \ qubit q) \ : OneQubitKernel<CLASSNAME>(_parent_kernel, q) { \ throw std::runtime_error("you cannot call this."); \ } \ void operator()(qubit q) { \ parent_kernel = \ qcor::__internal__::create_composite("__tmp_one_qubit_ctrl_enabler"); \ parent_kernel = qcor::__internal__::create_composite( \ "__tmp_one_qubit_ctrl_enabler"); \ quantum::set_current_program(parent_kernel); \ if (runtime_env == QrtType::FTQC) { \ quantum::set_current_buffer(q.results()); \ Loading @@ -446,5 +460,4 @@ ONE_QUBIT_KERNEL_CTRL_ENABLER(Tdg, tdg) ONE_QUBIT_KERNEL_CTRL_ENABLER(S, s) ONE_QUBIT_KERNEL_CTRL_ENABLER(Sdg, sdg) } // namespace qcor Loading
examples/grover/general_grover.cpp +14 −20 Original line number Diff line number Diff line Loading @@ -5,26 +5,27 @@ __qpu__ void reflect_about_uniform(qreg q) { H(q); X(q); } action { std::vector<qubit> ctrl_qubits; for (int i = 0; i < q.size() - 1; i++) { std::cout << "adding qubit " << q[i].second << "\n"; ctrl_qubits.push_back(q[i]); } auto last_qubit = q[2]; // we have N qubits, get the first N-1 as the // ctrl qubits, and the last one for the // ctrl-ctrl-...-ctrl-z operation qubit auto ctrl_qubits = q.head(q.size()-1); auto last_qubit = q.tail(); Z::ctrl(ctrl_qubits, last_qubit); } return; } __qpu__ void run_grover(qreg q, GroverPhaseOracle oracle, const int iterations) { // Put them all in a superposition H(q); // Iteratively apply the oracle then reflect for (int i = 0; i < iterations; i++) { oracle(q); reflect_about_uniform(q); } // Measure all qubits Measure(q); } Loading @@ -33,17 +34,10 @@ __qpu__ void oracle(qreg q) { CZ(q[1], q[2]); } __qpu__ void ccz(qreg q) { Z::ctrl({q[0], q[1]}, q[2]); } int main() { int main(int argc, char** argv) { auto q = qalloc(3); run_grover(q, oracle, 1); q.print(); run_grover::print_kernel(q, oracle, 1); auto m = ccz::as_unitary_matrix(q); std::cout << m << "\n"; std::cout << run_grover::openqasm(q, oracle, 1) << "\n"; for (auto [bits, count] : q.counts()) { print(bits, ":", count); } }
runtime/kernel/quantum_kernel.hpp +36 −23 Original line number Diff line number Diff line Loading @@ -98,6 +98,8 @@ class QuantumKernel { // Create the Adjoint of this quantum kernel static void adjoint(std::shared_ptr<CompositeInstruction> parent_kernel, Args... args) { auto provider = qcor::__internal__::get_provider(); // instantiate and don't let it call the destructor Derived derived(args...); derived.disable_destructor = true; Loading @@ -117,7 +119,6 @@ class QuantumKernel { "Unable to create Adjoint for kernels that have Measure operations."); } auto provider = qcor::__internal__::get_provider(); for (int i = 0; i < instructions.size(); i++) { auto inst = derived.parent_kernel->getInstruction(i); // Parametric gates: Loading @@ -144,6 +145,8 @@ class QuantumKernel { // add the instructions to the current parent kernel parent_kernel->addInstructions(new_instructions); quantum::set_current_program(parent_kernel); // no measures, so no execute } Loading Loading @@ -183,6 +186,15 @@ class QuantumKernel { ctrl(parent_kernel, {ctrlIdx}, args...); } static void ctrl(std::shared_ptr<CompositeInstruction> parent_kernel, qreg ctrl_qbits, Args... args) { std::vector<qubit> ctrl_qubit_vec; for (int i = 0; i < ctrl_qbits.size(); i++) ctrl_qubit_vec.push_back(ctrl_qbits[i]); ctrl(parent_kernel, ctrl_qubit_vec, args...); } static void ctrl(std::shared_ptr<CompositeInstruction> parent_kernel, const std::vector<qubit> &ctrl_qbits, Args... args) { const auto buffer_name = ctrl_qbits[0].first; Loading Loading @@ -412,21 +424,23 @@ class KernelSignature { } }; // We use the following to enable ctrl operations on our single // qubit gates, X::ctrl(), Z::ctrl(), H::ctrl(), etc.... template <typename Derived> using OneQubitKernel = QuantumKernel<Derived, qubit>; template <typename Derived> using TwoQubitKernel = QuantumKernel<Derived, qubit, qubit>; #define ONE_QUBIT_KERNEL_CTRL_ENABLER(CLASSNAME, QRTNAME) \ class CLASSNAME : public OneQubitKernel<class CLASSNAME> { \ public: \ CLASSNAME(qubit q) : OneQubitKernel<CLASSNAME>(q) {} \ CLASSNAME(std::shared_ptr<qcor::CompositeInstruction> _parent_kernel, qubit q) \ : OneQubitKernel<CLASSNAME>(_parent_kernel, q) { throw std::runtime_error("you cannot call this.");} \ CLASSNAME(std::shared_ptr<qcor::CompositeInstruction> _parent_kernel, \ qubit q) \ : OneQubitKernel<CLASSNAME>(_parent_kernel, q) { \ throw std::runtime_error("you cannot call this."); \ } \ void operator()(qubit q) { \ parent_kernel = \ qcor::__internal__::create_composite("__tmp_one_qubit_ctrl_enabler"); \ parent_kernel = qcor::__internal__::create_composite( \ "__tmp_one_qubit_ctrl_enabler"); \ quantum::set_current_program(parent_kernel); \ if (runtime_env == QrtType::FTQC) { \ quantum::set_current_buffer(q.results()); \ Loading @@ -446,5 +460,4 @@ ONE_QUBIT_KERNEL_CTRL_ENABLER(Tdg, tdg) ONE_QUBIT_KERNEL_CTRL_ENABLER(S, s) ONE_QUBIT_KERNEL_CTRL_ENABLER(Sdg, sdg) } // namespace qcor