diff --git a/examples/quantum/gate/teleport_scaffold.cpp b/examples/quantum/gate/teleport_scaffold.cpp index 1dffd82df32e5c833e0012e681da6e57a08d2eab..59bfb6bdbb765c8d31c3846edba1a27c9991b1f0 100644 --- a/examples/quantum/gate/teleport_scaffold.cpp +++ b/examples/quantum/gate/teleport_scaffold.cpp @@ -33,7 +33,7 @@ // Quantum Kernel executing teleportation of // qubit state to another. -const std::string src("__qpu__ teleport () {\n" +const std::string src("__qpu__ teleport (qbit qreg) {\n" " cbit creg[2];\n" " // Init qubit 0 to 1\n" " X(qreg[0]);\n" @@ -57,22 +57,24 @@ int main (int argc, char** argv) { auto qpu = std::make_shared<Simple6QubitAcc>(); // Allocate some qubits, give them a unique identifier... - auto qreg = qpu->allocate("qreg"); + auto qubitReg = qpu->createBuffer("qreg", 3); + using QubitRegisterType = decltype(qubitReg); // Construct a new Program xacc::Program quantumProgram(qpu, src); // Build the program - quantumProgram.build("--compiler scaffold --writeIR teleport.xir"); + quantumProgram.build("--compiler scaffold " + "--writeIR teleport.xir"); // Retrieve the constructed kernel - auto teleport = quantumProgram.getKernel("teleport"); + auto teleport = quantumProgram.getKernel<QubitRegisterType>("teleport"); // Execute the kernel! - teleport(); + teleport(qubitReg); // Get the execution result - qreg->printState(std::cout); + qubitReg->printBufferState(std::cout); return 0; } diff --git a/quantum/gate/accelerators/QPUGate.hpp b/quantum/gate/accelerators/QPUGate.hpp index 42b83217c5617c2d49c4e44e1b88233785f6d4d7..0c212d1c044bcdfb22191c8684707392c01ad870 100644 --- a/quantum/gate/accelerators/QPUGate.hpp +++ b/quantum/gate/accelerators/QPUGate.hpp @@ -32,7 +32,6 @@ #define QUANTUM_GATE_ACCELERATORS_QPU_HPP_ #include "Accelerator.hpp" -#include "Qubits.hpp" namespace xacc { namespace quantum { @@ -40,8 +39,8 @@ namespace quantum { /** * */ -template<const int NQubits> -class QPUGate: virtual public Accelerator<Qubits<NQubits>> { +template<typename BitsType> +class QPUGate: virtual public Accelerator<BitsType> { public: /** @@ -63,19 +62,6 @@ public: } virtual ~QPUGate() {} - -protected: - - /** - * This Accelerator can allocate any number of - * qubits (at a great computational cost...) - * - * @param N - * @return - */ - bool canAllocate(const int N) { - return N <= NQubits; - } }; } diff --git a/quantum/gate/accelerators/Qubits.hpp b/quantum/gate/accelerators/Qubits.hpp deleted file mode 100644 index b8ac4aae5c6ee8752b2e13880bf7dc636ae50be5..0000000000000000000000000000000000000000 --- a/quantum/gate/accelerators/Qubits.hpp +++ /dev/null @@ -1,70 +0,0 @@ -#ifndef QUANTUM_GATE_QUBITS_HPP_ -#define QUANTUM_GATE_QUBITS_HPP_ - -#include "Accelerator.hpp" -#include <complex> -#include <Eigen/Dense> - -namespace xacc { - -namespace quantum { - -using QubitState = Eigen::VectorXcd; - -/** - * - */ -template<const int NumberOfQubits> -class Qubits: public AcceleratorBits<NumberOfQubits> { -protected: - - QubitState state; - - QubitState subState; - - bool usingSubstate; - -public: - - Qubits() : - state((int) std::pow(2, NumberOfQubits)), usingSubstate(false) { - // Initialize to |000...000> state - state.setZero(); - state(0) = 1.0; - } - - template<typename ... ActiveBits> - Qubits(QubitState& currentState, ActiveBits ... activeBits) : - state(currentState), subState((int) std::pow(2, sizeof...(ActiveBits))), - usingSubstate(true) { - - } - - template<typename... SubBits> - auto allocateSubset( - SubBits... subset) -> decltype(std::shared_ptr<Qubits<sizeof...(SubBits)>>()) { - auto qubits = std::make_shared<Qubits<sizeof...(SubBits)>>(state, subset...); - return qubits; - } - - void applyUnitary(Eigen::MatrixXcd& U) { - state = U * state; - } - - QubitState& getState() { - return state; - } - - void setState(QubitState& st) { - state = st; - } - - void printState(std::ostream& stream) { - for (int i = 0; i < state.rows(); i++) { - stream << std::bitset<NumberOfQubits>(i).to_string() << " -> " << state(i) << "\n"; - } - } -}; -} -} -#endif diff --git a/quantum/gate/accelerators/SimulatedQubits.hpp b/quantum/gate/accelerators/SimulatedQubits.hpp new file mode 100644 index 0000000000000000000000000000000000000000..b93e9967fdd5b5abbb133c6f8e086974cd180fab --- /dev/null +++ b/quantum/gate/accelerators/SimulatedQubits.hpp @@ -0,0 +1,71 @@ +#ifndef QUANTUM_GATE_SIMULATEDQUBITS_HPP_ +#define QUANTUM_GATE_SIMULATEDQUBITS_HPP_ + +#include "Accelerator.hpp" +#include <complex> +#include <Eigen/Dense> + +namespace xacc { + +namespace quantum { + +using QubitState = Eigen::VectorXcd; + +/** + * + */ +template<const int TotalNumberOfQubits> +class SimulatedQubits: public AcceleratorBuffer { +protected: + + QubitState bufferState; + +public: + + SimulatedQubits(const std::string& str) : + AcceleratorBuffer(str), bufferState((int) std::pow(2, TotalNumberOfQubits)) { + // Initialize to |000...000> state + bufferState.setZero(); + bufferState(0) = 1.0; + } + + SimulatedQubits(const std::string& str, const int N) : + AcceleratorBuffer(str, N), bufferState((int) std::pow(2, N)) { + bufferState.setZero(); + bufferState(0) = 1.0; + } + + template<typename ... Indices> + SimulatedQubits(const std::string& str, int firstIndex, Indices ... indices) : + AcceleratorBuffer(str, firstIndex, indices...), bufferState( + (int) std::pow(2, sizeof...(indices) + 1)) { + } + + void applyUnitary(Eigen::MatrixXcd& U) { + bufferState = U * bufferState; + } + + QubitState& getState() { + return bufferState; + } + + void setState(QubitState& st) { + bufferState = st; + } + + void printBufferState(std::ostream& stream) { + for (int i = 0; i < bufferState.rows(); i++) { + stream + << std::bitset<TotalNumberOfQubits>(i).to_string().substr( + size(), TotalNumberOfQubits) << " -> " + << bufferState(i) << "\n"; + } + } + + void mapBufferStateToSystemState() { + + } +}; +} +} +#endif diff --git a/quantum/gate/accelerators/eigenaccelerator/EigenAccelerator.hpp b/quantum/gate/accelerators/eigenaccelerator/EigenAccelerator.hpp index c1140ef495c592063709a2031eb69b0076233d4e..488391dad576d8b18808849441edd9e8b6ca968e 100644 --- a/quantum/gate/accelerators/eigenaccelerator/EigenAccelerator.hpp +++ b/quantum/gate/accelerators/eigenaccelerator/EigenAccelerator.hpp @@ -34,6 +34,7 @@ #include "QPUGate.hpp" #include "QasmToGraph.hpp" #include "GraphIR.hpp" +#include "SimulatedQubits.hpp" #include <unsupported/Eigen/KroneckerProduct> #include <random> @@ -48,7 +49,7 @@ using QuantumGraphIR = xacc::GraphIR<GraphType>; * */ template<const int NQubits> -class EigenAccelerator : virtual public QPUGate<NQubits> { +class EigenAccelerator : virtual public QPUGate<SimulatedQubits<NQubits>> { public: /** @@ -76,9 +77,14 @@ public: * * @param ir */ - virtual void execute(const std::shared_ptr<xacc::IR> ir) { + virtual void execute(const std::string& bufferId, const std::shared_ptr<xacc::IR> ir) { - auto qubits = std::dynamic_pointer_cast<Qubits<NQubits>>(this->bits); + auto qubits = this->allocatedBuffers[bufferId]; + if (!qubits) { + QCIError("Invalid buffer id. Could not get qubit buffer."); + } + + int nQubits = qubits->size(); // Cast to a GraphIR, if we can... auto graphir = std::dynamic_pointer_cast<QuantumGraphIR>(ir); @@ -111,8 +117,8 @@ public: } // Create a list of nQubits Identity gates - std::vector<Eigen::MatrixXcd> productList(NQubits); - for (int i = 0; i < NQubits; i++) { + std::vector<Eigen::MatrixXcd> productList(nQubits); + for (int i = 0; i < nQubits; i++) { productList[i] = gates["I"]; } @@ -238,7 +244,7 @@ public: } // Make sure that localU is the correct size - assert(localU.rows() == std::pow(2, NQubits) && localU.cols() == std::pow(2,NQubits)); + assert(localU.rows() == std::pow(2, nQubits) && localU.cols() == std::pow(2,nQubits)); qubits->applyUnitary(localU); @@ -248,6 +254,9 @@ public: } } } + + // Map buffer state to accelerator system state + } /** diff --git a/quantum/gate/accelerators/tests/EigenAcceleratorTester.cpp b/quantum/gate/accelerators/tests/EigenAcceleratorTester.cpp index f5b0bd4925b9173119dc34120eeabebacab0d829..0c8dbdfc53548ca7c2c8ab1a6a7d02424866cc4e 100644 --- a/quantum/gate/accelerators/tests/EigenAcceleratorTester.cpp +++ b/quantum/gate/accelerators/tests/EigenAcceleratorTester.cpp @@ -41,7 +41,7 @@ using namespace xacc::quantum; BOOST_AUTO_TEST_CASE(checkConstruction) { EigenAccelerator<3> acc; - auto qreg = acc.allocate("qreg"); +// auto qreg = acc.allocate("qreg"); // Create a graph IR modeling a diff --git a/quantum/gate/accelerators/tests/QubitsTester.cpp b/quantum/gate/accelerators/tests/SimulatedQubitsTester.cpp similarity index 93% rename from quantum/gate/accelerators/tests/QubitsTester.cpp rename to quantum/gate/accelerators/tests/SimulatedQubitsTester.cpp index a4f30bc7d474cf5d6a7958088722976b81135475..df3a7c635e3200838abac6b455dd896a4bdfd196 100644 --- a/quantum/gate/accelerators/tests/QubitsTester.cpp +++ b/quantum/gate/accelerators/tests/SimulatedQubitsTester.cpp @@ -32,15 +32,11 @@ #define BOOST_TEST_MODULE QubitsTester #include <boost/test/included/unit_test.hpp> -#include "Qubits.hpp" +#include "SimulatedQubits.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.measure()); } diff --git a/quantum/gate/compilers/scaffold/ScaffoldCompiler.cpp b/quantum/gate/compilers/scaffold/ScaffoldCompiler.cpp index f2ce00e89aa70be76add30b0e84b9bfe4b843784..9ac31c84a0eb09c9b875e3edfacae875d8634a12 100644 --- a/quantum/gate/compilers/scaffold/ScaffoldCompiler.cpp +++ b/quantum/gate/compilers/scaffold/ScaffoldCompiler.cpp @@ -49,15 +49,20 @@ void ScaffoldCompiler::modifySource() { kernelSource.erase(kernelSource.find("__qpu__"), 7); kernelSource = std::string("module ") + kernelSource; - std::string qubitAllocationLine, cbitAllocationLine, cbitVarName; + std::string qubitAllocationLine, cbitAllocationLine, cbitVarName, qbitVarName; std::map<int, int> cbitToQubit; - std::regex qbitName("qbit\\s.*"); - qubitAllocationLine = (*std::sregex_iterator(kernelSource.begin(), - kernelSource.end(), qbitName)).str() + "\n"; - std::vector<std::string> splitQbit; - boost::split(splitQbit, qubitAllocationLine, boost::is_any_of(" ")); - auto qbitVarName = splitQbit[1].substr(0, splitQbit[1].find_first_of("[")); + if (typeToVarKernelArgs.find("qbit") != typeToVarKernelArgs.end()) { + qubitAllocationLine = "qbit " + typeToVarKernelArgs["qbit"] + ";\n"; + qbitVarName = typeToVarKernelArgs["qbit"].substr(0, typeToVarKernelArgs["qbit"].find_first_of("[")); + } else { + std::regex qbitName("qbit\\s.*"); + qubitAllocationLine = (*std::sregex_iterator(kernelSource.begin(), + kernelSource.end(), qbitName)).str() + "\n"; + std::vector<std::string> splitQbit; + boost::split(splitQbit, qubitAllocationLine, boost::is_any_of(" ")); + qbitVarName = splitQbit[1].substr(0, splitQbit[1].find_first_of("[")); + } // Create Cbit to Qbit mapping std::regex cbitName("cbit\\s.*"); @@ -150,8 +155,27 @@ void ScaffoldCompiler::modifySource() { functionName); std::string fName = (*begin).str(); + std::string qbitAllocation = "", fargs; + if (this->typeToVarKernelArgs.find("qbit") != this->typeToVarKernelArgs.end()) { + auto varName = this->typeToVarKernelArgs["qbit"]; + qbitAllocation = "qbit " + varName + ";\n "; + } + + for (auto i = typeToVarKernelArgs.begin(); i != typeToVarKernelArgs.end(); ++i) { + if ("qbit" == i->first) { + fargs += i->second.substr(0, i->second.find_first_of("[")) + ","; + } else { + fargs += i->second + ","; + } + } + + if (!fargs.empty()) { + fargs = fargs.substr(0, fargs.size()-1); + boost::replace_first(fName, "(", "(" + fargs); + } + // Now wrap in a main function for ScaffCC - kernelSource = kernelSource + std::string("\nint main() {\n ") + fName + kernelSource = kernelSource + std::string("\nint main() {\n ") + qbitAllocation + fName + std::string(");\n}"); // std::cout << "\n" << kernelSource << "\n"; diff --git a/xacc/accelerator/Accelerator.hpp b/xacc/accelerator/Accelerator.hpp index 42ddc5ccbafc87c8d00a4add5e88e5b5b29cbab6..73a1e34300d3985e0721b6193344b4534dfee54e 100644 --- a/xacc/accelerator/Accelerator.hpp +++ b/xacc/accelerator/Accelerator.hpp @@ -66,39 +66,64 @@ enum AcceleratorType { qpu_gate, qpu_aqc, npu }; * * @author Alex McCaskey */ -template<const int Number> -class AcceleratorBits { +class AcceleratorBuffer { public: - /** - * Reference to the number of bits - */ - static constexpr int N = Number; - - /** - * Return the current state of the bits - * @return - */ - virtual std::bitset<(size_t) Number> measure() { - return bits; + AcceleratorBuffer(const std::string& str) : + bufferId(str) { } - - template<typename... SubBits> - auto allocateSubset( - SubBits ... subset) -> - decltype(std::shared_ptr<AcceleratorBits<sizeof...(SubBits)>>()) { + AcceleratorBuffer(const std::string& str, const int N) : + bufferId(str), bufferSize(N) { + } + template<typename ... Indices> + AcceleratorBuffer(const std::string& str, int firstIndex, + Indices ... indices) : + bufferId(str), bufferSize(1 + sizeof...(indices)) { + } + int size() { + return bufferSize; + } + std::string name() { + return bufferId; } - virtual ~AcceleratorBits() {} protected: - /** - * The bits themselves - */ - std::bitset<(size_t)Number> bits; - - std::vector<int> activeBits; - + int bufferSize = 0; + std::string bufferId; }; +//template<const int Number> +//class AcceleratorBits { +//public: +// /** +// * Reference to the number of bits +// */ +// static constexpr int N = Number; +// +// /** +// * Return the current state of the bits +// * @return +// */ +// virtual std::bitset<(size_t) Number> measure() { +// return bits; +// } +// +// template<typename... SubBits> +// auto allocateSubset( +// SubBits ... subset) -> +// decltype(std::shared_ptr<AcceleratorBits<sizeof...(SubBits)>>()) { +// } +// virtual ~AcceleratorBits() {} +// +//protected: +// +// /** +// * The bits themselves +// */ +// std::bitset<(size_t)Number> bits; +// +// std::vector<int> activeBits; +// +//}; class IAccelerator : public qci::common::QCIObject { public: @@ -121,7 +146,7 @@ public: * * @param ir */ - virtual void execute(const std::shared_ptr<IR> ir) = 0; + virtual void execute(const std::string& bufferId, const std::shared_ptr<IR> ir) = 0; /** * Return the number of bits that the user most recently @@ -129,15 +154,14 @@ public: * * @return nBits The number of requested bits */ - virtual int getAllocationSize() = 0; + virtual int getBufferSize(const std::string& id) = 0; + + virtual int getBufferSize() = 0; + +protected: + + virtual bool isValidBufferSize(const int NBits) {return true;} - /** - * Return the variable name provided upon bit allocation - * (for example - qreg for gate model quantum bits in (qbit qreg[2];)) - * - * @return varName The name of the bits allocated. - */ - virtual const std::string getVariableName() = 0; }; /** @@ -153,49 +177,57 @@ public: * instances that transform XACC IR to be amenable to execution * on the hardware. */ -template<typename TotalBits> +template<typename BitsType> class Accelerator : public IAccelerator { - static_assert(is_valid_bitstype<TotalBits>::value, "Derived BitsType parameter must contain N int member for number of bits."); - static_assert(std::is_base_of<AcceleratorBits<TotalBits::N>, TotalBits>::value, ""); + static_assert(std::is_base_of<AcceleratorBuffer, BitsType>::value, ""); + + using BitsTypePtr = std::shared_ptr<BitsType>; public: - /** - * Allocate bit resources (if needed). - * - * @return bits The AcceleratorBits derived type - */ - std::shared_ptr<TotalBits> allocate(const std::string& variableNameId) { - if (!canAllocate(TotalBits::N)) { - QCIError("Error in allocated requested bits"); - } - bits = std::make_shared<TotalBits>(); - NBitsAllocated = TotalBits::N; - bitVarId = variableNameId; - return bits; + Accelerator() { + totalSystemBuffer = std::make_shared<BitsType>("default"); + allocatedBuffers.insert(std::make_pair("default", totalSystemBuffer)); } - /** - * Allocate some subset of Accelerator bit resources. - * - * @param variableNameId - * @param bitList - * @return - */ - template<typename... SubBits> - auto allocate(const std::string& variableNameId, - SubBits... bitList) -> decltype(std::declval<TotalBits>().allocateSubset(bitList...)) { - // FIXME CHECK THAT THEY PASSED IN LIST OF INTS - if (!canAllocate(sizeof...(SubBits))) { - QCIError("Error in allocated requested bits"); + BitsTypePtr createBuffer(const std::string& varId) { + if (isValidBufferVarId(varId)) { + auto buffer = std::make_shared<BitsType>(varId); + allocatedBuffers.insert(std::make_pair(varId, buffer)); + return buffer; + } else { + QCIError("Invalid buffer variable name."); } + } - auto subsetBits = bits->allocateSubset(bitList...); - NBitsAllocated = (int) sizeof...(SubBits); - bitVarId = variableNameId; + BitsTypePtr createBuffer(const std::string& varId, const int size) { + if (!isValidBufferVarId(varId)) { + QCIError("Invalid buffer variable name."); + } + if (!isValidBufferSize(size)) { + QCIError("Invalid buffer size."); + } + auto buffer = std::make_shared<BitsType>(varId, size); + allocatedBuffers.insert(std::make_pair(varId, buffer)); + return buffer; + } - return subsetBits; + template<typename... Indices> + BitsTypePtr createBuffer(const std::string& varId, int firstIndex, + Indices ... indices) { + if (!isValidBufferVarId(varId)) { + QCIError("Invalid buffer variable name."); + } + if (!isValidBufferSize(sizeof...(indices) + 1)) { + QCIError("Invalid buffer size."); + } + if (!validIndices(indices...)) { + QCIError("Invalid buffer indices."); + } + auto buffer = std::make_shared<BitsType>(varId, firstIndex, indices...); + allocatedBuffers.insert(std::make_pair(varId, buffer)); + return buffer; } /** @@ -204,20 +236,19 @@ public: * * @return nBits The number of requested bits */ - virtual int getAllocationSize() { - return NBitsAllocated; + virtual int getBufferSize(const std::string& id) { + return allocatedBuffers[id]->size(); } - /** - * Return the variable name provided upon bit allocation - * (for example - qreg for gate model quantum bits in (qbit qreg[2];)) - * - * @return varName The name of the bits allocated. - */ - virtual const std::string getVariableName() { - return bitVarId; + virtual int getBufferSize() { + return allocatedBuffers["default"]->size(); + } + + BitsTypePtr getExistingBuffer(const std::string& varId) { + return allocatedBuffers[varId]; } + /** * Destructor */ @@ -225,31 +256,20 @@ public: protected: - /** - * The number of bits allocated upon the most - * recent user request for bit resources. - */ - int NBitsAllocated = 0; + std::map<std::string, BitsTypePtr> allocatedBuffers; - /** - * The variable name of the bits - */ - std::string bitVarId; - - /** - * - */ - std::shared_ptr<TotalBits> bits; + BitsTypePtr totalSystemBuffer; - /** - * Return true if this Accelerator can allocate - * the provided number of bits. - * @param NBits The number of bits to allocate - * @return canAllocate True if can allocate, false if not. - */ - virtual bool canAllocate(const int NBits) = 0; + bool isValidBufferVarId(const std::string& str) { + return allocatedBuffers.find(str) == std::end(allocatedBuffers); + } + template<typename... Indices> + bool validIndices(int firstIndex, Indices... indices) { + return false; + } }; + } #endif diff --git a/xacc/compiler/Compiler.hpp b/xacc/compiler/Compiler.hpp index f17849a66a31a82a0014cba19e885c42dc0b360c..af94eae2344ca8b2706a85ed3e411c77c4d86f40 100644 --- a/xacc/compiler/Compiler.hpp +++ b/xacc/compiler/Compiler.hpp @@ -37,6 +37,8 @@ #include "QCIError.hpp" #include "IR.hpp" #include <ostream> +#include <boost/algorithm/string.hpp> +#include "Accelerator.hpp" using namespace qci::common; @@ -51,6 +53,14 @@ class ICompiler : public qci::common::QCIObject { public: virtual ~ICompiler() {} + /** + * + * @param src + * @return + */ + virtual std::shared_ptr<IR> compile(const std::string& src, + std::shared_ptr<IAccelerator>& accelerator) = 0; + /** * * @param src @@ -87,12 +97,67 @@ 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, + std::shared_ptr<IAccelerator>& acc) { // Set the provided kernel source string // so derived types can have reference to it kernelSource = src; + accelerator = acc; + + auto bitTypeStr = getAsDerived().getBitType(); + auto firstParen = kernelSource.find_first_of('('); + auto secondParen = kernelSource.find_first_of(')', firstParen); + auto functionArguments = kernelSource.substr(firstParen+1, (secondParen-firstParen)-1); + + if (!functionArguments.empty()) { + // First search the prototype to see if it has + // and argument that declares the accelerator bit buffer + // to use in the kernel + std::vector<std::string> splitArgs, splitTypeVar; + boost::split(splitArgs, functionArguments, boost::is_any_of(",")); + std::string varName; + for (int i = 0; i < splitArgs.size(); i++) { + // split type from var name + auto s = splitArgs[i]; + boost::split(splitTypeVar, s, boost::is_any_of(" ")); + auto type = splitTypeVar[0]; + auto var = splitTypeVar[1]; + boost::trim(type); + boost::trim(var); + typeToVarKernelArgs.insert(std::make_pair(type, var)); + if (boost::contains(type, bitTypeStr)) { + varName = var; + } + } + + if (typeToVarKernelArgs.find(bitTypeStr) + != typeToVarKernelArgs.end()) { + auto nBits = accelerator->getBufferSize(varName); + boost::replace_first(kernelSource, + std::string(bitTypeStr + " " + varName), + std::string( + bitTypeStr + " " + varName + "[" + + std::to_string(nBits) + "]")); + + // Replace the varname in the map with varName[#] + typeToVarKernelArgs[bitTypeStr] = varName + "[" + + std::to_string(nBits) + "]"; + } + } + // Xacc requires that clients provide + // only the body code for an attached + // accelerator... Some language compilers + // need to make updates to make that code + // amenable to their specific compilation. + modifySource(); + + return getAsDerived().compile(); + } + + virtual std::shared_ptr<IR> compile(const std::string& src) { + kernelSource = src; // Xacc requires that clients provide // only the body code for an attached // accelerator... Some language compilers @@ -120,6 +185,9 @@ protected: */ std::string kernelSource; + std::map<std::string, std::string> typeToVarKernelArgs; + + std::shared_ptr<IAccelerator> accelerator; /** * * Derived types implementing compile should perform language diff --git a/xacc/program/Program.hpp b/xacc/program/Program.hpp index 2dfcb31fa67a04cfa99e1e150dcd67f39a0de492..f21412386b59eeedc18c2f93549846cc58e1ac8d 100644 --- a/xacc/program/Program.hpp +++ b/xacc/program/Program.hpp @@ -141,41 +141,14 @@ public: QCIError("Invalid Compiler.\n"); } - // Update source with hardware bits information... - // FIXME Make this more robust in the future... - auto bitTypeStr = compiler->getBitType(); - auto nBits = accelerator->getAllocationSize(); - auto varName = accelerator->getVariableName(); - std::string bitAllocationSrc = bitTypeStr + " " + varName + "[" - + std::to_string(nBits) + "];\n"; - - std::vector<std::string> srcLines; - boost::split(srcLines, src, 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, bitAllocationSrc); - - // Merge all into new kernel source string - std::stringstream combine; - std::for_each(srcLines.begin(), srcLines.end(), [&](const std::string& elem) { combine << elem << "\n"; }); - src = combine.str(); - // Execute the compilation - xaccIR = compiler->compile(src); + xaccIR = compiler->compile(src, accelerator); // Validate the compilation if (!xaccIR) { QCIError("Bad source string or something.\n"); } - // Write the IR to file if the user requests it - if (compileParameters.count("writeIR")) { - auto fileStr = compileParameters["writeIR"].as<std::string>(); - std::ofstream ostr(fileStr); - xaccIR->persist(ostr); - } - // Execute IR Translations auto acceleratorType = accelerator->getType(); auto defaultTransforms = getAcceleratorIndependentTransformations(acceleratorType); @@ -187,6 +160,13 @@ public: t.transform(*xaccIR.get()); } + // Write the IR to file if the user requests it + if (compileParameters.count("writeIR")) { + auto fileStr = compileParameters["writeIR"].as<std::string>(); + std::ofstream ostr(fileStr); + xaccIR->persist(ostr); + } + return; } @@ -196,11 +176,10 @@ public: * @param args * @return */ - template<typename ... RuntimeArgs> - std::function<void(RuntimeArgs...)> getKernel(const std::string& name, - RuntimeArgs ... args) { - return [&]() { - accelerator->execute(xaccIR, args...); + template<typename BitsType, typename ... RuntimeArgs> + std::function<void(BitsType, RuntimeArgs...)> getKernel(const std::string& kernelName) { + return [&](BitsType bits, RuntimeArgs... args) { + accelerator->execute(bits->name(), xaccIR); return; }; } diff --git a/xacc/tests/ProgramTester.cpp b/xacc/tests/ProgramTester.cpp index 62c55e1cbc3fbcb50455110082ac0359830fd916..590641f5f8845151411db649313adab64bb77749 100644 --- a/xacc/tests/ProgramTester.cpp +++ b/xacc/tests/ProgramTester.cpp @@ -36,17 +36,14 @@ using namespace xacc; -class FakeAccelerator : public Accelerator<AcceleratorBits<5>> { +class FakeAccelerator : public Accelerator<AcceleratorBuffer> { 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 void execute(const std::string& bufferId, const std::shared_ptr<IR> ir) {} virtual ~FakeAccelerator() {} }; @@ -83,7 +80,7 @@ REGISTER_QCIOBJECT_WITH_QCITYPE(DummyCompiler, "compiler", BOOST_AUTO_TEST_CASE(checkBuildRuntimeArguments) { const std::string src("__qpu__ void teleport() {" - " qbit qs[3];" + " qbit q[3];" " H(q[1]);" " CNot(q[1],q[2]);" " CNot(q[0], q[1]);" @@ -97,10 +94,8 @@ BOOST_AUTO_TEST_CASE(checkBuildRuntimeArguments) { "}"); auto acc = std::make_shared<FakeAccelerator>(); - + acc->createBuffer("qreg"); Program prog(acc, src); prog.build("--compiler dummy"); - -// auto kernel = prog.getKernel("teleport"); }