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

adding work on open pulse instructions


Signed-off-by: Mccaskey, Alex's avatarAlex McCaskey <mccaskeyaj@ornl.gov>
parent e69d4712
......@@ -16,6 +16,7 @@
#include "Properties.hpp"
#include "QObjectExperimentVisitor.hpp"
#include "OpenPulseVisitor.hpp"
#define RAPIDJSON_HAS_STDSTRING 1
......@@ -28,6 +29,9 @@ using namespace rapidjson;
#include "QObject.hpp"
#include "pulse_instruction.hpp"
#include "pulse_composite.hpp"
#include <regex>
#include <thread>
......@@ -132,6 +136,7 @@ void IBMAccelerator::initialize(const HeterogeneousMap &params) {
auto j = json::parse("{\"backends\":" + response + "}");
from_json(j, backends_root);
getBackendPropsResponse = "{\"backends\":" + response + "}";
auto backendArray = d.GetArray();
for (auto &b : backends_root.get_backends()) {
......@@ -170,6 +175,101 @@ void IBMAccelerator::initialize(const HeterogeneousMap &params) {
}
}
void IBMAccelerator::contributeInstructions() {
auto j = json::parse(getBackendPropsResponse);
auto backends = j["backends"];
for (auto it = backends.begin(); it != backends.end(); ++it) {
auto t = (*it)["name"].get<std::string>();
if ((*it)["name"].get<std::string>() == backend) {
// std::cout << "Contributing analog instructions from " << backend <<
// "\n";
auto pulse_library =
(*it)["specificConfiguration"]["defaults"]["pulse_library"];
auto cmd_defs = (*it)["specificConfiguration"]["defaults"]["cmd_def"];
int counter = 0;
for (auto pulse_iter = pulse_library.begin();
pulse_iter != pulse_library.end(); ++pulse_iter) {
auto pulse_name = (*pulse_iter)["name"].get<std::string>();
// std::cout << counter << ", Pulse: " << pulse_name << "\n";
auto samples =
(*pulse_iter)["samples"].get<std::vector<std::vector<double>>>();
std::vector<std::complex<double>> samplesCplx;
for (auto &s : samples)
samplesCplx.emplace_back(s[0], s[1]);
InstructionParameter tmpS(samplesCplx);
auto pulse = std::make_shared<PulseInstruction>(pulse_name);
pulse->setParameter(3, tmpS);
xacc::contributeService(pulse_name, pulse);
counter++;
}
// also add frame chagne
auto fc = std::make_shared<PulseInstruction>("fc");
xacc::contributeService("fc", fc);
auto aq = std::make_shared<PulseInstruction>("acquire");
xacc::contributeService("acquire", aq);
for (auto cmd_def_iter = cmd_defs.begin(); cmd_def_iter != cmd_defs.end();
++cmd_def_iter) {
auto cmd_def_name = (*cmd_def_iter)["name"].get<std::string>();
auto qbits = (*cmd_def_iter)["qubits"].get<std::vector<std::size_t>>();
std::string tmpName =
"pulse::" + cmd_def_name + "_" + std::to_string(qbits[0]);
if (qbits.size() == 2) {
tmpName += "_" + std::to_string(qbits[1]);
}
auto cmd_def = std::make_shared<PulseComposite>(tmpName);
std::cout << "CMD_DEF: " << tmpName << "\n";
auto sequence = (*cmd_def_iter)["sequence"];
for (auto seq_iter = sequence.begin(); seq_iter != sequence.end();
++seq_iter) {
auto inst_name = (*seq_iter)["name"].get<std::string>();
auto inst = xacc::getContributedService<Instruction>(inst_name);
if (inst_name != "acquire") {
auto channel = (*seq_iter)["ch"].get<std::string>();
auto t0 = (*seq_iter)["t0"].get<int>();
inst->setBits(qbits);
inst->setParameter(0, channel);
inst->setParameter(1, t0);
if ((*seq_iter).find("phase") != (*seq_iter).end()) {
// we have phase too
auto p = (*seq_iter)["phase"];
if (p.is_string()) {
// this is a variable we have to keep track of
auto ptmp = p.get<std::string>();
ptmp.erase(std::remove_if(ptmp.begin(), ptmp.end(),
[](char ch) {
return ch == '(' || ch == ')' ||
ch == '-';
}),
ptmp.end());
InstructionParameter phase(ptmp);
inst->setParameter(2, phase);
cmd_def->addVariable(ptmp);
} else {
InstructionParameter phase(p.get<double>());
inst->setParameter(2, phase);
}
}
}
cmd_def->addInstruction(inst);
}
cmd_def->setBits(qbits);
xacc::contributeService(tmpName, cmd_def);
}
}
}
}
const std::string IBMAccelerator::processInput(
std::shared_ptr<AcceleratorBuffer> buffer,
std::vector<std::shared_ptr<CompositeInstruction>> functions) {
......@@ -180,6 +280,7 @@ const std::string IBMAccelerator::processInput(
auto connectivity = getConnectivity();
if (!functions[0]->isAnalog()) {
// Create a QObj
xacc::ibm::QObject qobj;
qobj.set_qobj_id("xacc-qobj-id");
......@@ -274,6 +375,66 @@ const std::string IBMAccelerator::processInput(
// exit(0);
return jsonStr;
} else {
// This was an openpulse program
std::vector<json> experiments;
std::vector<json> pulseLibrary;
int maxMemSlots = 0;
for (auto &kernel : functions) {
auto visitor = std::make_shared<OpenPulseVisitor>();
InstructionIterator it(kernel);
int memSlots = 0;
while (it.hasNext()) {
auto nextInst = it.next();
if (nextInst->isEnabled()) {
nextInst->accept(visitor);
}
}
json instructions, experiment;
auto plElements = visitor->pulseLibraryJson;
for (auto& p : plElements) pulseLibrary.push_back(p);
instructions = visitor->instructionsJson;
experiment["instructions"] = instructions;
experiment["header"] = {};
experiments.push_back(experiment);
}
json config, qobj;
config["pulse_library"] = pulseLibrary;
config["shots"] = shots;
config["meas_level"] = 2;
config["rep_time"] = 1000;
config["memory_slot_size"] = 100;
config["meas_return"] = "avg";
config["meas_slots"] = 1;
config["qubit_lo_freq"] = std::vector<double>{};
config["meas_lo_freq"] = std::vector<double>{};
config["memory"] = false;
qobj["config"] = config;
qobj["schema_version"] = "1.1.0";
qobj["qobj_id"] = "xacc-id";
qobj["type"] = "PULSE";
qobj["experiments"] = experiments;
json header;
header["backend_name"] = backend;
header["backend_version"] = "1.2.1";
qobj["header"] = header;
json root, bcknd;
root["qObject"] = qobj;
bcknd["name"] = backend;
root["backend"] = bcknd;
root["shots"] = shots;
std::cout << root.dump(4) << "\n";
exit(0);
}
}
/**
......@@ -354,7 +515,7 @@ void IBMAccelerator::processResponse(std::shared_ptr<AcceleratorBuffer> buffer,
std::cout << std::endl;
// std::cout << "JOBRESPONSE:\n" << getResponse << "\n";
// std::cout << "JOBRESPONSE:\n" << getResponse << "\n";
jobIsRunning = false;
currentJobId = "";
......@@ -408,7 +569,8 @@ void IBMAccelerator::processResponse(std::shared_ptr<AcceleratorBuffer> buffer,
buffer->appendMeasurement(bitStr, nOccurrences);
} else {
tmpBuffer->appendMeasurement(bitStr, nOccurrences);
buffer->appendChild(currentExperiment.get_header().get_name(), tmpBuffer);
buffer->appendChild(currentExperiment.get_header().get_name(),
tmpBuffer);
}
}
}
......
......@@ -63,6 +63,8 @@ public:
return "ibm" + chosenBackend.get_name();
}
void contributeInstructions() override;
std::vector<std::pair<int, int>> getConnectivity() override;
std::vector<std::shared_ptr<IRTransformation>>
......@@ -115,6 +117,8 @@ private:
bool initialized = false;
xacc::ibm_backend::Backends backends_root;
std::map<std::string, xacc::ibm_properties::Properties> backendProperties;
std::string getBackendPropsResponse = "";
};
} // namespace quantum
......
......@@ -15,131 +15,68 @@
#include <memory>
#include "AllGateVisitor.hpp"
#include "pulse_instruction.hpp"
#include "pulse_composite.hpp"
#include "json.hpp"
using nlohmann::json;
namespace xacc {
namespace quantum {
/**
*/
class OpenPulseVisitor: public AllGateVisitor {
class OpenPulseVisitor: public BaseInstructionVisitor,
public InstructionVisitor<xacc::quantum::PulseInstruction>,
public InstructionVisitor<xacc::quantum::PulseComposite> {
protected:
constexpr static double pi = 3.1415926;
std::string instructions = "";
int runningTime = 0;
int currentTime = 0;
public:
std::vector<json> instructionsJson;
std::vector<json> pulseLibraryJson;
virtual const std::string name() const {
const std::string name() const override {
return "openpulse-visitor";
}
virtual const std::string description() const {
const std::string description() const override{
return "Map XACC IR to OpenPulse.";
}
OpenPulseVisitor() : OpenPulseVisitor("dummy") {}
OpenPulseVisitor(const std::string name) {
native = "{ \"name\": \"" + name + "\", \"instructions\": [";
}
const std::string toString() override {
return native;
}
/**
* Visit hadamard gates
*/
void visit(Hadamard& h) override {
xacc::error("digital 2 analog not supported for hadamard yet.");
}
void visit(Identity& i) override {
}
void visit(CZ& cz) override {
xacc::error("cz not supported");
void visit(PulseInstruction& i) override {
std::vector<std::complex<double>> samples = i.getParameter(3).as<std::vector<std::complex<double>>>();
std::vector<std::vector<double>> tmp;
for (auto& s : samples) tmp.push_back({s.real(), s.imag()});
json j, ij;
j["name"] = i.name();
if (i.name() == "fc") {
j["phase"] = i.getParameter(2).as<double>();
}
// j["samples"] = tmp;
pulseLibraryJson.push_back(j);
/**
* Visit CNOT gates
*/
void visit(CNOT& cn) override {
xacc::error("digital 2 analog not supported for CNOT yet.");
}
/**
* Visit X gates
*/
void visit(X& x) override {
xacc::error("digital 2 analog not supported for x yet.");
}
/**
*
*/
void visit(Y& y) override {
xacc::error("digital 2 analog not supported for y yet.");
}
/**
* Visit Z gates
*/
void visit(Z& z) override {
xacc::error("digital 2 analog not supported for z yet.");
}
void visit(U &u) override {
xacc::error("digital 2 analog not supported for u yet.");
}
/**
* Visit Measurement gates
*/
void visit(Measure& m) override {
xacc::error("digital 2 analog not supported for measure yet.");
}
/**
* Visit Conditional functions
*/
void visit(ConditionalFunction& c) override {
}
void visit(Rx& rx) override {
xacc::error("digital 2 analog not supported for rx yet.");
}
void visit(Ry& ry) override {
xacc::error("digital 2 analog not supported for ry yet.");
}
void visit(Rz& rz) override {
xacc::error("digital 2 analog not supported for rz yet.");
}
void visit(CPhase& cp) override {
xacc::error("digital 2 analog not supported for cphase yet.");
}
void visit(Swap& s) override {
CNOT c1(s.bits()), c2(s.bits()[1],s.bits()[0]), c3(s.bits());
visit(c1);
visit(c2);
visit(c3);
}
ij["name"] = i.name();
ij["ch"] = i.getParameter(0).toString();
ij["phase"] = i.getParameter(2).as<double>();
ij["t0"] = runningTime + i.getParameter(1).as<int>();
instructionsJson.push_back(ij);
void visit(GateFunction& f) override {
return;
currentTime = runningTime + i.getParameter(1).as<int>();
}
std::string getOpenPulseInstructionsJson() {
return native.substr(0,native.length()-1) + "]}";
void visit(PulseComposite& c) override {
runningTime += currentTime;
}
// append to pulse library function
/**
* The destructor
*/
virtual ~OpenPulseVisitor() {}
};
......
......@@ -65,6 +65,10 @@ public:
virtual std::vector<std::shared_ptr<IRTransformation>>
getIRTransformations() = 0;
virtual void contributeInstructions() {
return;
}
virtual const std::vector<double> getOneBitErrorRates() {
return std::vector<double>{};
}
......
......@@ -13,13 +13,14 @@
#ifndef XACC_IR_INSTRUCTION_HPP_
#define XACC_IR_INSTRUCTION_HPP_
#include <memory>
#include <complex>
#include "Cloneable.hpp"
#include "InstructionVisitor.hpp"
#include "heterogeneous.hpp"
namespace xacc {
using InstructionParameter = Variant<int,double,std::string>;
using InstructionParameter = Variant<int,double,std::string,std::vector<std::complex<double>>>;
// The Instruction interface exposes an API for describing a general
// post-Moore's law low-level assembly instruction. Each Instruction
......
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