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

adding optimizer interface and initial simple implementation built on nlopt


Signed-off-by: Mccaskey, Alex's avatarAlex McCaskey <mccaskeyaj@ornl.gov>
parent 9779a100
Pipeline #43898 passed with stages
in 2 minutes and 15 seconds
[submodule "runtime/nlopt-optimizers/nlopt"]
path = runtime/nlopt-optimizers/nlopt
url = https://github.com/stevengj/nlopt
macro(qcor_enable_rpath LIBNAME)
if(APPLE)
set_target_properties(${LIBNAME} PROPERTIES INSTALL_RPATH "@loader_path/../lib")
set_target_properties(${LIBNAME}
PROPERTIES LINK_FLAGS "-undefined dynamic_lookup")
else()
set_target_properties(${LIBNAME} PROPERTIES INSTALL_RPATH "$ORIGIN/../lib")
set_target_properties(${LIBNAME} PROPERTIES LINK_FLAGS "-shared")
endif()
endmacro()
set(LIBRARY_NAME qcor)
file(GLOB SRC *.cpp)
......@@ -8,12 +19,20 @@ target_include_directories(${LIBRARY_NAME} PUBLIC . ${XACC_INCLUDE_DIRS})
target_link_libraries(${LIBRARY_NAME} PUBLIC xacc)
# qcor_enable_rpath(${LIBRARY_NAME})
if(QCOR_BUILD_TESTS)
# add_subdirectory(tests)
endif()
if(APPLE)
set_target_properties(${LIBRARY_NAME} PROPERTIES INSTALL_RPATH "@loader_path")
set_target_properties(${LIBRARY_NAME} PROPERTIES LINK_FLAGS "-undefined dynamic_lookup")
else()
set_target_properties(${LIBRARY_NAME} PROPERTIES INSTALL_RPATH "$ORIGIN")
set_target_properties(${LIBRARY_NAME} PROPERTIES LINK_FLAGS "-shared")
endif()
file(GLOB HEADERS *.hpp)
install(FILES ${HEADERS} DESTINATION include/qcor)
install(TARGETS ${LIBRARY_NAME} DESTINATION lib)
# install(TARGETS ${LIBRARY_NAME} DESTINATION ${CMAKE_INSTALL_PREFIX}/plugins)
add_subdirectory(nlopt-optimizers)
\ No newline at end of file
set(NLOPT_PYTHON OFF)
set(NLOPT_OCTAVE OFF)
set(NLOPT_MATLAB OFF)
set(NLOPT_GUILE OFF)
set(NLOPT_SWIG OFF)
add_subdirectory(nlopt)
set(LIBRARY_NAME qcor-runtime-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}/runtime/nlopt-optimizers/nlopt/src/api)
target_link_libraries(${LIBRARY_NAME} PUBLIC nlopt)
set(_bundle_name qcor_runtime_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)
qcor_enable_rpath(${LIBRARY_NAME})
if(QCOR_BUILD_TESTS)
add_subdirectory(tests)
endif()
install(TARGETS ${LIBRARY_NAME} DESTINATION ${CMAKE_INSTALL_PREFIX}/plugins)
/***********************************************************************************
* Copyright (c) 2017, UT-Battelle
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the xacc nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Contributors:
* Initial API and implementation - Alex McCaskey
*
**********************************************************************************/
#include "nlopt_optimizer.hpp"
#include "cppmicroservices/BundleActivator.h"
#include "cppmicroservices/BundleContext.h"
#include "cppmicroservices/ServiceProperties.h"
#include "nlopt_optimizer.hpp"
#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<qcor::NLOptimizer>();
context.RegisterService<qcor::Optimizer>(c);
}
/**
*/
void Stop(BundleContext /*context*/) {
}
};
}
CPPMICROSERVICES_EXPORT_BUNDLE_ACTIVATOR(NLOptActivator)
{
"bundle.symbolic_name" : "qcor_runtime_nlopt",
"bundle.activator" : true,
"bundle.name" : "QCOR Runtime NLOpt",
"bundle.description" : ""
}
Subproject commit e34e2599f134568776988ce124a8e02d86c1c6a3
#include "nlopt_optimizer.hpp"
#include "nlopt.hpp"
#include "Utils.hpp"
#include <iostream>
namespace qcor {
OptResult NLOptimizer::optimize(OptFunction &function,
OptimizerOptions options) {
auto dim = function.dimensions();
nlopt::algorithm algo = nlopt::algorithm::LN_COBYLA;
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);
}
}
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(100);
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 qcor
#ifndef RUNTIME_NLOPT_OPTIMIZER_HPP_
#define RUNTIME_NLOPT_OPTIMIZER_HPP_
#include <type_traits>
#include <utility>
#include "optimizer.hpp"
namespace qcor {
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)
fn = new_fn;
return fn;
}
};
using OptResult = std::pair<double, std::vector<double>>;
using OptimizerOptions = std::map<std::string, xacc::InstructionParameter>;
class NLOptimizer : public Optimizer {
public:
OptResult optimize(OptFunction &function,
OptimizerOptions options = OptimizerOptions{}) override;
const std::string name() const override {
return "nlopt";
}
const std::string description() const override {
return "";
}
};
} // namespace qcor
#endif
include_directories(${CMAKE_SOURCE_DIR}/runtime/nlopt-optimizers)
include_directories(${CMAKE_SOURCE_DIR}/runtime)
include_directories(${CMAKE_SOURCE_DIR}/runtime/nlopt-optimizers)
include_directories(${CMAKE_BUILD_DIR}/runtime/nlopt-optimizers/nlopt/src/api)
add_xacc_test(NLOptimizer)
target_link_libraries(NLOptimizerTester nlopt qcor-runtime-nlopt qcor)
\ No newline at end of file
#include <gtest/gtest.h>
#include "nlopt_optimizer.hpp"
using namespace qcor;
TEST(NLOptimizerTester, checkSimple) {
NLOptimizer optimizer;
OptFunction f([](const std::vector<double>& x) {return x[0]*x[0]+5;},1);
EXPECT_EQ(1,f.dimensions());
auto result = optimizer.optimize(f);
EXPECT_EQ(result.first, 5.0);
EXPECT_EQ(result.second, std::vector<double>{0.0});
}
int main(int argc, char **argv) {
::testing::InitGoogleTest(&argc, argv);
auto ret = RUN_ALL_TESTS();
return ret;
}
#ifndef RUNTIME_OPTIMIZER_HPP_
#define RUNTIME_OPTIMIZER_HPP_
#include <functional>
#include <vector>
#include "InstructionParameter.hpp"
#include "Identifiable.hpp"
namespace qcor {
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 {
public:
virtual OptResult optimize(OptFunction &function,
OptimizerOptions options = OptimizerOptions{}) = 0;
};
} // namespace qcor
#endif
......@@ -62,4 +62,8 @@ std::future<std::shared_ptr<AcceleratorBuffer>> submit(HandlerLambda &&totalJob)
});
}
std::shared_ptr<Optimizer> getOptimizer(const std::string& name) {
return xacc::getService<qcor::Optimizer>(name);
}
} // namespace qcor
\ No newline at end of file
......@@ -3,6 +3,7 @@
#include "AcceleratorBuffer.hpp"
#include <future>
#include "optimizer.hpp"
namespace xacc {
......@@ -31,6 +32,8 @@ std::shared_ptr<Function> loadCompiledCircuit(const std::string &fileName);
using HandlerLambda = std::function<void(qpu_handler &)>;
std::future<std::shared_ptr<AcceleratorBuffer>> submit(HandlerLambda &&);
std::shared_ptr<Optimizer> getOptimizer(const std::string& name);
} // namespace qcor
#include "qpu_handler.hpp"
......
#ifndef RUNTIME_QPU_HANDLER_HPP_
#define RUNTIME_QPU_HANDLER_HPP_
#include "XACC.hpp"
#include "qcor.hpp"
#include "Function.hpp"
#include "AcceleratorBuffer.hpp"
#include "InstructionIterator.hpp"
#include "XACC.hpp"
#include <string>
namespace qcor {
......@@ -23,10 +25,15 @@ public:
}
template <typename QuantumKernel>
void vqe(QuantumKernel &&kernel, double observable, double optimizer) {
void vqe(QuantumKernel &&kernel, double observable, std::shared_ptr<Optimizer> optimizer) {
xacc::info("[qcor] Executing vqe! :)");
xacc::info("[qcor] vqe running with " + optimizer->name() + " optimizer.");
auto function = qcor::loadCompiledCircuit(kernel());
// Here we just need to make a lambda function
// to optimize that makes calls to the targeted QPU.
}
template <typename QuantumKernel> void execute(QuantumKernel &&kernel) {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment