This GitLab instance is undergoing maintenance and is operating in read-only mode.

You are on a read-only GitLab instance.
Commit 38cc51c5 authored by Mccaskey, Alex's avatar Mccaskey, Alex
Browse files

adding start of xasm compiler, added exp, hwe, range ir generators, cleaned up...


adding start of xasm compiler, added exp, hwe, range ir generators, cleaned up irgenerator interface
Signed-off-by: Mccaskey, Alex's avatarAlex McCaskey <mccaskeyaj@ornl.gov>
parent 1dfaafdf
Pipeline #66275 passed with stage
in 6 minutes and 51 seconds
......@@ -123,14 +123,9 @@ public:
const std::string description() const override { return ""; }
std::shared_ptr<Function>
generate(std::map<std::string, InstructionParameter>& parameters) {
generate(std::map<std::string, InstructionParameter>& parameters) override {
PYBIND11_OVERLOAD_PURE(std::shared_ptr<Function>, xacc::IRGenerator, generate, parameters);
}
std::shared_ptr<Function>
generate(std::shared_ptr<AcceleratorBuffer> buffer,
std::vector<InstructionParameter> parameters =
std::vector<InstructionParameter>{}) override { return nullptr;}
};
class PyCompiler : public xacc::Compiler {
......@@ -144,7 +139,7 @@ public:
const std::string description() const override { return ""; }
std::shared_ptr<IR>
compile(const std::string& src, std::shared_ptr<Accelerator> acc) {
compile(const std::string& src, std::shared_ptr<Accelerator> acc) override {
PYBIND11_OVERLOAD_PURE(std::shared_ptr<IR>, xacc::Compiler, compile, src, acc);
}
......@@ -259,13 +254,8 @@ PYBIND11_MODULE(_pyxacc, m) {
.def(py::init<>(),"")
.def("generate",
(std::shared_ptr<xacc::Function>(xacc::IRGenerator::*)(
std::vector<xacc::InstructionParameter>)) &
xacc::IRGenerator::generate, "")
.def("generate",
(std::shared_ptr<xacc::Function>(xacc::IRGenerator::*)(
std::map<std::string, xacc::InstructionParameter> &)) &
xacc::IRGenerator::generate, "")
.def("analyzeResults", &xacc::IRGenerator::analyzeResults, "");
std::map<std::string, xacc::InstructionParameter>&)) &
xacc::IRGenerator::generate, "");
// Expose the Accelerator
py::class_<xacc::Accelerator, std::shared_ptr<xacc::Accelerator>,
......@@ -621,9 +611,6 @@ PYBIND11_MODULE(_pyxacc, m) {
"Indicate that this is using XACC via the Python API.");
m.def("optimizeFunction", &xacc::optimizeFunction,
"Run an optimizer on the given function.");
m.def("analyzeBuffer",
(void (*)(std::shared_ptr<AcceleratorBuffer>)) & xacc::analyzeBuffer,
"Analyze the AcceleratorBuffer to produce problem-specific results.");
m.def("getCache", &xacc::getCache, "");
m.def("appendCache",
(void (*)(const std::string, const std::string, InstructionParameter &,
......
......@@ -19,8 +19,7 @@ namespace xacc {
namespace quantum {
std::shared_ptr<Function>
InverseQFT::generate(std::shared_ptr<AcceleratorBuffer> buffer,
std::vector<InstructionParameter> parameters) {
InverseQFT::generate(std::map<std::string,InstructionParameter>& parameters) {
// Create a function to return
auto retFunction = std::make_shared<GateFunction>("inverse_qft");
......@@ -28,7 +27,7 @@ InverseQFT::generate(std::shared_ptr<AcceleratorBuffer> buffer,
// Generate the QFT algorithm and get the
// individual instructions
QFT qft;
auto qftFunction = qft.generate(buffer, parameters);
auto qftFunction = qft.generate(parameters);
auto instructions = qftFunction->getInstructions();
// Reverse those instructions
......
......@@ -35,14 +35,12 @@ public:
* @param bits The bits this algorithm operates on
* @return function The algorithm represented as an IR Function
*/
virtual std::shared_ptr<Function>
generate(std::shared_ptr<AcceleratorBuffer> buffer,
std::vector<InstructionParameter> parameters =
std::vector<InstructionParameter>{});
std::shared_ptr<Function>
generate(std::map<std::string,InstructionParameter>& parameters) override;
virtual const std::string name() const { return "InverseQFT"; }
const std::string name() const override { return "InverseQFT"; }
virtual const std::string description() const {
const std::string description() const override {
return "The Inverse QFT Algorithm Generator generates IR representing "
"an inverse Quantum Fourier Transform.";
}
......
......@@ -21,8 +21,7 @@ namespace xacc {
namespace quantum {
std::shared_ptr<Function>
QFT::generate(std::shared_ptr<AcceleratorBuffer> buffer,
std::vector<InstructionParameter> parameters) {
QFT::generate(std::map<std::string,InstructionParameter>& parameters) {
auto gateRegistry = xacc::getService<IRProvider>("gate");
auto bitReversal = [&](std::vector<int> qubits)
......@@ -93,7 +92,7 @@ QFT::generate(std::shared_ptr<AcceleratorBuffer> buffer,
}
};
auto bufferSize = buffer->size();
auto bufferSize = parameters["nqubits"].as<int>();
std::vector<int> qubits;
for (int i = 0; i < bufferSize; i++) {
qubits.push_back(i);
......
......@@ -38,14 +38,12 @@ public:
* @param bits The bits this algorithm operates on
* @return function The algorithm represented as an IR Function
*/
virtual std::shared_ptr<Function>
generate(std::shared_ptr<AcceleratorBuffer> buffer,
std::vector<InstructionParameter> parameters =
std::vector<InstructionParameter>{});
std::shared_ptr<Function>
generate(std::map<std::string, InstructionParameter>& parameters) override;
virtual const std::string name() const { return "QFT"; }
const std::string name() const override { return "QFT"; }
virtual const std::string description() const {
const std::string description() const override {
return "The QFT Algorithm Generator generates IR representing "
"a Quantum Fourier Transform.";
}
......
......@@ -22,11 +22,10 @@ using namespace xacc::quantum;
TEST(InverseQFTTester, checkCreation) {
xacc::Initialize();
auto iqft = std::make_shared<InverseQFT>();
auto iqft = xacc::getIRGenerator("InverseQFT");//std::make_shared<InverseQFT>();
auto buffer = std::make_shared<AcceleratorBuffer>("", 3);
auto iqftKernel = iqft->generate(buffer);
auto iqftKernel = iqft->generate({{"nqubits",3}});
auto ir = std::make_shared<GateIR>();
ir->addKernel(iqftKernel);
......
......@@ -23,10 +23,10 @@ using namespace xacc::quantum;
TEST(QFTTester, checkCreation) {
xacc::Initialize();
auto qft = std::make_shared<QFT>();
auto qft = xacc::getIRGenerator("QFT");//std::make_shared<QFT>();
auto buffer = std::make_shared<AcceleratorBuffer>("", 3);
auto qftKernel = qft->generate(buffer);
auto qftKernel = qft->generate({{"nqubits",3}});
auto ir = std::make_shared<GateIR>();
ir->addKernel(qftKernel);
......
......@@ -4,6 +4,7 @@ add_subdirectory(cmr)
add_subdirectory(dwave)
add_subdirectory(algorithms)
add_subdirectory(decorators)
add_subdirectory(generators)
#add_subdirectory(scaffold)
#add_subdirectory(xasm)
add_subdirectory(xasm)
......@@ -42,15 +42,9 @@ std::shared_ptr<Function> RBMGenerator::generate(
params.push_back(parameters["hidden-units"]);
}
return generate(nullptr, params);
}
std::shared_ptr<Function> RBMGenerator::generate(
std::shared_ptr<AcceleratorBuffer> buffer,
std::vector<InstructionParameter> parameters) {
int n_visible = parameters[1].as<int>();
int n_hidden = parameters[0].as<int>();
int n_visible = params[1].as<int>();
int n_hidden = params[0].as<int>();
auto kernel = std::make_shared<xacc::quantum::DWFunction>("rbm_function");
......
......@@ -13,25 +13,9 @@ class RBMGenerator: public xacc::IRGenerator {
public:
/**
* Implementations of this method generate a Function IR
* instance corresponding to the implementation's modeled
* algorithm. The algorithm is specified to operate over the
* provided AcceleratorBuffer and can take an optional
* vector of InstructionParameters.
*
* @param bits The bits this algorithm operates on
* @return function The algorithm represented as an IR Function
*/
std::shared_ptr<Function> generate(
std::shared_ptr<AcceleratorBuffer> buffer,
std::vector<InstructionParameter> parameters = std::vector<
InstructionParameter> { }) override;
std::shared_ptr<Function> generate(
std::map<std::string, InstructionParameter>& parameters) override ;
const std::string name() const override {
return "rbm";
}
......
......@@ -11,7 +11,7 @@ TEST(RBMGeneratorTester, checkRBM){
auto buffer = std::make_shared<xacc::AcceleratorBuffer>("", 4);
auto f = irgen->generate(buffer, {xacc::InstructionParameter(2), xacc::InstructionParameter(2)});
auto f = irgen->generate({{"visible_units",2},{"hidden_units",2}});
std::cout << f->toString() << std::endl;
std::cout << f->nParameters() << std::endl;
......
set(LIBRARY_NAME xacc-generators)
file(GLOB SRC hwe/hwe.cpp
range/range.cpp
exp/exp.cpp
GeneratorsActivator.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 . hwe exp range)
target_link_libraries(${LIBRARY_NAME} PUBLIC xacc PRIVATE xacc-pauli xacc-fermion)
set(_bundle_name xacc_generators)
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(hwe/tests)
add_subdirectory(exp/tests)
add_subdirectory(range/tests)
endif()
install(TARGETS ${LIBRARY_NAME} DESTINATION ${CMAKE_INSTALL_PREFIX}/plugins)
#include "hwe.hpp"
#include "exp.hpp"
#include "range.hpp"
#include "cppmicroservices/BundleActivator.h"
#include "cppmicroservices/BundleContext.h"
#include "cppmicroservices/ServiceProperties.h"
using namespace cppmicroservices;
class US_ABI_LOCAL GeneratorsActivator : public BundleActivator {
public:
GeneratorsActivator() {}
void Start(BundleContext context) {
auto hwe = std::make_shared<xacc::generators::HWE>();
auto expit = std::make_shared<xacc::generators::Exp>();
auto r = std::make_shared<xacc::generators::Range>();
context.RegisterService<xacc::IRGenerator>(hwe);
context.RegisterService<xacc::IRGenerator>(expit);
context.RegisterService<xacc::IRGenerator>(r);
}
void Stop(BundleContext context) {}
};
CPPMICROSERVICES_EXPORT_BUNDLE_ACTIVATOR(GeneratorsActivator)
#include "exp.hpp"
#include "FermionOperator.hpp"
#include "IRProvider.hpp"
#include "ObservableTransform.hpp"
#include "PauliOperator.hpp"
#include "XACC.hpp"
#include "xacc_service.hpp"
#include <memory>
#include <regex>
using namespace xacc;
using namespace xacc::quantum;
namespace xacc {
namespace generators {
bool Exp::validateOptions() {
if (options.count("pauli")) {
return true;
}
if (options.count("fermion")) {
return true;
}
return false;
}
std::shared_ptr<xacc::Function>
Exp::generate(std::map<std::string, xacc::InstructionParameter> &parameters) {
if (!parameters.empty()) {
options = parameters;
}
std::string paramLetter = "t";
if (options.count("param_id")) {
paramLetter = options["param_id"].toString();
}
std::unordered_map<std::string, xacc::quantum::Term> terms;
if (options.count("fermion")) {
auto fermionStr = options["fermion"].toString();
auto op = std::make_shared<FermionOperator>(fermionStr);
terms = std::dynamic_pointer_cast<PauliOperator>(
xacc::getService<ObservableTransform>("jw")->transform(op))
->getTerms();
} else {
auto pauliStr = options["pauli"].toString();
PauliOperator op(pauliStr);
terms = op.getTerms();
}
double pi = 3.1415926;
auto gateRegistry = xacc::getService<IRProvider>("gate");
auto function = gateRegistry->createFunction("temp", {}, {});
for (auto spinInst : terms) {
// Get the individual pauli terms
auto termsMap = std::get<2>(spinInst.second);
std::vector<std::pair<int, std::string>> terms;
for (auto &kv : termsMap) {
if (kv.second != "I" && !kv.second.empty()) {
terms.push_back({kv.first, kv.second});
}
}
if (!terms.empty()) {
// The largest qubit index is on the last term
int largestQbitIdx = terms[terms.size() - 1].first;
for (int i = 0; i < terms.size(); i++) {
auto qbitIdx = terms[i].first;
auto gateName = terms[i].second;
if (i < terms.size() - 1) {
auto cnot = gateRegistry->createInstruction(
"CNOT", std::vector<int>{qbitIdx, terms[i + 1].first});
function->addInstruction(cnot);
}
if (gateName == "X") {
auto hadamard =
gateRegistry->createInstruction("H", std::vector<int>{qbitIdx});
function->insertInstruction(0, hadamard);
} else if (gateName == "Y") {
auto rx =
gateRegistry->createInstruction("Rx", std::vector<int>{qbitIdx});
InstructionParameter p(pi / 2.0);
rx->setParameter(0, p);
function->insertInstruction(0, rx);
}
// Add the Rotation for the last term
if (i == terms.size() - 1) {
// FIXME DONT FORGET DIVIDE BY 2
// std::stringstream ss;
// ss << 2 * std::imag(std::get<0>(spinInst.second)) << " * "
// << std::get<1>(spinInst.second);
auto rz = gateRegistry->createInstruction(
"Rz", std::vector<int>{qbitIdx}, {std::to_string(std::real(spinInst.second.coeff()))+" * " + paramLetter});
// InstructionParameter p(ss.str());
// rz->setParameter(0, p);
function->addInstruction(rz);
}
}
}
int counter = function->nInstructions();
// Add the instruction on the backend of the circuit
for (int i = terms.size() - 1; i >= 0; i--) {
auto qbitIdx = terms[i].first;
auto gateName = terms[i].second;
if (i < terms.size() - 1) {
auto cnot = gateRegistry->createInstruction(
"CNOT", std::vector<int>{qbitIdx, terms[i + 1].first});
function->insertInstruction(counter, cnot);
counter++;
}
if (gateName == "X") {
auto hadamard =
gateRegistry->createInstruction("H", std::vector<int>{qbitIdx});
function->addInstruction(hadamard);
} else if (gateName == "Y") {
auto rx =
gateRegistry->createInstruction("Rx", std::vector<int>{qbitIdx});
InstructionParameter p(-1.0 * (pi / 2.0));
rx->setParameter(0, p);
function->addInstruction(rx);
}
}
}
return function;
} // namespace instructions
} // namespace instructions
} // namespace qcor
\ No newline at end of file
#ifndef XACC_GENERATORS_EXP_HPP_
#define XACC_GENERATORS_EXP_HPP_
#include "IRGenerator.hpp"
namespace xacc {
class AcceleratorBuffer;
class Function;
}
namespace xacc {
namespace generators {
class Exp: public xacc::IRGenerator {
public:
std::shared_ptr<xacc::Function> generate(
std::map<std::string, xacc::InstructionParameter>& parameters) override;
bool validateOptions() override;
const std::string name() const override {
return "exp_i_theta";
}
const std::string description() const override {
return "";
}
};
}
}
#endif
\ No newline at end of file
add_xacc_test(Exp)
target_link_libraries(ExpTester xacc)
\ No newline at end of file
#include "XACC.hpp"
#include <gtest/gtest.h>
using namespace xacc;
TEST(ExpTester, checkSimple) {
// NOW Test it somehow...
auto exp = xacc::getIRGenerator("exp_i_theta");
auto f =
exp->generate({{"pauli","Y0 X1 X2"}});
std::cout << "F:\n" << f->toString() << "\n";
f =
exp->generate({{"pauli","X0 Y1 - X1 Y0"}});
std::cout << "F:\n" << f->toString() << "\n";
}
int main(int argc, char **argv) {
xacc::Initialize(argc, argv);
// xacc::Initialize();
::testing::InitGoogleTest(&argc, argv);
auto ret = RUN_ALL_TESTS();
xacc::Finalize();
return ret;
}
#include "hwe.hpp"
#include "XACC.hpp"
#include "IRProvider.hpp"
#include "xacc_service.hpp"
#include <regex>
using namespace xacc;
namespace xacc {
namespace generators {
bool HWE::validateOptions() {
if (options.count("n-qubits")) {
if (!options["n-qubits"].isNumeric()) {
return false;
}
}
return true;
}
std::shared_ptr<xacc::Function>
HWE::generate(std::map<std::string, xacc::InstructionParameter> &parameters) {
if (!parameters.empty()) {
options = parameters;
}
int nQubits = 0, layers = 1;
std::vector<std::pair<int, int>> connectivity;
try {
nQubits = options["n-qubits"].as<int>();
layers = options.count("layers") ? options["layers"].as<int>() : layers;
if (options.count("coupling")) {
connectivity = options["coupling"].as<std::vector<std::pair<int, int>>>();
} else {
for (int i = 0; i < nQubits - 1; i++) {
connectivity.push_back({i, i + 1});
}
}
} catch (std::exception &e) {
xacc::error("Could not cast HWE parameter to correct type: " +
std::string(e.what()));
}
std::string paramLetter = "t";
if (options.count("param_id")) {
paramLetter = options["param_id"].toString();
}
std::vector<InstructionParameter> fParams;
for (int nP = 0; nP < (2 * nQubits + 3 * nQubits * layers); nP++)
fParams.push_back(InstructionParameter(paramLetter + std::to_string(nP)));
auto provider = xacc::getService<IRProvider>("gate");
auto f = provider->createFunction("hwe", {}, fParams);
int angleCounter = 0;
// Zeroth layer, start with X and Z rotations
for (int q = 0; q < nQubits; q++) {
auto rx = provider->createInstruction(
"Rx", {q},
{InstructionParameter(paramLetter + std::to_string(angleCounter))});
auto rz = provider->createInstruction(
"Rz", {q},
{InstructionParameter(paramLetter + std::to_string(angleCounter + 1))});
f->addInstruction(rx);
f->addInstruction(rz);
angleCounter += 2;
}
for (int d = 0; d < layers; d++) {
for (auto &p : connectivity) {
auto cnot = provider->createInstruction("CNOT", {p.first, p.second});
f->addInstruction(cnot);
}
for (int q = 0; q < nQubits; q++) {
auto rz1 = provider->createInstruction(
"Rz", {q},