Commit 786bf023 authored by Mccaskey, Alex's avatar Mccaskey, Alex
Browse files

First pass at xacc-py compiler that enables @qpu decorated python quantum kernels



Signed-off-by: Mccaskey, Alex's avatarAlex McCaskey <mccaskeyaj@ornl.gov>
parent 5ef053ec
......@@ -97,18 +97,18 @@ include_directories(${CPR_INCLUDE_DIRS})
include_directories(${CMAKE_SOURCE_DIR}/tpls/spdlog)
include_directories(${CMAKE_SOURCE_DIR}/tpls/eigen)
add_subdirectory(xacc)
add_subdirectory(quantum)
if(PYTHON_INCLUDE_DIR)
add_subdirectory(python)
endif()
set(XACC_HAS_ANTLR FALSE)
if(TARGET antlr4_shared)
message (STATUS "XACC Building with Antlr4 support")
set(XACC_HAS_ANTLR TRUE)
endif()
add_subdirectory(xacc)
add_subdirectory(quantum)
if(PYTHON_INCLUDE_DIR)
add_subdirectory(python)
endif()
# Install the config file for external projects to use
# This is cool, users just add find_package(XACC REQUIRED) to
# their CMake builds, and pass -DXACC_DIR=/path/to/install/xacc
......
......@@ -50,3 +50,7 @@ endif()
install(TARGETS _pyxacc DESTINATION ${CMAKE_INSTALL_PREFIX})
install(FILES pyxacc.py DESTINATION ${CMAKE_INSTALL_PREFIX})
if (${XACC_HAS_ANTLR})
add_subdirectory(compiler)
endif()
\ No newline at end of file
#***********************************************************************************
# Copyright (c) 2016, 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
#
#**********************************************************************************/
set (PACKAGE_NAME "PYXACC Compiler")
set (PACKAGE_DESCIPTION "PYXACC Compiler Bundle")
set (LIBRARY_NAME xacc-py-compiler)
file (GLOB_RECURSE HEADERS *.hpp generated/*.hpp)
file (GLOB SRC *.cpp generated/*.cpp)
include_directories(${CMAKE_BINARY_DIR}/tpls/cppmicroservices/framework/include)
include_directories(${CMAKE_BINARY_DIR}/tpls/cppmicroservices/include)
include_directories(${CMAKE_SOURCE_DIR}/tpls/antlr/runtime/src)
include_directories(${CMAKE_SOURCE_DIR}/tpls/cppmicroservices/framework/include)
include_directories(generated)
include_directories(${CMAKE_SOURCE_DIR}/tpls/boost-cmake/boost/boost_1_64_0)
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
link_directories(${CMAKE_SOURCE_DIR}/dist)
# Set up dependencies to resources to track changes
usFunctionGetResourceSource(TARGET ${LIBRARY_NAME} OUT SRC)
# Generate bundle initialization code
usFunctionGenerateBundleInit(TARGET ${LIBRARY_NAME} OUT SRC)
add_library(${LIBRARY_NAME} SHARED ${SRC})
set(_bundle_name xacc_py_compiler)
set_target_properties(${LIBRARY_NAME} PROPERTIES
# This is required for every bundle
COMPILE_DEFINITIONS US_BUNDLE_NAME=${_bundle_name}
# This is for convenience, used by other CMake functions
US_BUNDLE_NAME ${_bundle_name}
)
# Embed meta-data from a manifest.json file
usFunctionEmbedResources(TARGET ${LIBRARY_NAME}
WORKING_DIRECTORY
${CMAKE_CURRENT_SOURCE_DIR}
FILES
manifest.json
)
target_link_libraries(${LIBRARY_NAME} PUBLIC xacc xacc-quantum-gate xacc-quantum-aqc antlr4-runtime)
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()
install(TARGETS ${LIBRARY_NAME} DESTINATION ${CMAKE_INSTALL_PREFIX}/plugins)
if (${XACC_BUILD_TESTS})
include_directories(${GTEST_INCLUDE_DIRS})
add_subdirectory(tests)
endif()
\ No newline at end of file
/*******************************************************************************
* Copyright (c) 2018 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 "PyXACCCompiler.hpp"
#include "PyXACCListener.hpp"
#include "PyXACCIRLexer.h"
#include "GateIR.hpp"
using namespace antlr4;
using namespace pyxacc;
namespace xacc {
namespace quantum {
std::shared_ptr<IR> PyXACCCompiler::compile(const std::string& src,
std::shared_ptr<Accelerator> acc) {
ANTLRInputStream input(src);
PyXACCIRLexer lexer(&input);
CommonTokenStream tokens(&lexer);
PyXACCIRParser parser(&tokens);
parser.removeErrorListeners();
parser.addErrorListener(new PyXACCErrorListener());
tree::ParseTree *tree = parser.xaccsrc();
PyXACCListener listener;//fName, params);
tree::ParseTreeWalker::DEFAULT.walk(&listener, tree);
// Create and return the IR
auto ir = std::make_shared<GateIR>();
ir->addKernel(listener.getKernel());
return ir;
}
std::shared_ptr<IR> PyXACCCompiler::compile(const std::string& src) {
return compile(src, nullptr);
}
}
}
/*******************************************************************************
* Copyright (c) 2018 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 PYTHON_PYXACCCOMPILER_HPP_
#define PYTHON_PYXACCCOMPILER_HPP_
#include "XACC.hpp"
#include "antlr4-runtime.h"
namespace xacc {
namespace quantum {
class PyXACCErrorListener : public antlr4::BaseErrorListener {
public:
void syntaxError(antlr4::Recognizer *recognizer, antlr4::Token * offendingSymbol, size_t line, size_t charPositionInLine, const std::string &msg, std::exception_ptr e) override {
std::ostringstream output;
output << "Invalid PyXACC source: ";
output << "line " << line << ":" << charPositionInLine << " " << msg;
xacc::error(output.str());
}
};
/**
* The DWQMICompiler is an XACC Compiler that compiles
* D-Wave quantum machine instructions to produce an
* appropriate Ising form for execution on the D-Wave QPU.
*
* This compilation leverages XACC EmbeddingAlgorithms to
* compute the minor graph embedding represented by the
* input source kernel code to output the embedded Ising
* graph for D-Wave execution.
*/
class PyXACCCompiler: public xacc::Compiler {
public:
/**
* The Compiler.
*/
PyXACCCompiler() {}
/**
* Compile the given kernel code for the
* given D-Wave Accelerator.
*
* @param src The QMI source code
* @param acc Reference to the D-Wave Accelerator
* @return
*/
virtual std::shared_ptr<xacc::IR> compile(const std::string& src,
std::shared_ptr<Accelerator> acc);
/**
* This method is not implemented - we must always have
* D-Wave Accelerator connectivity information for compilation.
*
* @return
*/
virtual std::shared_ptr<xacc::IR> compile(const std::string& src);
/**
* Return the command line options for this compiler
*
* @return options Description of command line options.
*/
virtual std::shared_ptr<options_description> getOptions() {
auto desc = std::make_shared<options_description>(
"PyXACC Compiler Options");
return desc;
}
virtual bool handleOptions(variables_map& map) {
return false;
}
/**
* We don't allow translations for the DW Compiler.
* @param bufferVariable
* @param function
* @return
*/
virtual const std::string translate(const std::string& bufferVariable,
std::shared_ptr<Function> function) {
xacc::error("PyXACCCompiler::translate - Method not implemented");
};
virtual const std::string name() const {
return "xacc-py";
}
virtual const std::string description() const {
return "";
}
/**
* The destructor
*/
virtual ~PyXACCCompiler() {}
};
}
}
#endif
/*******************************************************************************
* Copyright (c) 2018 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 "PyXACCCompiler.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 PyXACCCompilerActivator: public BundleActivator {
public:
PyXACCCompilerActivator() {
}
/**
*/
void Start(BundleContext context) {
auto c = std::make_shared<xacc::quantum::PyXACCCompiler>();
context.RegisterService<xacc::Compiler>(c);
context.RegisterService<xacc::OptionsProvider>(c);
}
/**
*/
void Stop(BundleContext /*context*/) {
}
};
}
CPPMICROSERVICES_EXPORT_BUNDLE_ACTIVATOR(PyXACCCompilerActivator)
/*
* 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.
*
* Originally devloped by:
* Travis Humble, Oak Ridge National Laboratory, March 2017
*
* Updated by:
* H. Charles Zhao, Oak Ridge National Laboratory, July 2018
*
* An ANTLR4 specification for Version 2.0 of the IBM Open QASM Grammar
* See https://github.com/IBM/qiskit-openqasm for the written spec
*
*/
grammar PyXACCIR;
/* This part of the grammar is particular to XACC */
/**********************************************************************/
xaccsrc
: xacckernel*
;
xacckernel
: 'def' kernelname=id '(' ( ','? param )* ')' ':' mainprog
;
/***********************************************************************/
/* The main program */
mainprog
: program
;
/* The actual program statements */
program
: (line)+
;
line
: statement+
| comment
;
/* A program statement */
statement
: uop
| 'return'
;
/* A program comment */
comment
: COMMENT
;
/* A list of parameters */
paramlist
: param (',' paramlist)?
;
/* A parameter */
param
: id
;
/* A quantum operation */
/* FIXME: Spec calls for 'reset' keyword but this clashes with antlr parser.reset()
* we use 'reeset' instead..ha-ha, I know, right?
*/
/* A unitary operation */
uop
: gatename=gate '(' ( explist ) ')'
;
gate
: 'X'
| 'Rx'
| 'Rz'
| 'Ry'
| 'Y'
| 'Z'
| 'CNOT'
| 'Cz'
| 'H'
| 'Swap'
| 'Identity'
| 'CPhase'
| 'Measure'
;
/* A list of expressions */
explist
: exp ( ',' exp )*
;
/* An expression */
exp
: real
| INT
| 'pi'
| id
| exp '+' exp
| exp '-' exp
| exp '*' exp
| exp '/' exp
| '-'exp
| exp '^' exp
| '(' exp ')'
| unaryop '(' exp ')'
;
/* unary operations */
unaryop
: 'sin'
| 'cos'
| 'tan'
| 'exp'
| 'ln'
| 'sqrt'
;
/* variable identity */
id
: ID
;
/* real numbers */
real
: REAL
;
/* strings are enclosed in quotes */
string
: STRING
;
/* Tokens for the grammer */
/* Comment */
COMMENT
: '#' ~ [\r\n]* EOL
;
/* id, ego, and super-ego */
ID
: [a-z][A-Za-z0-9_]*
;
/* Keep it real...numbers */
REAL
: INT ( '.' (INT)? )
;
/* Non-negative integers */
INT
: ('0'..'9')+
;
/* Strings include numbers and slashes */
STRING
: '"' ~ ["]* '"'
;
/* Whitespaces, we skip'em */
WS
: [ \t\r\n] -> skip
;
/* This is the end of the line, boys */
EOL
: '\r'? '\n'
;
/*******************************************************************************
* Copyright (c) 2018 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 <iostream>
#include <IRProvider.hpp>
#include "PyXACCListener.hpp"
#include "XACC.hpp"
#include "GateFunction.hpp"
using namespace pyxacc;
namespace xacc {
namespace quantum {
PyXACCListener::PyXACCListener() {
provider = xacc::getService<IRProvider>("gate");
}
std::shared_ptr<Function> PyXACCListener::getKernel() {
return f;
}
void PyXACCListener::enterXacckernel(PyXACCIRParser::XacckernelContext * ctx) {
std::vector<InstructionParameter> params;
for (int i = 0; i < ctx->param().size(); i++) {
params.push_back(InstructionParameter(ctx->param(static_cast<size_t>(i))->getText()));
}
f = provider->createFunction(ctx->kernelname->getText(), {}, params);
}
void PyXACCListener::enterUop(PyXACCIRParser::UopContext * ctx) {
auto is_double = [](const std::string& s) -> bool
{
try {
std::stod(s);
} catch(std::exception& e) {
return false;
}
return true;
};
auto gateName = ctx->gatename->getText();
if (ctx->explist()->exp().size() > 0) {
auto paramStr = ctx->explist()->exp(0);
std::vector<int> qubits;
std::vector<InstructionParameter> params;
for (int i = 0; i < ctx->explist()->exp().size(); i++) {
if (i == 0 && (ctx->explist()->exp(i)->real() != nullptr ||
ctx->explist()->exp(i)->id() != nullptr)) {
// we have a parameter for a parameterized gate
auto str = ctx->explist()->exp(i)->getText();
auto param = is_double(str) ? InstructionParameter(std::stod(str)) : InstructionParameter(str);
params.push_back(param);
} else {
qubits.push_back(std::stoi(ctx->explist()->exp(i)->INT()->getText()));
}
}
std::shared_ptr<Instruction> gate;
if (gateName == "Measure") {
std::vector<int> measurebit {qubits[0]};
InstructionParameter p1(qubits[1]);
gate = provider->createInstruction("Measure", measurebit);
gate->setParameter(0, p1);
} else {
gate = provider->createInstruction(gateName, qubits);
int count = 0;
for (auto p : params) {
gate->setParameter(count, p);
count++;
}