Loading compiler/fuzzy_parsing.cpp +0 −1 Original line number Diff line number Diff line Loading @@ -86,7 +86,6 @@ bool FuzzyParsingExternalSemaSource::LookupUnqualified(clang::LookupResult &R, S->getFlags() != 128 && S->getBlockParent() != nullptr) { if (!qbit) { std::cout << unknownName << ", TRYING TO FIND QBIT\n"; // Save pointers to xacc::qbit, xacc::HeterogeneousMap&& ParmVarDecl qbit = FirstDeclMatcher<ParmVarDecl>().match( ci.getASTContext().getTranslationUnitDecl(), Loading compiler/qcor_ast_visitor.hpp +7 −3 Original line number Diff line number Diff line Loading @@ -9,6 +9,7 @@ #include "clang/Parse/ParseAST.h" #include "clang/Rewrite/Core/Rewriter.h" #include "clang/Tooling/Tooling.h" #include <type_traits> #include "xacc.hpp" Loading @@ -28,14 +29,17 @@ protected: public: make_pair_visitor(std::stringstream &ss, std::vector<std::string> &c) : s(ss), captures(c) {} template <typename T> void operator()(const std::string &key, const T &t) { if (std::find(captures.begin(), captures.end(), key) != std::end(captures)) { void operator()(const std::string &key, const std::string &t) { if (std::find(captures.begin(), captures.end(), t) != std::end(captures)) { s << "std::make_pair(\"" << key << "\"," << t << "),"; } else { s << "std::make_pair(\"" << key << "\",\"" << t << "\"),"; } } template <typename T> void operator()(const std::string &key, const T &t) { s << "std::make_pair(\"" << key << "\"," << t << "),"; } }; class QCORASTVisitor : public RecursiveASTVisitor<QCORASTVisitor> { Loading examples/custom_objective_qcbm.cpp 0 → 100644 +114 −0 Original line number Diff line number Diff line #include "qcor.hpp" class QCBM : public qcor::ObjectiveFunction { protected: // Example Bars and Stripes PDF std::vector<double> target{ 0.16666667, 0., 0., 0.16666667, 0., 0.16666667, 0., 0., 0., 0., 0.16666667, 0., 0.16666667, 0., 0., 0.16666667}; // Helper function double entropy(const std::vector<double> p, const std::vector<double> q) { double sum = 0.0; for (int i = 0; i < p.size(); i++) { if (std::fabs(p[i]) > 1e-12) { sum += p[i] * std::log(p[i] / q[i]); } } return sum; } public: // All ObjectiveFunctions must implement this method. // QCOR will take your ObjectiveFunction and inject it // with the Observable (observable), Kernel (kernel), // and Global ResultsBuffer (buffer). You can use those as // you wish to construct your function. Also, note you have // reference to the backend QPU (backend) that this // file was compiled for. double operator()(const std::vector<double> &x) override { // Evaluate the ansatz at the given parameters. auto evaledKernel = kernel->operator()(x); // Observe the ansatz (appends measurements). We // should only have one measured kernel auto observed = observable->observe(evaledKernel)[0]; // Create a temp buffer to store results auto tmpBuffer = qcor::qalloc(buffer->size()); // Execute backend->execute(tmpBuffer, observed); // Get the counts auto counts = tmpBuffer->getMeasurementCounts(); int shots = 0; for (auto &x : counts) { shots += x.second; } // Compute the probability distribution std::vector<double> q(target.size()); // all zeros for (auto &x : counts) { int idx = std::stoi(x.first, nullptr, 2); q[idx] = (double) x.second / shots; } // get M=1/2(P+Q) std::vector<double> m(target.size()); for (int i = 0; i < m.size(); i++) m[i] = .5 * (target[i] + q[i]); auto js = 0.5 * (entropy(target, m) + entropy(q, m)); std::cout << "JS: " << js << "\n"; return js; } }; int main(int argc, char **argv) { // Initialize QCOR qcor::Initialize(argc, argv); // Create our custom ObjectiveFunction // as a shared_ptr, this is the QCBM work // from https://journals.aps.org/pra/abstract/10.1103/PhysRevA.99.062323 auto qcbm = std::make_shared<QCBM>(); // Define a few of the CNOT couplings for the // HWE ansatz, the paper defines dc3 and dc4 amongst others std::vector<std::pair<int, int>> dc3{{0, 1}, {0,2}, {0, 3}}; std::vector<std::pair<int, int>> dc4{{0, 1}, {0,2}, {1, 3}, {2,3}}; // Create the quantum kernel, a standard lambda // that uses the HWE circuit generator auto ansatz = [&](qbit q, std::vector<double> x) { hwe(q, x, {{"nq", 4}, {"layers", 1}, {"coupling", dc4}}); }; // Create the NLOpt cobyla optimizer // FIXME implement ADAM optimizer from mlpack auto optimizer = qcor::getOptimizer("nlopt", {std::make_pair("nlopt-optimizer", "cobyla"), std::make_pair("nlopt-maxeval", 500)}); // Call taskInitiate with the objective function // and optimizer, default initial params (all zeros) // No observable implies QCOR will measure in // computational basis auto handle = qcor::taskInitiate(ansatz, qcbm, optimizer, std::vector<double>{}); // We have the handle, its an async call, // maybe go do other work... // Get the results auto results = qcor::sync(handle); auto optJS = results->getInformation("opt-val").as<double>(); auto params = results->getInformation("opt-params").as<std::vector<double>>(); std::cout << "Opt JS = " << optJS << "\n"; std::cout << "At parameters: " << params << "\n"; // Finalize the framewokr qcor::Finalize(); } runtime/qcor.hpp +49 −42 Original line number Diff line number Diff line Loading @@ -94,28 +94,24 @@ using ResultBuffer = xacc::qbit; // this handle to query the results using the qcor::sync call using Handle = std::future<ResultBuffer>; class ObjectiveFunction : public OptFunction { class ObjectiveFunction : public std::function<double(const std::vector<double> &)> { protected: std::shared_ptr<Observable> observable; std::shared_ptr<CompositeInstruction> kernel; std::vector<std::shared_ptr<CompositeInstruction>> kernels; std::shared_ptr<Accelerator> backend; ResultBuffer buffer; std::shared_ptr<AcceleratorBuffer> buffer; public: ObjectiveFunction() = default; const int dimensions() const override { return kernel->nVariables(); } double operator()(const std::vector<double> ¶ms) override { xacc::error("[qpu_handler] You must implement operator()() on custom " "ObjectiveFunction."); return 0.0; } virtual double operator()(const std::vector<double> ¶ms) = 0; void initialize(std::shared_ptr<Observable> obs, std::shared_ptr<CompositeInstruction> k, ResultBuffer b) { std::shared_ptr<CompositeInstruction> k, std::shared_ptr<AcceleratorBuffer> b) { observable = obs; kernel = k; kernels = obs->observe(k); buffer = b; backend = xacc::getAccelerator(kernel->accelerator_signature()); buffer = b; } }; Loading Loading @@ -338,6 +334,27 @@ public: algo->execute(buffer); } template <typename QuantumKernel, typename... InitialArgs> void execute(QuantumKernel &kernel, std::shared_ptr<ObjectiveFunction> objFunction, std::shared_ptr<Optimizer> optimizer, std::shared_ptr<Observable> observable, InitialArgs... args) { auto function = qcor::__internal::getCompositeInstruction(kernel, args...); auto nLogicalBits = function->nLogicalBits(); if (!buffer) { buffer = xacc::qalloc(nLogicalBits); } objFunction->initialize(observable, function, buffer); OptFunction optF( [&, objFunction](const std::vector<double> &x) { return objFunction->operator()(x); }, function->nVariables()); auto result = optimizer->optimize(optF); buffer->addExtraInfo("opt-val", ExtraInfo(result.first)); buffer->addExtraInfo("opt-params", ExtraInfo(result.second)); } }; // Full TaskInitiate, built in objective function (given by its name) Loading @@ -349,7 +366,6 @@ taskInitiate(QuantumKernel &&kernel, const std::string objectiveFunctionName, auto function = qcor::__internal::getCompositeInstruction(kernel, args...); auto parameters = __internal::parametersFromVariadic(function, args...); return qcor::submit([&, parameters, function](qcor::qpu_handler &q) { auto nLogicalBits = function->nLogicalBits(); auto accelerator = xacc::getAccelerator(function->accelerator_signature()); auto buffer = xacc::qalloc(nLogicalBits); Loading Loading @@ -403,40 +419,31 @@ taskInitiate(QuantumKernel &&kernel, const std::string objectiveFunctionName, }); } // FIXME Need to think about this more... // // Custom objective function // Custom Objective Function, no Observable // template <typename QuantumKernel, typename... InitialArgs> // Handle taskInitiate(QuantumKernel &&kernel, ObjectiveFunction &&objFunction, // std::shared_ptr<Optimizer> optimizer, // std::shared_ptr<Observable> observable, // InitialArgs... args) { // return taskInitiate(kernel, objFunction, optimizer, observable, args...); // } // template <typename QuantumKernel, typename... InitialArgs> // Handle taskInitiate(QuantumKernel &&kernel, ObjectiveFunction &objFunction, // std::shared_ptr<Optimizer> optimizer, // std::shared_ptr<Observable> observable, // InitialArgs... args) { // auto function = qcor::__internal::getCompositeInstruction(kernel, args...); // auto parameters = __internal::parametersFromVariadic(function, args...); // return qcor::submit([&, parameters, function](qcor::qpu_handler &q) { // // auto function = qcor::__internal::getCompositeInstruction(kernel, // // args...); // auto nLogicalBits = function->nLogicalBits(); // auto accelerator = xacc::getAccelerator(function->accelerator_signature()); // auto buffer = xacc::qalloc(nLogicalBits); // optimizer->appendOption("initial-parameters", parameters); // objFunction.initialize(observable, function, buffer); // auto result = optimizer->optimize(objFunction); // buffer->addExtraInfo("opt-val", ExtraInfo(result.first)); // buffer->addExtraInfo("opt-params", ExtraInfo(result.second)); // }); // std::shared_ptr<Optimizer> optimizer, InitialArgs... args) { // return taskInitiate(kernel, objFunction, optimizer, args...); // } template <typename QuantumKernel, typename... InitialArgs> Handle taskInitiate(QuantumKernel &&kernel, std::shared_ptr<ObjectiveFunction> objFunction, std::shared_ptr<Optimizer> optimizer, InitialArgs... args) { auto function = qcor::__internal::getCompositeInstruction(kernel, args...); auto parameters = __internal::parametersFromVariadic(function, args...); return qcor::submit( [&, parameters, function, optimizer](qcor::qpu_handler &qh) { optimizer->appendOption("initial-parameters", parameters); std::string allZsObsStr = ""; for (int i = 0; i < function->nLogicalBits(); i++) { allZsObsStr += "Z" + std::to_string(i) + " "; } auto observable = getObservable("pauli", allZsObsStr); qh.execute(kernel, objFunction, optimizer, observable, args...); }); } } // namespace qcor #endif Loading
compiler/fuzzy_parsing.cpp +0 −1 Original line number Diff line number Diff line Loading @@ -86,7 +86,6 @@ bool FuzzyParsingExternalSemaSource::LookupUnqualified(clang::LookupResult &R, S->getFlags() != 128 && S->getBlockParent() != nullptr) { if (!qbit) { std::cout << unknownName << ", TRYING TO FIND QBIT\n"; // Save pointers to xacc::qbit, xacc::HeterogeneousMap&& ParmVarDecl qbit = FirstDeclMatcher<ParmVarDecl>().match( ci.getASTContext().getTranslationUnitDecl(), Loading
compiler/qcor_ast_visitor.hpp +7 −3 Original line number Diff line number Diff line Loading @@ -9,6 +9,7 @@ #include "clang/Parse/ParseAST.h" #include "clang/Rewrite/Core/Rewriter.h" #include "clang/Tooling/Tooling.h" #include <type_traits> #include "xacc.hpp" Loading @@ -28,14 +29,17 @@ protected: public: make_pair_visitor(std::stringstream &ss, std::vector<std::string> &c) : s(ss), captures(c) {} template <typename T> void operator()(const std::string &key, const T &t) { if (std::find(captures.begin(), captures.end(), key) != std::end(captures)) { void operator()(const std::string &key, const std::string &t) { if (std::find(captures.begin(), captures.end(), t) != std::end(captures)) { s << "std::make_pair(\"" << key << "\"," << t << "),"; } else { s << "std::make_pair(\"" << key << "\",\"" << t << "\"),"; } } template <typename T> void operator()(const std::string &key, const T &t) { s << "std::make_pair(\"" << key << "\"," << t << "),"; } }; class QCORASTVisitor : public RecursiveASTVisitor<QCORASTVisitor> { Loading
examples/custom_objective_qcbm.cpp 0 → 100644 +114 −0 Original line number Diff line number Diff line #include "qcor.hpp" class QCBM : public qcor::ObjectiveFunction { protected: // Example Bars and Stripes PDF std::vector<double> target{ 0.16666667, 0., 0., 0.16666667, 0., 0.16666667, 0., 0., 0., 0., 0.16666667, 0., 0.16666667, 0., 0., 0.16666667}; // Helper function double entropy(const std::vector<double> p, const std::vector<double> q) { double sum = 0.0; for (int i = 0; i < p.size(); i++) { if (std::fabs(p[i]) > 1e-12) { sum += p[i] * std::log(p[i] / q[i]); } } return sum; } public: // All ObjectiveFunctions must implement this method. // QCOR will take your ObjectiveFunction and inject it // with the Observable (observable), Kernel (kernel), // and Global ResultsBuffer (buffer). You can use those as // you wish to construct your function. Also, note you have // reference to the backend QPU (backend) that this // file was compiled for. double operator()(const std::vector<double> &x) override { // Evaluate the ansatz at the given parameters. auto evaledKernel = kernel->operator()(x); // Observe the ansatz (appends measurements). We // should only have one measured kernel auto observed = observable->observe(evaledKernel)[0]; // Create a temp buffer to store results auto tmpBuffer = qcor::qalloc(buffer->size()); // Execute backend->execute(tmpBuffer, observed); // Get the counts auto counts = tmpBuffer->getMeasurementCounts(); int shots = 0; for (auto &x : counts) { shots += x.second; } // Compute the probability distribution std::vector<double> q(target.size()); // all zeros for (auto &x : counts) { int idx = std::stoi(x.first, nullptr, 2); q[idx] = (double) x.second / shots; } // get M=1/2(P+Q) std::vector<double> m(target.size()); for (int i = 0; i < m.size(); i++) m[i] = .5 * (target[i] + q[i]); auto js = 0.5 * (entropy(target, m) + entropy(q, m)); std::cout << "JS: " << js << "\n"; return js; } }; int main(int argc, char **argv) { // Initialize QCOR qcor::Initialize(argc, argv); // Create our custom ObjectiveFunction // as a shared_ptr, this is the QCBM work // from https://journals.aps.org/pra/abstract/10.1103/PhysRevA.99.062323 auto qcbm = std::make_shared<QCBM>(); // Define a few of the CNOT couplings for the // HWE ansatz, the paper defines dc3 and dc4 amongst others std::vector<std::pair<int, int>> dc3{{0, 1}, {0,2}, {0, 3}}; std::vector<std::pair<int, int>> dc4{{0, 1}, {0,2}, {1, 3}, {2,3}}; // Create the quantum kernel, a standard lambda // that uses the HWE circuit generator auto ansatz = [&](qbit q, std::vector<double> x) { hwe(q, x, {{"nq", 4}, {"layers", 1}, {"coupling", dc4}}); }; // Create the NLOpt cobyla optimizer // FIXME implement ADAM optimizer from mlpack auto optimizer = qcor::getOptimizer("nlopt", {std::make_pair("nlopt-optimizer", "cobyla"), std::make_pair("nlopt-maxeval", 500)}); // Call taskInitiate with the objective function // and optimizer, default initial params (all zeros) // No observable implies QCOR will measure in // computational basis auto handle = qcor::taskInitiate(ansatz, qcbm, optimizer, std::vector<double>{}); // We have the handle, its an async call, // maybe go do other work... // Get the results auto results = qcor::sync(handle); auto optJS = results->getInformation("opt-val").as<double>(); auto params = results->getInformation("opt-params").as<std::vector<double>>(); std::cout << "Opt JS = " << optJS << "\n"; std::cout << "At parameters: " << params << "\n"; // Finalize the framewokr qcor::Finalize(); }
runtime/qcor.hpp +49 −42 Original line number Diff line number Diff line Loading @@ -94,28 +94,24 @@ using ResultBuffer = xacc::qbit; // this handle to query the results using the qcor::sync call using Handle = std::future<ResultBuffer>; class ObjectiveFunction : public OptFunction { class ObjectiveFunction : public std::function<double(const std::vector<double> &)> { protected: std::shared_ptr<Observable> observable; std::shared_ptr<CompositeInstruction> kernel; std::vector<std::shared_ptr<CompositeInstruction>> kernels; std::shared_ptr<Accelerator> backend; ResultBuffer buffer; std::shared_ptr<AcceleratorBuffer> buffer; public: ObjectiveFunction() = default; const int dimensions() const override { return kernel->nVariables(); } double operator()(const std::vector<double> ¶ms) override { xacc::error("[qpu_handler] You must implement operator()() on custom " "ObjectiveFunction."); return 0.0; } virtual double operator()(const std::vector<double> ¶ms) = 0; void initialize(std::shared_ptr<Observable> obs, std::shared_ptr<CompositeInstruction> k, ResultBuffer b) { std::shared_ptr<CompositeInstruction> k, std::shared_ptr<AcceleratorBuffer> b) { observable = obs; kernel = k; kernels = obs->observe(k); buffer = b; backend = xacc::getAccelerator(kernel->accelerator_signature()); buffer = b; } }; Loading Loading @@ -338,6 +334,27 @@ public: algo->execute(buffer); } template <typename QuantumKernel, typename... InitialArgs> void execute(QuantumKernel &kernel, std::shared_ptr<ObjectiveFunction> objFunction, std::shared_ptr<Optimizer> optimizer, std::shared_ptr<Observable> observable, InitialArgs... args) { auto function = qcor::__internal::getCompositeInstruction(kernel, args...); auto nLogicalBits = function->nLogicalBits(); if (!buffer) { buffer = xacc::qalloc(nLogicalBits); } objFunction->initialize(observable, function, buffer); OptFunction optF( [&, objFunction](const std::vector<double> &x) { return objFunction->operator()(x); }, function->nVariables()); auto result = optimizer->optimize(optF); buffer->addExtraInfo("opt-val", ExtraInfo(result.first)); buffer->addExtraInfo("opt-params", ExtraInfo(result.second)); } }; // Full TaskInitiate, built in objective function (given by its name) Loading @@ -349,7 +366,6 @@ taskInitiate(QuantumKernel &&kernel, const std::string objectiveFunctionName, auto function = qcor::__internal::getCompositeInstruction(kernel, args...); auto parameters = __internal::parametersFromVariadic(function, args...); return qcor::submit([&, parameters, function](qcor::qpu_handler &q) { auto nLogicalBits = function->nLogicalBits(); auto accelerator = xacc::getAccelerator(function->accelerator_signature()); auto buffer = xacc::qalloc(nLogicalBits); Loading Loading @@ -403,40 +419,31 @@ taskInitiate(QuantumKernel &&kernel, const std::string objectiveFunctionName, }); } // FIXME Need to think about this more... // // Custom objective function // Custom Objective Function, no Observable // template <typename QuantumKernel, typename... InitialArgs> // Handle taskInitiate(QuantumKernel &&kernel, ObjectiveFunction &&objFunction, // std::shared_ptr<Optimizer> optimizer, // std::shared_ptr<Observable> observable, // InitialArgs... args) { // return taskInitiate(kernel, objFunction, optimizer, observable, args...); // } // template <typename QuantumKernel, typename... InitialArgs> // Handle taskInitiate(QuantumKernel &&kernel, ObjectiveFunction &objFunction, // std::shared_ptr<Optimizer> optimizer, // std::shared_ptr<Observable> observable, // InitialArgs... args) { // auto function = qcor::__internal::getCompositeInstruction(kernel, args...); // auto parameters = __internal::parametersFromVariadic(function, args...); // return qcor::submit([&, parameters, function](qcor::qpu_handler &q) { // // auto function = qcor::__internal::getCompositeInstruction(kernel, // // args...); // auto nLogicalBits = function->nLogicalBits(); // auto accelerator = xacc::getAccelerator(function->accelerator_signature()); // auto buffer = xacc::qalloc(nLogicalBits); // optimizer->appendOption("initial-parameters", parameters); // objFunction.initialize(observable, function, buffer); // auto result = optimizer->optimize(objFunction); // buffer->addExtraInfo("opt-val", ExtraInfo(result.first)); // buffer->addExtraInfo("opt-params", ExtraInfo(result.second)); // }); // std::shared_ptr<Optimizer> optimizer, InitialArgs... args) { // return taskInitiate(kernel, objFunction, optimizer, args...); // } template <typename QuantumKernel, typename... InitialArgs> Handle taskInitiate(QuantumKernel &&kernel, std::shared_ptr<ObjectiveFunction> objFunction, std::shared_ptr<Optimizer> optimizer, InitialArgs... args) { auto function = qcor::__internal::getCompositeInstruction(kernel, args...); auto parameters = __internal::parametersFromVariadic(function, args...); return qcor::submit( [&, parameters, function, optimizer](qcor::qpu_handler &qh) { optimizer->appendOption("initial-parameters", parameters); std::string allZsObsStr = ""; for (int i = 0; i < function->nLogicalBits(); i++) { allZsObsStr += "Z" + std::to_string(i) + " "; } auto observable = getObservable("pauli", allZsObsStr); qh.execute(kernel, objFunction, optimizer, observable, args...); }); } } // namespace qcor #endif