Commit 7d94a659 authored by Mccaskey, Alex's avatar Mccaskey, Alex
Browse files

Committing initial ddcl algorithm work with simple test using js loss function and cobyla opt


Signed-off-by: Mccaskey, Alex's avatarAlex McCaskey <mccaskeyaj@ornl.gov>
parent aa56dc68
Pipeline #73225 passed with stage
in 4 minutes and 39 seconds
......@@ -13,5 +13,6 @@
add_subdirectory(vqe)
add_subdirectory(rdm)
add_subdirectory(vqe-energy)
add_subdirectory(ddcl)
file(GLOB PYDECORATORS ${CMAKE_CURRENT_SOURCE_DIR}/vqe/python/*.py ${CMAKE_CURRENT_SOURCE_DIR}/vqe-energy/python/*.py)
install(FILES ${PYDECORATORS} DESTINATION ${CMAKE_INSTALL_PREFIX}/py-plugins)
# *******************************************************************************
# Copyright (c) 2019 UT-Battelle, LLC.
# All rights reserved. This program and the accompanying materials
# are made available under the terms of the Eclipse Public License v1.0
# and Eclipse Distribution License v.10 which accompany this distribution.
# The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
# and the Eclipse Distribution License is available at
# https://eclipse.org/org/documents/edl-v10.php
#
# Contributors:
# Alexander J. McCaskey - initial API and implementation
# *******************************************************************************/
set(LIBRARY_NAME xacc-algorithm-ddcl)
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)
set(_bundle_name xacc_algorithm_ddcl)
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)
/*******************************************************************************
* Copyright (c) 2019 UT-Battelle, LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompanies this
* distribution. The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html and the Eclipse Distribution
*License is available at https://eclipse.org/org/documents/edl-v10.php
*
* Contributors:
* Alexander J. McCaskey - initial API and implementation
*******************************************************************************/
#include "ddcl.hpp"
#include "xacc.hpp"
#include "xacc_service.hpp"
#include <memory>
#include <iomanip>
using namespace xacc;
namespace xacc {
namespace algorithm {
bool DDCL::initialize(const HeterogeneousMap &parameters) {
if (!parameters.keyExists<std::shared_ptr<CompositeInstruction>>("ansatz")) {
std::cout << "Ansatz was false\n";
return false;
} else if (!parameters.keyExists<std::shared_ptr<Optimizer>>("optimizer")) {
std::cout << "Opt was false\n";
return false;
} else if (!parameters.keyExists<std::shared_ptr<Accelerator>>(
"accelerator")) {
std::cout << "Acc was false\n";
return false;
} else if (!parameters.keyExists<std::vector<double>>("target_dist")) {
return false;
} else if (!parameters.stringExists("loss")) {
return false;
}
optimizer = parameters.get<std::shared_ptr<Optimizer>>("optimizer");
kernel = parameters.get<std::shared_ptr<CompositeInstruction>>("ansatz");
accelerator = parameters.get<std::shared_ptr<Accelerator>>("accelerator");
target_dist = parameters.get<std::vector<double>>("target_dist");
loss = parameters.getString("loss");
gradient = parameters.stringExists("gradient") ? parameters.getString("gradient") : "";
return true;
}
const std::vector<std::string> DDCL::requiredParameters() const {
return {"target_dist", "loss", "gradient",
"optimizer", "accelerator", "ansatz"};
}
void DDCL::execute(const std::shared_ptr<AcceleratorBuffer> buffer) const {
auto provider = xacc::getIRProvider("quantum");
// 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> &dx) {
// Evaluate and add measurements to all qubits
auto evaled = kernel->operator()(x);
for (std::size_t i = 0; i < buffer->size(); i++) {
auto m = provider->createInstruction("Measure",
std::vector<std::size_t>{i});
evaled->addInstruction(m);
}
// Start the list of circuits to execute
std::vector<Circuit> circuits{evaled};
// Get the user specified loss and gradient strategies
auto gradientStrategy =
dx.empty() ? std::make_shared<NullGradientStrategy>()
: xacc::getService<GradientStrategy>(gradient);
auto lossStrategy = xacc::getService<LossStrategy>(loss);
// Only compute gradients if this is
// a gradient based optimizer
if (!dx.empty()) {
// Request the circuits to be executed in support of
// computing the gradient, add it to the circuits list
auto gradientCircuits =
gradientStrategy->getCircuitExecutions(kernel, x);
for (auto &g : gradientCircuits) {
circuits.push_back(g);
}
}
// Execute!
auto tmpBuffer = xacc::qalloc(buffer->size());
accelerator->execute(tmpBuffer, circuits);
auto buffers = tmpBuffer->getChildren();
// The first child buffer is for the loss function
auto counts = buffers[0]->getMeasurementCounts();
// Only compute gradients if this is
// a gradient based optimizer
if (!dx.empty()) {
// The rest of the buffers are for the gradients
std::vector<Counts> gradResults;
for (int i = 1; i < buffers.size(); i++) {
gradResults.push_back(buffers[i]->getMeasurementCounts());
}
// Compute the gradient with the results
gradientStrategy->compute(dx, gradResults);
}
// Compute and return the loss
auto js = lossStrategy->compute(counts, target_dist);
std::stringstream ss;
ss << x << ") = " << js;
xacc::info("JSDiv(" + ss.str());
return js;
},
kernel->nVariables());
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
/*******************************************************************************
* Copyright (c) 2019 UT-Battelle, LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompanies this
* distribution. The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html and the Eclipse Distribution
*License is available at https://eclipse.org/org/documents/edl-v10.php
*
* Contributors:
* Alexander J. McCaskey - initial API and implementation
*******************************************************************************/
#ifndef XACC_ALGORITHM_DDCL_HPP_
#define XACC_ALGORITHM_DDCL_HPP_
#include "Algorithm.hpp"
#include <vector>
namespace xacc {
namespace algorithm {
using Circuit = std::shared_ptr<CompositeInstruction>;
using Counts = std::map<std::string, int>;
class LossStrategy : public Identifiable {
public:
virtual double compute(Counts &counts, const std::vector<double> &target) = 0;
};
class GradientStrategy : public Identifiable {
public:
// Generate circuits to run that will be used to
// compute gradients. Need the un-evaluated, original ansatz
// and the current iterate's parameters
virtual std::vector<Circuit>
getCircuitExecutions(Circuit circuit, const std::vector<double> &x) = 0;
virtual void compute(std::vector<double> &grad,
std::vector<Counts> results) = 0;
};
class NullGradientStrategy : public GradientStrategy {
public:
std::vector<Circuit>
getCircuitExecutions(Circuit circuit, const std::vector<double> &x) override {
return {};
}
void compute(std::vector<double> &grad,
std::vector<Counts> results) override {
return;
}
const std::string name() const override { return "null-gs"; }
const std::string description() const override { return ""; }
};
class DDCL : public Algorithm {
protected:
std::shared_ptr<Optimizer> optimizer;
std::shared_ptr<CompositeInstruction> kernel;
std::shared_ptr<Accelerator> accelerator;
std::vector<double> initial_params;
std::vector<double> target_dist;
std::string gradient;
std::string loss;
HeterogeneousMap parameters;
public:
bool initialize(const HeterogeneousMap &parameters) override;
const std::vector<std::string> requiredParameters() const override;
void execute(const std::shared_ptr<AcceleratorBuffer> buffer) const override;
const std::string name() const override { return "ddcl"; }
const std::string description() const override { return ""; }
};
} // namespace algorithm
} // namespace xacc
#endif
\ No newline at end of file
/*******************************************************************************
* Copyright (c) 2019 UT-Battelle, LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompanies this
* distribution. The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html and the Eclipse Distribution
*License is available at https://eclipse.org/org/documents/edl-v10.php
*
* Contributors:
* Alexander J. McCaskey - initial API and implementation
*******************************************************************************/
#include "ddcl.hpp"
#include "strategies/js_loss.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 DDCLActivator : public BundleActivator {
public:
DDCLActivator() {}
/**
*/
void Start(BundleContext context) {
auto c = std::make_shared<xacc::algorithm::DDCL>();
context.RegisterService<xacc::Algorithm>(c);
auto js = std::make_shared<xacc::algorithm::JSLossStrategy>();
context.RegisterService<xacc::algorithm::LossStrategy>(js);
}
/**
*/
void Stop(BundleContext /*context*/) {}
};
} // namespace
CPPMICROSERVICES_EXPORT_BUNDLE_ACTIVATOR(DDCLActivator)
{
"bundle.symbolic_name" : "xacc_algorithm_ddcl",
"bundle.activator" : true,
"bundle.name" : "XACC DDCL Algorithm",
"bundle.description" : ""
}
/*******************************************************************************
* Copyright (c) 2019 UT-Battelle, LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompanies this
* distribution. The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html and the Eclipse Distribution
*License is available at https://eclipse.org/org/documents/edl-v10.php
*
* Contributors:
* Alexander J. McCaskey - initial API and implementation
*******************************************************************************/
#ifndef XACC_ALGORITHM_DDCL_STRATEGIES_JS_LOSS_HPP_
#define XACC_ALGORITHM_DDCL_STRATEGIES_JS_LOSS_HPP_
#include "ddcl.hpp"
#include "xacc.hpp"
namespace xacc {
namespace algorithm {
class JSLossStrategy : public LossStrategy {
protected:
// 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:
double compute(Counts &counts, const std::vector<double>& target) override {
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]);
// for (auto& kv : counts) {
// std::cout << kv.first <<", " << kv.second << "\n";
// }
auto js = 0.5 * (entropy(target, m) + entropy(q, m));
// xacc::info("JSDiv: " + std::to_string(js));
return js;
}
const std::string name() const override { return "js"; }
const std::string description() const override { return ""; }
};
}
}
#endif
\ No newline at end of file
# *******************************************************************************
# Copyright (c) 2019 UT-Battelle, LLC.
# All rights reserved. This program and the accompanying materials
# are made available under the terms of the Eclipse Public License v1.0
# and Eclipse Distribution License v.10 which accompany this distribution.
# The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
# and the Eclipse Distribution License is available at
# https://eclipse.org/org/documents/edl-v10.php
#
# Contributors:
# Alexander J. McCaskey - initial API and implementation
# *******************************************************************************/
include_directories(${CMAKE_BINARY_DIR})
add_xacc_test(DDCL)
target_link_libraries(DDCLTester xacc)
\ No newline at end of file
/*******************************************************************************
* Copyright (c) 2019 UT-Battelle, LLC.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompanies this
* distribution. The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html and the Eclipse Distribution
*License is available at https://eclipse.org/org/documents/edl-v10.php
*
* Contributors:
* Alexander J. McCaskey - initial API and implementation
*******************************************************************************/
#include <gtest/gtest.h>
#include "xacc.hpp"
#include "xacc_service.hpp"
#include "Optimizer.hpp"
#include "Algorithm.hpp"
using namespace xacc;
const std::string src = R"rucc(__qpu__ void f(qbit q, double t0, double t1, double t2) {
Rx(q[0], t0);
Ry(q[0], t1);
Rx(q[0], t2);
})rucc";
TEST(VQETester, checkSimpleGradientFree) {
if (xacc::hasAccelerator("local-ibm")) {
auto acc = xacc::getAccelerator("local-ibm");
auto buffer = xacc::qalloc(1);
auto compiler = xacc::getCompiler("xasm");
auto ir = compiler->compile(src, acc);
auto simple = ir->getComposite("f");
// get cobyla optimizer
auto optimizer = xacc::getOptimizer("nlopt", HeterogeneousMap{std::make_pair("nlopt-maxeval", 20)});
std::vector<double> target {.5, .5};
auto ddcl = xacc::getService<Algorithm>("ddcl");
EXPECT_TRUE(ddcl->initialize({std::make_pair("ansatz",simple),
std::make_pair("accelerator",acc),
std::make_pair("target_dist", target),
std::make_pair("loss", "js"),
std::make_pair("optimizer",optimizer)}));
ddcl->execute(buffer);
std::cout << buffer->getInformation("opt-params").as<std::vector<double>>() << "\n";
}
}
int main(int argc, char **argv) {
xacc::Initialize(argc, argv);
::testing::InitGoogleTest(&argc, argv);
auto ret = RUN_ALL_TESTS();
xacc::Finalize();
return ret;
}
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