GateQIR.hpp 5.38 KB
Newer Older
1
2
3
4
5
6
7
8
/*******************************************************************************
 * Copyright (c) 2017 UT-Battelle, LLC.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * and Eclipse Distribution License v1.0 which accompanies this
 * distribution. The Eclipse Public License is available at
 * http://www.eclipse.org/legal/epl-v10.html and the Eclipse Distribution License
 * is available at https://eclipse.org/org/documents/edl-v10.php
9
10
 *
 * Contributors:
11
12
 *   Alexander J. McCaskey - initial API and implementation
 *******************************************************************************/
13
14
15
#ifndef QUANTUM_GATE_GATEQIR_HPP_
#define QUANTUM_GATE_GATEQIR_HPP_

16
17
18
#include "GateInstruction.hpp"
#include "GateFunction.hpp"
#include "InstructionIterator.hpp"
Mccaskey, Alex's avatar
Mccaskey, Alex committed
19
20
#include "Graph.hpp"
#include "IR.hpp"
21
22
23

#include "Hadamard.hpp"
#include "CNOT.hpp"
24
25
26
27
28
#include "X.hpp"
#include "Z.hpp"
#include "ConditionalFunction.hpp"
#include "Rz.hpp"
#include "Measure.hpp"
29

30
31
32
33
34
35
36
37
38
39
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
 */
Mccaskey, Alex's avatar
Mccaskey, Alex committed
40
41
class CircuitNode: public XACCVertex<std::string, int, int, std::vector<int>,
		bool, std::vector<std::string>> {
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
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;

	}
};

/**
60
61
62
 * 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).
63
64
 *
 */
65
class GateQIR: public xacc::IR, public Graph<CircuitNode> {
Mccaskey, Alex's avatar
Mccaskey, Alex committed
66

67
68
public:

69
70
71
	/**
	 * The nullary Constructor
	 */
Mccaskey, Alex's avatar
Mccaskey, Alex committed
72
73
	GateQIR() {
	}
74
75

	/**
76
77
78
	 * This method takes the list of quantum instructions that this
	 * QIR contains and creates a graph representation of the
	 * quantum circuit.
79
	 */
80
	virtual void generateGraph(const std::string& kernelName);
81

82
83
84
85
86
87
88
89
90
91
92
93
94
95
	virtual const int maxBit() {
		int maxBit = 0;
		for (auto k : kernels) {
			for (auto inst : k->getInstructions()) {
				for (auto b : inst->bits()) {
					if (b > maxBit) {
						maxBit = b;
					}
				}
			}
		}
		return maxBit;
	}

Mccaskey, Alex's avatar
Mccaskey, Alex committed
96
97
98
99
100
101
102
103
104
105
106
107
108
	/**
	 * Add a quantum function to this intermediate representation.
	 * @param kernel
	 */
	virtual void addKernel(std::shared_ptr<Function> kernel) {
		kernels.push_back(kernel);
	}

	virtual const int numberOfKernels() {
		return kernels.size();
	}

	virtual std::shared_ptr<Function> getKernel(const std::string& name) {
109
		std::shared_ptr<Function> ret;
Mccaskey, Alex's avatar
Mccaskey, Alex committed
110
		for (auto f : kernels) {
111
			if (f->name() == name) {
112
				ret = f;
Mccaskey, Alex's avatar
Mccaskey, Alex committed
113
114
			}
		}
115
116
117
118
		if (!ret) {
			xacc::error("Invalid kernel name.");
		}
		return ret;
Mccaskey, Alex's avatar
Mccaskey, Alex committed
119
120
	}

121
122
	virtual bool kernelExists(const std::string& name) {
		return std::any_of(kernels.cbegin(), kernels.cend(),
123
				[=](std::shared_ptr<Function> i) {return i->name() == name;});
124
125
	}

126
127
128
129
130
131
	virtual void mapBits(std::vector<int> bitMap) {
		for (auto k : kernels) {
			k->mapBits(bitMap);
		}
	}

132
133
134
135
136
	/**
	 * Return a string representation of this
	 * intermediate representation
	 * @return
	 */
137
	virtual std::string toAssemblyString(const std::string& kernelName, const std::string& accBufferVarName);
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164

	/**
	 * 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);

165
166
167
168
	virtual std::vector<std::shared_ptr<Function>> getKernels() {
		return kernels;
	}

169
170
171
172
173
174
	/**
	 * The destructor
	 */
	virtual ~GateQIR() {
	}

Mccaskey, Alex's avatar
Mccaskey, Alex committed
175
176
177
178
179
180
181
protected:

	/**
	 * Reference to this QIR's list of quantum functions
	 */
	std::vector<std::shared_ptr<Function>> kernels;

182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
private:

	/**
	 * 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);
221
222
223
224
};
}
}
#endif