Commit 9482aff0 authored by Mccaskey, Alex's avatar Mccaskey, Alex
Browse files

cleaned up the instruction/function ir infrastructure

parent 68841bac
......@@ -31,6 +31,7 @@
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/utils)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/gateqir)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/gateqir/instructions)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/gateqir/functions)
add_subdirectory(gateqir)
add_subdirectory(compilers)
......
......@@ -26,7 +26,7 @@ bool ScaffoldASTConsumer::VisitDecl(Decl *d) {
}
} else if (isa<FunctionDecl>(d)) {
auto c = cast<FunctionDecl>(d);
function = std::make_shared<xacc::quantum::GateFunction>(0,
function = std::make_shared<xacc::quantum::GateFunction>(
c->getDeclName().getAsString());
}
return true;
......@@ -51,12 +51,14 @@ bool ScaffoldASTConsumer::VisitStmt(Stmt *s) {
std::string str;
llvm::raw_string_ostream s(str);
LHS->printPretty(s, nullptr, policy);
std::cout << "LHS IF: " << s.str() << "\n";
if (boost::contains(s.str(), cbitVarName)) {
auto RHS = binOp->getRHS();
std::string rhsstr;
llvm::raw_string_ostream rhss(rhsstr);
RHS->printPretty(rhss, nullptr, policy);
std::cout << "RHS IF: " << rhss.str() << "\n";
auto thenCode = ifStmt->getThen();
std::string thenStr;
......@@ -70,6 +72,14 @@ bool ScaffoldASTConsumer::VisitStmt(Stmt *s) {
boost::replace_all(then, "}\n", "");
boost::replace_all(then, " ", "");
boost::trim(then);
int conditionalQubit = cbitRegToMeasuredQubit[s.str()];
currentConditional = std::make_shared<xacc::quantum::ConditionalFunction>(conditionalQubit);
std::vector<std::string> vec;
boost::split(vec, then, boost::is_any_of("\n"));
nCallExprToSkip = vec.size();
std::cout << "NCALLEXPRTOSKIP = " << nCallExprToSkip << "\n";
}
}
}
......@@ -113,27 +123,39 @@ bool ScaffoldASTConsumer::VisitCallExpr(CallExpr* c) {
if (isParameterizedInst) {
if (params.size() == 1) {
inst = xacc::quantum::ParameterizedGateInstructionRegistry<
double>::instance()->create(gateName, currentInstId,
currentInstLayer, qubits, params[0]);
double>::instance()->create(gateName, qubits,
params[0]);
} else if (params.size() == 2) {
inst = xacc::quantum::ParameterizedGateInstructionRegistry<
double, double>::instance()->create(gateName,
currentInstId, currentInstLayer, qubits, params[0],
params[1]);
double, double>::instance()->create(gateName, qubits,
params[0], params[1]);
} else {
XACCError(
"Can only handle 1 and 2 parameter gates... and only doubles... for now.");
}
std::cout << "CREATED A " << gateName << " gate\n";
std::cout << "CREATED A " << gateName << " parameterized gate\n";
} else if (gateName != "MeasZ") {
inst = xacc::quantum::GateInstructionRegistry::instance()->create(
gateName, currentInstId, currentInstLayer, qubits);
gateName, qubits);
std::cout << "CREATED A " << gateName << " gate\n";
}
if (gateName != "MeasZ") function->addInstruction(inst);
if (gateName != "MeasZ") {
if (nCallExprToSkip == 0) {
function->addInstruction(inst);
} else {
std::cout << "Adding Conditional Inst: " << gateName << "\n";
currentConditional->addConditionalInstruction(inst);
nCallExprToSkip--;
if (nCallExprToSkip == 0) {
function->addInstruction(currentConditional);
}
}
}
}
return true;
......@@ -161,23 +183,26 @@ bool ScaffoldASTConsumer::VisitBinaryOperator(BinaryOperator * b) {
std::cout << "HELLO BINOP LHS: " << lhsString << "\n";
boost::replace_all(lhsString, cbitVarName, "");
boost::replace_all(lhsString, "[","");
boost::replace_all(lhsString, "[", "");
boost::replace_all(lhsString, "]", "");
boost::replace_all(rhsString, "MeasZ", "");
boost::replace_all(rhsString, "(","");
boost::replace_all(rhsString, "(", "");
boost::replace_all(rhsString, ")", "");
boost::replace_all(rhsString, qbitVarName, "");
boost::replace_all(rhsString, "[","");
boost::replace_all(rhsString, "[", "");
boost::replace_all(rhsString, "]", "");
// lhsString now just contains the classical index bit
auto inst =
xacc::quantum::ParameterizedGateInstructionRegistry<int>::instance()->create(
"Measure", currentInstId, currentInstLayer,
"Measure",
std::vector<int> { std::stoi(rhsString) },
std::stoi(lhsString));
cbitRegToMeasuredQubit.insert(std::make_pair(lhsString, std::stoi(rhsString)));
std::cout << "ADDING A MEASUREMENT GATE " << lhsString << "\n";
function->addInstruction(inst);
}
......
......@@ -36,6 +36,7 @@
//#include "GateQIR.hpp"
//
#include "GateFunction.hpp"
#include "ConditionalFunction.hpp"
using namespace clang;
......@@ -65,11 +66,13 @@ protected:
std::string cbitVarName;
std::string qbitVarName;
int currentInstId = 0;
int currentInstLayer = 0;
std::shared_ptr<xacc::quantum::GateFunction> function;
std::shared_ptr<xacc::quantum::ConditionalFunction> currentConditional;
int nCallExprToSkip = 0;
std::map<std::string, int> cbitRegToMeasuredQubit;
};
}
......
......@@ -101,6 +101,7 @@ BOOST_AUTO_TEST_CASE(checkWithRzParameterized) {
BOOST_AUTO_TEST_CASE(checkWithMeasurementIf) {
std::cout <<" CHECKING WITH MEASUREMNT IF\n";
const std::string src("module teleport (qbit qreg[3]) {\n"
" cbit creg[2];\n"
" // Init qubit 0 to 1\n"
......@@ -113,7 +114,7 @@ BOOST_AUTO_TEST_CASE(checkWithMeasurementIf) {
" creg[0] = MeasZ(qreg[0]);\n"
" creg[1] = MeasZ(qreg[1]);\n"
" if (creg[0] == 1) Z(qreg[2]);\n"
// " if (creg[1] == 1) X(qreg[2]);\n"
" if (creg[1] == 1) X(qreg[2]);\n"
"}\n");
auto qir = compiler->compile(src);
......@@ -124,6 +125,8 @@ BOOST_AUTO_TEST_CASE(checkWithMeasurementIf) {
auto k = gateqir->getKernel("teleport");
std::cout << "STR: \n\n" << k->toString("qreg") << "\n";
}
BOOST_AUTO_TEST_SUITE_END()
......@@ -32,8 +32,8 @@ set (PACKAGE_NAME "XACC Quantum Gate IR Runtime")
set (PACKAGE_DESCIPTION "XACC Quantum Gate Model Intermediate Representation")
set (LIBRARY_NAME xacc-gateqir)
file (GLOB HEADERS *.hpp)
file (GLOB SRC *.cpp instructions/*.cpp)
file (GLOB_RECURSE HEADERS *.hpp)
file (GLOB SRC *.cpp instructions/*.cpp functions/*.cpp)
add_library(${LIBRARY_NAME} SHARED ${SRC})
......@@ -42,5 +42,5 @@ install(TARGETS ${LIBRARY_NAME} DESTINATION lib)
# Gather tests
file (GLOB test_files tests/*.cpp)
add_tests("${test_files}" "${CMAKE_CURRENT_SOURCE_DIR};${CMAKE_CURRENT_SOURCE_DIR}/instructions" "${LIBRARY_NAME};${Boost_LIBRARIES};xacc-gateqir")
add_tests("${test_files}" "${CMAKE_CURRENT_SOURCE_DIR};${CMAKE_CURRENT_SOURCE_DIR}/instructions;${CMAKE_CURRENT_SOURCE_DIR}/functions" "${LIBRARY_NAME};${Boost_LIBRARIES};xacc-gateqir")
......@@ -31,8 +31,8 @@
#ifndef QUANTUM_GATEQIR_QFUNCTION_HPP_
#define QUANTUM_GATEQIR_QFUNCTION_HPP_
#include "QFunction.hpp"
#include "GateInstruction.hpp"
#include "Function.hpp"
#include "XACCError.hpp"
namespace xacc {
namespace quantum {
......@@ -42,45 +42,46 @@ namespace quantum {
* quantum computing. It is composed of QInstructions that
* are themselves derivations of the GateInstruction class.
*/
class GateFunction: public virtual QFunction {
class GateFunction: public virtual Function {
protected:
/**
* The list of QInstructions that this GateFunction
* contains.
*/
std::vector<std::shared_ptr<QInstruction>> instructions;
/**
* The name of this function
*/
std::string functionName;
/**
* The unique id integer for this function
*/
int functionId;
/**
* The list of qubits this function acts on.
*/
std::vector<int> qbits;
std::list<InstPtr> instructions;
public:
/**
* The nullary constructor.
*/
GateFunction();
/**
* The constructor, takes the function unique id and its name.
*
* @param id
* @param name
*/
GateFunction(int id, const std::string name);
GateFunction(const std::string& name) : functionName(name) {}
virtual const int nInstructions() {
return instructions.size();
}
virtual InstPtr getInstruction(const int idx) {
if (instructions.size() > idx) {
return *std::next(instructions.begin(), idx);
} else {
XACCError("Invalid instruction index.");
}
}
virtual std::list<InstPtr> getInstructions() {
return instructions;
}
virtual void removeInstruction(const int idx) {
instructions.remove(getInstruction(idx));
}
/**
* Add an instruction to this quantum
......@@ -88,7 +89,9 @@ public:
*
* @param instruction
*/
virtual void addInstruction(InstPtr instruction);
virtual void addInstruction(InstPtr instruction) {
instructions.push_back(instruction);
}
/**
* Replace the given current quantum instruction
......@@ -97,43 +100,39 @@ public:
* @param currentInst
* @param replacingInst
*/
virtual void replaceInstruction(InstPtr currentInst,
InstPtr replacingInst);
/**
* Replace the given current quantum instruction
* with the new replacingInst quantum Instruction.
*
* @param currentInst
* @param replacingInst
*/
virtual void replaceInstruction(int instId,
InstPtr replacingInst);
/**
* Return the id of this function
* @return
*/
virtual const int getId();
virtual void replaceInstruction(const int idx, InstPtr replacingInst) {
std::replace(instructions.begin(), instructions.end(),
getInstruction(idx), replacingInst);
}
/**
* Return the name of this function
* @return
*/
virtual const std::string getName();
virtual const std::string getName() {
return functionName;
}
/**
* Return the qubits this function acts on.
* @return
*/
virtual const std::vector<int> qubits();
virtual const std::vector<int> bits() {
return std::vector<int> { };
}
/**
* Return an assembly-like string representation for this function .
* @param bufferVarName
* @return
*/
virtual const std::string toString(const std::string bufferVarName);
virtual const std::string toString(const std::string& bufferVarName) {
std::string retStr = "";
for (auto i : instructions) {
retStr += i->toString(bufferVarName) + "\n";
}
return retStr;
}
/**
* This method should simply be implemented to invoke the
......@@ -141,13 +140,9 @@ public:
*
* @param visitor
*/
virtual void accept(QInstructionVisitor& visitor);
virtual void accept(std::shared_ptr<InstructionVisitor> visitor) {
}
/**
* Return the number of instructions in this function.
* @return
*/
const int nInstructions();
};
}
}
......
......@@ -31,35 +31,23 @@
#ifndef QUANTUM_GATE_GATEQIR_GATEINSTRUCTION_HPP_
#define QUANTUM_GATE_GATEQIR_GATEINSTRUCTION_HPP_
#include "QInstruction.hpp"
#include "Instruction.hpp"
#include "Registry.hpp"
namespace xacc {
namespace quantum {
/**
* The GateInstruction is an implementation of QInstruction
* for gate-model quantum computing.
*/
class GateInstruction: public virtual QInstruction {
class GateInstruction: public virtual Instruction {
protected:
/**
* Reference to this instructions id
*/
int gateId;
/**
* Reference to this instructions name
*/
std::string gateName;
/**
* Reference to the circuit layer for this instruction.
*/
int circuitLayer;
/**
* Reference to the qubits this instruction acts on
*/
......@@ -67,16 +55,8 @@ protected:
public:
/**
* The nullary contructor.
*/
GateInstruction() :
gateId(0), gateName("UNKNOWN"), circuitLayer(0), qbits(
std::vector<int> { }) {
}
GateInstruction(int id, int layer, std::vector<int> qubts) :
gateId(id), circuitLayer(layer), gateName("UNKNOWN"), qbits(qubts) {
GateInstruction(std::vector<int> qubts) :
gateName("UNKNOWN"), qbits(qubts) {
}
/**
......@@ -88,16 +68,8 @@ public:
* @param name
* @param qubts
*/
GateInstruction(int id, int layer, std::string name, std::vector<int> qubts) :
gateId(id), circuitLayer(layer), gateName(name), qbits(qubts) {
}
/**
* Return the unique instruction id.
* @return
*/
virtual const int getId() {
return gateId;
GateInstruction(std::string name, std::vector<int> qubts) :
gateName(name), qbits(qubts) {
}
/**
......@@ -108,20 +80,11 @@ public:
return gateName;
}
/**
* Return the instruction layer.
*
* @return
*/
virtual const int layer() {
return circuitLayer;
}
/**
* Return the list of qubits this instruction acts on.
* @return
*/
virtual const std::vector<int> qubits() {
virtual const std::vector<int> bits() {
return qbits;
}
......@@ -131,9 +94,9 @@ public:
* @param bufferVarName
* @return
*/
virtual const std::string toString(const std::string bufferVarName) {
virtual const std::string toString(const std::string& bufferVarName) {
auto str = gateName + " ";
for (auto q : qubits()) {
for (auto q : bits()) {
str += bufferVarName + std::to_string(q) + ",";
}
......@@ -152,7 +115,7 @@ public:
/**
*/
using GateInstructionRegistry = Registry<GateInstruction, int, int, std::vector<int>>;
using GateInstructionRegistry = Registry<GateInstruction, std::vector<int>>;
/**
*/
......@@ -162,13 +125,13 @@ public:
RegisterGateInstruction(const std::string& name) {
GateInstructionRegistry::instance()->add(name,
(std::function<
std::shared_ptr<xacc::quantum::GateInstruction>(int,
int, std::vector<int>)>) ([](int id, int layer, std::vector<int> qubits) {
return std::make_shared<T>(id, layer, qubits);
std::shared_ptr<xacc::quantum::GateInstruction>(
std::vector<int>)>) ([](std::vector<int> qubits) {
return std::make_shared<T>(qubits);
}));
}
};
}
}
#endif /* QUANTUM_GATE_GATEQIR_GATEINSTRUCTION_HPP_ */
#endif
......@@ -62,7 +62,7 @@ public:
* @param pars
*/
ParameterizedGateInstruction(InstructionParameter ... pars) :
params(std::make_tuple(pars...)) {
params(std::make_tuple(pars...)), GateInstruction(std::vector<int>{}) {
}
/**
......@@ -85,7 +85,7 @@ public:
* @param bufferVarName
* @return
*/
virtual const std::string toString(const std::string bufferVarName) {
virtual const std::string toString(const std::string& bufferVarName) {
auto str = gateName;
str += "(";
xacc::tuple_for_each(params, [&](auto element) {
......@@ -93,7 +93,7 @@ public:
});
str = str.substr(0, str.length() - 1) + ") ";
for (auto q : qubits()) {
for (auto q : bits()) {
str += bufferVarName + std::to_string(q) + ",";
}
......@@ -106,20 +106,21 @@ public:
};
/**
*/
template<typename... Params>
using ParameterizedGateInstructionRegistry = Registry<ParameterizedGateInstruction<Params...>, int, int, std::vector<int>, Params...>;
template<typename ... Params>
using ParameterizedGateInstructionRegistry = Registry<ParameterizedGateInstruction<Params...>, std::vector<int>, Params...>;
/**
*/
template<typename T, typename... Params>
template<typename T, typename ... Params>
class RegisterParameterizedGateInstruction {
public:
RegisterParameterizedGateInstruction(const std::string& name) {
ParameterizedGateInstructionRegistry<Params...>::instance()->add(name,
(std::function<
std::shared_ptr<xacc::quantum::ParameterizedGateInstruction<Params...>>(int,
int, std::vector<int>, Params...)>) ([](int id, int layer, std::vector<int> qubits, Params... args) {
return std::make_shared<T>(id, layer, qubits, args...);
std::shared_ptr<
xacc::quantum::ParameterizedGateInstruction<
Params...>>(std::vector<int>, Params...)>) ([](std::vector<int> qubits, Params... args) {
return std::make_shared<T>(qubits, args...);
}));
}
};
......
#ifndef QUANTUM_GATE_GATEQIR_FUNCTIONS_CONDITIONALFUNCTION_HPP_
#define QUANTUM_GATE_GATEQIR_FUNCTIONS_CONDITIONALFUNCTION_HPP_
#include "GateFunction.hpp"
namespace xacc {
namespace quantum {
class ConditionalFunction: public virtual GateFunction {
protected:
std::list<InstPtr> conditionalInstructions;
int qbitIdx;
public:
ConditionalFunction(int qbit) : GateFunction("conditional_"+std::to_string(qbit)), qbitIdx(qbit) {}
virtual void addConditionalInstruction(InstPtr inst) {
conditionalInstructions.push_back(inst);
}
const int getConditionalQubit() {
return qbitIdx;
}
void evaluate(const int accBitState) {
if (accBitState == 1) {
instructions = conditionalInstructions;
}
}
virtual void accept(std::shared_ptr<InstructionVisitor> visitor) {
}
virtual const std::string toString(const std::string& bufferVarName) {
return "";
}
};
}
}
#endif /* QUANTUM_GATE_GATEQIR_FUNCTIONS_CONDITIONALFUNCTION_HPP_ */
......@@ -33,16 +33,15 @@
namespace xacc {
namespace quantum {
CNOT::CNOT(int id, int layer, std::vector<int> qbits) :
GateInstruction(id, layer, "CNOT", qbits) {
CNOT::CNOT(std::vector<int> qbits) :
GateInstruction("CNOT", qbits) {
}