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

adding persistable interface, making Function persistable, minor updates to observable


Signed-off-by: Mccaskey, Alex's avatarAlex McCaskey <mccaskeyaj@ornl.gov>
parent 5f39537c
Pipeline #46610 failed with stages
in 6 minutes and 38 seconds
......@@ -31,7 +31,11 @@ public:
PyXACCVisitor() { pyxaccStr += "@qpu()\ndef foo(buffer):\n"; }
void visit(IRGenerator& irg) {
pyxaccStr += " " + irg.name() + "()\n";
pyxaccStr += " " + irg.name() + "(buffer";
for (auto&kv : irg.getOptions()) {
pyxaccStr += ","+kv.first +"="+kv.second.toString();
}
pyxaccStr += ")\n";
}
/**
* Visit hadamard gates
......
......@@ -193,6 +193,13 @@ const int nRequiredBits() const override {
return weights;
}
void persist(std::ostream &outStream) override {
}
void load(std::istream &inStream) override {
}
InstructionParameter getParameter(const int idx) const override {
return parameters[idx];
}
......
......@@ -3,6 +3,7 @@
#include <ctype.h>
#include <memory>
#include <string>
#include "Function.hpp"
#include "InstructionIterator.hpp"
#include "IRToGraphVisitor.hpp"
#include "IRGenerator.hpp"
......@@ -10,6 +11,13 @@
#include "Graph.hpp"
#include "JsonVisitor.hpp"
#define RAPIDJSON_HAS_STDSTRING 1
#include "rapidjson/document.h"
#include "rapidjson/prettywriter.h"
using namespace rapidjson;
namespace xacc {
namespace quantum {
......@@ -19,15 +27,137 @@ void GateFunction::mapBits(std::vector<int> bitMap) {
}
}
void GateFunction::persist(std::ostream &outStream) {
JsonVisitor<PrettyWriter<StringBuffer>, StringBuffer> visitor(
shared_from_this());
outStream << visitor.write();
}
// {
// "kernels": [
// {
// "function": "foo",
// "instructions": [
// {
// "gate": "H",
// "enabled": true,
// "qubits": [
// 1
// ]
// },
// {
// "gate": "CNOT",
// "enabled": true,
// "qubits": [
// 0,
// 1
// ]
// }
// ]
// }
// ]
// }
void GateFunction::load(std::istream &inStream) {
std::vector<std::string> irGeneratorNames;
auto irgens = xacc::getRegisteredIds<xacc::IRGenerator>();
for (auto &irg : irgens) {
irGeneratorNames.push_back(irg);
}
auto provider = xacc::getService<IRProvider>("gate");
std::string json(std::istreambuf_iterator<char>(inStream), {});
// std::cout << "JSON: " << json << "\n";
Document doc;
doc.Parse(json);
auto &kernel = doc["kernels"].GetArray()[0];
functionName = kernel["function"].GetString();
auto instructionsArray = kernel["instructions"].GetArray();
for (int i = 0; i < instructionsArray.Size(); i++) {
auto &inst = instructionsArray[i];
auto gname = inst["gate"].GetString();
bool isAnIRG = false;
if (std::find(irGeneratorNames.begin(), irGeneratorNames.end(), gname) != irGeneratorNames.end()) {
// this is an IRG
isAnIRG = true;
}
std::vector<int> qbits;
auto bitsArray = inst["qubits"].GetArray();
for (int k = 0; k < bitsArray.Size(); k++) {
qbits.push_back(bitsArray[k].GetInt());
}
std::vector<InstructionParameter> local_parameters;
auto &paramsArray = inst["parameters"];
for (int k = 0; k < paramsArray.Size(); k++) {
auto &value = paramsArray[k];
if (value.IsInt()) {
local_parameters.push_back(InstructionParameter(value.GetInt()));
} else if (value.IsDouble()) {
local_parameters.push_back(InstructionParameter(value.GetDouble()));
} else {
local_parameters.push_back(InstructionParameter(value.GetString()));
}
}
std::shared_ptr<Instruction> instToAdd;
if (!isAnIRG) {
instToAdd =
provider->createInstruction(gname, qbits, local_parameters);
} else {
instToAdd = xacc::getService<IRGenerator>(gname);
}
auto &optionsObj = inst["options"];
for (auto itr = optionsObj.MemberBegin(); itr != optionsObj.MemberEnd();
++itr) {
auto &value = optionsObj[itr->name.GetString()];
if (value.IsInt()) {
instToAdd->setOption(itr->name.GetString(),
InstructionParameter(value.GetInt()));
} else if (value.IsDouble()) {
instToAdd->setOption(itr->name.GetString(),
InstructionParameter(value.GetDouble()));
} else {
instToAdd->setOption(itr->name.GetString(),
InstructionParameter(value.GetString()));
}
}
if (!inst["enabled"].GetBool()) {
instToAdd->disable();
}
addInstruction(instToAdd);
}
}
void GateFunction::expandIRGenerators(
std::map<std::string, InstructionParameter> irGenMap) {
std::list<InstPtr> newinsts;
for (int idx = 0; idx < nInstructions(); idx++) {
auto inst = getInstruction(idx);
auto irg = std::dynamic_pointer_cast<IRGenerator>(inst);
if (irg) {
auto evaluated = irg->generate(irGenMap);
replaceInstruction(idx, evaluated);
// replaceInstruction(idx, evaluated);
for (auto i : evaluated->getInstructions()) {
newinsts.push_back(i);
}
} else {
newinsts.push_back(inst);
}
}
instructions.clear();
for (auto i : newinsts) {
addInstruction(i);
}
}
......@@ -410,11 +540,11 @@ GateFunction::operator()(const std::vector<double> &params) {
}
const int GateFunction::depth() { return toGraph()->depth() - 2; }
const std::string GateFunction::persistGraph() {
const std::string GateFunction::persistGraph() {
std::stringstream s;
toGraph()->write(s);
return s.str();
}
}
std::shared_ptr<Graph> GateFunction::toGraph() {
......
......@@ -72,6 +72,9 @@ public:
return 0;
}
void persist(std::ostream &outStream) override;
void load(std::istream &inStream) override;
InstPtr getInstruction(const int idx) override;
std::list<InstPtr> getInstructions() override;
......
......@@ -56,13 +56,6 @@ void GateIR::persist(std::ostream &outStream) {
JsonVisitor<PrettyWriter<StringBuffer>,StringBuffer> visitor(kernels);
outStream << visitor.write();
// StringBuffer sb;
// PrettyWriter<StringBuffer> writer(sb);
//
// serializeJson(writer);
//
// outStream << sb.GetString();
return;
}
......
......@@ -29,7 +29,7 @@ public:
*/
GateIR() {}
virtual const int maxBit() {
const int maxBit() override {
int maxBit = 0;
for (auto k : kernels) {
for (auto inst : k->getInstructions()) {
......@@ -47,13 +47,13 @@ public:
* Add a quantum function to this intermediate representation.
* @param kernel
*/
virtual void addKernel(std::shared_ptr<Function> kernel) {
void addKernel(std::shared_ptr<Function> kernel) override {
kernels.push_back(kernel);
}
virtual const int numberOfKernels() { return kernels.size(); }
virtual std::shared_ptr<Function> getKernel(const std::string &name) {
std::shared_ptr<Function> getKernel(const std::string &name) override {
std::shared_ptr<Function> ret;
for (auto f : kernels) {
if (f->name() == name) {
......@@ -66,13 +66,13 @@ public:
return ret;
}
virtual bool kernelExists(const std::string &name) {
bool kernelExists(const std::string &name) override {
return std::any_of(
kernels.cbegin(), kernels.cend(),
[=](std::shared_ptr<Function> i) { return i->name() == name; });
}
virtual void mapBits(std::vector<int> bitMap) {
void mapBits(std::vector<int> bitMap) override {
for (auto k : kernels) {
k->mapBits(bitMap);
}
......@@ -83,8 +83,8 @@ public:
* intermediate representation
* @return
*/
virtual std::string toAssemblyString(const std::string &kernelName,
const std::string &accBufferVarName);
std::string toAssemblyString(const std::string &kernelName,
const std::string &accBufferVarName) override;
/**
* Persist this IR instance to the given
......@@ -92,7 +92,7 @@ public:
*
* @param outStream
*/
virtual void persist(std::ostream &outStream);
void persist(std::ostream &outStream) override;
/**
* Create this IR instance from the given input
......@@ -100,9 +100,9 @@ public:
*
* @param inStream
*/
virtual void load(std::istream &inStream);
void load(std::istream &inStream) override;
virtual std::vector<std::shared_ptr<Function>> getKernels() {
std::vector<std::shared_ptr<Function>> getKernels() override {
return kernels;
}
......
......@@ -222,6 +222,35 @@ TEST(GateFunctionTester, checkParameterInsertion) {
"Rx(0.5 * psi) qreg3\nRx(1 * phi) qreg4\nRy(1 * theta) qreg2\n");
}
TEST(GateFunctionTester, checkPersistLoad) {
auto f = std::make_shared<GateFunction>("foo");
auto h = std::make_shared<Hadamard>(1);
auto cn1 = std::make_shared<CNOT>(0, 1);
auto rz = std::make_shared<Rz>(0, 3.1415);
auto rz2 = std::make_shared<Rz>(std::vector<int>{1});
xacc::InstructionParameter p("phi");
rz2->setParameter(0, p);
h->setOption("key1", 3.3);
f->addInstruction(h);
f->addInstruction(cn1);
f->addInstruction(rz);
f->addInstruction(rz2);
std::stringstream ss;
f->persist(ss);
std::cout << ss.str() << "\n";
std::istringstream iss(ss.str());
auto newF = std::make_shared<GateFunction>("new");
newF->load(iss);
std::cout << "HELLO: " << newF->toString() << "\n";
}
TEST(GateFunctionTester, checkGenerateGraph) {
auto f = std::make_shared<GateFunction>("foo");
......
......@@ -295,6 +295,7 @@ public:
eval(const std::map<std::string, std::complex<double>> varToValMap);
bool isClose(PauliOperator &other);
int nQubits();
const int nBits() override {return nQubits();}
PauliOperator &operator+=(const PauliOperator &v) noexcept;
PauliOperator &operator-=(const PauliOperator &v) noexcept;
......
......@@ -27,17 +27,17 @@ using Writer = PrettyWriter<StringBuffer>;
/**
* FIXME write this
*/
template<class W, class B> JsonVisitor<W,B>::JsonVisitor(std::shared_ptr<xacc::Function> f)
template <class W, class B>
JsonVisitor<W, B>::JsonVisitor(std::shared_ptr<xacc::Function> f)
: buffer(std::make_shared<B>()),
writer(std::make_shared<W>(*buffer.get())),
functions{f} {}
writer(std::make_shared<W>(*buffer.get())), functions{f} {}
template<class W, class B> JsonVisitor<W,B>::JsonVisitor(std::vector<std::shared_ptr<xacc::Function>> fs)
: buffer(std::make_shared<B>()),
writer(std::make_shared<W>(*buffer.get())),
template <class W, class B>
JsonVisitor<W, B>::JsonVisitor(std::vector<std::shared_ptr<xacc::Function>> fs)
: buffer(std::make_shared<B>()), writer(std::make_shared<W>(*buffer.get())),
functions(fs) {}
template<class W, class B> std::string JsonVisitor<W,B>::write() {
template <class W, class B> std::string JsonVisitor<W, B>::write() {
writer->StartObject();
writer->String("kernels");
......@@ -71,91 +71,92 @@ template<class W, class B> std::string JsonVisitor<W,B>::write() {
writer->EndArray();
writer->EndObject();
return buffer->GetString();
}
template<class W, class B> void JsonVisitor<W,B>::visit(Rz &rz) {
baseGateInst(dynamic_cast<GateInstruction &>(rz), false);
writer->String("angle");
auto p = rz.getParameter(0);
switch (p.which()) {
case 0:
writer->Int(p.as<int>());
break;
case 1:
writer->Double(p.as<double>());
break;
case 2:
writer->String(p.as<std::string>());
break;
default:
xacc::error("Invalid InstructionParameter: " + p.toString());
}
writer->EndObject();
}
template<class W, class B> void JsonVisitor<W,B>::visit(Rx &rx) {
baseGateInst(dynamic_cast<GateInstruction &>(rx), false);
writer->String("angle");
auto p = rx.getParameter(0);
switch (p.which()) {
case 0:
writer->Int(p.as<int>());
break;
case 1:
writer->Double(p.as<double>());
break;
case 2:
writer->String(p.as<std::string>());
break;
default:
xacc::error("Invalid InstructionParameter: " + p.toString());
}
writer->EndObject();
}
template<class W, class B> void JsonVisitor<W,B>::visit(Ry &ry) {
baseGateInst(dynamic_cast<GateInstruction &>(ry), false);
writer->String("angle");
auto p = ry.getParameter(0);
switch (p.which()) {
case 0:
writer->Int(p.as<int>());
break;
case 1:
writer->Double(p.as<double>());
break;
case 2:
writer->String(p.as<std::string>());
break;
default:
xacc::error("Invalid InstructionParameter: " + p.toString());
}
writer->EndObject();
}
template<class W, class B> void JsonVisitor<W,B>::visit(CPhase &cp) {
baseGateInst(dynamic_cast<GateInstruction &>(cp), false);
writer->String("angle");
auto p = cp.getParameter(0);
switch (p.which()) {
case 0:
writer->Int(p.as<int>());
break;
case 1:
writer->Double(p.as<double>());
break;
case 2:
writer->String(p.as<std::string>());
break;
default:
xacc::error("Invalid InstructionParameter: " + p.toString());
}
writer->EndObject();
}
template<class W, class B> void JsonVisitor<W,B>::visit(ConditionalFunction &cn) {
}
template <class W, class B> void JsonVisitor<W, B>::visit(Rz &rz) {
baseGateInst(dynamic_cast<GateInstruction &>(rz));
// writer->String("angle");
// auto p = rz.getParameter(0);
// switch (p.which()) {
// case 0:
// writer->Int(p.as<int>());
// break;
// case 1:
// writer->Double(p.as<double>());
// break;
// case 2:
// writer->String(p.as<std::string>());
// break;
// default:
// xacc::error("Invalid InstructionParameter: " + p.toString());
// }
// writer->EndObject();
}
template <class W, class B> void JsonVisitor<W, B>::visit(Rx &rx) {
baseGateInst(dynamic_cast<GateInstruction &>(rx));
// writer->String("angle");
// auto p = rx.getParameter(0);
// switch (p.which()) {
// case 0:
// writer->Int(p.as<int>());
// break;
// case 1:
// writer->Double(p.as<double>());
// break;
// case 2:
// writer->String(p.as<std::string>());
// break;
// default:
// xacc::error("Invalid InstructionParameter: " + p.toString());
// }
// writer->EndObject();
}
template <class W, class B> void JsonVisitor<W, B>::visit(Ry &ry) {
baseGateInst(dynamic_cast<GateInstruction &>(ry));
// writer->String("angle");
// auto p = ry.getParameter(0);
// switch (p.which()) {
// case 0:
// writer->Int(p.as<int>());
// break;
// case 1:
// writer->Double(p.as<double>());
// break;
// case 2:
// writer->String(p.as<std::string>());
// break;
// default:
// xacc::error("Invalid InstructionParameter: " + p.toString());
// }
// writer->EndObject();
}
template <class W, class B> void JsonVisitor<W, B>::visit(CPhase &cp) {
baseGateInst(dynamic_cast<GateInstruction &>(cp));
// writer->String("angle");
// auto p = cp.getParameter(0);
// switch (p.which()) {
// case 0:
// writer->Int(p.as<int>());
// break;
// case 1:
// writer->Double(p.as<double>());
// break;
// case 2:
// writer->String(p.as<std::string>());
// break;
// default:
// xacc::error("Invalid InstructionParameter: " + p.toString());
// }
// writer->EndObject();
}
template <class W, class B>
void JsonVisitor<W, B>::visit(ConditionalFunction &cn) {
writer->StartObject();
writer->String("conditional_function");
writer->String(cn.name());
......@@ -183,21 +184,86 @@ template<class W, class B> std::string JsonVisitor<W,B>::write() {
// the conditional function
for (int i = 0; i < nInsts; i++)
topLevelInstructionIterator->next();
}
template <class W, class B> void JsonVisitor<W, B>::visit(Measure &cn) {
baseGateInst(dynamic_cast<GateInstruction &>(cn));
// writer->String("classicalBitIdx");
// writer->Int(cn.getClassicalBitIndex());
// writer->EndObject();
}
template <class W, class B> void JsonVisitor<W, B>::visit(U &u) {
baseGateInst(dynamic_cast<GateInstruction &>(u));
// writer->String("theta");
// auto p = u.getParameter(0);
// switch (p.which()) {
// case 0:
// writer->Int(p.as<int>());
// break;
// case 1:
// writer->Double(p.as<double>());
// break;
// case 2:
// writer->String(p.as<std::string>());
// break;
// default:
// xacc::error("Invalid InstructionParameter: " + p.toString());
// }
// writer->String("phi");
// auto p2 = u.getParameter(1);
// switch (p.which()) {
// case 0:
// writer->Int(p.as<int>());
// break;
// case 1:
// writer->Double(p.as<double>());
// break;
// case 2:
// writer->String(p.as<std::string>());
// break;
// default:
// xacc::error("Invalid InstructionParameter: " + p.toString());
// }
// writer->String("lambda");
// auto p3 = u.getParameter(2);
// switch (p.which()) {
// case 0:
// writer->Int(p.as<int>());
// break;
// case 1:
// writer->Double(p.as<double>());
// break;