Commit 581c08da authored by Mccaskey, Alex's avatar Mccaskey, Alex
Browse files

Removing old ParameterizedGateInstruction, modifying Instruction concept to...

Removing old ParameterizedGateInstruction, modifying Instruction concept to provide 0 to N parameters, updated Rz and Measure
parent 7413d1a3
......@@ -64,7 +64,6 @@ std::shared_ptr<IR> QuilCompiler::compile(const std::string& src) {
bool isConditional = false;
std::shared_ptr<xacc::Instruction> instruction;
auto gateRegistry = xacc::quantum::GateInstructionRegistry::instance();
auto oneParamRegistry = xacc::quantum::ParameterizedGateInstructionRegistry<int>::instance();
std::vector<std::shared_ptr<xacc::Instruction>> measurements;
std::string currentLabel;
std::shared_ptr<ConditionalFunction> currentConditional;
......@@ -86,7 +85,9 @@ std::shared_ptr<IR> QuilCompiler::compile(const std::string& src) {
boost::replace_all(splitSpaces[2], "[", "");
boost::replace_all(splitSpaces[2], "]", "");
int classicalBit = std::stoi(splitSpaces[2]);
instruction = oneParamRegistry->create("Measure", qubits, classicalBit);
instruction = gateRegistry->create("Measure", qubits);
xacc::InstructionParameter p(classicalBit);
instruction->setParameter(0,p);
measurements.push_back(instruction);
} else if (gateName == "JUMP-UNLESS") {
isConditional = true;
......@@ -96,9 +97,8 @@ std::shared_ptr<IR> QuilCompiler::compile(const std::string& src) {
auto classicalIdx = std::stoi(splitSpaces[2]);
int conditionalQubit = -1;
for (auto m : measurements) {
auto measure = std::dynamic_pointer_cast<xacc::quantum::ParameterizedGateInstruction<int>>(m);
if (measure->getParameter(0) == classicalIdx) {
conditionalQubit = measure->bits()[0];
if (boost::get<int>(m->getParameter(0)) == classicalIdx) {
conditionalQubit = m->bits()[0];
break;
}
}
......
......@@ -106,7 +106,7 @@ public:
* Visit Measurement gates
*/
void visit(Measure& m) {
int classicalBitIdx = m.getParameter(0);
int classicalBitIdx = m.getClassicalBitIndex();
quilStr += "MEASURE " + std::to_string(m.bits()[0]) + " [" + std::to_string(classicalBitIdx) + "]\n";
classicalAddresses += std::to_string(classicalBitIdx) + ", ";
numAddresses++;
......
......@@ -174,7 +174,7 @@ public:
auto fd = c->getDirectCallee();
auto gateName = fd->getNameInfo().getAsString();
std::vector<int> qubits;
std::vector<double> params;
std::vector<xacc::InstructionParameter> params;
for (auto i = c->arg_begin(); i != c->arg_end(); ++i) {
std::string arg;
llvm::raw_string_ostream argstream(arg);
......@@ -197,26 +197,19 @@ public:
double d = boost::lexical_cast<double>(argStr);
params.push_back(d);
} catch (const boost::bad_lexical_cast &) {
params.push_back(0.0);
params.push_back(argStr);
}
// params.push_back(std::stod(argStr));
}
}
std::shared_ptr<xacc::quantum::GateInstruction> inst;
if (isParameterizedInst) {
if (params.size() == 1) {
inst = xacc::quantum::ParameterizedGateInstructionRegistry<
double>::instance()->create(gateName, qubits,
params[0]);
} else if (params.size() == 2) {
inst = xacc::quantum::ParameterizedGateInstructionRegistry<
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.");
int idx = 0;
inst = xacc::quantum::GateInstructionRegistry::instance()->create(gateName, qubits);
for (auto p : params) {
inst->setParameter(idx, p);
idx++;
}
} else if (gateName != "MeasZ") {
......@@ -276,9 +269,13 @@ public:
boost::replace_all(rhsString, "]", "");
// lhsString now just contains the classical index bit
auto inst = xacc::quantum::ParameterizedGateInstructionRegistry<
int>::instance()->create("Measure", std::vector<int> {
std::stoi(rhsString) }, std::stoi(lhsString));
auto inst =
xacc::quantum::GateInstructionRegistry::instance()->create(
"Measure",
std::vector<int> { std::stoi(rhsString) });
// , std::stoi(lhsString));
xacc::InstructionParameter classicalIdx(std::stoi(lhsString));
inst->setParameter(0, classicalIdx);
cbitRegToMeasuredQubit.insert(
std::make_pair(lhss.str(), std::stoi(rhsString)));
......
......@@ -54,6 +54,8 @@ protected:
std::list<InstPtr> instructions;
std::vector<InstructionParameter> parameters;
public:
/**
......@@ -63,6 +65,10 @@ public:
* @param name
*/
GateFunction(const std::string& name) : functionName(name) {}
GateFunction(const std::string& name,
std::vector<InstructionParameter> params) :
functionName(name), parameters(params) {
}
virtual const int nInstructions() {
return instructions.size();
......@@ -135,6 +141,32 @@ public:
return retStr;
}
virtual InstructionParameter getParameter(const int idx) {
if (idx + 1 > parameters.size()) {
XACCError(
"Invalid Parameter requested.");
}
return parameters[idx];
}
virtual void setParameter(const int idx, InstructionParameter& p) {
if (idx + 1 > parameters.size()) {
XACCError(
"Invalid Parameter requested.");
}
parameters[idx] = p;
}
virtual bool isParameterized() {
return nParameters() > 0;
}
virtual const int nParameters() {
return parameters.size();
}
DEFINE_VISITABLE()
/**
......
......@@ -33,6 +33,7 @@
#include "Instruction.hpp"
#include "Registry.hpp"
#include <boost/lexical_cast.hpp>
namespace xacc {
namespace quantum {
......@@ -55,12 +56,14 @@ protected:
bool enabled = true;
std::vector<InstructionParameter> parameters;
public:
GateInstruction() = delete;
GateInstruction(std::vector<int> qubts) :
gateName("UNKNOWN"), qbits(qubts) {
gateName("UNKNOWN"), qbits(qubts), parameters(std::vector<InstructionParameter>{}) {
}
/**
......@@ -73,7 +76,12 @@ public:
* @param qubts
*/
GateInstruction(std::string name, std::vector<int> qubts) :
gateName(name), qbits(qubts) {
gateName(name), qbits(qubts), parameters(std::vector<InstructionParameter>{}) {
}
GateInstruction(std::string name, std::vector<int> qubts,
std::vector<InstructionParameter> params) :
gateName(name), qbits(qubts), parameters(params) {
}
/**
......@@ -99,7 +107,17 @@ public:
* @return
*/
virtual const std::string toString(const std::string& bufferVarName) {
auto str = gateName + " ";
auto str = gateName;
if (!parameters.empty()) {
str += "(";
for (auto p : parameters) {
str += boost::lexical_cast<std::string>(p) + ",";
}
str = str.substr(0, str.length() - 1) + ") ";
} else {
str += " ";
}
for (auto q : bits()) {
str += bufferVarName + std::to_string(q) + ",";
}
......@@ -108,6 +126,7 @@ public:
str = str.substr(0, str.length() - 1);
return str;
}
virtual bool isEnabled() {
......@@ -122,84 +141,38 @@ public:
enabled = true;
}
DEFINE_VISITABLE()
/**
* The destructor
*/
virtual ~GateInstruction() {
}
};
/**
* The ParamaterizedGateInstruction is a GateInstruction that is
* templated on a list of variadic parameters that model the
* instructions gate parameters. For example, this class could be
* subclassed to provide a rotation gate with an angle theta
* (ParamaterizedGateInstruction<double>).
*/
template<typename ... InstructionParameter>
class ParameterizedGateInstruction: public virtual GateInstruction {
protected:
/**
* The paramaters that this gate instruction requires.
*/
std::tuple<InstructionParameter...> params;
public:
virtual InstructionParameter getParameter(const int idx) {
if (idx + 1 > parameters.size()) {
XACCError("Invalid Parameter requested from Parameterized Gate Instruction.");
}
/**
* The constructor, takes the parameters
* @param pars
*/
ParameterizedGateInstruction(InstructionParameter ... pars) :
params(std::make_tuple(pars...)), GateInstruction(std::vector<int>{}) {
return parameters[idx];
}
/**
* Return the gate parameter at the given index.
*
* @param idx
* @return
*/
auto getParameter(const std::size_t idx) {
if (idx + 1 > sizeof...(InstructionParameter)) {
virtual void setParameter(const int idx, InstructionParameter& p) {
if (idx + 1 > parameters.size()) {
XACCError("Invalid Parameter requested from Parameterized Gate Instruction.");
}
return xacc::tuple_runtime_get(params, idx);
}
/**
* Return an assembly-like string representation for this
* instruction.
*
* @param bufferVarName
* @return
*/
virtual const std::string toString(const std::string& bufferVarName) {
auto str = gateName;
str += "(";
xacc::tuple_for_each(params, [&](auto element) {
str += std::to_string(element) + ",";
});
str = str.substr(0, str.length() - 1) + ") ";
for (auto q : bits()) {
str += bufferVarName + std::to_string(q) + ",";
}
parameters[idx] = p;
}
// Remove trailing comma
str = str.substr(0, str.length() - 1);
virtual bool isParameterized() {
return nParameters() > 0;
}
return str;
virtual const int nParameters() {
return parameters.size();
}
DEFINE_VISITABLE()
/**
* The destructor
*/
virtual ~GateInstruction() {
}
};
/**
......@@ -221,26 +194,6 @@ public:
}
};
/**
*/
template<typename ... Params>
using ParameterizedGateInstructionRegistry = Registry<ParameterizedGateInstruction<Params...>, std::vector<int>, 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...>>(std::vector<int>, Params...)>) ([](std::vector<int> qubits, Params... args) {
return std::make_shared<T>(qubits, args...);
}));
}
};
}
}
......
......@@ -33,29 +33,22 @@
namespace xacc {
namespace quantum {
Measure::Measure(std::vector<int> qbit, int classicalIdx) :
ParameterizedGateInstruction<int>(classicalIdx), GateInstruction(
"Measure", qbit) {
Measure::Measure(std::vector<int> qbit) :
GateInstruction("Measure", qbit, std::vector<InstructionParameter> {
InstructionParameter(0) }) {
}
Measure::Measure(int qbit, int classicalIdx) :
Measure(std::vector<int> { qbit }, classicalIdx) {
GateInstruction("Measure", std::vector<int> { qbit },
std::vector<InstructionParameter> { InstructionParameter(
classicalIdx) }) {
}
//
//void Measure::accept(std::shared_ptr<InstructionVisitor> visitor) {
// auto v = std::dynamic_pointer_cast<GateInstructionVisitor>(visitor);
// if (v) {
// v->visit(*this);
// } else {
// visitor->visit(*this);
// }
//}
const std::string Measure::toString(const std::string& bufferVarName) {
return gateName + " " + bufferVarName + std::to_string(bits()[0]);
}
RegisterParameterizedGateInstruction<Measure, int> MEASURETEMP("Measure");
RegisterGateInstruction<Measure> MEASURETEMP("Measure");
}
}
......
......@@ -39,14 +39,19 @@ namespace quantum {
/**
*
*/
class Measure : public virtual ParameterizedGateInstruction<int> {
class Measure : public GateInstruction {
public:
Measure(std::vector<int> qbit, int classicalIdx);
Measure(std::vector<int> qbit);
Measure(int qbit, int classicalIdx);
virtual const std::string toString(const std::string& bufferVarName);
int getClassicalBitIndex() {
return boost::get<int>(parameters[0]);
}
DEFINE_VISITABLE()
};
......
......@@ -32,23 +32,19 @@
namespace xacc {
namespace quantum {
Rz::Rz(std::vector<int> qbits, double theta) :
ParameterizedGateInstruction<double>(theta), GateInstruction("Rz",
qbits) {
}
Rz::Rz(int qbit, double theta) :
Rz(std::vector<int> { qbit }, theta) {
GateInstruction("Rz", std::vector<int> { qbit },
std::vector<InstructionParameter> { InstructionParameter(theta) }) {
}
Rz::Rz(std::vector<int> qbits) :
GateInstruction("Rz", qbits, std::vector<InstructionParameter> {
InstructionParameter(0.0) }) {
}
//
//void Rz::accept(std::shared_ptr<InstructionVisitor> visitor) {
// auto v = std::dynamic_pointer_cast<GateInstructionVisitor>(visitor);
// if (v) {
//// v->visit(*this);
// } else {
// visitor->visit(*this);
// }
//}
RegisterParameterizedGateInstruction<Rz, double> RZTEMP("Rz");
RegisterGateInstruction<Rz> RZTEMP("Rz");
//RegisterParameterizedGateInstruction<Rz, double> RZTEMP("Rz");
}
}
......@@ -35,9 +35,9 @@
namespace xacc {
namespace quantum {
class Rz: public virtual ParameterizedGateInstruction<double> {
class Rz: public virtual GateInstruction {
public:
Rz(std::vector<int> qbits, double theta);
Rz(std::vector<int> qbits);
Rz(int qbit, double theta);
DEFINE_VISITABLE()
......
......@@ -40,7 +40,7 @@ using namespace xacc::quantum;
BOOST_AUTO_TEST_CASE(checkCreation) {
Measure meas(0, 1);
BOOST_VERIFY(meas.getParameter(0) == 1);
BOOST_VERIFY(boost::get<int>(meas.getParameter(0)) == 1);
BOOST_VERIFY(meas.toString("qreg") == "Measure qreg0");
BOOST_VERIFY(meas.bits().size() == 1);
BOOST_VERIFY(meas.bits()[0] == 0);
......@@ -51,7 +51,9 @@ BOOST_AUTO_TEST_CASE(checkCreation) {
BOOST_AUTO_TEST_CASE(checkAutoRegistration) {
auto meas = ParameterizedGateInstructionRegistry<int>::instance()->create("Measure", std::vector<int>{0}, 1);
xacc::InstructionParameter p(1);
auto meas = GateInstructionRegistry::instance()->create("Measure", std::vector<int>{0});
meas->setParameter(0, p);
BOOST_VERIFY(meas->getName() == "Measure");
BOOST_VERIFY(meas->getParameter(0) == 1);
BOOST_VERIFY(boost::get<int>(meas->getParameter(0)) == 1);
}
/***********************************************************************************
* 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 ParameterizedGateTester
#include <boost/test/included/unit_test.hpp>
#include "GateInstruction.hpp"
using namespace xacc;
using namespace xacc::quantum;
class DummyGate: public virtual ParameterizedGateInstruction<double, double> {
public:
DummyGate(int qbit, double param1, double param2) :
ParameterizedGateInstruction(param1, param2), GateInstruction(
"Dummy", std::vector<int> { qbit }) {
}
DEFINE_VISITABLE()
};
BOOST_AUTO_TEST_CASE(checkParameterizedGate) {
auto dgate = std::make_shared<DummyGate>(0, 3.14, 33.3);
BOOST_VERIFY(dgate->getParameter(0) == 3.14);
BOOST_VERIFY(dgate->getParameter(1) == 33.3);
}
......@@ -40,15 +40,16 @@ using namespace xacc::quantum;
BOOST_AUTO_TEST_CASE(checkCreation) {
Rz rz(0, 3.14);
BOOST_VERIFY(rz.getParameter(0) == 3.14);
BOOST_VERIFY(rz.toString("qreg") == "Rz(3.140000) qreg0");
BOOST_VERIFY(boost::get<double>(rz.getParameter(0)) == 3.14);
BOOST_VERIFY(rz.toString("qreg") == "Rz(3.14) qreg0");
BOOST_VERIFY(rz.bits().size() == 1);
BOOST_VERIFY(rz.bits()[0] == 0);
BOOST_VERIFY(rz.getName() == "Rz");
Rz rz2(44, 1.71234);
BOOST_VERIFY(rz2.getParameter(0) == 1.71234);
BOOST_VERIFY(rz2.toString("qreg") == "Rz(1.712340) qreg44");
BOOST_VERIFY(boost::get<double>(rz2.getParameter(0)) == 1.71234);
BOOST_VERIFY(rz2.toString("qreg") == "Rz(1.71234) qreg44");
BOOST_VERIFY(rz2.bits().size() == 1);
BOOST_VERIFY(rz2.bits()[0] == 44);
BOOST_VERIFY(rz2.getName() == "Rz");
......@@ -58,7 +59,9 @@ BOOST_AUTO_TEST_CASE(checkCreation) {
BOOST_AUTO_TEST_CASE(checkAutoRegistration) {
auto rz = ParameterizedGateInstructionRegistry<double>::instance()->create("Rz", std::vector<int>{0}, 3.14);
xacc::InstructionParameter p = 3.1415;
auto rz = GateInstructionRegistry::instance()->create("Rz", std::vector<int>{0});
rz->setParameter(0, p);
BOOST_VERIFY(rz->getName() == "Rz");
BOOST_VERIFY(rz->getParameter(0) == 3.14);
BOOST_VERIFY(boost::get<double>(rz->getParameter(0)) == 3.1415);
}
......@@ -99,7 +99,10 @@ public:
void visit(Rz& rz) {
baseGateInst(dynamic_cast<GateInstruction&>(rz), false);
writer->String("angle");
writer->Double(rz.getParameter(0));
auto p = rz.getParameter(0);
p.which() == 1 ? // Rz's parameter can only be of type double or string
writer->Double(boost::get<double>(p)) :
writer->String(boost::get<std::string>(p));
writer->EndObject();
}
......@@ -136,7 +139,7 @@ public:
void visit(Measure& cn) {
baseGateInst(dynamic_cast<GateInstruction&>(cn), false);
writer->String("classicalBitIdx");
writer->Int(cn.getParameter(0));
writer->Int(cn.getClassicalBitIndex());
writer->EndObject();
}
......
......@@ -119,16 +119,17 @@ int main(int argc, char** argv) {
std::shared_ptr<xacc::Instruction> inst;
if (gateCommand[0] == "MeasZ" || gateCommand[0] == "MeasX"
|| gateCommand[0] == "Measure") {
inst = xacc::quantum::ParameterizedGateInstructionRegistry<
int>::instance()->create("Measure", actingQubits,
c);
inst = xacc::quantum::GateInstructionRegistry::instance()->create("Measure", actingQubits);
xacc::InstructionParameter p(c);
inst->setParameter(0, p);
c++;
} else {