Loading python/examples/kernel_builder.py 0 → 100644 +14 −0 Original line number Diff line number Diff line from qcor import * nq = 10 builder = KernelBuilder() builder.h(0) for i in range(nq-1): builder.cnot(i, i+1) builder.measure_all() ghz = builder.create() q = qalloc(nq) ghz(q) print(q.counts()) python/py-qcor.cpp +11 −0 Original line number Diff line number Diff line Loading @@ -694,6 +694,17 @@ PYBIND11_MODULE(_pyqcor, m) { }, ""); m.def("internal_get_all_instructions", []() -> std::vector<py::tuple> { auto insts = xacc::getServices<xacc::Instruction>(); std::vector<py::tuple> ret; for (auto inst : insts) { if (!inst->isComposite()) { ret.push_back(py::make_tuple(inst->name(), inst->nRequiredBits(), inst->isParameterized())); } } return ret; }); // QuaSiMo sub-module bindings: { py::module qsim = m.def_submodule("QuaSiMo", "QCOR's python QuaSiMo submodule"); Loading python/qcor.in.py +63 −4 Original line number Diff line number Diff line import sys, atexit import xacc, sys, atexit if '@QCOR_APPEND_PLUGIN_PATH@': sys.argv += ['__internal__add__plugin__path', '@QCOR_APPEND_PLUGIN_PATH@'] import xacc from _pyqcor import * import inspect, ast from typing import List Loading Loading @@ -197,6 +195,9 @@ class qjit(object): self.extra_cpp_code = '' # Get the kernel function body as a string if '__internal_fbody_src_provided__' in kwargs: fbody_src = kwargs['__internal_fbody_src_provided__'] else: fbody_src = '\n'.join(inspect.getsource(self.function).split('\n')[2:]) # Get the arg variable names and their types Loading Loading @@ -594,6 +595,64 @@ class qjit(object): return class KernelBuilder(object): """ The QCOR KernelBuilder is a high-level data structure that enables the development of qcor quantum kernels programmatically in Python. Example usage: from qcor import * nq = 10 builder = KernelBuilder() builder.h(0) for i in range(nq-1): builder.cnot(i, i+1) builder.measure_all() ghz = builder.create() q = qalloc(nq) ghz(q) print(q.counts()) """ def __init__(self, py_args_dict : dict = {}): self.kernel_args = py_args_dict all_instructions = internal_get_all_instructions() self.qjit_str = '' self.qreg_name = 'q' TAB = ' ' for instruction in all_instructions: isParameterized = instruction[2] n_bits = instruction[1] name = instruction[0] if not instruction[2]: # No parameters... # set it as a method on this class qbits_str = ','.join(['q{}'.format(i) for i in range(n_bits)]) new_func_str = 'def {}(self, {}):\n'.format(instruction[0].lower(),qbits_str) qbit_str = ','.join([]) new_func_str += TAB +"self.qjit_str += ' {}(".format(name)+','.join( ["{}[{{}}]".format(self.qreg_name) for i in range(n_bits)])+")\\n'.format({})".format(qbits_str) # print(new_func_str) result = {} exec (new_func_str.strip(), result) setattr(KernelBuilder, instruction[0].lower(), result[instruction[0].lower()]) def measure_all(self): self.qjit_str += ' for i in range({}.size()):\n'.format(self.qreg_name) self.qjit_str += ' Measure({}[i])\n'.format(self.qreg_name) def create(self): # print(self.qjit_str) result = globals() exec('def test(q : qreg):\n'+self.qjit_str, result) # print(result) function = result['test'] _qjit = qjit(function, __internal_fbody_src_provided__ = self.qjit_str) return _qjit # Must have qpu in the init kwargs # defaults to qpp, but will search for -qpu flag Loading runtime/kernel/quantum_kernel.hpp +21 −0 Original line number Diff line number Diff line Loading @@ -79,6 +79,14 @@ class QuantumKernel { os << derived.parent_kernel->toString() << "\n"; } static void print_kernel(Args... args) { Derived derived(args...); derived.disable_destructor = true; derived(args...); xacc::internal_compiler::execute_pass_manager(); std::cout << derived.parent_kernel->toString() << "\n"; } // Static method to query how many instructions are in this kernel static std::size_t n_instructions(Args... args) { Derived derived(args...); Loading Loading @@ -232,6 +240,8 @@ class QuantumKernel { "Unable to observe kernels that already have Measure operations."); } xacc::internal_compiler::execute_pass_manager(); // Will fail to compile if more than one qreg is passed. std::tuple<Args...> tmp(std::forward_as_tuple(args...)); auto q = std::get<qreg>(tmp); Loading @@ -256,11 +266,22 @@ class QuantumKernel { "Unable to observe kernels that already have Measure operations."); } xacc::internal_compiler::execute_pass_manager(); // Will fail to compile if more than one qreg is passed. std::tuple<Args...> tmp(std::forward_as_tuple(args...)); auto q = std::get<qreg>(tmp); return qcor::observe(derived.parent_kernel, obs, q); } static std::string openqasm(Args... args) { Derived derived(args...); derived.disable_destructor = true; derived(args...); xacc::internal_compiler::execute_pass_manager(); return __internal__::translate("staq", derived.parent_kernel); } virtual ~QuantumKernel() {} }; Loading runtime/qrt/pass_manager.cpp +1 −0 Original line number Diff line number Diff line Loading @@ -105,6 +105,7 @@ void PassManager::applyPlacement( return "default-placement"; } // Use the specified placement if any. // Fall back on QPU specified placement if no placement specified by user // Note: placement will only be activated if the accelerator // has a connectivity graph. return m_placement.empty() Loading Loading
python/examples/kernel_builder.py 0 → 100644 +14 −0 Original line number Diff line number Diff line from qcor import * nq = 10 builder = KernelBuilder() builder.h(0) for i in range(nq-1): builder.cnot(i, i+1) builder.measure_all() ghz = builder.create() q = qalloc(nq) ghz(q) print(q.counts())
python/py-qcor.cpp +11 −0 Original line number Diff line number Diff line Loading @@ -694,6 +694,17 @@ PYBIND11_MODULE(_pyqcor, m) { }, ""); m.def("internal_get_all_instructions", []() -> std::vector<py::tuple> { auto insts = xacc::getServices<xacc::Instruction>(); std::vector<py::tuple> ret; for (auto inst : insts) { if (!inst->isComposite()) { ret.push_back(py::make_tuple(inst->name(), inst->nRequiredBits(), inst->isParameterized())); } } return ret; }); // QuaSiMo sub-module bindings: { py::module qsim = m.def_submodule("QuaSiMo", "QCOR's python QuaSiMo submodule"); Loading
python/qcor.in.py +63 −4 Original line number Diff line number Diff line import sys, atexit import xacc, sys, atexit if '@QCOR_APPEND_PLUGIN_PATH@': sys.argv += ['__internal__add__plugin__path', '@QCOR_APPEND_PLUGIN_PATH@'] import xacc from _pyqcor import * import inspect, ast from typing import List Loading Loading @@ -197,6 +195,9 @@ class qjit(object): self.extra_cpp_code = '' # Get the kernel function body as a string if '__internal_fbody_src_provided__' in kwargs: fbody_src = kwargs['__internal_fbody_src_provided__'] else: fbody_src = '\n'.join(inspect.getsource(self.function).split('\n')[2:]) # Get the arg variable names and their types Loading Loading @@ -594,6 +595,64 @@ class qjit(object): return class KernelBuilder(object): """ The QCOR KernelBuilder is a high-level data structure that enables the development of qcor quantum kernels programmatically in Python. Example usage: from qcor import * nq = 10 builder = KernelBuilder() builder.h(0) for i in range(nq-1): builder.cnot(i, i+1) builder.measure_all() ghz = builder.create() q = qalloc(nq) ghz(q) print(q.counts()) """ def __init__(self, py_args_dict : dict = {}): self.kernel_args = py_args_dict all_instructions = internal_get_all_instructions() self.qjit_str = '' self.qreg_name = 'q' TAB = ' ' for instruction in all_instructions: isParameterized = instruction[2] n_bits = instruction[1] name = instruction[0] if not instruction[2]: # No parameters... # set it as a method on this class qbits_str = ','.join(['q{}'.format(i) for i in range(n_bits)]) new_func_str = 'def {}(self, {}):\n'.format(instruction[0].lower(),qbits_str) qbit_str = ','.join([]) new_func_str += TAB +"self.qjit_str += ' {}(".format(name)+','.join( ["{}[{{}}]".format(self.qreg_name) for i in range(n_bits)])+")\\n'.format({})".format(qbits_str) # print(new_func_str) result = {} exec (new_func_str.strip(), result) setattr(KernelBuilder, instruction[0].lower(), result[instruction[0].lower()]) def measure_all(self): self.qjit_str += ' for i in range({}.size()):\n'.format(self.qreg_name) self.qjit_str += ' Measure({}[i])\n'.format(self.qreg_name) def create(self): # print(self.qjit_str) result = globals() exec('def test(q : qreg):\n'+self.qjit_str, result) # print(result) function = result['test'] _qjit = qjit(function, __internal_fbody_src_provided__ = self.qjit_str) return _qjit # Must have qpu in the init kwargs # defaults to qpp, but will search for -qpu flag Loading
runtime/kernel/quantum_kernel.hpp +21 −0 Original line number Diff line number Diff line Loading @@ -79,6 +79,14 @@ class QuantumKernel { os << derived.parent_kernel->toString() << "\n"; } static void print_kernel(Args... args) { Derived derived(args...); derived.disable_destructor = true; derived(args...); xacc::internal_compiler::execute_pass_manager(); std::cout << derived.parent_kernel->toString() << "\n"; } // Static method to query how many instructions are in this kernel static std::size_t n_instructions(Args... args) { Derived derived(args...); Loading Loading @@ -232,6 +240,8 @@ class QuantumKernel { "Unable to observe kernels that already have Measure operations."); } xacc::internal_compiler::execute_pass_manager(); // Will fail to compile if more than one qreg is passed. std::tuple<Args...> tmp(std::forward_as_tuple(args...)); auto q = std::get<qreg>(tmp); Loading @@ -256,11 +266,22 @@ class QuantumKernel { "Unable to observe kernels that already have Measure operations."); } xacc::internal_compiler::execute_pass_manager(); // Will fail to compile if more than one qreg is passed. std::tuple<Args...> tmp(std::forward_as_tuple(args...)); auto q = std::get<qreg>(tmp); return qcor::observe(derived.parent_kernel, obs, q); } static std::string openqasm(Args... args) { Derived derived(args...); derived.disable_destructor = true; derived(args...); xacc::internal_compiler::execute_pass_manager(); return __internal__::translate("staq", derived.parent_kernel); } virtual ~QuantumKernel() {} }; Loading
runtime/qrt/pass_manager.cpp +1 −0 Original line number Diff line number Diff line Loading @@ -105,6 +105,7 @@ void PassManager::applyPlacement( return "default-placement"; } // Use the specified placement if any. // Fall back on QPU specified placement if no placement specified by user // Note: placement will only be activated if the accelerator // has a connectivity graph. return m_placement.empty() Loading