-
Mccaskey, Alex authoredMccaskey, Alex authored
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
GateQIR.hpp 8.38 KiB
/***********************************************************************************
* 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_GATEQIR_HPP_
#define QUANTUM_GATE_GATEQIR_HPP_
#include "QIR.hpp"
#include "GateInstruction.hpp"
#include "GateFunction.hpp"
#include "InstructionIterator.hpp"
#include "Hadamard.hpp"
#include "CNOT.hpp"
#include "X.hpp"
#include "Z.hpp"
#include "ConditionalFunction.hpp"
#include "Rz.hpp"
#include "Measure.hpp"
#define RAPIDJSON_HAS_STDSTRING 1
namespace xacc {
namespace quantum {
/**
* CircuitNode subclasses QCIVertex to provide the following
* parameters in the given order:
*
* Parameters: Gate, Layer (ie time sequence), Gate Vertex Id,
* Qubit Ids that the gate acts on, enabled state, vector of parameters names
*/
class CircuitNode: public XACCVertex<std::string, int, int, std::vector<int>,
bool, std::vector<std::string>> {
public:
CircuitNode() :
XACCVertex() {
propertyNames[0] = "Gate";
propertyNames[1] = "Circuit Layer";
propertyNames[2] = "Gate Vertex Id";
propertyNames[3] = "Gate Acting Qubits";
propertyNames[4] = "Enabled";
propertyNames[5] = "RuntimeParameters";
// by default all circuit nodes
// are enabled and
std::get<4>(properties) = true;
}
};
template<typename Writer>
class JsonSerializerGateVisitor:
public BaseInstructionVisitor,
public InstructionVisitor<GateFunction>,
public InstructionVisitor<Hadamard>,
public InstructionVisitor<CNOT>,
public InstructionVisitor<Rz>,
public InstructionVisitor<ConditionalFunction>,
public InstructionVisitor<X>,
public InstructionVisitor<Z>,
public InstructionVisitor<Measure> {
protected:
Writer& writer;
std::string currentFuncName;
std::string previousFuncName;
std::map<std::string, int> subInstMap;
public:
JsonSerializerGateVisitor(Writer& w) : writer(w) {}
void baseGateInst(GateInstruction& inst, bool endObject = true) {
writer.StartObject();
writer.String("gate");
writer.String(inst.getName().c_str());
writer.String("enabled");
writer.Bool(inst.isEnabled());
writer.String("qubits");
writer.StartArray();
for (auto qi : inst.bits()) {
writer.Int(qi);
}
writer.EndArray();
if (endObject) {
writer.EndObject();
}
subInstMap[currentFuncName]--;
if (subInstMap[currentFuncName] == 0) {
std::cout << "ENDING " << currentFuncName << ", setting " << previousFuncName << "\n";
endFunction();
currentFuncName = previousFuncName;
}
}
void visit(Hadamard& h) {
baseGateInst(dynamic_cast<GateInstruction&>(h));
}
void visit(CNOT& cn) {
baseGateInst(dynamic_cast<GateInstruction&>(cn));
}
void visit(Rz& rz) {
baseGateInst(dynamic_cast<GateInstruction&>(rz), false);
writer.String("angle");
writer.Double(rz.getParameter(0));
writer.EndObject();
}
void visit(ConditionalFunction& cn) {
writer.StartObject();
writer.String("conditional_function");
writer.String(cn.getName());
writer.String("conditional_qubit");
writer.Int(cn.getConditionalQubit());
writer.String("instructions");
writer.StartArray();
subInstMap.insert(std::make_pair(cn.getName(), cn.nInstructions()));
previousFuncName = currentFuncName;
currentFuncName = cn.getName();
}
void visit(Measure& cn) {
// baseGateInst(dynamic_cast<GateInstruction&>(cn));
baseGateInst(dynamic_cast<GateInstruction&>(cn), false);
writer.String("classicalBitIdx");
writer.Int(cn.getParameter(0));
writer.EndObject();
}
void visit(X& cn) {
baseGateInst(dynamic_cast<GateInstruction&>(cn));
}
void visit(Z& cn) {
baseGateInst(dynamic_cast<GateInstruction&>(cn));
}
void visit(GateFunction& function) {
writer.StartObject();
writer.String("function");
writer.String(function.getName());
writer.String("instructions");
writer.StartArray();
subInstMap.insert(std::make_pair(function.getName(), function.nInstructions()));
currentFuncName = function.getName();
}
private:
void endFunction() {
writer.EndArray();
writer.EndObject();
}
};
/**
* The GateQIR is an implementation of the QIR for gate model quantum
* computing. It provides a Graph node type that models a quantum
* circuit gate (CircuitNode).
*
*/
class GateQIR: public virtual QIR<xacc::quantum::CircuitNode> {
public:
/**
* The nullary Constructor
*/
GateQIR() {
}
/**
* This method takes the list of quantum instructions that this
* QIR contains and creates a graph representation of the
* quantum circuit.
*/
virtual void generateGraph(const std::string& kernelName);
/**
* Return a string representation of this
* intermediate representation
* @return
*/
virtual std::string toAssemblyString(const std::string& kernelName, const std::string& accBufferVarName);
/**
* Persist this IR instance to the given
* output stream.
*
* @param outStream
*/
virtual void persist(std::ostream& outStream);
/**
* Create this IR instance from the given input
* stream.
*
* @param inStream
*/
virtual void load(std::istream& inStream);
/**
* This is the implementation of the Graph.read method...
*
* Read in a graphviz dot graph from the given input
* stream. This is left for subclasses.
*
* @param stream
*/
virtual void read(std::istream& stream);
/**
* The destructor
*/
virtual ~GateQIR() {
}
private:
template<typename Writer>
void serializeJson(Writer& writer) {
std::string retStr = "";
auto visitor = std::make_shared<JsonSerializerGateVisitor<Writer>>(
writer);
writer.StartArray();
for (auto kernel : kernels) {
InstructionIterator it(kernel);
while (it.hasNext()) {
// Get the next node in the tree
auto nextInst = it.next();
nextInst->accept(visitor);
}
writer.EndArray();
writer.EndObject();
}
writer.EndArray();
}
/**
* This method determines if a new layer should be added to the circuit.
*
* @param gateCommand
* @param qubitVarNameToId
* @param gates
* @param currentLayer
* @return
*/
bool incrementLayer(const std::vector<std::string>& gateCommand,
std::map<std::string, int>& qubitVarNameToId,
const std::vector<CircuitNode>& gates, const int& currentLayer);
/**
* Generate all edges for the circuit graph starting at
* the given layer.
*
* @param layer
* @param graph
* @param gateOperations
* @param initialStateId
*/
void generateEdgesFromLayer(const int layer,
std::vector<CircuitNode>& gateOperations, int initialStateId);
/**
* Create connecting conditional nodes that link the main
* circuit graph to subsequent conditional graphs. The conditional
* nodes can be used by Accelerators to figure out if the condition
* code should be executed or not.
* s
* @param mainGraph
* @param conditionalGraphs
*/
// static void linkConditionalQasm(QuantumCircuit& mainGraph,
// std::vector<QuantumCircuit>& conditionalGraphs,
// std::vector<int>& conditionalQubits);
};
}
}
#endif