Commit fd22e045 authored by Mccaskey, Alex's avatar Mccaskey, Alex
Browse files

work on moving Algorithm and Optimizer to xacc core for use in other apps


Signed-off-by: Mccaskey, Alex's avatarAlex McCaskey <mccaskeyaj@ornl.gov>
parent 7f3f4fb8
Pipeline #63291 passed with stage
in 9 minutes and 24 seconds
......@@ -13,3 +13,6 @@
[submodule "quantum/plugins/dwave/embedding/minorminer"]
path = quantum/plugins/dwave/embedding/minorminer
url = https://github.com/dwavesystems/minorminer
[submodule "xacc/optimizer/nlopt-optimizers/nlopt"]
path = xacc/optimizer/nlopt-optimizers/nlopt
url = https://github.com/stevengj/nlopt
add_subdirectory(ibm)
add_subdirectory(rigetti)
add_subdirectory(cmr)
add_subdirectory(dwave)
\ No newline at end of file
add_subdirectory(dwave)
add_subdirectory(algorithms)
\ No newline at end of file
add_subdirectory(vqe)
\ No newline at end of file
set(LIBRARY_NAME xacc-algorithm-vqe)
file(GLOB SRC *.cpp)
usfunctiongetresourcesource(TARGET ${LIBRARY_NAME} OUT SRC)
usfunctiongeneratebundleinit(TARGET ${LIBRARY_NAME} OUT SRC)
add_library(${LIBRARY_NAME} SHARED ${SRC})
target_include_directories(
${LIBRARY_NAME}
PUBLIC .)
target_link_libraries(${LIBRARY_NAME} PUBLIC xacc CppMicroServices)
set(_bundle_name xacc_algorithm_vqe)
set_target_properties(${LIBRARY_NAME}
PROPERTIES COMPILE_DEFINITIONS
US_BUNDLE_NAME=${_bundle_name}
US_BUNDLE_NAME
${_bundle_name})
usfunctionembedresources(TARGET
${LIBRARY_NAME}
WORKING_DIRECTORY
${CMAKE_CURRENT_SOURCE_DIR}
FILES
manifest.json)
if(APPLE)
set_target_properties(${LIBRARY_NAME}
PROPERTIES INSTALL_RPATH "@loader_path/../lib")
set_target_properties(${LIBRARY_NAME}
PROPERTIES LINK_FLAGS "-undefined dynamic_lookup")
else()
set_target_properties(${LIBRARY_NAME}
PROPERTIES INSTALL_RPATH "$ORIGIN/../lib")
set_target_properties(${LIBRARY_NAME} PROPERTIES LINK_FLAGS "-shared")
endif()
if(XACC_BUILD_TESTS)
add_subdirectory(tests)
endif()
install(TARGETS ${LIBRARY_NAME} DESTINATION ${CMAKE_INSTALL_PREFIX}/plugins)
#include "vqe.hpp"
#include "cppmicroservices/BundleActivator.h"
#include "cppmicroservices/BundleContext.h"
#include "cppmicroservices/ServiceProperties.h"
#include <memory>
#include <set>
using namespace cppmicroservices;
namespace {
/**
*/
class US_ABI_LOCAL VQEActivator : public BundleActivator {
public:
VQEActivator() {}
/**
*/
void Start(BundleContext context) {
auto c = std::make_shared<xacc::algorithm::VQE>();
context.RegisterService<xacc::Algorithm>(c);
}
/**
*/
void Stop(BundleContext /*context*/) {}
};
} // namespace
CPPMICROSERVICES_EXPORT_BUNDLE_ACTIVATOR(VQEActivator)
{
"bundle.symbolic_name" : "xacc_algorithm_vqe",
"bundle.activator" : true,
"bundle.name" : "XACC VQE Algorithm",
"bundle.description" : ""
}
include_directories(${CMAKE_BINARY_DIR})
add_xacc_test(VQE)
target_link_libraries(VQETester xacc CppMicroServices xacc-pauli)
\ No newline at end of file
#include <gtest/gtest.h>
#include "XACC.hpp"
#include "xacc_service.hpp"
#include "Optimizer.hpp"
#include "Observable.hpp"
#include "Algorithm.hpp"
#include "PauliOperator.hpp"
using namespace xacc;
const std::string rucc = R"rucc(def f(buffer, theta):
X(0)
X(1)
Rx(1.5707,0)
H(1)
H(2)
H(3)
CNOT(0,1)
CNOT(1,2)
CNOT(2,3)
Rz(theta,3)
CNOT(2,3)
CNOT(1,2)
CNOT(0,1)
Rx(-1.5707,0)
H(1)
H(2)
H(3)
)rucc";
TEST(VQETester, checkSimple) {
if (xacc::hasAccelerator("tnqvm") && xacc::hasCompiler("xacc-py")) {
auto acc = xacc::getAccelerator("tnqvm");
auto buffer = acc->createBuffer("q", 4);
auto compiler = xacc::getService<xacc::Compiler>("xacc-py");
auto ir = compiler->compile(rucc, nullptr);
auto ruccsd = ir->getKernel("f");
auto optimizer = xacc::getService<Optimizer>("nlopt");
auto observable = std::make_shared<xacc::quantum::PauliOperator>();
observable->fromString(
"(0.174073,0) Z2 Z3 + (0.1202,0) Z1 Z3 + (0.165607,0) Z1 Z2 + "
"(0.165607,0) Z0 Z3 + (0.1202,0) Z0 Z2 + (-0.0454063,0) Y0 Y1 X2 X3 + "
"(-0.220041,0) Z3 + (-0.106477,0) + (0.17028,0) Z0 + (-0.220041,0) Z2 "
"+ (0.17028,0) Z1 + (-0.0454063,0) X0 X1 Y2 Y3 + (0.0454063,0) X0 Y1 "
"Y2 X3 + (0.168336,0) Z0 Z1 + (0.0454063,0) Y0 X1 X2 Y3");
auto vqe = xacc::getService<Algorithm>("vqe");
EXPECT_TRUE(vqe->initialize({{"ansatz",ruccsd}, {"accelerator",acc}, {"observable", observable},{"optimizer",optimizer}}));//
vqe->execute(buffer);
EXPECT_NEAR(-1.13717, mpark::get<double>(buffer->getInformation("opt-val")), 1e-4);
}
}
int main(int argc, char **argv) {
xacc::Initialize(argc, argv);
::testing::InitGoogleTest(&argc, argv);
auto ret = RUN_ALL_TESTS();
xacc::Finalize();
return ret;
}
#include "vqe.hpp"
#include "Observable.hpp"
#include "XACC.hpp"
#include "InstructionParameter.hpp"
#include <memory>
using namespace xacc;
namespace xacc {
namespace algorithm {
bool VQE::initialize(const AlgorithmParameters &parameters) {
if (!parameters.count("observable")) {
return false;
} else if (!parameters.count("ansatz")) {
return false;
} else if (!parameters.count("optimizer")) {
return false;
} else if (!parameters.count("accelerator")) {
return false;
}
observable = parameters.at("observable").as<std::shared_ptr<Observable>>();
optimizer = parameters.at("optimizer").as<std::shared_ptr<Optimizer>>();
kernel = parameters.at("ansatz").as<std::shared_ptr<Function>>();
accelerator = parameters.at("accelerator").as<std::shared_ptr<Accelerator>>();
return true;
}
const std::vector<std::string> VQE::requiredParameters() const {
return {"observable", "optimizer", "accelerator", "ansatz"};
}
void VQE::execute(const std::shared_ptr<AcceleratorBuffer> buffer) const {
// void VQE::execute(xacc::Observable &observable, Optimizer &optimizer) {
auto kernels = observable->observe(kernel);
// Here we just need to make a lambda kernel
// to optimize that makes calls to the targeted QPU.
OptFunction f(
[&, this](const std::vector<double> &x) {
std::vector<double> coefficients;
std::vector<std::string> kernelNames;
std::vector<std::shared_ptr<Function>> fsToExec;
double identityCoeff = 0.0;
for (auto &f : kernels) {
kernelNames.push_back(f->name());
InstructionParameter p = f->getOption("coefficient");
std::complex<double> coeff = p.as<std::complex<double>>();
if (f->nInstructions() > kernel->nInstructions()) {
fsToExec.push_back(f->operator()(x));
coefficients.push_back(std::real(coeff));
} else {
identityCoeff += std::real(coeff);
}
}
auto buffers = accelerator->execute(buffer, fsToExec);
double energy = identityCoeff;
for (int i = 0; i < buffers.size(); i++) {
auto expval = buffers[i]->getExpectationValueZ();
energy += expval * coefficients[i];
buffers[i]->addExtraInfo("coefficient", coefficients[i]);
buffers[i]->addExtraInfo("kernel", fsToExec[i]->name());
buffers[i]->addExtraInfo("exp-val-z", expval);
buffers[i]->addExtraInfo("parameters", x);
buffer->appendChild(fsToExec[i]->name(), buffers[i]);
}
std::stringstream ss;
ss << "E(" << x[0];
for (int i = 1; i < x.size(); i++)
ss << "," << x[i];
ss << ") = " << energy;
xacc::info(ss.str());
return energy;
},
kernel->nParameters());
// std::cout << f({.55}) << "\n";
auto result = optimizer->optimize(f);
buffer->addExtraInfo("opt-val", ExtraInfo(result.first));
buffer->addExtraInfo("opt-params", ExtraInfo(result.second));
return;
}
} // namespace algorithm
} // namespace xacc
\ No newline at end of file
#ifndef XACC_ALGORITHM_VQE_HPP_
#define XACC_ALGORITHM_VQE_HPP_
#include "Algorithm.hpp"
namespace xacc {
namespace algorithm {
class VQE : public Algorithm {
protected:
std::shared_ptr<Observable> observable;
std::shared_ptr<Optimizer> optimizer;
std::shared_ptr<Function> kernel;
std::shared_ptr<Accelerator> accelerator;
AlgorithmParameters parameters;
public:
bool initialize(const AlgorithmParameters &parameters) override;
const std::vector<std::string> requiredParameters() const override;
void execute(const std::shared_ptr<AcceleratorBuffer> buffer) const override;
// void execute(xacc::Observable &observable, Optimizer &optimizer)
// override;
const std::string name() const override { return "vqe"; }
const std::string description() const override { return ""; }
};
} // namespace algorithm
} // namespace xacc
#endif
\ No newline at end of file
......@@ -21,7 +21,9 @@ file(GLOB HEADERS
accelerator/*.hpp
accelerator/remote/*.hpp
utils/*.hpp
service/*.hpp)
service/*.hpp
algorithm/*.hpp
optimizer/*.hpp)
add_library(xacc
SHARED
......@@ -49,6 +51,8 @@ target_include_directories(xacc
accelerator/remote
utils
service
algorithm
optimizer
${CMAKE_SOURCE_DIR}/tpls/mpark-variant)
if(APPLE)
......@@ -71,3 +75,5 @@ endif()
install(FILES ${HEADERS} DESTINATION include/xacc)
install(TARGETS xacc DESTINATION lib)
add_subdirectory(optimizer/nlopt-optimizers)
\ No newline at end of file
#ifndef XACC_ALGORITHM_HPP_
#define XACC_ALGORITHM_HPP_
#include "Identifiable.hpp"
#include "InstructionParameter.hpp"
#include "Observable.hpp"
#include "Accelerator.hpp"
#include "Optimizer.hpp"
#include <memory>
namespace xacc {
using AlgorithmParameter =
Variant<int, double, std::string, std::vector<int>, std::vector<double>,
std::vector<std::string>, std::shared_ptr<Observable>,
std::shared_ptr<Accelerator>, std::shared_ptr<Function>,
std::shared_ptr<Optimizer>>;
using AlgorithmParameters = std::map<std::string, AlgorithmParameter>;
class Algorithm : public xacc::Identifiable {
public:
bool initialize(const AlgorithmParameters &&parameters) { return initialize(parameters); }
virtual bool initialize(const AlgorithmParameters &parameters) = 0;
virtual const std::vector<std::string> requiredParameters() const = 0;
virtual void execute(const std::shared_ptr<AcceleratorBuffer> buffer) const = 0;
};
} // namespace xacc
#endif
\ No newline at end of file
#ifndef XACC_OPTIMIZER_HPP_
#define XACC_OPTIMIZER_HPP_
#include <functional>
#include <vector>
#include "InstructionParameter.hpp"
#include "Identifiable.hpp"
namespace xacc {
using OptResult = std::pair<double, std::vector<double>>;
using OptimizerOptions = std::map<std::string, xacc::InstructionParameter>;
class OptFunction {
protected:
std::function<double(const std::vector<double> &)> _function;
int _dim = 0;
public:
OptFunction(std::function<double(const std::vector<double> &)> f, const int d)
: _function(f), _dim(d) {}
virtual const int dimensions() const { return _dim; }
virtual double operator()(const std::vector<double> &params) {
return _function(params);
}
};
class Optimizer : public xacc::Identifiable {
protected:
std::map<std::string, xacc::InstructionParameter> options;
public:
virtual OptResult optimize(OptFunction &function) = 0;
void
setOptions(const std::map<std::string, xacc::InstructionParameter> &opts) {
options = opts;
}
};
} // namespace xacc
#endif
SET(NLOPT_PYTHON OFF CACHE BOOL "")
SET(NLOPT_OCTAVE OFF CACHE BOOL "")
SET(NLOPT_MATLAB OFF CACHE BOOL "")
SET(NLOPT_GUILE OFF CACHE BOOL "")
SET(NLOPT_SWIG OFF CACHE BOOL "")
add_subdirectory(nlopt)
set(LIBRARY_NAME xacc-optimizer-nlopt)
file(GLOB SRC *.cpp)
usfunctiongetresourcesource(TARGET ${LIBRARY_NAME} OUT SRC)
usfunctiongeneratebundleinit(TARGET ${LIBRARY_NAME} OUT SRC)
add_library(${LIBRARY_NAME} SHARED ${SRC})
target_include_directories(
${LIBRARY_NAME}
PUBLIC . .. ${CMAKE_BUILD_DIR}/xacc/optimizer/nlopt-optimizers/nlopt/src/api)
target_link_libraries(${LIBRARY_NAME} PUBLIC nlopt xacc CppMicroServices)
set(_bundle_name xacc_optimizer_nlopt)
set_target_properties(${LIBRARY_NAME}
PROPERTIES COMPILE_DEFINITIONS
US_BUNDLE_NAME=${_bundle_name}
US_BUNDLE_NAME
${_bundle_name})
usfunctionembedresources(TARGET
${LIBRARY_NAME}
WORKING_DIRECTORY
${CMAKE_CURRENT_SOURCE_DIR}
FILES
manifest.json)
if(APPLE)
set_target_properties(${LIBRARY_NAME}
PROPERTIES INSTALL_RPATH "@loader_path/../lib")
set_target_properties(${LIBRARY_NAME}
PROPERTIES LINK_FLAGS "-undefined dynamic_lookup")
else()
set_target_properties(${LIBRARY_NAME}
PROPERTIES INSTALL_RPATH "$ORIGIN/../lib")
set_target_properties(${LIBRARY_NAME} PROPERTIES LINK_FLAGS "-shared")
endif()
if(XACC_BUILD_TESTS)
add_subdirectory(tests)
endif()
install(TARGETS ${LIBRARY_NAME} DESTINATION ${CMAKE_INSTALL_PREFIX}/plugins)
#include "nlopt_optimizer.hpp"
#include "cppmicroservices/BundleActivator.h"
#include "cppmicroservices/BundleContext.h"
#include "cppmicroservices/ServiceProperties.h"
#include <memory>
#include <set>
using namespace cppmicroservices;
namespace {
/**
*/
class US_ABI_LOCAL NLOptActivator: public BundleActivator {
public:
NLOptActivator() {
}
/**
*/
void Start(BundleContext context) {
auto c = std::make_shared<xacc::NLOptimizer>();
context.RegisterService<xacc::Optimizer>(c);
}
/**
*/
void Stop(BundleContext /*context*/) {
}
};
}
CPPMICROSERVICES_EXPORT_BUNDLE_ACTIVATOR(NLOptActivator)
{
"bundle.symbolic_name" : "xacc_optimizer_nlopt",
"bundle.activator" : true,
"bundle.name" : "XACC Runtime NLOpt",
"bundle.description" : ""
}
Subproject commit 945d055b98be2db327f694b36ba507c41e1955fc
#include "nlopt_optimizer.hpp"
#include "nlopt.hpp"
#include "Utils.hpp"
#include <iostream>
namespace xacc {
OptResult NLOptimizer::optimize(OptFunction &function) {
auto dim = function.dimensions();
nlopt::algorithm algo = nlopt::algorithm::LN_COBYLA;
double tol = 1e-8;
int maxeval = 1000;
if (options.count("nlopt-optimizer")) {
auto optimizerAlgo = options["nlopt-optimizer"].as<std::string>();
if (optimizerAlgo == "cobyla") {
algo = nlopt::algorithm::LN_COBYLA;
} else if (optimizerAlgo == "nelder-mead") {
algo = nlopt::algorithm::LN_NELDERMEAD;
} else {
xacc::XACCLogger::instance()->error("Invalid optimizer at this time: " +
optimizerAlgo);
}
}
if (options.count("nlopt-ftol")) {
tol = options["nlopt-ftol"].as<double>();
}
if (options.count("nlopt-maxeval")) {
maxeval = options["nlopt-maxeval"].as<int>();
}
nlopt::opt _opt(algo, dim);
std::function<double(const std::vector<double> &, std::vector<double> &,
void *)>
f = [&](const std::vector<double> &x, std::vector<double> &grad,
void *f_data) -> double { return function(x); };
auto fptr = LambdaToVFunc::ptr(f);
_opt.set_min_objective(fptr, NULL);
_opt.set_lower_bounds(std::vector<double>(dim, -3.1415926));
_opt.set_upper_bounds(std::vector<double>(dim, 3.1415926));
_opt.set_maxeval(maxeval);
_opt.set_ftol_rel(tol);
double optF;
std::vector<double> x(dim);
try {
auto result = _opt.optimize(x, optF);
} catch (std::exception &e) {
xacc::XACCLogger::instance()->error("NLOpt failed: " +
std::string(e.what()));
}
return OptResult{optF, x};
}
} // namespace xacc
#ifndef XACC_NLOPT_OPTIMIZER_HPP_
#define XACC_NLOPT_OPTIMIZER_HPP_
#include <type_traits>
#include <utility>
#include "Optimizer.hpp"
namespace xacc {
struct LambdaToVFunc {
template<typename Tret, typename T>
static Tret lambda_ptr_exec(const std::vector<double>& x, std::vector<double>& grad, void* fd) {
return (Tret) (*(T*)fn<T>())(x,grad,fd);
}
template<typename Tret = double, typename Tfp = Tret(*)(const std::vector<double>&,std::vector<double>&,void*), typename T>
static Tfp ptr(T& t) {
fn<T>(&t);
return (Tfp) lambda_ptr_exec<Tret, T>;
}
template<typename T>
static void* fn(void* new_fn = nullptr) {
static void* fn;
if (new_fn != nullptr)