Loading python/py-qcor.cpp +47 −15 Original line number Diff line number Diff line Loading @@ -118,7 +118,8 @@ class PyObjectiveFunction : public qcor::ObjectiveFunction { const std::string name() const override { return "py-objective-impl"; } const std::string description() const override { return ""; } PyObjectiveFunction(py::object q, qcor::PauliOperator &qq, const int n_dim, const std::string &helper_name) const std::string &helper_name, xacc::HeterogeneousMap opts = {}) : py_kernel(q) { // Set the OptFunction dimensions _dim = n_dim; Loading @@ -128,6 +129,9 @@ class PyObjectiveFunction : public qcor::ObjectiveFunction { // Store the observable pointer and give it to the helper observable = xacc::as_shared_ptr(&qq); options = opts; options.insert("observable", observable); helper->set_options(options); helper->update_observable(observable); // Extract the QJIT source code Loading @@ -141,21 +145,29 @@ class PyObjectiveFunction : public qcor::ObjectiveFunction { // Evaluate this ObjectiveFunction at the dictionary of kernel args, // return the scalar value double operator()(const KernelArgDict args) { double operator()(const KernelArgDict args, std::vector<double> &dx) { std::function<std::shared_ptr<CompositeInstruction>(std::vector<double>)> kernel_evaluator = [&](std::vector<double> x) { qreg = ::qalloc(observable->nBits()); auto _args = py_kernel.attr("translate")(qreg, x).cast<KernelArgDict>(); // Map the kernel args to a hetmap xacc::HeterogeneousMap m; for (auto &item : args) { for (auto &item : _args) { KernelArgDictToHeterogeneousMap vis(m, item.first); mpark::visit(vis, item.second); } // Get the kernel as a CompositeInstruction auto kernel_name = py_kernel.attr("kernel_name")().cast<std::string>(); kernel = qjit.extract_composite_with_hetmap(kernel_name, m); auto kernel_name = py_kernel.attr("kernel_name")().cast<std::string>(); return qjit.extract_composite_with_hetmap(kernel_name, m); }; kernel = kernel_evaluator(current_iterate_parameters); helper->update_kernel(kernel); helper->update_options("kernel-evaluator", kernel_evaluator); // FIXME, handle gradients std::vector<double> dx; return (*helper)(qreg, dx); } Loading @@ -169,7 +181,7 @@ class PyObjectiveFunction : public qcor::ObjectiveFunction { qreg = ::qalloc(observable->nBits()); auto args = py_kernel.attr("translate")(qreg, x).cast<KernelArgDict>(); // args will be a dictionary, arg_name to arg return operator()(args); return operator()(args, dx); } virtual double operator()(xacc::internal_compiler::qreg &qreg, Loading Loading @@ -324,6 +336,14 @@ PYBIND11_MODULE(_pyqcor, m) { [](qcor::ObjectiveFunction &obj, std::vector<double> x) { return obj(x); }, "") .def( "__call__", [](qcor::ObjectiveFunction &obj, std::vector<double> x, std::vector<double> &dx) { auto val = obj(x, dx); return std::make_pair(val, dx); }, ""); m.def( Loading @@ -336,6 +356,18 @@ PYBIND11_MODULE(_pyqcor, m) { return obj; }, ""); m.def( "createObjectiveFunction", [](py::object kernel, qcor::PauliOperator &obs, const int n_params, PyHeterogeneousMap &options) { auto nativeHetMap = heterogeneousMapConvert(options); auto q = ::qalloc(obs.nBits()); std::shared_ptr<qcor::ObjectiveFunction> obj = std::make_shared<qcor::PyObjectiveFunction>(kernel, obs, n_params, "vqe", nativeHetMap); return obj; }, ""); // qsim sub-module bindings: { Loading python/tests/test_qcor_spec_api.py +18 −0 Original line number Diff line number Diff line Loading @@ -32,6 +32,24 @@ class TestVQEObjectiveFunction(unittest.TestCase): print(ansatz.openqasm(q, [2.2])) def test_simple_deuteron_with_grad(self): @qjit def ansatz(q: qreg, theta: float): X(q[0]) Ry(q[1], theta) CX(q[1], q[0]) H = -2.1433 * X(0) * X(1) - 2.1433 * \ Y(0) * Y(1) + .21829 * Z(0) - 6.125 * Z(1) + 5.907 n_params = 1 obj = createObjectiveFunction(ansatz, H, n_params, {'gradient-strategy':'parameter-shift'}) optimizer = createOptimizer('nlopt', {'nlopt-optimizer':'l-bfgs'}) results = optimizer.optimize(obj) self.assertAlmostEqual(results[0], -1.74, places=1) print(results) if __name__ == '__main__': unittest.main() runtime/objectives/objective_function.hpp +146 −78 Original line number Diff line number Diff line #pragma once #include <functional> #include "qcor_observable.hpp" #include "qcor_utils.hpp" #include "quantum_kernel.hpp" #include <functional> namespace qcor { Loading Loading @@ -50,7 +51,8 @@ public: } // Set any extra options needed for the objective function virtual void set_options(HeterogeneousMap &opts) { options = opts; } template <typename T> void update_options(const std::string key, T value) { template <typename T> void update_options(const std::string key, T value) { options.insert(key, value); } Loading @@ -61,6 +63,56 @@ public: } }; namespace __internal__ { // Get the objective function from the service registry std::shared_ptr<ObjectiveFunction> get_objective(const std::string &type); template <typename T> std::shared_ptr<T> qcor_as_shared(T *t) { return std::shared_ptr<T>(t, [](T *const) {}); } template <std::size_t... Is> auto create_tuple_impl(std::index_sequence<Is...>, const std::vector<double> &arguments) { return std::make_tuple(arguments[Is]...); } template <std::size_t N> auto create_tuple(const std::vector<double> &arguments) { return create_tuple_impl(std::make_index_sequence<N>{}, arguments); } struct ArgsTranslatorAutoGenerator { std::shared_ptr<ArgsTranslator<qreg, std::vector<double>>> operator()( qreg &q, std::tuple<qreg, std::vector<double>> &&) { return std::make_shared<ArgsTranslator<qreg, std::vector<double>>>( [&](const std::vector<double> &x) { return std::make_tuple(q, x); }); } template <typename... DoubleTypes> std::shared_ptr<ArgsTranslator<qreg, DoubleTypes...>> operator()( qreg &q, std::tuple<qreg, DoubleTypes...> &&t) { if constexpr ((std::is_same<DoubleTypes, double>::value && ...)) { return std::make_shared<ArgsTranslator<qreg, DoubleTypes...>>( [&](const std::vector<double> &x) { auto qreg_tuple = std::make_tuple(q); auto double_tuple = create_tuple<sizeof...(DoubleTypes)>(x); return std::tuple_cat(qreg_tuple, double_tuple); }); } else { error( "QCOR cannot auto-generate a ArgsTranslator for this " "ObjectiveFunction. Please provide a custom ArgsTranslator to " "createObjectiveFunction."); return std::make_shared<ArgsTranslator<qreg, DoubleTypes...>>( [&](const std::vector<double> &x) { return t; }); } } }; } // namespace __internal__ template <typename... KernelArgs> class ObjectiveFunctionImpl : public ObjectiveFunction { private: Loading @@ -77,7 +129,7 @@ private: protected: std::shared_ptr<LocalArgsTranslator> args_translator; std::shared_ptr<ObjectiveFunction> helper; xacc::internal_compiler::qreg &qreg; xacc::internal_compiler::qreg qreg; public: ObjectiveFunctionImpl(void *k_ptr, std::shared_ptr<Observable> obs, Loading @@ -97,6 +149,25 @@ public: helper->update_observable(observable); helper->set_options(options); } ObjectiveFunctionImpl(void *k_ptr, std::shared_ptr<Observable> obs, std::shared_ptr<ObjectiveFunction> obj_helper, const int dim, HeterogeneousMap opts) { qreg = ::qalloc(obs->nBits()); kernel_ptr = k_ptr; observable = obs; __internal__::ArgsTranslatorAutoGenerator auto_gen; args_translator = auto_gen(qreg, std::tuple<KernelArgs...>()); // args_translator = translator; helper = obj_helper; _dim = dim; _function = *this; options = opts; options.insert("observable", observable); helper->update_observable(observable); helper->set_options(options); } void set_options(HeterogeneousMap &opts) override { options = opts; helper->set_options(opts); Loading Loading @@ -164,62 +235,12 @@ public: const std::string description() const override { return ""; } }; namespace __internal__ { // Get the objective function from the service registry std::shared_ptr<ObjectiveFunction> get_objective(const std::string &type); template <typename T> std::shared_ptr<T> qcor_as_shared(T *t) { return std::shared_ptr<T>(t, [](T *const) {}); } template <std::size_t... Is> auto create_tuple_impl(std::index_sequence<Is...>, const std::vector<double> &arguments) { return std::make_tuple(arguments[Is]...); } template <std::size_t N> auto create_tuple(const std::vector<double> &arguments) { return create_tuple_impl(std::make_index_sequence<N>{}, arguments); } struct ArgsTranslatorAutoGenerator { std::shared_ptr<ArgsTranslator<qreg, std::vector<double>>> operator()(qreg &q, std::tuple<qreg, std::vector<double>> &&) { return std::make_shared<ArgsTranslator<qreg, std::vector<double>>>( [&](const std::vector<double> &x) { return std::make_tuple(q, x); }); } template <typename... DoubleTypes> std::shared_ptr<ArgsTranslator<qreg, DoubleTypes...>> operator()(qreg &q, std::tuple<qreg, DoubleTypes...> &&t) { if constexpr ((std::is_same<DoubleTypes, double>::value && ...)) { return std::make_shared<ArgsTranslator<qreg, DoubleTypes...>>( [&](const std::vector<double> &x) { auto qreg_tuple = std::make_tuple(q); auto double_tuple = create_tuple<sizeof...(DoubleTypes)>(x); return std::tuple_cat(qreg_tuple, double_tuple); }); } else { error("QCOR cannot auto-generate a ArgsTranslator for this " "ObjectiveFunction. Please provide a custom ArgsTranslator to " "createObjectiveFunction."); return std::make_shared<ArgsTranslator<qreg, DoubleTypes...>>( [&](const std::vector<double> &x) { return t; }); } } }; } // namespace __internal__ template <typename... Args> std::shared_ptr<ObjectiveFunction> createObjectiveFunction( void (*quantum_kernel_functor)(std::shared_ptr<CompositeInstruction>, Args...), std::shared_ptr<Observable> observable, qreg &q, const int nParams, HeterogeneousMap &&options = {}) { auto helper = qcor::__internal__::get_objective("vqe"); __internal__::ArgsTranslatorAutoGenerator auto_gen; auto args_translator = auto_gen(q, std::tuple<Args...>()); Loading @@ -237,7 +258,6 @@ std::shared_ptr<ObjectiveFunction> createObjectiveFunction( Args...), std::shared_ptr<Observable> observable, qreg &q, const int nParams, HeterogeneousMap &&options = {}) { auto helper = qcor::__internal__::get_objective(obj_name); __internal__::ArgsTranslatorAutoGenerator auto_gen; auto args_translator = auto_gen(q, std::tuple<Args...>()); Loading @@ -254,7 +274,6 @@ std::shared_ptr<ObjectiveFunction> createObjectiveFunction( Args...), Observable &observable, qreg &q, const int nParams, HeterogeneousMap &&options = {}) { auto helper = qcor::__internal__::get_objective("vqe"); __internal__::ArgsTranslatorAutoGenerator auto_gen; auto args_translator = auto_gen(q, std::tuple<Args...>()); Loading @@ -273,7 +292,6 @@ std::shared_ptr<ObjectiveFunction> createObjectiveFunction( Args...), Observable &observable, qreg &q, const int nParams, HeterogeneousMap &&options = {}) { auto helper = qcor::__internal__::get_objective(obj_name); __internal__::ArgsTranslatorAutoGenerator auto_gen; auto args_translator = auto_gen(q, std::tuple<Args...>()); Loading @@ -290,7 +308,6 @@ std::shared_ptr<ObjectiveFunction> createObjectiveFunction( void (*quantum_kernel_functor)(std::shared_ptr<CompositeInstruction>, Args...), qreg &q, const int nParams, HeterogeneousMap &&options = {}) { auto helper = qcor::__internal__::get_objective("vqe"); __internal__::ArgsTranslatorAutoGenerator auto_gen; auto args_translator = auto_gen(q, std::tuple<Args...>()); Loading @@ -298,8 +315,7 @@ std::shared_ptr<ObjectiveFunction> createObjectiveFunction( void *kernel_ptr = reinterpret_cast<void *>(quantum_kernel_functor); std::map<int, std::string> all_zs; for (int i = 0; i < q.size(); i++) all_zs.insert({i, "Z"}); for (int i = 0; i < q.size(); i++) all_zs.insert({i, "Z"}); auto observable = std::make_shared<PauliOperator>(all_zs); return std::make_shared<ObjectiveFunctionImpl<Args...>>( kernel_ptr, observable, q, args_translator, helper, nParams, options); Loading @@ -311,7 +327,6 @@ std::shared_ptr<ObjectiveFunction> createObjectiveFunction( void (*quantum_kernel_functor)(std::shared_ptr<CompositeInstruction>, Args...), qreg &q, const int nParams, HeterogeneousMap &&options = {}) { auto helper = qcor::__internal__::get_objective(obj_name); __internal__::ArgsTranslatorAutoGenerator auto_gen; auto args_translator = auto_gen(q, std::tuple<Args...>()); Loading @@ -319,8 +334,7 @@ std::shared_ptr<ObjectiveFunction> createObjectiveFunction( void *kernel_ptr = reinterpret_cast<void *>(quantum_kernel_functor); std::map<int, std::string> all_zs; for (int i = 0; i < q.size(); i++) all_zs.insert({i, "Z"}); for (int i = 0; i < q.size(); i++) all_zs.insert({i, "Z"}); auto observable = std::make_shared<PauliOperator>(all_zs); return std::make_shared<ObjectiveFunctionImpl<Args...>>( kernel_ptr, observable, q, args_translator, helper, nParams, options); Loading @@ -335,7 +349,6 @@ std::shared_ptr<ObjectiveFunction> createObjectiveFunction( std::shared_ptr<Observable> observable, std::shared_ptr<ArgsTranslator<Args...>> args_translator, qreg &q, const int nParams, HeterogeneousMap &&options = {}) { auto helper = qcor::__internal__::get_objective("vqe"); void *kernel_ptr = reinterpret_cast<void *>(quantum_kernel_functor); Loading @@ -352,7 +365,6 @@ std::shared_ptr<ObjectiveFunction> createObjectiveFunction( std::shared_ptr<Observable> observable, std::shared_ptr<ArgsTranslator<Args...>> args_translator, qreg &q, const int nParams, HeterogeneousMap &&options = {}) { auto helper = qcor::__internal__::get_objective(obj_name); void *kernel_ptr = reinterpret_cast<void *>(quantum_kernel_functor); Loading @@ -368,7 +380,6 @@ std::shared_ptr<ObjectiveFunction> createObjectiveFunction( Observable &observable, std::shared_ptr<ArgsTranslator<Args...>> args_translator, qreg &q, const int nParams, HeterogeneousMap &&options = {}) { auto helper = qcor::__internal__::get_objective("vqe"); void *kernel_ptr = reinterpret_cast<void *>(quantum_kernel_functor); Loading @@ -386,7 +397,6 @@ std::shared_ptr<ObjectiveFunction> createObjectiveFunction( Observable &observable, std::shared_ptr<ArgsTranslator<Args...>> args_translator, qreg &q, const int nParams, HeterogeneousMap &&options = {}) { auto helper = qcor::__internal__::get_objective(obj_name); void *kernel_ptr = reinterpret_cast<void *>(quantum_kernel_functor); Loading @@ -402,14 +412,12 @@ std::shared_ptr<ObjectiveFunction> createObjectiveFunction( Args...), std::shared_ptr<ArgsTranslator<Args...>> args_translator, qreg &q, const int nParams, HeterogeneousMap &&options = {}) { auto helper = qcor::__internal__::get_objective("vqe"); void *kernel_ptr = reinterpret_cast<void *>(quantum_kernel_functor); std::map<int, std::string> all_zs; for (int i = 0; i < q.size(); i++) all_zs.insert({i, "Z"}); for (int i = 0; i < q.size(); i++) all_zs.insert({i, "Z"}); auto observable = std::make_shared<PauliOperator>(all_zs); return std::make_shared<ObjectiveFunctionImpl<Args...>>( kernel_ptr, observable, q, args_translator, helper, nParams, options); Loading @@ -422,17 +430,77 @@ std::shared_ptr<ObjectiveFunction> createObjectiveFunction( Args...), std::shared_ptr<ArgsTranslator<Args...>> args_translator, qreg &q, const int nParams, HeterogeneousMap &&options = {}) { auto helper = qcor::__internal__::get_objective(obj_name); void *kernel_ptr = reinterpret_cast<void *>(quantum_kernel_functor); std::map<int, std::string> all_zs; for (int i = 0; i < q.size(); i++) all_zs.insert({i, "Z"}); for (int i = 0; i < q.size(); i++) all_zs.insert({i, "Z"}); auto observable = std::make_shared<PauliOperator>(all_zs); return std::make_shared<ObjectiveFunctionImpl<Args...>>( kernel_ptr, observable, q, args_translator, helper, nParams, options); } /// no qreg args template <typename... Args> std::shared_ptr<ObjectiveFunction> createObjectiveFunction( void (*quantum_kernel_functor)(std::shared_ptr<CompositeInstruction>, Args...), std::shared_ptr<Observable> observable, const int nParams, HeterogeneousMap &&options = {}) { auto helper = qcor::__internal__::get_objective("vqe"); void *kernel_ptr = reinterpret_cast<void *>(quantum_kernel_functor); return std::make_shared<ObjectiveFunctionImpl<Args...>>( kernel_ptr, observable, helper, nParams, options); } template <typename... Args> std::shared_ptr<ObjectiveFunction> createObjectiveFunction( const std::string obj_name, void (*quantum_kernel_functor)(std::shared_ptr<CompositeInstruction>, Args...), std::shared_ptr<Observable> observable, const int nParams, HeterogeneousMap &&options = {}) { auto helper = qcor::__internal__::get_objective(obj_name); void *kernel_ptr = reinterpret_cast<void *>(quantum_kernel_functor); return std::make_shared<ObjectiveFunctionImpl<Args...>>( kernel_ptr, observable, helper, nParams, options); } template <typename... Args> std::shared_ptr<ObjectiveFunction> createObjectiveFunction( void (*quantum_kernel_functor)(std::shared_ptr<CompositeInstruction>, Args...), Observable &observable, const int nParams, HeterogeneousMap &&options = {}) { auto helper = qcor::__internal__::get_objective("vqe"); void *kernel_ptr = reinterpret_cast<void *>(quantum_kernel_functor); return std::make_shared<ObjectiveFunctionImpl<Args...>>( kernel_ptr, __internal__::qcor_as_shared(&observable), helper, nParams, options); } template <typename... Args> std::shared_ptr<ObjectiveFunction> createObjectiveFunction( const std::string obj_name, void (*quantum_kernel_functor)(std::shared_ptr<CompositeInstruction>, Args...), Observable &observable, const int nParams, HeterogeneousMap &&options = {}) { auto helper = qcor::__internal__::get_objective(obj_name); void *kernel_ptr = reinterpret_cast<void *>(quantum_kernel_functor); return std::make_shared<ObjectiveFunctionImpl<Args...>>( kernel_ptr, __internal__::qcor_as_shared(&observable), helper, nParams, options); } } // namespace qcor No newline at end of file tools/driver/qcor-macosx.in +4 −0 Original line number Diff line number Diff line Loading @@ -62,6 +62,10 @@ def main(argv=None): sys.argv.remove('-qpu') sys.argv += ['-D__internal__qcor__compile__backend=\"'+accName+'\"'] sHandlerArgs = ['-Xclang', '-plugin-arg-qcor-args', '-Xclang', '-qpu', '-Xclang', '-plugin-arg-qcor-args', '-Xclang', accName] else: accName = 'qpp' sys.argv += ['-D__internal__qcor__compile__backend=\"'+accName+'\"'] sHandlerArgs = ['-Xclang', '-plugin-arg-qcor-args', '-Xclang', '-qpu', '-Xclang', '-plugin-arg-qcor-args', '-Xclang', accName] # Get the shots if necessary shots = 0 Loading tools/driver/qcor.in +5 −1 Original line number Diff line number Diff line Loading @@ -59,6 +59,10 @@ def main(argv=None): sys.argv.remove('-qpu') sys.argv += ['-D__internal__qcor__compile__backend=\"'+accName+'\"'] sHandlerArgs = ['-Xclang', '-plugin-arg-qcor-args', '-Xclang', '-qpu', '-Xclang', '-plugin-arg-qcor-args', '-Xclang', accName] else: accName = 'qpp' sys.argv += ['-D__internal__qcor__compile__backend=\"'+accName+'\"'] sHandlerArgs = ['-Xclang', '-plugin-arg-qcor-args', '-Xclang', '-qpu', '-Xclang', '-plugin-arg-qcor-args', '-Xclang', accName] # Get the shots if necessary shots = 0 Loading Loading
python/py-qcor.cpp +47 −15 Original line number Diff line number Diff line Loading @@ -118,7 +118,8 @@ class PyObjectiveFunction : public qcor::ObjectiveFunction { const std::string name() const override { return "py-objective-impl"; } const std::string description() const override { return ""; } PyObjectiveFunction(py::object q, qcor::PauliOperator &qq, const int n_dim, const std::string &helper_name) const std::string &helper_name, xacc::HeterogeneousMap opts = {}) : py_kernel(q) { // Set the OptFunction dimensions _dim = n_dim; Loading @@ -128,6 +129,9 @@ class PyObjectiveFunction : public qcor::ObjectiveFunction { // Store the observable pointer and give it to the helper observable = xacc::as_shared_ptr(&qq); options = opts; options.insert("observable", observable); helper->set_options(options); helper->update_observable(observable); // Extract the QJIT source code Loading @@ -141,21 +145,29 @@ class PyObjectiveFunction : public qcor::ObjectiveFunction { // Evaluate this ObjectiveFunction at the dictionary of kernel args, // return the scalar value double operator()(const KernelArgDict args) { double operator()(const KernelArgDict args, std::vector<double> &dx) { std::function<std::shared_ptr<CompositeInstruction>(std::vector<double>)> kernel_evaluator = [&](std::vector<double> x) { qreg = ::qalloc(observable->nBits()); auto _args = py_kernel.attr("translate")(qreg, x).cast<KernelArgDict>(); // Map the kernel args to a hetmap xacc::HeterogeneousMap m; for (auto &item : args) { for (auto &item : _args) { KernelArgDictToHeterogeneousMap vis(m, item.first); mpark::visit(vis, item.second); } // Get the kernel as a CompositeInstruction auto kernel_name = py_kernel.attr("kernel_name")().cast<std::string>(); kernel = qjit.extract_composite_with_hetmap(kernel_name, m); auto kernel_name = py_kernel.attr("kernel_name")().cast<std::string>(); return qjit.extract_composite_with_hetmap(kernel_name, m); }; kernel = kernel_evaluator(current_iterate_parameters); helper->update_kernel(kernel); helper->update_options("kernel-evaluator", kernel_evaluator); // FIXME, handle gradients std::vector<double> dx; return (*helper)(qreg, dx); } Loading @@ -169,7 +181,7 @@ class PyObjectiveFunction : public qcor::ObjectiveFunction { qreg = ::qalloc(observable->nBits()); auto args = py_kernel.attr("translate")(qreg, x).cast<KernelArgDict>(); // args will be a dictionary, arg_name to arg return operator()(args); return operator()(args, dx); } virtual double operator()(xacc::internal_compiler::qreg &qreg, Loading Loading @@ -324,6 +336,14 @@ PYBIND11_MODULE(_pyqcor, m) { [](qcor::ObjectiveFunction &obj, std::vector<double> x) { return obj(x); }, "") .def( "__call__", [](qcor::ObjectiveFunction &obj, std::vector<double> x, std::vector<double> &dx) { auto val = obj(x, dx); return std::make_pair(val, dx); }, ""); m.def( Loading @@ -336,6 +356,18 @@ PYBIND11_MODULE(_pyqcor, m) { return obj; }, ""); m.def( "createObjectiveFunction", [](py::object kernel, qcor::PauliOperator &obs, const int n_params, PyHeterogeneousMap &options) { auto nativeHetMap = heterogeneousMapConvert(options); auto q = ::qalloc(obs.nBits()); std::shared_ptr<qcor::ObjectiveFunction> obj = std::make_shared<qcor::PyObjectiveFunction>(kernel, obs, n_params, "vqe", nativeHetMap); return obj; }, ""); // qsim sub-module bindings: { Loading
python/tests/test_qcor_spec_api.py +18 −0 Original line number Diff line number Diff line Loading @@ -32,6 +32,24 @@ class TestVQEObjectiveFunction(unittest.TestCase): print(ansatz.openqasm(q, [2.2])) def test_simple_deuteron_with_grad(self): @qjit def ansatz(q: qreg, theta: float): X(q[0]) Ry(q[1], theta) CX(q[1], q[0]) H = -2.1433 * X(0) * X(1) - 2.1433 * \ Y(0) * Y(1) + .21829 * Z(0) - 6.125 * Z(1) + 5.907 n_params = 1 obj = createObjectiveFunction(ansatz, H, n_params, {'gradient-strategy':'parameter-shift'}) optimizer = createOptimizer('nlopt', {'nlopt-optimizer':'l-bfgs'}) results = optimizer.optimize(obj) self.assertAlmostEqual(results[0], -1.74, places=1) print(results) if __name__ == '__main__': unittest.main()
runtime/objectives/objective_function.hpp +146 −78 Original line number Diff line number Diff line #pragma once #include <functional> #include "qcor_observable.hpp" #include "qcor_utils.hpp" #include "quantum_kernel.hpp" #include <functional> namespace qcor { Loading Loading @@ -50,7 +51,8 @@ public: } // Set any extra options needed for the objective function virtual void set_options(HeterogeneousMap &opts) { options = opts; } template <typename T> void update_options(const std::string key, T value) { template <typename T> void update_options(const std::string key, T value) { options.insert(key, value); } Loading @@ -61,6 +63,56 @@ public: } }; namespace __internal__ { // Get the objective function from the service registry std::shared_ptr<ObjectiveFunction> get_objective(const std::string &type); template <typename T> std::shared_ptr<T> qcor_as_shared(T *t) { return std::shared_ptr<T>(t, [](T *const) {}); } template <std::size_t... Is> auto create_tuple_impl(std::index_sequence<Is...>, const std::vector<double> &arguments) { return std::make_tuple(arguments[Is]...); } template <std::size_t N> auto create_tuple(const std::vector<double> &arguments) { return create_tuple_impl(std::make_index_sequence<N>{}, arguments); } struct ArgsTranslatorAutoGenerator { std::shared_ptr<ArgsTranslator<qreg, std::vector<double>>> operator()( qreg &q, std::tuple<qreg, std::vector<double>> &&) { return std::make_shared<ArgsTranslator<qreg, std::vector<double>>>( [&](const std::vector<double> &x) { return std::make_tuple(q, x); }); } template <typename... DoubleTypes> std::shared_ptr<ArgsTranslator<qreg, DoubleTypes...>> operator()( qreg &q, std::tuple<qreg, DoubleTypes...> &&t) { if constexpr ((std::is_same<DoubleTypes, double>::value && ...)) { return std::make_shared<ArgsTranslator<qreg, DoubleTypes...>>( [&](const std::vector<double> &x) { auto qreg_tuple = std::make_tuple(q); auto double_tuple = create_tuple<sizeof...(DoubleTypes)>(x); return std::tuple_cat(qreg_tuple, double_tuple); }); } else { error( "QCOR cannot auto-generate a ArgsTranslator for this " "ObjectiveFunction. Please provide a custom ArgsTranslator to " "createObjectiveFunction."); return std::make_shared<ArgsTranslator<qreg, DoubleTypes...>>( [&](const std::vector<double> &x) { return t; }); } } }; } // namespace __internal__ template <typename... KernelArgs> class ObjectiveFunctionImpl : public ObjectiveFunction { private: Loading @@ -77,7 +129,7 @@ private: protected: std::shared_ptr<LocalArgsTranslator> args_translator; std::shared_ptr<ObjectiveFunction> helper; xacc::internal_compiler::qreg &qreg; xacc::internal_compiler::qreg qreg; public: ObjectiveFunctionImpl(void *k_ptr, std::shared_ptr<Observable> obs, Loading @@ -97,6 +149,25 @@ public: helper->update_observable(observable); helper->set_options(options); } ObjectiveFunctionImpl(void *k_ptr, std::shared_ptr<Observable> obs, std::shared_ptr<ObjectiveFunction> obj_helper, const int dim, HeterogeneousMap opts) { qreg = ::qalloc(obs->nBits()); kernel_ptr = k_ptr; observable = obs; __internal__::ArgsTranslatorAutoGenerator auto_gen; args_translator = auto_gen(qreg, std::tuple<KernelArgs...>()); // args_translator = translator; helper = obj_helper; _dim = dim; _function = *this; options = opts; options.insert("observable", observable); helper->update_observable(observable); helper->set_options(options); } void set_options(HeterogeneousMap &opts) override { options = opts; helper->set_options(opts); Loading Loading @@ -164,62 +235,12 @@ public: const std::string description() const override { return ""; } }; namespace __internal__ { // Get the objective function from the service registry std::shared_ptr<ObjectiveFunction> get_objective(const std::string &type); template <typename T> std::shared_ptr<T> qcor_as_shared(T *t) { return std::shared_ptr<T>(t, [](T *const) {}); } template <std::size_t... Is> auto create_tuple_impl(std::index_sequence<Is...>, const std::vector<double> &arguments) { return std::make_tuple(arguments[Is]...); } template <std::size_t N> auto create_tuple(const std::vector<double> &arguments) { return create_tuple_impl(std::make_index_sequence<N>{}, arguments); } struct ArgsTranslatorAutoGenerator { std::shared_ptr<ArgsTranslator<qreg, std::vector<double>>> operator()(qreg &q, std::tuple<qreg, std::vector<double>> &&) { return std::make_shared<ArgsTranslator<qreg, std::vector<double>>>( [&](const std::vector<double> &x) { return std::make_tuple(q, x); }); } template <typename... DoubleTypes> std::shared_ptr<ArgsTranslator<qreg, DoubleTypes...>> operator()(qreg &q, std::tuple<qreg, DoubleTypes...> &&t) { if constexpr ((std::is_same<DoubleTypes, double>::value && ...)) { return std::make_shared<ArgsTranslator<qreg, DoubleTypes...>>( [&](const std::vector<double> &x) { auto qreg_tuple = std::make_tuple(q); auto double_tuple = create_tuple<sizeof...(DoubleTypes)>(x); return std::tuple_cat(qreg_tuple, double_tuple); }); } else { error("QCOR cannot auto-generate a ArgsTranslator for this " "ObjectiveFunction. Please provide a custom ArgsTranslator to " "createObjectiveFunction."); return std::make_shared<ArgsTranslator<qreg, DoubleTypes...>>( [&](const std::vector<double> &x) { return t; }); } } }; } // namespace __internal__ template <typename... Args> std::shared_ptr<ObjectiveFunction> createObjectiveFunction( void (*quantum_kernel_functor)(std::shared_ptr<CompositeInstruction>, Args...), std::shared_ptr<Observable> observable, qreg &q, const int nParams, HeterogeneousMap &&options = {}) { auto helper = qcor::__internal__::get_objective("vqe"); __internal__::ArgsTranslatorAutoGenerator auto_gen; auto args_translator = auto_gen(q, std::tuple<Args...>()); Loading @@ -237,7 +258,6 @@ std::shared_ptr<ObjectiveFunction> createObjectiveFunction( Args...), std::shared_ptr<Observable> observable, qreg &q, const int nParams, HeterogeneousMap &&options = {}) { auto helper = qcor::__internal__::get_objective(obj_name); __internal__::ArgsTranslatorAutoGenerator auto_gen; auto args_translator = auto_gen(q, std::tuple<Args...>()); Loading @@ -254,7 +274,6 @@ std::shared_ptr<ObjectiveFunction> createObjectiveFunction( Args...), Observable &observable, qreg &q, const int nParams, HeterogeneousMap &&options = {}) { auto helper = qcor::__internal__::get_objective("vqe"); __internal__::ArgsTranslatorAutoGenerator auto_gen; auto args_translator = auto_gen(q, std::tuple<Args...>()); Loading @@ -273,7 +292,6 @@ std::shared_ptr<ObjectiveFunction> createObjectiveFunction( Args...), Observable &observable, qreg &q, const int nParams, HeterogeneousMap &&options = {}) { auto helper = qcor::__internal__::get_objective(obj_name); __internal__::ArgsTranslatorAutoGenerator auto_gen; auto args_translator = auto_gen(q, std::tuple<Args...>()); Loading @@ -290,7 +308,6 @@ std::shared_ptr<ObjectiveFunction> createObjectiveFunction( void (*quantum_kernel_functor)(std::shared_ptr<CompositeInstruction>, Args...), qreg &q, const int nParams, HeterogeneousMap &&options = {}) { auto helper = qcor::__internal__::get_objective("vqe"); __internal__::ArgsTranslatorAutoGenerator auto_gen; auto args_translator = auto_gen(q, std::tuple<Args...>()); Loading @@ -298,8 +315,7 @@ std::shared_ptr<ObjectiveFunction> createObjectiveFunction( void *kernel_ptr = reinterpret_cast<void *>(quantum_kernel_functor); std::map<int, std::string> all_zs; for (int i = 0; i < q.size(); i++) all_zs.insert({i, "Z"}); for (int i = 0; i < q.size(); i++) all_zs.insert({i, "Z"}); auto observable = std::make_shared<PauliOperator>(all_zs); return std::make_shared<ObjectiveFunctionImpl<Args...>>( kernel_ptr, observable, q, args_translator, helper, nParams, options); Loading @@ -311,7 +327,6 @@ std::shared_ptr<ObjectiveFunction> createObjectiveFunction( void (*quantum_kernel_functor)(std::shared_ptr<CompositeInstruction>, Args...), qreg &q, const int nParams, HeterogeneousMap &&options = {}) { auto helper = qcor::__internal__::get_objective(obj_name); __internal__::ArgsTranslatorAutoGenerator auto_gen; auto args_translator = auto_gen(q, std::tuple<Args...>()); Loading @@ -319,8 +334,7 @@ std::shared_ptr<ObjectiveFunction> createObjectiveFunction( void *kernel_ptr = reinterpret_cast<void *>(quantum_kernel_functor); std::map<int, std::string> all_zs; for (int i = 0; i < q.size(); i++) all_zs.insert({i, "Z"}); for (int i = 0; i < q.size(); i++) all_zs.insert({i, "Z"}); auto observable = std::make_shared<PauliOperator>(all_zs); return std::make_shared<ObjectiveFunctionImpl<Args...>>( kernel_ptr, observable, q, args_translator, helper, nParams, options); Loading @@ -335,7 +349,6 @@ std::shared_ptr<ObjectiveFunction> createObjectiveFunction( std::shared_ptr<Observable> observable, std::shared_ptr<ArgsTranslator<Args...>> args_translator, qreg &q, const int nParams, HeterogeneousMap &&options = {}) { auto helper = qcor::__internal__::get_objective("vqe"); void *kernel_ptr = reinterpret_cast<void *>(quantum_kernel_functor); Loading @@ -352,7 +365,6 @@ std::shared_ptr<ObjectiveFunction> createObjectiveFunction( std::shared_ptr<Observable> observable, std::shared_ptr<ArgsTranslator<Args...>> args_translator, qreg &q, const int nParams, HeterogeneousMap &&options = {}) { auto helper = qcor::__internal__::get_objective(obj_name); void *kernel_ptr = reinterpret_cast<void *>(quantum_kernel_functor); Loading @@ -368,7 +380,6 @@ std::shared_ptr<ObjectiveFunction> createObjectiveFunction( Observable &observable, std::shared_ptr<ArgsTranslator<Args...>> args_translator, qreg &q, const int nParams, HeterogeneousMap &&options = {}) { auto helper = qcor::__internal__::get_objective("vqe"); void *kernel_ptr = reinterpret_cast<void *>(quantum_kernel_functor); Loading @@ -386,7 +397,6 @@ std::shared_ptr<ObjectiveFunction> createObjectiveFunction( Observable &observable, std::shared_ptr<ArgsTranslator<Args...>> args_translator, qreg &q, const int nParams, HeterogeneousMap &&options = {}) { auto helper = qcor::__internal__::get_objective(obj_name); void *kernel_ptr = reinterpret_cast<void *>(quantum_kernel_functor); Loading @@ -402,14 +412,12 @@ std::shared_ptr<ObjectiveFunction> createObjectiveFunction( Args...), std::shared_ptr<ArgsTranslator<Args...>> args_translator, qreg &q, const int nParams, HeterogeneousMap &&options = {}) { auto helper = qcor::__internal__::get_objective("vqe"); void *kernel_ptr = reinterpret_cast<void *>(quantum_kernel_functor); std::map<int, std::string> all_zs; for (int i = 0; i < q.size(); i++) all_zs.insert({i, "Z"}); for (int i = 0; i < q.size(); i++) all_zs.insert({i, "Z"}); auto observable = std::make_shared<PauliOperator>(all_zs); return std::make_shared<ObjectiveFunctionImpl<Args...>>( kernel_ptr, observable, q, args_translator, helper, nParams, options); Loading @@ -422,17 +430,77 @@ std::shared_ptr<ObjectiveFunction> createObjectiveFunction( Args...), std::shared_ptr<ArgsTranslator<Args...>> args_translator, qreg &q, const int nParams, HeterogeneousMap &&options = {}) { auto helper = qcor::__internal__::get_objective(obj_name); void *kernel_ptr = reinterpret_cast<void *>(quantum_kernel_functor); std::map<int, std::string> all_zs; for (int i = 0; i < q.size(); i++) all_zs.insert({i, "Z"}); for (int i = 0; i < q.size(); i++) all_zs.insert({i, "Z"}); auto observable = std::make_shared<PauliOperator>(all_zs); return std::make_shared<ObjectiveFunctionImpl<Args...>>( kernel_ptr, observable, q, args_translator, helper, nParams, options); } /// no qreg args template <typename... Args> std::shared_ptr<ObjectiveFunction> createObjectiveFunction( void (*quantum_kernel_functor)(std::shared_ptr<CompositeInstruction>, Args...), std::shared_ptr<Observable> observable, const int nParams, HeterogeneousMap &&options = {}) { auto helper = qcor::__internal__::get_objective("vqe"); void *kernel_ptr = reinterpret_cast<void *>(quantum_kernel_functor); return std::make_shared<ObjectiveFunctionImpl<Args...>>( kernel_ptr, observable, helper, nParams, options); } template <typename... Args> std::shared_ptr<ObjectiveFunction> createObjectiveFunction( const std::string obj_name, void (*quantum_kernel_functor)(std::shared_ptr<CompositeInstruction>, Args...), std::shared_ptr<Observable> observable, const int nParams, HeterogeneousMap &&options = {}) { auto helper = qcor::__internal__::get_objective(obj_name); void *kernel_ptr = reinterpret_cast<void *>(quantum_kernel_functor); return std::make_shared<ObjectiveFunctionImpl<Args...>>( kernel_ptr, observable, helper, nParams, options); } template <typename... Args> std::shared_ptr<ObjectiveFunction> createObjectiveFunction( void (*quantum_kernel_functor)(std::shared_ptr<CompositeInstruction>, Args...), Observable &observable, const int nParams, HeterogeneousMap &&options = {}) { auto helper = qcor::__internal__::get_objective("vqe"); void *kernel_ptr = reinterpret_cast<void *>(quantum_kernel_functor); return std::make_shared<ObjectiveFunctionImpl<Args...>>( kernel_ptr, __internal__::qcor_as_shared(&observable), helper, nParams, options); } template <typename... Args> std::shared_ptr<ObjectiveFunction> createObjectiveFunction( const std::string obj_name, void (*quantum_kernel_functor)(std::shared_ptr<CompositeInstruction>, Args...), Observable &observable, const int nParams, HeterogeneousMap &&options = {}) { auto helper = qcor::__internal__::get_objective(obj_name); void *kernel_ptr = reinterpret_cast<void *>(quantum_kernel_functor); return std::make_shared<ObjectiveFunctionImpl<Args...>>( kernel_ptr, __internal__::qcor_as_shared(&observable), helper, nParams, options); } } // namespace qcor No newline at end of file
tools/driver/qcor-macosx.in +4 −0 Original line number Diff line number Diff line Loading @@ -62,6 +62,10 @@ def main(argv=None): sys.argv.remove('-qpu') sys.argv += ['-D__internal__qcor__compile__backend=\"'+accName+'\"'] sHandlerArgs = ['-Xclang', '-plugin-arg-qcor-args', '-Xclang', '-qpu', '-Xclang', '-plugin-arg-qcor-args', '-Xclang', accName] else: accName = 'qpp' sys.argv += ['-D__internal__qcor__compile__backend=\"'+accName+'\"'] sHandlerArgs = ['-Xclang', '-plugin-arg-qcor-args', '-Xclang', '-qpu', '-Xclang', '-plugin-arg-qcor-args', '-Xclang', accName] # Get the shots if necessary shots = 0 Loading
tools/driver/qcor.in +5 −1 Original line number Diff line number Diff line Loading @@ -59,6 +59,10 @@ def main(argv=None): sys.argv.remove('-qpu') sys.argv += ['-D__internal__qcor__compile__backend=\"'+accName+'\"'] sHandlerArgs = ['-Xclang', '-plugin-arg-qcor-args', '-Xclang', '-qpu', '-Xclang', '-plugin-arg-qcor-args', '-Xclang', accName] else: accName = 'qpp' sys.argv += ['-D__internal__qcor__compile__backend=\"'+accName+'\"'] sHandlerArgs = ['-Xclang', '-plugin-arg-qcor-args', '-Xclang', '-qpu', '-Xclang', '-plugin-arg-qcor-args', '-Xclang', accName] # Get the shots if necessary shots = 0 Loading