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

Merge branch 'xacc-devel' into amrut/compilers

parents be5a7a9f bbff4bcf
......@@ -17,6 +17,7 @@ set(CMAKE_CXX_STANDARD 11)
message(STATUS "C++ version ${CXX_STANDARD} configured.")
option(XACC_BUILD_TESTS "Build test programs" OFF)
option(XACC_BUILD_EXAMPLES "Build example programs" OFF)
if (FROM_SETUP_PY AND NOT APPLE)
message(STATUS "Running build from setup.py, linking to static libstdc++")
......
......@@ -72,4 +72,8 @@ else()
endif()
#install(FILES ${QHEADERS} DESTINATION include/quantum/)
install(TARGETS ${LIBRARY_NAME} DESTINATION plugins)
\ No newline at end of file
install(TARGETS ${LIBRARY_NAME} DESTINATION plugins)
if (XACC_BUILD_EXAMPLES)
add_subdirectory(examples)
endif()
\ No newline at end of file
add_subdirectory(qasm)
\ No newline at end of file
add_executable(deuteron_from_qasm deuteron.cpp)
target_link_libraries(deuteron_from_qasm PRIVATE xacc xacc-pauli)
add_executable(deuteron_from_qasm_vqe_algo deuteron_vqe_algo.cpp)
target_link_libraries(deuteron_from_qasm_vqe_algo PRIVATE xacc xacc-pauli)
\ No newline at end of file
#include "XACC.hpp"
#include "Optimizer.hpp"
#include "PauliOperator.hpp"
#include "xacc_service.hpp"
int main(int argc, char **argv) {
xacc::Initialize(argc, argv);
// Get reference to the Accelerator
// specified by --accelerator argument
auto accelerator = xacc::getAccelerator();
// Allocate some qubits
auto buffer = xacc::qalloc(2);
// Create the N=2 deuteron Hamiltonian
auto H_N_2 =
std::make_shared<xacc::quantum::PauliOperator>("5.907 - 2.1433 X0X1 "
"- 2.1433 Y0Y1"
"+ .21829 Z0 - 6.125 Z1");
// JIT map Quil QASM Ansatz to IR
xacc::qasm(R"(
.compiler quil
.function deuteron_ansatz
X 0
Ry(theta) 1
CNOT 1 0
)");
auto ansatz = xacc::getCompiled("deuteron_ansatz");
// Observe the Ansatz, creating measured kernels
auto kernels = H_N_2->observe(ansatz);
// Create the OptFunction to be optimized
xacc::OptFunction vqeOptFunc(
[&](const std::vector<double> &x) -> double {
std::vector<double> coefficients;
std::vector<std::shared_ptr<xacc::Function>> fsToExec;
// Get function coefficients (pauli term weights)
// into a list, separate from the identity coeff
double identityCoeff = 0.0;
for (auto &f : kernels) {
std::complex<double> coeff =
f->getOption("coefficient").as<std::complex<double>>();
if (f->nInstructions() > ansatz->nInstructions()) {
fsToExec.push_back(f->operator()(x));
coefficients.push_back(std::real(coeff));
} else {
identityCoeff += std::real(coeff);
}
}
// Execute on the QPU!
auto buffers = accelerator->execute(buffer, fsToExec);
// Compute the Energy
double energy = identityCoeff;
for (int i = 0; i < buffers.size(); i++) {
energy += buffers[i]->getExpectationValueZ() * coefficients[i];
}
// Print the energy at this iteration
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;
},
ansatz->nParameters());
// Run Optimization routine, default is NLOPT COBYLA
auto optimizer = xacc::getOptimizer("nlopt");
auto results = optimizer->optimize(vqeOptFunc);
// Print the result
std::cout << "Energy: " << results.first << "\n";
}
\ No newline at end of file
#include "XACC.hpp"
#include "Optimizer.hpp"
#include "PauliOperator.hpp"
#include "xacc_service.hpp"
int main(int argc, char **argv) {
xacc::Initialize(argc, argv);
// Get reference to the Accelerator
// specified by --accelerator argument
auto accelerator = xacc::getAccelerator();
// Create the N=2 deuteron Hamiltonian
auto H_N_2 =
std::make_shared<xacc::quantum::PauliOperator>("5.907 - 2.1433 X0X1 "
"- 2.1433 Y0Y1"
"+ .21829 Z0 - 6.125 Z1");
auto optimizer = xacc::getOptimizer("nlopt");
// JIT map Quil QASM Ansatz to IR
xacc::qasm(R"(
.compiler quil
.function deuteron_ansatz
X 0
Ry(theta) 1
CNOT 1 0
)");
auto ansatz = xacc::getCompiled("deuteron_ansatz");
// Get the VQE Algorithm and initialize it
auto vqe = xacc::getAlgorithm("vqe");
vqe->initialize({{"ansatz", ansatz},
{"observable", H_N_2},
{"accelerator", accelerator},
{"optimizer", optimizer}});
// Allocate some qubits and execute
auto buffer = xacc::qalloc(2);
vqe->execute(buffer);
// Print the result
std::cout << "Energy: "
<< buffer->getInformation("opt-val").as<double>() << "\n";
}
\ No newline at end of file
......@@ -373,6 +373,22 @@ void GateFunction::addInstruction(InstPtr instruction) {
}
}
}
if (instruction->isComposite()) {
std::cout << "GateFunction Adding composite instruction\n";
for (auto p : instruction->getParameters()) {
// these have to be variable params
bool dupParam = false;
for (auto p2 : getParameters()) {
if (p.as<std::string>() == p2.as<std::string>()) {
dupParam = true;
}
}
if (!dupParam) {
parameters.push_back(p);
}
}
}
// Add the GateInstruction
instructions.push_back(instruction);
}
......
......@@ -37,9 +37,9 @@ TEST(VQETester, checkSimple) {
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(
auto optimizer = xacc::getOptimizer("nlopt");
xacc::quantum::PauliOperator 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 "
......@@ -47,7 +47,7 @@ TEST(VQETester, checkSimple) {
"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}}));//
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);
}
......
......@@ -19,7 +19,12 @@ bool VQE::initialize(const AlgorithmParameters &parameters) {
} else if (!parameters.count("accelerator")) {
return false;
}
observable = parameters.at("observable").as<std::shared_ptr<Observable>>();
try {
observable = parameters.at("observable").as_no_error<std::shared_ptr<Observable>>();
} catch (std::exception &e) {
observable = std::shared_ptr<Observable>(parameters.at("observable").as<Observable*>(), [](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>>();
......
......@@ -32,7 +32,7 @@ namespace xacc {
bool isPyApi = false;
bool xaccFrameworkInitialized = false;
std::shared_ptr<CLIParser> xaccCLParser;// = std::make_shared<CLIParser>();
std::shared_ptr<CLIParser> xaccCLParser; // = std::make_shared<CLIParser>();
int argc = 0;
char **argv = NULL;
std::map<std::string, std::shared_ptr<Function>> compilation_database{};
......@@ -60,7 +60,7 @@ void ctrl_c_handler(int signal) {
}
std::vector<std::string> getIncludePaths() {
return xaccCLParser->getIncludePaths();
return xaccCLParser->getIncludePaths();
}
void PyInitialize(const std::string rootPath) {
......@@ -78,7 +78,7 @@ void Initialize(int arc, char **arv) {
xacc::ServiceAPI_Initialize(argc, argv);
// Parse any user-supplied command line options
xaccCLParser->parse(argc, argv);//, serviceRegistry.get());
xaccCLParser->parse(argc, argv); //, serviceRegistry.get());
struct sigaction sigIntHandler;
sigIntHandler.sa_handler = ctrl_c_handler;
sigemptyset(&sigIntHandler.sa_mask);
......@@ -126,7 +126,6 @@ void error(const std::string &msg, MessagePredicate predicate) {
}
}
qbit qalloc(const int n) {
return std::make_shared<xacc::AcceleratorBuffer>(n);
}
......@@ -190,7 +189,7 @@ std::shared_ptr<Accelerator> getAccelerator() {
auto name = getOption("accelerator");
auto name_backend = split(name, ':');
if (name_backend.size() > 1) {
setOption(name_backend[0]+"-backend",name_backend[1]);
setOption(name_backend[0] + "-backend", name_backend[1]);
}
auto acc = xacc::getService<Accelerator>(name_backend[0]);
......@@ -203,7 +202,8 @@ std::shared_ptr<Accelerator> getAccelerator() {
}
return acc;
}
std::shared_ptr<Accelerator> getAccelerator(const std::string &name, std::shared_ptr<Client> client) {
std::shared_ptr<Accelerator> getAccelerator(const std::string &name,
std::shared_ptr<Client> client) {
if (!xacc::xaccFrameworkInitialized) {
error("XACC not initialized before use. Please execute "
"xacc::Initialize() before using API.");
......@@ -212,13 +212,13 @@ std::shared_ptr<Accelerator> getAccelerator(const std::string &name, std::shared
auto name_backend = split(name, ':');
auto acc = xacc::getService<Accelerator>(name_backend[0]);
if (name_backend.size() > 1) {
setOption(name_backend[0]+"-backend",name_backend[1]);
setOption(name_backend[0] + "-backend", name_backend[1]);
}
if (acc) {
auto remoteacc = std::dynamic_pointer_cast<RemoteAccelerator>(acc);
if (remoteacc) {
remoteacc->setClient(client);
remoteacc->setClient(client);
}
acc->initialize();
} else {
......@@ -236,7 +236,7 @@ std::shared_ptr<Accelerator> getAccelerator(const std::string &name) {
auto name_backend = split(name, ':');
auto acc = xacc::getService<Accelerator>(name_backend[0]);
if (name_backend.size() > 1) {
setOption(name_backend[0]+"-backend",name_backend[1]);
setOption(name_backend[0] + "-backend", name_backend[1]);
}
if (acc) {
......@@ -267,8 +267,25 @@ std::shared_ptr<Compiler> getCompiler(const std::string &name) {
}
return c;
}
std::shared_ptr<IRProvider> getIRProvider(const std::string& name) {
if (!xacc::xaccFrameworkInitialized) {
std::shared_ptr<Algorithm> getAlgorithm(const std::string name) {
if (!xacc::xaccFrameworkInitialized) {
error("XACC not initialized before use. Please execute "
"xacc::Initialize() before using API.");
}
return xacc::getService<Algorithm>(name);
}
std::shared_ptr<Optimizer> getOptimizer(const std::string name) {
if (!xacc::xaccFrameworkInitialized) {
error("XACC not initialized before use. Please execute "
"xacc::Initialize() before using API.");
}
return xacc::getService<Optimizer>(name);
}
std::shared_ptr<IRProvider> getIRProvider(const std::string &name) {
if (!xacc::xaccFrameworkInitialized) {
error("XACC not initialized before use. Please execute "
"xacc::Initialize() before using API.");
}
......@@ -337,8 +354,7 @@ const std::string translateWithVisitor(const std::string &originalSource,
auto acc = getAccelerator(accelerator);
auto originalCompiler = getCompiler(originalLanguage);
auto ir = originalCompiler->compile(originalSource, acc);
auto visitor =
xacc::getService<BaseInstructionVisitor>(visitorMappingName);
auto visitor = xacc::getService<BaseInstructionVisitor>(visitorMappingName);
std::vector<std::string> previouslySeenKernels;
......@@ -379,22 +395,22 @@ std::shared_ptr<Function> optimizeFunction(const std::string optimizer,
bool hasCache(const std::string fileName, const std::string subdirectory) {
auto rootPathStr = xacc::getRootPathString();
if (!subdirectory.empty()) {
rootPathStr += "/"+subdirectory;
if (!xacc::directoryExists(rootPathStr)) {
return false;
}
rootPathStr += "/" + subdirectory;
if (!xacc::directoryExists(rootPathStr)) {
return false;
}
}
return xacc::fileExists(rootPathStr + "/" +
fileName);
return xacc::fileExists(rootPathStr + "/" + fileName);
}
std::map<std::string, InstructionParameter>
getCache(const std::string fileName, const std::string subdirectory) {
std::string rootPathStr = xacc::getRootPathString();
if (!subdirectory.empty()) {
rootPathStr += "/"+subdirectory;
if (!xacc::directoryExists(rootPathStr)) {
error("Tried to get Cache at " + rootPathStr+"/"+fileName + ", and it does not exist.");
}
rootPathStr += "/" + subdirectory;
if (!xacc::directoryExists(rootPathStr)) {
error("Tried to get Cache at " + rootPathStr + "/" + fileName +
", and it does not exist.");
}
}
std::ifstream t(rootPathStr + "/" + fileName);
......@@ -420,10 +436,11 @@ void appendCache(const std::string fileName, const std::string key,
auto rootPathStr = xacc::getRootPathString();
if (!subdirectory.empty()) {
rootPathStr += "/"+subdirectory;
if (!xacc::directoryExists(rootPathStr)) {
auto status = mkdir(rootPathStr.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
}
rootPathStr += "/" + subdirectory;
if (!xacc::directoryExists(rootPathStr)) {
auto status =
mkdir(rootPathStr.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
}
}
if (xacc::fileExists(rootPathStr + "/" + fileName)) {
......@@ -457,10 +474,11 @@ void appendCache(const std::string fileName, const std::string key,
InstructionParameter &&param, const std::string subdirectory) {
auto rootPathStr = xacc::getRootPathString();
if (!subdirectory.empty()) {
rootPathStr += "/"+subdirectory;
if (!xacc::directoryExists(rootPathStr)) {
auto status = mkdir(rootPathStr.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
}
rootPathStr += "/" + subdirectory;
if (!xacc::directoryExists(rootPathStr)) {
auto status =
mkdir(rootPathStr.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
}
}
// Check if file exists
if (xacc::fileExists(rootPathStr + "/" + fileName)) {
......@@ -491,17 +509,19 @@ void appendCache(const std::string fileName, const std::string key,
}
void appendCache(const std::string fileName,
std::map<std::string, InstructionParameter> &params, const std::string subdirectory) {
std::map<std::string, InstructionParameter> &params,
const std::string subdirectory) {
// This will over write the ip cache file
auto rootPathStr = xacc::getRootPathString();
if (!subdirectory.empty()) {
rootPathStr += "/"+subdirectory;
if (!xacc::directoryExists(rootPathStr)) {
auto status = mkdir(rootPathStr.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
}
rootPathStr += "/" + subdirectory;
if (!xacc::directoryExists(rootPathStr)) {
auto status =
mkdir(rootPathStr.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
}
}
InstructionParameter2ExtraInfo ip2e;
AcceleratorBuffer b;
......@@ -518,34 +538,68 @@ void appendCache(const std::string fileName,
out << s.str();
out.close();
}
const std::string getRootDirectory() {
return xacc::getRootPathString();
}
const std::string getRootDirectory() { return xacc::getRootPathString(); }
void appendCompiled(std::shared_ptr<Function> function) {
if (compilation_database.count(function->name())) {
xacc::error("Invalid Function name, already in compilation database.");
}
compilation_database.insert({function->name(), function});
if (compilation_database.count(function->name())) {
xacc::error("Invalid Function name, already in compilation database.");
}
compilation_database.insert({function->name(), function});
}
std::shared_ptr<Function> getCompiled(const std::string name) {
if (!compilation_database.count(name)) {
xacc::error("Invalid Function requested. Not in compilation database " + name);
if (!compilation_database.count(name)) {
xacc::error("Invalid Function requested. Not in compilation database " +
name);
}
return compilation_database[name];
}
void qasm(const std::string &qasmString) {
std::regex rgx(".compiler \\w+"), rgxx(".function \\w+");
std::smatch match, match2;
std::map<std::string, std::string> function2code;
if (!std::regex_search(qasmString.begin(), qasmString.end(), match, rgx)) {
error("Cannot parse which compiler this qasm corresponds to.");
}
auto compiler = split(match[0], ' ')[1];
auto lines = split(qasmString, '\n');
std::string currentFunctionName = "";
for (auto &l : lines) {
if (l.find(".compiler") == std::string::npos &&
l.find(".function") == std::string::npos && !l.empty()) {
function2code[currentFunctionName] += l + "\n";
}
if (l.find(".function") != std::string::npos) {
currentFunctionName = split(l, ' ')[1];
}
return compilation_database[name];
}
std::string newQasm = "";
for (auto &kv : function2code) {
newQasm += "__qpu__ " + kv.first + "(AcceleratorBuffer b) {\n" + kv.second +
"\n}\n";
}
std::shared_ptr<IR> ir;
if (optionExists("accelerator")) {
ir = getCompiler(compiler)->compile(newQasm, getAccelerator());
} else {
ir = getCompiler(compiler)->compile(newQasm);
}
for (auto &k : ir->getKernels())
appendCompiled(k);
}
/**
* This method should be called by clients to
* clean up and finalize the XACC framework. It should
* be called after using the XACC API.
*/
void Finalize() {
XACCLogger::instance()->dumpQueue();
// info("");
// info("[xacc::plugins] Cleaning up Plugin Registry.");
// xacc::xacc::destroy();
xacc::xaccFrameworkInitialized = false;
// info("[xacc] Finalizing XACC Framework.");
if (xaccFrameworkInitialized) {
xacc::xaccFrameworkInitialized = false;
xacc::ServiceAPI_Finalize();
}
}
} // namespace xacc
......@@ -16,6 +16,8 @@
#include "Compiler.hpp"
#include "RemoteAccelerator.hpp"
#include "IRProvider.hpp"
#include "Algorithm.hpp"
#include "Optimizer.hpp"
namespace xacc {
......@@ -244,6 +246,8 @@ std::shared_ptr<Compiler> getCompiler(const std::string &name);
*/
std::shared_ptr<Compiler> getCompiler();
std::shared_ptr<Algorithm> getAlgorithm(const std::string name);
std::shared_ptr<Optimizer> getOptimizer(const std::string name);
using qbit = std::shared_ptr<xacc::AcceleratorBuffer>;
qbit qalloc(const int n);
......@@ -319,6 +323,7 @@ const std::string translateWithVisitor(const std::string &originalSource,
void appendCompiled(std::shared_ptr<Function> function);
std::shared_ptr<Function> getCompiled(const std::string name);
void qasm(const std::string& qasmString);
/**
* This method should be called by clients to
* clean up and finalize the XACC framework. It should
......
......@@ -25,7 +25,7 @@ class AcceleratorBuffer;
using AcceleratorBufferChildPair =
std::pair<std::string, std::shared_ptr<AcceleratorBuffer>>;
using ExtraInfo = mpark::variant<int, double, std::string, std::vector<int>,
using ExtraInfo = xacc::Variant<int, double, std::string, std::vector<int>,
std::vector<double>, std::vector<std::string>,
std::map<int, std::vector<int>>,
std::vector<std::pair<double, double>>,
......@@ -295,7 +295,7 @@ public:
void setName(const std::string n) {
bufferId = n;
}
/**
* Print information about this AcceleratorBuffer to the
* given output stream.
......
......@@ -13,7 +13,7 @@ namespace xacc {
using AlgorithmParameter =
Variant<int, double, std::string, std::vector<int>, std::vector<double>,
std::vector<std::string>, std::shared_ptr<Observable>,
std::vector<std::string>, std::shared_ptr<Observable>, Observable*,
std::shared_ptr<Accelerator>, std::shared_ptr<Function>,
std::shared_ptr<Optimizer>>;
using AlgorithmParameters = std::map<std::string, AlgorithmParameter>;
......
......@@ -73,6 +73,12 @@ public:
}
return T();
}
template <typename T> T as_no_error() const {
// First off just try to get it
return mpark::get<T>(*this);
}
int which() const {
return this->index();
}
......
......@@ -61,7 +61,14 @@ public:
const std::string getRootPathString() { return rootPathStr; }
void initialize(const std::string rootPath);
void finalize() {
auto bundles = context.GetBundles();
for (auto b : bundles) {
if (b.GetSymbolicName() != "system") {
b.Stop();
}
}
}
template <typename ServiceInterface> bool hasService(const std::string name) {
auto allServiceRefs = context.GetServiceReferences<ServiceInterface>();
for (auto s : allServiceRefs) {
......
......@@ -52,6 +52,13 @@ void ServiceAPI_Initialize(int argc, char **argv) {
}
}
void ServiceAPI_Finalize() {
if (serviceAPIInitialized) {
serviceAPIInitialized = false;
serviceRegistry->finalize();
}
}
std::vector<OptionPairs> getRegisteredOptions() {
return serviceRegistry->getRegisteredOptions();
}
......