Loading handlers/token_collector/pyxasm/pyxasm_token_collector.cpp +8 −9 Original line number Diff line number Diff line Loading @@ -69,15 +69,14 @@ void PyXasmTokenCollector::collect(clang::Preprocessor &PP, line += PP.getSpelling(Toks[i]); if (Toks[i].is(clang::tok::TokenKind::kw_for)) { // Right now we only assume 'for var in range' line += " "; // add var space i += 1; line += PP.getSpelling(Toks[i]); line += " "; // add 'in space' i += 1; line += PP.getSpelling(Toks[i]); line += " "; // or 'for i , var in enumerate( list_var ): // Slurp all elements of the for loop stmt, separate with spaces std::string for_stmt = " "; i++; while(Toks[i].isNot(clang::tok::TokenKind::colon)) { for_stmt += PP.getSpelling(Toks[i]) + " "; i++; } line += for_stmt; } // If statement: Loading handlers/token_collector/pyxasm/pyxasm_visitor.hpp +16 −6 Original line number Diff line number Diff line Loading @@ -3,9 +3,9 @@ #include "IRProvider.hpp" #include "pyxasmBaseVisitor.h" #include "qcor_utils.hpp" #include "qrt.hpp" #include "xacc.hpp" #include "qcor_utils.hpp" using namespace pyxasm; Loading Loading @@ -216,14 +216,25 @@ class pyxasm_visitor : public pyxasmBaseVisitor { } antlrcpp::Any visitFor_stmt(pyxasmParser::For_stmtContext *context) override { auto counter_expr = context->exprlist()->expr()[0]; auto iter_container = context->testlist()->test()[0]->getText(); // Rewrite: // Python: "for <var> in <expr>:" // C++: for (auto& var: <expr>) {} // C++: for (auto var: <expr>) {} // Note: we add range(int) as a C++ function to support this common pattern. // or // Python: "for <idx>,<var> in enumerate(<listvar>):" // C++: for (auto [idx, var] : enumerate(listvar)) auto iter_container = context->testlist()->test()[0]->getText(); std::string counter_expr = context->exprlist()->expr()[0]->getText(); if (context->exprlist()->expr().size() > 1) { counter_expr = "[" + counter_expr; for (int i = 1; i < context->exprlist()->expr().size(); i++) { counter_expr += ", " + context->exprlist()->expr()[i]->getText(); } counter_expr += "]"; } std::stringstream ss; ss << "for (auto &" << counter_expr->getText() << " : " << iter_container ss << "for (auto " << counter_expr << " : " << iter_container << ") {\n"; result.first = ss.str(); in_for_loop = true; Loading @@ -232,7 +243,6 @@ class pyxasm_visitor : public pyxasmBaseVisitor { antlrcpp::Any visitExpr_stmt(pyxasmParser::Expr_stmtContext *ctx) override { if (ctx->ASSIGN().size() == 1 && ctx->testlist_star_expr().size() == 2) { // Handle simple assignment: a = expr std::stringstream ss; const std::string lhs = ctx->testlist_star_expr(0)->getText(); Loading python/examples/deuteron_3qbit_exp_fermion.py +3 −4 Original line number Diff line number Diff line Loading @@ -7,7 +7,7 @@ from qcor import * @qjit def ansatz(q: qreg, x: List[float], exp_args: List[FermionOperator]): X(q[0]) for i in range(len(exp_args)): for i, exp_arg in enumerate(exp_args): exp_i_theta(q, x[i], exp_args[i]) exp_args = [adag(0) * a(1) - adag(1)*a(0), adag(0)*a(2) - adag(2)*a(0)] Loading @@ -28,11 +28,10 @@ H = createOperator( # Create the ObjectiveFunction, specify central finite diff gradient obj = createObjectiveFunction( ansatz, H, 2) #, {'gradient-strategy': 'central', 'step': 1e-1}) ansatz, H, 2, {'gradient-strategy': 'central', 'step': 1e-2}) # create the lbfgs optimizer optimizer = createOptimizer('nlopt')#, {'algorithm': 'l-bfgs', 'ftol': 1e-3}) optimizer = createOptimizer('nlopt', {'algorithm': 'l-bfgs', 'ftol': 1e-3}) # Run VQE... results = optimizer.optimize(obj) Loading python/py-qcor.cpp +18 −6 Original line number Diff line number Diff line Loading @@ -56,7 +56,8 @@ using AllowedKernelArgTypes = xacc::Variant<bool, int, double, std::string, xacc::internal_compiler::qreg, std::vector<double>, std::vector<int>, qcor::PauliOperator, qcor::FermionOperator, qcor::PairList<int>, std::vector<qcor::PauliOperator>, std::vector<qcor::FermionOperator>>; std::vector<qcor::PauliOperator>, std::vector<qcor::FermionOperator>>; // We will take as input a mapping of arg variable names to the argument itself. using KernelArgDict = std::map<std::string, AllowedKernelArgTypes>; Loading Loading @@ -96,7 +97,8 @@ xacc::HeterogeneousMap heterogeneousMapConvert( return result; } std::shared_ptr<qcor::Observable> convertToPauliOperator(py::object op) { std::shared_ptr<qcor::Observable> convertToQCOROperator( py::object op, bool keep_fermion = false) { if (py::hasattr(op, "terms")) { // this is from openfermion if (py::hasattr(op, "is_two_body_number_conserving")) { Loading Loading @@ -134,9 +136,16 @@ std::shared_ptr<qcor::Observable> convertToPauliOperator(py::object op) { } } auto obs_tmp = qcor::createOperator("fermion", ss.str()); if (keep_fermion) { return obs_tmp; } else { return qcor::operatorTransform("jw", obs_tmp); } } else { if (keep_fermion) { xacc::error("Error - you asked for a qcor::FermionOperator, but this is an OpenFermion QubitOperator."); } // this is a qubit operator auto terms = op.attr("terms"); // terms is a list of tuples Loading Loading @@ -528,7 +537,7 @@ PYBIND11_MODULE(_pyqcor, m) { m.def( "createObjectiveFunction", [](py::object kernel, py::object &py_obs, const int n_params) { auto obs = convertToPauliOperator(py_obs); auto obs = convertToQCOROperator(py_obs); auto q = ::qalloc(obs->nBits()); std::shared_ptr<qcor::ObjectiveFunction> obj = std::make_shared<qcor::PyObjectiveFunction>(kernel, obs, n_params, Loading @@ -553,7 +562,7 @@ PYBIND11_MODULE(_pyqcor, m) { [](py::object kernel, py::object &py_obs, const int n_params, PyHeterogeneousMap &options) { auto nativeHetMap = heterogeneousMapConvert(options); auto obs = convertToPauliOperator(py_obs); auto obs = convertToQCOROperator(py_obs); auto q = ::qalloc(obs->nBits()); std::shared_ptr<qcor::ObjectiveFunction> obj = std::make_shared<qcor::PyObjectiveFunction>(kernel, obs, n_params, Loading @@ -578,6 +587,9 @@ PYBIND11_MODULE(_pyqcor, m) { return qcor::createOperator(type, nativeHetMap); }, ""); m.def("createOperator", [](const std::string &type, py::object pyobject) { return convertToQCOROperator(pyobject, type == "fermion"); }); m.def( "createObservable", [](const std::string &repr) { return qcor::createOperator(repr); }, ""); Loading Loading @@ -612,7 +624,7 @@ PYBIND11_MODULE(_pyqcor, m) { m.def( "internal_observe", [](std::shared_ptr<CompositeInstruction> kernel, py::object obs) { auto observable = convertToPauliOperator(obs); auto observable = convertToQCOROperator(obs); auto q = ::qalloc(observable->nBits()); return qcor::observe(kernel, observable, q); }, Loading python/tests/test_kernel_jit.py +13 −1 Original line number Diff line number Diff line Loading @@ -252,6 +252,18 @@ class TestKernelJIT(unittest.TestCase): comp = testFor.extract_composite(q) self.assertEqual(comp.nInstructions(), 5) def test_for_loop_enumerate(self): @qjit def ansatz(q: qreg, x: List[float], exp_args: List[FermionOperator]): X(q[0]) for i, exp_arg in enumerate(exp_args): exp_i_theta(q, x[i], exp_args[i]) exp_args = [adag(0) * a(1) - adag(1)*a(0), adag(0)*a(2) - adag(2)*a(0)] H = createOperator('5.907 - 2.1433 X0X1 - 2.1433 Y0Y1 + .21829 Z0 - 6.125 Z1 + 9.625 - 9.625 Z2 - 3.91 X1 X2 - 3.91 Y1 Y2') energy = ansatz.observe(H, qalloc(3), [0.7118083109334505, 0.27387413138588135], exp_args) self.assertAlmostEqual(energy, -2.044, places=1) def test_multiple_kernels(self): @qjit def apply_H(q : qreg): Loading Loading
handlers/token_collector/pyxasm/pyxasm_token_collector.cpp +8 −9 Original line number Diff line number Diff line Loading @@ -69,15 +69,14 @@ void PyXasmTokenCollector::collect(clang::Preprocessor &PP, line += PP.getSpelling(Toks[i]); if (Toks[i].is(clang::tok::TokenKind::kw_for)) { // Right now we only assume 'for var in range' line += " "; // add var space i += 1; line += PP.getSpelling(Toks[i]); line += " "; // add 'in space' i += 1; line += PP.getSpelling(Toks[i]); line += " "; // or 'for i , var in enumerate( list_var ): // Slurp all elements of the for loop stmt, separate with spaces std::string for_stmt = " "; i++; while(Toks[i].isNot(clang::tok::TokenKind::colon)) { for_stmt += PP.getSpelling(Toks[i]) + " "; i++; } line += for_stmt; } // If statement: Loading
handlers/token_collector/pyxasm/pyxasm_visitor.hpp +16 −6 Original line number Diff line number Diff line Loading @@ -3,9 +3,9 @@ #include "IRProvider.hpp" #include "pyxasmBaseVisitor.h" #include "qcor_utils.hpp" #include "qrt.hpp" #include "xacc.hpp" #include "qcor_utils.hpp" using namespace pyxasm; Loading Loading @@ -216,14 +216,25 @@ class pyxasm_visitor : public pyxasmBaseVisitor { } antlrcpp::Any visitFor_stmt(pyxasmParser::For_stmtContext *context) override { auto counter_expr = context->exprlist()->expr()[0]; auto iter_container = context->testlist()->test()[0]->getText(); // Rewrite: // Python: "for <var> in <expr>:" // C++: for (auto& var: <expr>) {} // C++: for (auto var: <expr>) {} // Note: we add range(int) as a C++ function to support this common pattern. // or // Python: "for <idx>,<var> in enumerate(<listvar>):" // C++: for (auto [idx, var] : enumerate(listvar)) auto iter_container = context->testlist()->test()[0]->getText(); std::string counter_expr = context->exprlist()->expr()[0]->getText(); if (context->exprlist()->expr().size() > 1) { counter_expr = "[" + counter_expr; for (int i = 1; i < context->exprlist()->expr().size(); i++) { counter_expr += ", " + context->exprlist()->expr()[i]->getText(); } counter_expr += "]"; } std::stringstream ss; ss << "for (auto &" << counter_expr->getText() << " : " << iter_container ss << "for (auto " << counter_expr << " : " << iter_container << ") {\n"; result.first = ss.str(); in_for_loop = true; Loading @@ -232,7 +243,6 @@ class pyxasm_visitor : public pyxasmBaseVisitor { antlrcpp::Any visitExpr_stmt(pyxasmParser::Expr_stmtContext *ctx) override { if (ctx->ASSIGN().size() == 1 && ctx->testlist_star_expr().size() == 2) { // Handle simple assignment: a = expr std::stringstream ss; const std::string lhs = ctx->testlist_star_expr(0)->getText(); Loading
python/examples/deuteron_3qbit_exp_fermion.py +3 −4 Original line number Diff line number Diff line Loading @@ -7,7 +7,7 @@ from qcor import * @qjit def ansatz(q: qreg, x: List[float], exp_args: List[FermionOperator]): X(q[0]) for i in range(len(exp_args)): for i, exp_arg in enumerate(exp_args): exp_i_theta(q, x[i], exp_args[i]) exp_args = [adag(0) * a(1) - adag(1)*a(0), adag(0)*a(2) - adag(2)*a(0)] Loading @@ -28,11 +28,10 @@ H = createOperator( # Create the ObjectiveFunction, specify central finite diff gradient obj = createObjectiveFunction( ansatz, H, 2) #, {'gradient-strategy': 'central', 'step': 1e-1}) ansatz, H, 2, {'gradient-strategy': 'central', 'step': 1e-2}) # create the lbfgs optimizer optimizer = createOptimizer('nlopt')#, {'algorithm': 'l-bfgs', 'ftol': 1e-3}) optimizer = createOptimizer('nlopt', {'algorithm': 'l-bfgs', 'ftol': 1e-3}) # Run VQE... results = optimizer.optimize(obj) Loading
python/py-qcor.cpp +18 −6 Original line number Diff line number Diff line Loading @@ -56,7 +56,8 @@ using AllowedKernelArgTypes = xacc::Variant<bool, int, double, std::string, xacc::internal_compiler::qreg, std::vector<double>, std::vector<int>, qcor::PauliOperator, qcor::FermionOperator, qcor::PairList<int>, std::vector<qcor::PauliOperator>, std::vector<qcor::FermionOperator>>; std::vector<qcor::PauliOperator>, std::vector<qcor::FermionOperator>>; // We will take as input a mapping of arg variable names to the argument itself. using KernelArgDict = std::map<std::string, AllowedKernelArgTypes>; Loading Loading @@ -96,7 +97,8 @@ xacc::HeterogeneousMap heterogeneousMapConvert( return result; } std::shared_ptr<qcor::Observable> convertToPauliOperator(py::object op) { std::shared_ptr<qcor::Observable> convertToQCOROperator( py::object op, bool keep_fermion = false) { if (py::hasattr(op, "terms")) { // this is from openfermion if (py::hasattr(op, "is_two_body_number_conserving")) { Loading Loading @@ -134,9 +136,16 @@ std::shared_ptr<qcor::Observable> convertToPauliOperator(py::object op) { } } auto obs_tmp = qcor::createOperator("fermion", ss.str()); if (keep_fermion) { return obs_tmp; } else { return qcor::operatorTransform("jw", obs_tmp); } } else { if (keep_fermion) { xacc::error("Error - you asked for a qcor::FermionOperator, but this is an OpenFermion QubitOperator."); } // this is a qubit operator auto terms = op.attr("terms"); // terms is a list of tuples Loading Loading @@ -528,7 +537,7 @@ PYBIND11_MODULE(_pyqcor, m) { m.def( "createObjectiveFunction", [](py::object kernel, py::object &py_obs, const int n_params) { auto obs = convertToPauliOperator(py_obs); auto obs = convertToQCOROperator(py_obs); auto q = ::qalloc(obs->nBits()); std::shared_ptr<qcor::ObjectiveFunction> obj = std::make_shared<qcor::PyObjectiveFunction>(kernel, obs, n_params, Loading @@ -553,7 +562,7 @@ PYBIND11_MODULE(_pyqcor, m) { [](py::object kernel, py::object &py_obs, const int n_params, PyHeterogeneousMap &options) { auto nativeHetMap = heterogeneousMapConvert(options); auto obs = convertToPauliOperator(py_obs); auto obs = convertToQCOROperator(py_obs); auto q = ::qalloc(obs->nBits()); std::shared_ptr<qcor::ObjectiveFunction> obj = std::make_shared<qcor::PyObjectiveFunction>(kernel, obs, n_params, Loading @@ -578,6 +587,9 @@ PYBIND11_MODULE(_pyqcor, m) { return qcor::createOperator(type, nativeHetMap); }, ""); m.def("createOperator", [](const std::string &type, py::object pyobject) { return convertToQCOROperator(pyobject, type == "fermion"); }); m.def( "createObservable", [](const std::string &repr) { return qcor::createOperator(repr); }, ""); Loading Loading @@ -612,7 +624,7 @@ PYBIND11_MODULE(_pyqcor, m) { m.def( "internal_observe", [](std::shared_ptr<CompositeInstruction> kernel, py::object obs) { auto observable = convertToPauliOperator(obs); auto observable = convertToQCOROperator(obs); auto q = ::qalloc(observable->nBits()); return qcor::observe(kernel, observable, q); }, Loading
python/tests/test_kernel_jit.py +13 −1 Original line number Diff line number Diff line Loading @@ -252,6 +252,18 @@ class TestKernelJIT(unittest.TestCase): comp = testFor.extract_composite(q) self.assertEqual(comp.nInstructions(), 5) def test_for_loop_enumerate(self): @qjit def ansatz(q: qreg, x: List[float], exp_args: List[FermionOperator]): X(q[0]) for i, exp_arg in enumerate(exp_args): exp_i_theta(q, x[i], exp_args[i]) exp_args = [adag(0) * a(1) - adag(1)*a(0), adag(0)*a(2) - adag(2)*a(0)] H = createOperator('5.907 - 2.1433 X0X1 - 2.1433 Y0Y1 + .21829 Z0 - 6.125 Z1 + 9.625 - 9.625 Z2 - 3.91 X1 X2 - 3.91 Y1 Y2') energy = ansatz.observe(H, qalloc(3), [0.7118083109334505, 0.27387413138588135], exp_args) self.assertAlmostEqual(energy, -2.044, places=1) def test_multiple_kernels(self): @qjit def apply_H(q : qreg): Loading