QCOR
qrt.hpp
1 #ifndef RUNTIME_QCOR_QRT_HPP_
2 #define RUNTIME_QCOR_QRT_HPP_
3 
4 #include "Identifiable.hpp"
5 #include "qalloc.hpp"
6 #include <memory>
7 #include <unordered_map>
8 #include "qcor_ir.hpp"
9 
10 namespace qcor {
11  class Operator;
12 }
13 using namespace xacc::internal_compiler;
14 
15 namespace xacc {
16 class AcceleratorBuffer;
17 // class CompositeInstruction;
18 class Instruction;
19 class IRProvider;
20 class Observable;
21 } // namespace xacc
22 
23 namespace quantum {
24 
25 class QuantumRuntime : public xacc::Identifiable {
26 
27 public:
28  virtual void initialize(const std::string kernel_name) = 0;
29  virtual void __begin_mark_segment_as_compute() = 0;
30  virtual void __end_mark_segment_as_compute() = 0;
31  virtual bool isComputeSection() = 0;
32 
33  virtual void h(const qubit &qidx) = 0;
34  virtual void x(const qubit &qidx) = 0;
35  virtual void y(const qubit &qidx) = 0;
36  virtual void z(const qubit &qidx) = 0;
37  virtual void t(const qubit &qidx) = 0;
38  virtual void tdg(const qubit &qidx) = 0;
39  virtual void s(const qubit &qidx) = 0;
40  virtual void sdg(const qubit &qidx) = 0;
41 
42  // Common single-qubit, parameterized instructions
43  virtual void rx(const qubit &qidx, const double theta) = 0;
44  virtual void ry(const qubit &qidx, const double theta) = 0;
45  virtual void rz(const qubit &qidx, const double theta) = 0;
46  // U1(theta) gate
47  virtual void u1(const qubit &qidx, const double theta) = 0;
48  virtual void u3(const qubit &qidx, const double theta, const double phi,
49  const double lambda) = 0;
50  // Reset
51  virtual void reset(const qubit &qidx) = 0;
52  // Measure-Z
53  virtual bool mz(const qubit &qidx) = 0;
54 
55  // Common two-qubit gates.
56  virtual void cnot(const qubit &src_idx, const qubit &tgt_idx) = 0;
57  virtual void cy(const qubit &src_idx, const qubit &tgt_idx) = 0;
58  virtual void cz(const qubit &src_idx, const qubit &tgt_idx) = 0;
59  virtual void ch(const qubit &src_idx, const qubit &tgt_idx) = 0;
60  virtual void swap(const qubit &src_idx, const qubit &tgt_idx) = 0;
61 
62  // Common parameterized 2 qubit gates.
63  virtual void cphase(const qubit &src_idx, const qubit &tgt_idx,
64  const double theta) = 0;
65  virtual void crz(const qubit &src_idx, const qubit &tgt_idx,
66  const double theta) = 0;
67 
68  // exponential of i * theta * H, where H is an Observable pointer
69  // virtual void exp(qreg q, const double theta, xacc::Observable &H) = 0;
70  // virtual void exp(qreg q, const double theta, xacc::Observable *H) = 0;
71  virtual void exp(qreg q, const double theta,
72  qcor::Operator& H) = 0;
73 
74  virtual void general_instruction(std::shared_ptr<xacc::Instruction> inst) = 0;
75 
76  // Submission API. Submit the constructed CompositeInstruction operating
77  // on the provided AcceleratorBuffer(s) (note qreg wraps an AcceleratorBuffer)
78  virtual void submit(xacc::AcceleratorBuffer *buffer) = 0;
79  virtual void submit(xacc::AcceleratorBuffer **buffers,
80  const int nBuffers) = 0;
81 
82  // Some getters for the qcor runtime library.
83  virtual void
84  set_current_program(std::shared_ptr<qcor::CompositeInstruction> p) = 0;
85  virtual std::shared_ptr<qcor::CompositeInstruction> get_current_program() = 0;
86  virtual void set_current_buffer(xacc::AcceleratorBuffer *buffer) = 0;
87  // Ancilla qubit allocator:
88  // i.e. handle in kernel allocation.
89  virtual QubitAllocator *get_anc_qubit_allocator() = 0;
90 };
91 // This represents the public API for the xacc-enabled
92 // qcor quantum runtime library. The goal here is to provide
93 // and API that compilers can translate high-level
94 // quantum kernel language representations to
95 // (written in openqasm, quil, xasm, etc). The implementation of this API
96 // seeks to build up an xacc::CompositeInstruction with each individual
97 // quantum instruction invocation. Once done, clients can invoke
98 // the submit method to launch the built up program the
99 // user specified backend.
100 
101 // Clients must invoke initialize before building up the CompositeInstruction.
102 // This call will take the name of the backend and the name of the
103 // CompositeInstruction.
104 
105 // Note the qubit type is a typedef from xacc, falls back to a
106 // std::pair<std::string, std::size_t> where the string represents
107 // the variable name of the qubit register the qubit belongs to, and the
108 // size_t represents the qubit index in that register.
109 
110 extern int current_shots;
111 extern std::shared_ptr<QuantumRuntime> qrt_impl;
112 extern std::vector<std::string> kernels_in_translation_unit;
113 extern std::unordered_map<
114  std::string, std::pair<std::vector<std::string>, std::vector<std::string>>>
115  kernel_signatures_in_translation_unit;
116 
117 void initialize(const std::string qpu_name, const std::string kernel_name);
118 void set_shots(int shots);
119 int get_shots();
120 void set_backend(std::string accelerator_name);
121 void set_backend(std::string accelerator_name, const int shots);
122 void set_qrt(const std::string &qrt_name);
123 
124 // Common single-qubit gates.
125 void h(const qubit &qidx);
126 void x(const qubit &qidx);
127 void y(const qubit &qidx);
128 void z(const qubit &qidx);
129 void t(const qubit &qidx);
130 void tdg(const qubit &qidx);
131 void s(const qubit &qidx);
132 void sdg(const qubit &qidx);
133 // Reset a qubit (to zero state)
134 void reset(const qubit &qidx);
135 
136 // broadcast across qreg
137 void h(qreg q);
138 void x(qreg q);
139 void y(qreg q);
140 void z(qreg q);
141 void t(qreg q);
142 void tdg(qreg q);
143 void s(qreg q);
144 void sdg(qreg q);
145 void reset(qreg qidx);
146 
147 // Common single-qubit, parameterized instructions
148 void rx(const qubit &qidx, const double theta);
149 void ry(const qubit &qidx, const double theta);
150 void rz(const qubit &qidx, const double theta);
151 // U1(theta) gate
152 void u1(const qubit &qidx, const double theta);
153 void u3(const qubit &qidx, const double theta, const double phi,
154  const double lambda);
155 
156 // broadcast rotations across qubits
157 void rx(qreg qidx, const double theta);
158 void ry(qreg qidx, const double theta);
159 void rz(qreg qidx, const double theta);
160 // U1(theta) gate
161 void u1(qreg qidx, const double theta);
162 void u3(qreg qidx, const double theta, const double phi,
163  const double lambda);
164 
165 // Measure-Z and broadcast mz
166 bool mz(const qubit &qidx);
167 void mz(qreg q);
168 
169 // Common two-qubit gates.
170 void cnot(const qubit &src_idx, const qubit &tgt_idx);
171 void cy(const qubit &src_idx, const qubit &tgt_idx);
172 void cz(const qubit &src_idx, const qubit &tgt_idx);
173 void ch(const qubit &src_idx, const qubit &tgt_idx);
174 void swap(const qubit &src_idx, const qubit &tgt_idx);
175 
176 // Common parameterized 2 qubit gates.
177 void cphase(const qubit &src_idx, const qubit &tgt_idx, const double theta);
178 void crz(const qubit &src_idx, const qubit &tgt_idx, const double theta);
179 
180 // Broadcast two registers
181 void cnot(qreg src, qreg tgt);
182 void cy(qreg src, qreg tgt);
183 void cz(qreg src, qreg tgt);
184 void ch(qreg src, qreg tgt);
185 
186 // exponential of i * theta * H, where H is an Observable pointer
187 void exp(qreg q, const double theta, qcor::Operator &H);
188 // void exp(qreg q, const double theta, xacc::Observable *H);
189 // void exp(qreg q, const double theta, std::shared_ptr<xacc::Observable> H);
190 
191 // Submission API. Submit the constructed CompositeInstruction operating
192 // on the provided AcceleratorBuffer(s) (note qreg wraps an AcceleratorBuffer)
193 void submit(xacc::AcceleratorBuffer *buffer);
194 void submit(xacc::AcceleratorBuffer **buffers, const int nBuffers);
195 
196 // Some getters for the qcor runtime library.
197 void set_current_program(std::shared_ptr<qcor::CompositeInstruction> p);
198 
199 // Set the *runtime* buffer
200 void set_current_buffer(xacc::AcceleratorBuffer *buffer);
201 // std::shared_ptr<xacc::CompositeInstruction> getProgram();
202 // xacc::CompositeInstruction *program_raw_pointer();
203 
204 // // Clear the current program
205 // void clearProgram();
206 
207 // Persist bit-string result from single-bit measurements (if any)
208 void persistBitstring(xacc::AcceleratorBuffer *buffer);
209 
210 // Get the ancilla qubit allocator:
211 QubitAllocator *getAncillaQubitAllocator();
212 } // namespace quantum
213 
214 namespace xacc {
215 
216 namespace internal_compiler {
217 
218 // Optimization level: parsed from command line input.
219 // Convention:
220 // 0 : no optimization
221 // 1 : standard optimization (within reasonable walltime limit)
222 // 2 : extensive optimization (TBD)
223 extern int __opt_level;
224 // Should we print out the circuit optimizer stats.
225 // Disabled by default. Enabled by qcor CLI option.
226 extern bool __print_opt_stats;
227 
228 // User-customized passes to run
229 extern std::string __user_opt_passes;
230 
231 // Placement strategy specified in the QCOR command line.
232 extern std::string __placement_name;
233 // Qubit map for DefaultPlacement transformation.
234 // If provided in the command line (not empty),
235 // we'll map qubits according to this.
236 extern std::vector<int> __qubit_map;
237 extern std::vector<int> parse_qubit_map(const char *qubit_map_str);
238 extern void apply_decorators(const std::string &decorator_cmdline_string);
239 extern std::string __qrt_env;
240 // Print final CompositeInstruction for backend submission
241 extern bool __print_final_submission;
242 extern std::string __print_final_submission_filename;
243 
244 // Execute the pass manager on the provided kernel.
245 // If none provided, execute the pass manager on the current QRT kernel.
246 void execute_pass_manager(
247  std::shared_ptr<qcor::CompositeInstruction> optional_composite = nullptr);
248 
249 } // namespace internal_compiler
250 } // namespace xacc
251 namespace qcor {
252 // Ancilla qubit allocator:
254 public:
255  static inline const std::string ANC_BUFFER_NAME = "aux_temp_buffer";
256  virtual void onAllocate(xacc::internal_compiler::qubit *in_qubit) override {
257  // std::cout << "Allocate: " << (void *)in_qubit << "\n";
258  }
259 
260  // On deallocate: don't try to deref the qubit since it may have been gone.
261  virtual void onDealloc(xacc::internal_compiler::qubit *in_qubit) override;
262 
263  virtual xacc::internal_compiler::qubit allocate() override;
264  std::shared_ptr<xacc::AcceleratorBuffer> get_buffer() { return m_buffer; }
265 
266 protected:
267  std::vector<xacc::internal_compiler::qubit> m_qubitPool;
268  // Track the list of qubit pointers for those
269  // that was allocated by this Allocator.
270  std::vector<xacc::internal_compiler::qubit *> m_allocatedQubits;
271  std::shared_ptr<xacc::AcceleratorBuffer> m_buffer;
272 };
273 } // namespace qcor
274 #endif
qcor::Operator
Definition: qcor_observable.hpp:24
xacc::internal_compiler::QubitAllocator
Definition: qalloc.hpp:63
xacc::internal_compiler::qubit
Definition: qalloc.hpp:67
xacc::internal_compiler::AllocEventListener
Definition: qalloc.hpp:39
qcor
Definition: qcor_syntax_handler.cpp:15
xacc::internal_compiler::qreg
Definition: qalloc.hpp:101
qcor::AncQubitAllocator
Definition: qrt.hpp:253
quantum::QuantumRuntime
Definition: qrt.hpp:25