Commit db56699f authored by Mccaskey, Alex's avatar Mccaskey, Alex
Browse files

Adding Compiler.translate() and ScaffoldIRToSrcVisitor

parent 6e791d2a
......@@ -30,6 +30,7 @@
**********************************************************************************/
#include "GateQIR.hpp"
#include "QuilCompiler.hpp"
#include "QuilVisitor.hpp"
namespace xacc {
......@@ -138,6 +139,20 @@ std::shared_ptr<IR> QuilCompiler::compile(const std::string& src) {
return ir;
}
const std::string QuilCompiler::translate(std::shared_ptr<Function> function) {
auto visitor = std::make_shared<QuilVisitor>();
InstructionIterator it(function);
while (it.hasNext()) {
// Get the next node in the tree
auto nextInst = it.next();
if (nextInst->isEnabled()) {
nextInst->accept(visitor);
}
}
return visitor->getQuilString();
}
}
}
......@@ -80,6 +80,15 @@ public:
"quil");
}
/**
* This produces a Quil source code representation of the
* given IR Function
*
* @param function The XACC IR Function to translate
* @return src The source code as a string
*/
virtual const std::string translate(std::shared_ptr<Function> function);
/**
* The destructor
*/
......
......@@ -35,6 +35,9 @@
#include <boost/test/included/unit_test.hpp>
#include "QuilCompiler.hpp"
#include "GateQIR.hpp"
#include "QuilVisitor.hpp"
using namespace xacc;
using namespace xacc::quantum;
......@@ -123,4 +126,64 @@ BOOST_AUTO_TEST_CASE(checkTeleportQuil) {
}
BOOST_AUTO_TEST_CASE(checkTranslateIR) {
auto f = std::make_shared<GateFunction>("foo");
auto x = std::make_shared<X>(0);
auto h = std::make_shared<Hadamard>(1);
auto cn1 = std::make_shared<CNOT>(1, 2);
auto cn2 = std::make_shared<CNOT>(0, 1);
auto h2 = std::make_shared<Hadamard>(0);
auto m0 = std::make_shared<Measure>(0, 0);
auto m1 = std::make_shared<Measure>(1, 1);
auto cond1 = std::make_shared<ConditionalFunction>(0);
auto z = std::make_shared<Z>(2);
cond1->addInstruction(z);
auto cond2 = std::make_shared<ConditionalFunction>(1);
auto x2 = std::make_shared<X>(2);
cond2->addInstruction(x2);
auto rz = std::make_shared<Rz>(0, 3.1415);
auto swap = std::make_shared<Swap>(0, 1);
auto cphase = std::make_shared<CPhase>(1, 2, 3.1415926);
InstructionParameter p("theta");
auto varCphase = std::make_shared<CPhase>(std::vector<int> { 1, 2 });
varCphase->setParameter(0, p);
f->addInstruction(x);
f->addInstruction(h);
f->addInstruction(cn1);
f->addInstruction(cn2);
f->addInstruction(h2);
f->addInstruction(m0);
f->addInstruction(m1);
f->addInstruction(cond1);
f->addInstruction(cond2);
std::string src = compiler->translate(f);
const std::string expected(
"X 0\n"
"H 1\n"
"CNOT 1 2\n"
"CNOT 0 1\n"
"H 0\n"
"MEASURE 0 [0]\n"
"MEASURE 1 [1]\n"
"JUMP-UNLESS @conditional_0 [0]\n"
"Z 2\n"
"LABEL @conditional_0\n"
"JUMP-UNLESS @conditional_1 [1]\n"
"X 2\n"
"LABEL @conditional_1\n");
BOOST_VERIFY(expected == src);
}
BOOST_AUTO_TEST_SUITE_END()
......@@ -158,8 +158,15 @@ std::shared_ptr<IR> ScaffoldCompiler::compile(const std::string& src) {
return consumer->getIR();
}
const std::string ScaffoldCompiler::translate(std::shared_ptr<Function> function) {
std::string srcString = "";
return srcString;
}
}
}
//static xacc::RegisterCompiler<xacc::quantum::ScaffoldCompiler> X(
// "scaffold");
......@@ -68,6 +68,15 @@ public:
*/
virtual std::shared_ptr<xacc::IR> compile(const std::string& src);
/**
* This produces a Scaffold source code representation of the
* given IR Function
*
* @param function The XACC IR Function to translate
* @return src The source code as a string
*/
virtual const std::string translate(std::shared_ptr<Function> function);
/**
* Return the name of this Compiler
* @return name Compiler name
......
/***********************************************************************************
* 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.
*
* Contributors:
* Initial API and implementation - Alex McCaskey
*
**********************************************************************************/
#ifndef QUANTUM_GATE_ACCELERATORS_RIGETTI_SCAFFOLDIRTOSRCVISITOR_HPP_
#define QUANTUM_GATE_ACCELERATORS_RIGETTI_SCAFFOLDIRTOSRCVISITOR_HPP_
#include <memory>
#include "AllGateVisitor.hpp"
namespace xacc {
namespace quantum {
/**
* The QuilVisitor is an InstructionVisitor that visits
* quantum gate instructions and creates an equivalent
* Quil string that can be executed by the Rigetti
* superconducting quantum computer.
*
*/
class ScaffoldIRToSrcVisitor: public AllGateVisitor {
protected:
/**
* Reference to the Quil string
* this visitor is trying to construct
*/
std::string scaffoldStr;
std::string qubitVarName;
int nMeasurements = 0;
std::map<int, int> qubitToClassicalBitIndex;
void baseInstruction(std::string gateName, std::vector<int> qubits) {
std::string qubitArgs = "";
for (auto i : qubits) {
qubitArgs += qubitVarName + "[" + std::to_string(i) + "],";
}
qubitArgs = qubitArgs.substr(0, qubitArgs.size() - 1);
scaffoldStr += gateName + "(" + qubitArgs + ");\n";
}
void baseParameterizedInstruction(std::string gateName, std::vector<int> qubits, std::vector<InstructionParameter> params) {
std::string qubitArgs = "", paramsStr = "";
for (auto p : params) {
paramsStr += boost::lexical_cast<std::string>(p) + ",";
}
paramsStr = paramsStr.substr(0, paramsStr.size() - 1);
for (auto i : qubits) {
qubitArgs += qubitVarName + "[" + std::to_string(i) + "],";
}
qubitArgs = qubitArgs.substr(0, qubitArgs.size() - 1);
scaffoldStr += gateName + "(" + qubitArgs + "," + paramsStr + ");\n";
}
public:
ScaffoldIRToSrcVisitor(std::string var) : qubitVarName(var) {}
/**
* Visit hadamard gates
*/
void visit(Hadamard& h) {
baseInstruction("H", h.bits());
}
/**
* Visit CNOT gates
*/
void visit(CNOT& cn) {
baseInstruction("CNOT", cn.bits());
}
/**
* Visit X gates
*/
void visit(X& x) {
baseInstruction("X", x.bits());
}
/**
*
*/
void visit(Y& y) {
baseInstruction("Y", y.bits());
}
/**
* Visit Z gates
*/
void visit(Z& z) {
baseInstruction("Z", z.bits());
}
/**
* Visit Measurement gates
*/
void visit(Measure& m) {
int classicalBitIdx = m.getClassicalBitIndex();
nMeasurements++;
scaffoldStr += "creg[" + std::to_string(classicalBitIdx) + "] = ";
baseInstruction("MeasZ", m.bits());
qubitToClassicalBitIndex.insert(std::make_pair(m.bits()[0], classicalBitIdx));
}
/**
* Visit Conditional functions
*/
void visit(ConditionalFunction& c) {
auto visitor = std::make_shared<ScaffoldIRToSrcVisitor>(qubitVarName);
auto classicalBitIdx = qubitToClassicalBitIndex[c.getConditionalQubit()];
scaffoldStr += "if (creg[" + std::to_string(classicalBitIdx) + "] == 1) {\n";
for (auto inst : c.getInstructions()) {
scaffoldStr += " ";
inst->accept(visitor);
}
scaffoldStr += visitor->getScaffoldString() + "}\n";
}
void visit(Rx& rx) {
auto params = rx.getParameters();
baseParameterizedInstruction("Rx", rx.bits(), params);
}
void visit(Ry& ry) {
auto params = ry.getParameters();
baseParameterizedInstruction("Ry", ry.bits(), params);
}
void visit(Rz& rz) {
auto params = rz.getParameters();
baseParameterizedInstruction("Rz", rz.bits(), params);
}
void visit(CPhase& cp) {
auto srcQubit = cp.bits()[0];
auto targetQubit = cp.bits()[1];
auto params = cp.getParameters();
// Check if this is a string
if (params[0].which() == 3) {
params[0] = "0.5 * " + boost::get<std::string>(params[0]);
} else {
params[0] = 0.5 * boost::get<double>(params[0]);
}
scaffoldStr += "// BEGIN CPHASE GATE\n";
baseParameterizedInstruction("Rz", std::vector<int>{targetQubit}, params);
baseInstruction("CNOT", std::vector<int>{targetQubit, srcQubit});
// Check if this is a string
if (params[0].which() == 3) {
params[0] = "-1 * " + boost::get<std::string>(params[0]);
} else {
params[0] = -1 * boost::get<double>(params[0]);
}
baseParameterizedInstruction("Rz", std::vector<int>{targetQubit}, params);
baseInstruction("CNOT", std::vector<int>{targetQubit, srcQubit});
scaffoldStr += "// END CPHASE GATE\n";
}
void visit(Swap& s) {
auto srcQubit = s.bits()[0];
auto targetQubit = s.bits()[1];
scaffoldStr += "// BEGIN SWAP " + std::to_string(srcQubit) + " " + std::to_string(targetQubit) + "\n";
baseInstruction("CNOT", std::vector<int>{targetQubit, srcQubit});
baseInstruction("CNOT", std::vector<int>{srcQubit, targetQubit});
baseInstruction("CNOT", std::vector<int>{targetQubit, srcQubit});
scaffoldStr += "// END SWAP " + std::to_string(srcQubit) + " " + std::to_string(targetQubit) + "\n";
}
void visit(GateFunction& f) {
return;
}
/**
* Return the quil string
*/
std::string getScaffoldString() {
if (nMeasurements > 0) {
scaffoldStr = "cbit creg[" + std::to_string(nMeasurements) + "];\n" + scaffoldStr;
}
return scaffoldStr;
}
/**
* The destructor
*/
virtual ~ScaffoldIRToSrcVisitor() {}
};
}
}
#endif
/***********************************************************************************
* 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.
*
* Contributors:
* Initial API and implementation - Alex McCaskey
*
**********************************************************************************/
#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE ScaffoldIRToSrcVisitorTester
#include <memory>
#include <boost/test/included/unit_test.hpp>
#include "ScaffoldIRToSrcVisitor.hpp"
#include "InstructionIterator.hpp"
using namespace xacc;
using namespace xacc::quantum;
BOOST_AUTO_TEST_CASE(checkIRToScaffold) {
auto f = std::make_shared<GateFunction>("foo");
auto x = std::make_shared<X>(0);
auto h = std::make_shared<Hadamard>(1);
auto cn1 = std::make_shared<CNOT>(1, 2);
auto cn2 = std::make_shared<CNOT>(0, 1);
auto h2 = std::make_shared<Hadamard>(0);
auto m0 = std::make_shared<Measure>(0, 0);
auto m1 = std::make_shared<Measure>(1,1);
auto cond1 = std::make_shared<ConditionalFunction>(0);
auto z = std::make_shared<Z>(2);
cond1->addInstruction(z);
auto cond2 = std::make_shared<ConditionalFunction>(1);
auto x2 = std::make_shared<X>(2);
cond2->addInstruction(x2);
auto rz = std::make_shared<Rz>(0, 3.1415);
auto swap = std::make_shared<Swap>(0, 1);
auto cphase = std::make_shared<CPhase>(1, 2, 3.1415926);
InstructionParameter p("theta");
auto varCphase = std::make_shared<CPhase>(std::vector<int>{1,2});
varCphase->setParameter(0, p);
f->addInstruction(x);
f->addInstruction(h);
f->addInstruction(cn1);
f->addInstruction(cn2);
f->addInstruction(h2);
f->addInstruction(m0);
f->addInstruction(m1);
f->addInstruction(cond1);
f->addInstruction(cond2);
f->addInstruction(rz);
f->addInstruction(swap);
f->addInstruction(cphase);
f->addInstruction(varCphase);
// Create the Instruction Visitor that is going
// to map our IR to Quil.
auto visitor = std::make_shared<ScaffoldIRToSrcVisitor>("qreg");
// Our QIR is really a tree structure
// so create a pre-order tree traversal
// InstructionIterator to walk it
InstructionIterator it(f);
while (it.hasNext()) {
// Get the next node in the tree
auto nextInst = it.next();
if (nextInst->isEnabled())
nextInst->accept(visitor);
}
std::string expectedStr = "cbit creg[2];\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"
"creg[0] = MeasZ(qreg[0]);\n"
"creg[1] = MeasZ(qreg[1]);\n"
"if (creg[0] == 1) {\n"
" Z(qreg[2]);\n"
"}\n"
"if (creg[1] == 1) {\n"
" X(qreg[2]);\n"
"}\n"
"Rz(qreg[0],3.1415);\n"
"// BEGIN SWAP 0 1\n"
"CNOT(qreg[1],qreg[0]);\n"
"CNOT(qreg[0],qreg[1]);\n"
"CNOT(qreg[1],qreg[0]);\n"
"// END SWAP 0 1\n"
"// BEGIN CPHASE GATE\n"
"Rz(qreg[2],1.5708);\n"
"CNOT(qreg[2],qreg[1]);\n"
"Rz(qreg[2],-1.5708);\n"
"CNOT(qreg[2],qreg[1]);\n"
"// END CPHASE GATE\n"
"// BEGIN CPHASE GATE\n"
"Rz(qreg[2],0.5 * theta);\n"
"CNOT(qreg[2],qreg[1]);\n"
"Rz(qreg[2],-1 * 0.5 * theta);\n"
"CNOT(qreg[2],qreg[1]);\n"
"// END CPHASE GATE\n";
BOOST_VERIFY(expectedStr == visitor->getScaffoldString());
}
......@@ -52,6 +52,9 @@ public:
"DWave");
}
virtual const std::string translate(std::shared_ptr<Function> function) {
};
/**
* The destructor
*/
......
......@@ -165,6 +165,10 @@ public:
parameters[idx] = p;
}
virtual std::vector<InstructionParameter> getParameters() {
return parameters;
}
virtual bool isParameterized() {
return nParameters() > 0;
}
......
......@@ -157,6 +157,10 @@ public:
parameters[idx] = p;
}
virtual std::vector<InstructionParameter> getParameters() {
return parameters;
}
virtual bool isParameterized() {
return nParameters() > 0;
}
......
......@@ -75,6 +75,16 @@ public:
*/
virtual std::shared_ptr<IR> compile(const std::string& src) = 0;
/**
* This method is to be implemented by derived Compilers and
* is in charge of taking the provided Function IR and converting
* it to source code in this Compiler's language.
*
* @param function The XACC IR Function to translate
* @return src The source code as a string
*/
virtual const std::string translate(std::shared_ptr<Function> function) = 0;
/**
* Return the name of this Compiler
* @return name Compiler name
......
......@@ -93,6 +93,8 @@ public:
*/
virtual InstructionParameter getParameter(const int idx) = 0;
virtual std::vector<InstructionParameter> getParameters() = 0;
/**
* Set this Instruction's parameter at the given index.
*
......
Markdown is supported
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