Commit 8643e116 authored by Mccaskey, Alex's avatar Mccaskey, Alex
Browse files

Adding initial ability to allocate qubit registries tied to language source code / compiler

parent a6fff090
......@@ -28,5 +28,6 @@
# Initial API and implementation - Alex McCaskey
#
#**********************************************************************************/
include_directories(${CMAKE_SOURCE_DIR}/quantum/gate)
add_executable(teleport_scaffold teleport_scaffold.cpp)
target_link_libraries(teleport_scaffold xacc-scaffold ${Boost_LIBRARIES})
\ No newline at end of file
......@@ -29,6 +29,7 @@
*
**********************************************************************************/
#include "Program.hpp"
#include "Qubits.hpp"
/**
* FIXME For now, create a fake accelerator
......@@ -43,36 +44,58 @@ public:
std::vector<xacc::IRTransformation> v;
return v;
}
virtual void execute(const std::shared_ptr<xacc::IR> ir) {
}
virtual ~IBM5Qubit() {
}
protected:
bool canAllocate(const int N) {
return true;
}
};
// Quantum Kernel executing teleportation of
// qubit state to another.
const std::string src("__qpu__ teleport () {\n"
" qbit q[3];\n"
" cbit c[2];\n"
" H(q[1]);\n"
" CNOT(q[1],q[2]);\n"
" CNOT(q[0],q[1]);\n"
" H(q[0]);\n"
" MeasZ(q[0]);\n"
" MeasZ(q[1]);\n"
" // Initialize qubit to 1\n"
" X(qreg[0]);\n"
" H(qreg[1]);\n"
" CNOT(qreg[1],qreg[2]);\n"
" CNOT(qreg[0],qreg[1]);\n"
" H(qreg[0]);\n"
" MeasZ(qreg[0]);\n"
" MeasZ(qreg[1]);\n"
" // cZ\n"
" H(q[2]);\n"
" CNOT(q[2], q[1]);\n"
" H(q[2]);\n"
" H(qreg[2]);\n"
" CNOT(qreg[2], qreg[1]);\n"
" H(qreg[2]);\n"
" // cX = CNOT\n"
" CNOT(q[2], q[0]);\n"
" CNOT(qreg[2], qreg[0]);\n"
"}\n");
int main (int argc, char** argv) {
// Create a reference to the IBM5Qubit Accelerator
auto ibm_qpu = std::make_shared<IBM5Qubit>();
// Allocate some qubits...
auto qreg = ibm_qpu->allocate<xacc::quantum::Qubits<3>>("qreg");
// Construct a new Program
xacc::Program quantumProgram(ibm_qpu, src);
// Build the program
quantumProgram.build("--compiler scaffold --writeIR teleport.xir");
// FIXME Get Kernel, execute, get result
// Retrieve the constructed kernel
auto teleport = quantumProgram.getKernel("teleport");
// Execute the kernel!
teleport();
// Get the execution result
auto bits = qreg.toBits();
return 0;
}
......
......@@ -30,3 +30,8 @@
#**********************************************************************************/
add_subdirectory(scaffold)
add_subdirectory(utils)
# Gather tests
file (GLOB test_files tests/*.cpp)
add_tests("${test_files}" "${CMAKE_CURRENT_SOURCE_DIR}/utils;${CMAKE_CURRENT_SOURCE_DIR}" "${Boost_LIBRARIES}")
#ifndef QUANTUM_GATE_QUBITS_HPP_
#define QUANTUM_GATE_QUBITS_HPP_
#include "Accelerator.hpp"
#include <complex>
namespace xacc {
namespace quantum {
using QubitState = std::vector<std::complex<double>>;
/**
*
*/
template<const int NumberOfQubits>
class Qubits: public AcceleratorBits<NumberOfQubits> {
QubitState state;
public:
QubitState& getState() {
return state;
}
};
}
}
#endif
......@@ -35,6 +35,8 @@ set (LIBRARY_NAME xacc-scaffold)
file (GLOB HEADERS *.hpp)
file (GLOB SRC *.cpp)
include_directories(${CMAKE_SOURCE_DIR}/quantum/gate)
add_library(${LIBRARY_NAME} SHARED ${SRC})
install(FILES ${HEADERS} DESTINATION include)
......
......@@ -73,7 +73,7 @@ public:
// Execute the scaffold compiler
std::system("scaffcc -fp .tmpSrcFile.scaffold");
// Remove the temporary source file, we don't need it anymroe
// Remove the temporary source file, we don't need it anymore
std::remove(".tmpSrcFile.scaffold");
// Read in the generated QASM
......
......@@ -40,6 +40,26 @@ namespace quantum {
void ScaffoldCompiler::modifySource() {
// Execute default QuantumCompiler method
auto qubitTypeStr = std::string("qbit");
auto nBits = this->hardware->getAllocationSize();
auto varName = this->hardware->getVariableName();
std::cout << "HELLO WORLD: " << nBits << ", " << varName << "\n";
std::string qubitAllocationSrc = qubitTypeStr + " " + varName + "["
+ std::to_string(nBits) + "];\n";
std::vector<std::string> srcLines;
boost::split(srcLines, this->kernelSource, boost::is_any_of("\n"));
// First line should be function __qpu__ call, next one
// is where we should put the qubit allocation src
srcLines.insert(srcLines.begin() + 1, qubitAllocationSrc);
// Merge all into new kernel source string
std::stringstream combine;
std::for_each(srcLines.begin(), srcLines.end(), [&](const std::string& elem) { combine << elem << "\n"; });
this->kernelSource = combine.str();
// Here we assume we've been given just
// the body of the quantum code, as part
// of an xacc __qpu__ kernel function.
......
......@@ -41,19 +41,49 @@
using namespace qci::common;
using namespace xacc::quantum;
template<const int n>
class FakeAccelerator: public xacc::Accelerator {
public:
virtual int getAllocationSize() {
return n;
}
virtual const std::string getVariableName() {
return "qreg";
}
virtual AcceleratorType getType() {
return AcceleratorType::qpu_gate;
}
virtual std::vector<xacc::IRTransformation> getIRTransformations() {
std::vector<xacc::IRTransformation> v;
return v;
}
virtual void execute(const std::shared_ptr<xacc::IR> ir) {
}
virtual ~FakeAccelerator() {
}
protected:
bool canAllocate(const int N) {
return true;
}
};
BOOST_AUTO_TEST_CASE(checkSimpleCompile) {
using GraphType = Graph<CircuitNode>;
auto accelerator = std::make_shared<FakeAccelerator<2>>();
auto compiler = qci::common::AbstractFactory::createAndCast<xacc::ICompiler>("compiler", "scaffold");
BOOST_VERIFY(compiler);
const std::string src("__qpu__ eprCreation () {\n"
" qbit qs[2];\n"
" H(qs[0]);\n"
" CNOT(qs[0],qs[1]);\n"
// " qbit qs[2];\n"
" H(qreg[0]);\n"
" CNOT(qreg[0],qreg[1]);\n"
"}\n");
auto ir = compiler->compile(src);
auto ir = compiler->compile(src, accelerator);
BOOST_VERIFY(ir);
auto graphir = std::dynamic_pointer_cast<xacc::GraphIR<GraphType>>(ir);
BOOST_VERIFY(graphir);
......@@ -71,28 +101,30 @@ BOOST_AUTO_TEST_CASE(checkSimpleCompile) {
BOOST_AUTO_TEST_CASE(checkAnotherSimpleCompile) {
using GraphType = Graph<CircuitNode>;
auto accelerator = std::make_shared<FakeAccelerator<3>>();
auto compiler = qci::common::AbstractFactory::createAndCast<xacc::ICompiler>("compiler", "scaffold");
auto compiler =
qci::common::AbstractFactory::createAndCast<xacc::ICompiler>(
"compiler", "scaffold");
BOOST_VERIFY(compiler);
const std::string src("__qpu__ teleport () {\n"
" qbit q[3];\n"
" cbit c[2];\n"
" H(q[1]);\n"
" CNOT(q[1],q[2]);\n"
" CNOT(q[0],q[1]);\n"
" H(q[0]);\n"
" MeasZ(q[0]);\n"
" MeasZ(q[1]);\n"
// " qbit q[3];\n"
" H(qreg[1]);\n"
" CNOT(qreg[1],qreg[2]);\n"
" CNOT(qreg[0],qreg[1]);\n"
" H(qreg[0]);\n"
" MeasZ(qreg[0]);\n"
" MeasZ(qreg[1]);\n"
" // Cz\n"
" H(q[2]);\n"
" CNOT(q[2], q[1]);\n"
" H(q[2]);\n"
" H(qreg[2]);\n"
" CNOT(qreg[2], qreg[1]);\n"
" H(qreg[2]);\n"
" // CX = CNOT\n"
" CNOT(q[2], q[0]);\n"
" CNOT(qreg[2], qreg[0]);\n"
"}\n");
auto ir = compiler->compile(src);
auto ir = compiler->compile(src, accelerator);
BOOST_VERIFY(ir);
auto graphir = std::dynamic_pointer_cast<xacc::GraphIR<GraphType>>(ir);
BOOST_VERIFY(graphir);
......
/***********************************************************************************
* 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
*
**********************************************************************************/
#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE ScaffoldCompilerTester
#include <boost/test/included/unit_test.hpp>
#include "QasmToGraph.hpp"
BOOST_AUTO_TEST_CASE(checkConversion) {
const std::string qasm =
"qubit qreg0\nqubit qreg1\nqubit qreg2\nH qreg1\nCNOT qreg1,qreg2\nCNOT qreg0,qreg1\nH qreg0\nMeasZ qreg0\nMeasZ qreg1\nH qreg2\nCNOT qreg2,qreg1\nH qreg2\nCNOT qreg2,qreg0";
auto graph = xacc::quantum::QasmToGraph::getCircuitGraph(qasm);
// FIXME Need to create a graph to check against
}
/***********************************************************************************
* 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
*
**********************************************************************************/
#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE QubitsTester
#include <boost/test/included/unit_test.hpp>
#include "Qubits.hpp"
using namespace qci::common;
using namespace xacc::quantum;
BOOST_AUTO_TEST_CASE(checkConstruction) {
Qubits<3> qubits;
BOOST_VERIFY(qubits.N == 3);
std::bitset<3> bits;
BOOST_VERIFY(bits == qubits.toBits());
}
......@@ -33,9 +33,25 @@
#include <string>
#include "IRTransformation.hpp"
#include <array>
#include <bitset>
namespace xacc {
template<const int Number>
class AcceleratorBits {
public:
static constexpr int N = Number;
std::bitset<(size_t)Number> bits;
std::bitset<(size_t)Number> toBits() {
return bits;
}
};
/**
*
*/
class Accelerator {
public:
......@@ -45,12 +61,41 @@ public:
virtual std::vector<IRTransformation> getIRTransformations() = 0;
template<typename T>
T executeKernel(std::string accArgs) {
virtual void execute(const std::shared_ptr<IR> ir) = 0;
/**
*
* @return
*/
template<typename BitsType>
BitsType allocate(const std::string& variableNameId) {
static_assert(std::is_base_of<AcceleratorBits<BitsType::N>, BitsType>::value, "");
if (!canAllocate(BitsType::N)) {
QCIError("Error in allocated requested bits");
}
BitsType bits;
NBitsAllocated = BitsType::N;
bitVarId = variableNameId;
return bits;
}
virtual int getAllocationSize() {
return NBitsAllocated;
}
virtual const std::string getVariableName() {
return bitVarId;
}
virtual ~Accelerator() {}
protected:
int NBitsAllocated = 0;
std::string bitVarId;
virtual bool canAllocate(const int NBits) = 0;
};
}
#endif
......@@ -36,6 +36,8 @@
#include "AbstractFactory.hpp"
#include "QCIError.hpp"
#include "IR.hpp"
#include "Accelerator.hpp"
#include <ostream>
using namespace qci::common;
......@@ -55,7 +57,8 @@ public:
* @param src
* @return
*/
virtual std::shared_ptr<IR> compile(const std::string& src) = 0;
virtual std::shared_ptr<IR> compile(const std::string& src,
const std::shared_ptr<Accelerator>& accelerator) = 0;
};
/**
......@@ -80,12 +83,15 @@ public:
* @param src The kernel source string.
* @return ir Intermediate representation for provided source kernel code.
*/
virtual std::shared_ptr<IR> compile(const std::string& src) {
virtual std::shared_ptr<IR> compile(const std::string& src,
const std::shared_ptr<Accelerator>& acc) {
// Set the provided kernel source string
// so derived types can have reference to it
kernelSource = src;
hardware = acc;
// Xacc requires that clients provide
// only the body code for an attached
// accelerator... Some language compilers
......@@ -100,9 +106,17 @@ public:
protected:
protected:
/**
*
*/
std::string kernelSource;
std::shared_ptr<Accelerator> hardware;
/**
*
* Derived types implementing compile should perform language
* specific compilation and return a shared pointer to an
* intermediate representation IR instance.
......
......@@ -80,6 +80,8 @@ protected:
*/
std::shared_ptr<options_description> compilerOptions;
std::shared_ptr<IR> xaccIR;
public:
/**
......@@ -131,10 +133,10 @@ public:
}
// Execute the compilation
auto ir = compiler->compile(src);
auto xaccIR = compiler->compile(src, accelerator);
// Validate the compilation
if (!ir) {
if (!xaccIR) {
QCIError("Bad source string or something.\n");
}
......@@ -142,7 +144,7 @@ public:
if (compileParameters.count("writeIR")) {
auto fileStr = compileParameters["writeIR"].as<std::string>();
std::ofstream ostr(fileStr);
ir->persist(ostr);
xaccIR->persist(ostr);
}
// Execute IR Translations and Optimizations
......@@ -151,18 +153,30 @@ public:
auto defaultTransforms = getAcceleratorIndependentTransformations(acceleratorType);
auto accDepTransforms = accelerator->getIRTransformations();
for (IRTransformation& t : defaultTransforms) {
t.transform(*ir.get());
t.transform(*xaccIR.get());
}
for (IRTransformation& t : accDepTransforms) {
t.transform(*ir.get());
t.transform(*xaccIR.get());
}
// FIXME Create Kernel from IR
return;
}
void getKernel(std::string& name) {}
/**
*
* @param name
* @param args
* @return
*/
template<typename ... RuntimeArgs>
std::function<void(RuntimeArgs...)> getKernel(const std::string& name,
RuntimeArgs ... args) {
return [&]() {
std::cout << "HELLO WORLD FROM KERNEL\n";
accelerator->execute(xaccIR, args...);
return;
};
}
};
}
......
......@@ -79,7 +79,7 @@ BOOST_AUTO_TEST_CASE(checkCompile) {
"}");
auto compiler = std::shared_ptr<ICompiler>(new FakeCompiler());
auto ir = compiler->compile(src);
BOOST_VERIFY(ir);
// auto ir = compiler->compile(src);
// BOOST_VERIFY(ir);
}
......@@ -43,9 +43,11 @@ public:
virtual AcceleratorType getType() { return qpu_gate; }
virtual std::vector<IRTransformation> getIRTransformations() {std::vector<IRTransformation> v; return v;}
virtual void execute(const std::shared_ptr<IR> ir) {}
virtual bool canAllocate(const int NBits) {
return true;
}
virtual ~FakeAccelerator() {}
};
class FakeIR: public IR {
......
Supports Markdown
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