Maestro 0.1.0
Unified interface for quantum circuit simulation
Loading...
Searching...
No Matches
NetworkJob.h
Go to the documentation of this file.
1
10#pragma once
11
12#ifndef _NETWORK_JOB_H
13#define _NETWORK_JOB_H
14
15#include "../Types.h"
16#include "../Utils/ThreadsPool.h"
17
18namespace Network {
19
20template <typename Time = Types::time_type>
22 public:
24
25 ExecuteJob() = delete;
26
27 explicit ExecuteJob(const std::shared_ptr<Circuits::Circuit<Time>> &c,
28 ExecuteResults &r, size_t cnt, size_t nq, size_t nc,
29 size_t ncr, Simulators::SimulatorType t,
30 Simulators::SimulationType m, std::mutex &mut)
31 : dcirc(c),
32 res(r),
33 curCnt(cnt),
34 nrQubits(nq),
35 nrCbits(nc),
36 nrResultCbits(ncr),
37 simType(t),
38 method(m),
39 resultsMutex(mut) {}
40
41 void DoWork() {
42 if (curCnt == 0) return;
43
45 state.AllocateBits(nrCbits);
46
47 const bool hasMeasurementsOnlyAtEnd = !dcirc->HasOpsAfterMeasurements();
48 const bool optimiseMultipleShots = optimiseMultipleShotsExecution;
49 const bool specialOptimizationForStatevector =
50 optimiseMultipleShots &&
52 hasMeasurementsOnlyAtEnd;
53 const bool specialOptimizationForMPS =
54 optimiseMultipleShots &&
56 hasMeasurementsOnlyAtEnd;
57
58 if (!optSim) {
60 if (!optSim) return;
61
62 if (!maxBondDim.empty())
63 optSim->Configure("matrix_product_state_max_bond_dimension",
64 maxBondDim.c_str());
65 if (!singularValueThreshold.empty())
66 optSim->Configure("matrix_product_state_truncation_threshold",
68 if (!mpsSample.empty())
69 optSim->Configure("mps_sample_measure_algorithm", mpsSample.c_str());
70
71 optSim->AllocateQubits(nrQubits);
72 optSim->Initialize();
73
74 if (optimiseMultipleShots) {
75 executedGates = dcirc->ExecuteNonMeasurements(optSim, state);
76
77 if (!specialOptimizationForStatevector && !specialOptimizationForMPS &&
78 curCnt > 1)
79 optSim->SaveState();
80 }
81 }
82
83 std::shared_ptr<Circuits::MeasurementOperation<Time>> measurementsOp;
84
85 const std::vector<bool> executed = std::move(executedGates);
86
87 if (optimiseMultipleShots && hasMeasurementsOnlyAtEnd) {
88 bool isQiskitAer = false;
89#ifndef NO_QISKIT_AER
91 isQiskitAer = true;
92 }
93#endif
94 measurementsOp = dcirc->GetLastMeasurements(executed, isQiskitAer);
95 const auto &qbits = measurementsOp->GetQubits();
96 if (qbits.empty()) {
97 auto bits = state.GetAllBits();
98 bits.resize(nrResultCbits, false);
99
100 const std::lock_guard lock(resultsMutex);
101 res[bits] += curCnt;
102
103 return;
104 }
105 }
106
107 ExecuteResults localRes;
108
109 if (optimiseMultipleShots &&
110 (specialOptimizationForStatevector || hasMeasurementsOnlyAtEnd)) {
111 const auto &qbits = measurementsOp->GetQubits();
112
113 const auto sampleres = optSim->SampleCounts(qbits, curCnt);
114
115 for (const auto &[mstate, cnt] : sampleres) {
116 measurementsOp->SetStateFromSample(mstate, state);
117
118 auto bits = state.GetAllBits();
119 bits.resize(nrResultCbits, false);
120
121 localRes[bits] += cnt;
122
123 state.Reset();
124 }
125
126 const std::lock_guard lock(resultsMutex);
127 for (const auto &r : localRes) res[r.first] += r.second;
128
129 return;
130 }
131
132 const auto curCnt1 = curCnt > 0 ? curCnt - 1 : 0;
133 for (size_t i = 0; i < curCnt; ++i) {
134 if (optimiseMultipleShots) {
135 if (i > 0) optSim->RestoreState();
136 dcirc->ExecuteMeasurements(optSim, state, executed);
137 } else {
138 dcirc->Execute(optSim, state);
139 if (i < curCnt1) optSim->Reset();
140 }
141
142 auto bits = state.GetAllBits();
143 bits.resize(nrResultCbits, false);
144
145 ++localRes[bits];
146
147 state.Reset();
148 }
149
150 const std::lock_guard lock(resultsMutex);
151 for (const auto &r : localRes) res[r.first] += r.second;
152 }
153
155 if (curCnt == 0) return;
156
158 state.AllocateBits(nrCbits);
159
160 const bool hasMeasurementsOnlyAtEnd = !dcirc->HasOpsAfterMeasurements();
161 const bool optimiseMultipleShots = optimiseMultipleShotsExecution;
162 const bool specialOptimizationForStatevector =
163 optimiseMultipleShots &&
165 hasMeasurementsOnlyAtEnd;
166 const bool specialOptimizationForMPS =
167 optimiseMultipleShots &&
169 hasMeasurementsOnlyAtEnd;
170
171 if (optSim) {
172 optSim->SetMultithreading(true);
173
174 if (optSim->GetNumberOfQubits() != nrQubits) {
175 optSim->Clear();
176
177 if (!maxBondDim.empty())
178 optSim->Configure("matrix_product_state_max_bond_dimension",
179 maxBondDim.c_str());
180 if (!singularValueThreshold.empty())
181 optSim->Configure("matrix_product_state_truncation_threshold",
182 singularValueThreshold.c_str());
183 if (!mpsSample.empty())
184 optSim->Configure("mps_sample_measure_algorithm", mpsSample.c_str());
185
186 optSim->AllocateQubits(nrQubits);
187 optSim->Initialize();
188
189 if (optimiseMultipleShots) {
190 executedGates = dcirc->ExecuteNonMeasurements(optSim, state);
191
192 if (!specialOptimizationForStatevector &&
193 !specialOptimizationForMPS && curCnt > 1)
194 optSim->SaveState();
195 }
196 } else if (executedGates.size() == dcirc->size()) {
197 // special case for when the simulator is passed from the network
198 // and no gates were executed yet
199 bool needToExecuteGates = true;
200 for (const bool val : executedGates) {
201 if (val) {
202 needToExecuteGates = false;
203 break;
204 }
205 }
206 if (needToExecuteGates && optimiseMultipleShots) {
207 executedGates = dcirc->ExecuteNonMeasurements(optSim, state);
208 if (!specialOptimizationForStatevector &&
209 !specialOptimizationForMPS && curCnt > 1)
210 optSim->SaveState();
211 }
212 }
213 } else {
215 if (!optSim) return;
216
217 optSim->SetMultithreading(true);
218
219 if (!maxBondDim.empty())
220 optSim->Configure("matrix_product_state_max_bond_dimension",
221 maxBondDim.c_str());
222 if (!singularValueThreshold.empty())
223 optSim->Configure("matrix_product_state_truncation_threshold",
224 singularValueThreshold.c_str());
225 if (!mpsSample.empty())
226 optSim->Configure("mps_sample_measure_algorithm", mpsSample.c_str());
227
228 optSim->AllocateQubits(nrQubits);
229 optSim->Initialize();
230
231 if (optimiseMultipleShots) {
232 executedGates = dcirc->ExecuteNonMeasurements(optSim, state);
233
234 if (!specialOptimizationForStatevector && !specialOptimizationForMPS &&
235 curCnt > 1)
236 optSim->SaveState();
237 }
238 }
239
240 std::shared_ptr<Circuits::MeasurementOperation<Time>> measurementsOp;
241
242 const std::vector<bool> executed = std::move(executedGates);
243
244 if (optimiseMultipleShots && hasMeasurementsOnlyAtEnd) {
245 bool isQiskitAer = false;
246#ifndef NO_QISKIT_AER
248 isQiskitAer = true;
249 }
250#endif
251 measurementsOp = dcirc->GetLastMeasurements(executed, isQiskitAer);
252 const auto &qbits = measurementsOp->GetQubits();
253 if (qbits.empty()) {
254 auto bits = state.GetAllBits();
255 bits.resize(nrResultCbits, false);
256
257 res[bits] += curCnt;
258
259 return;
260 }
261 }
262
263 if (optimiseMultipleShots &&
264 (specialOptimizationForStatevector || hasMeasurementsOnlyAtEnd)) {
265 const auto &qbits = measurementsOp->GetQubits();
266
267 const auto sampleres = optSim->SampleCounts(qbits, curCnt);
268
269 for (const auto &[mstate, cnt] : sampleres) {
270 measurementsOp->SetStateFromSample(mstate, state);
271
272 auto bits = state.GetAllBits();
273 bits.resize(nrResultCbits, false);
274
275 res[bits] += cnt;
276
277 state.Reset();
278 }
279
280 return;
281 }
282
283 const auto curCnt1 = curCnt > 0 ? curCnt - 1 : 0;
284 for (size_t i = 0; i < curCnt; ++i) {
285 if (optimiseMultipleShots) {
286 if (i > 0) optSim->RestoreState();
287 dcirc->ExecuteMeasurements(optSim, state, executed);
288 } else {
289 dcirc->Execute(optSim, state);
290 if (i < curCnt1)
291 optSim->Reset(); // leave the simulator state for the last iteration
292 }
293
294 auto bits = state.GetAllBits();
295 bits.resize(nrResultCbits, false);
296
297 ++res[bits];
298
299 state.Reset();
300 }
301 }
302
304 size_t curCnt) {
305 return curCnt > 1;
306 }
307
308 size_t GetJobCount() const { return curCnt; }
309
310 const std::shared_ptr<Circuits::Circuit<Time>> dcirc;
312 const size_t curCnt;
313 const size_t nrQubits;
314 const size_t nrCbits;
315 const size_t nrResultCbits;
316
319 std::mutex &resultsMutex;
320
322 std::shared_ptr<Simulators::ISimulator> optSim;
323 std::vector<bool> executedGates;
324
325 // only fill them if passing null simulator
326 std::string maxBondDim;
328 std::string mpsSample;
329};
330
331} // namespace Network
332
333#endif // ! _NETWORK_JOB_H
Circuit class for holding the sequence of operations.
Definition Circuit.h:45
std::unordered_map< std::vector< bool >, size_t > ExecuteResults
The results of the execution of the circuit.
Definition Circuit.h:50
The state class that stores the classical state of a quantum circuit execution.
Definition Operations.h:62
void Reset(bool value=false)
Set the classical bits with the specified value.
Definition Operations.h:243
const std::vector< bool > & GetAllBits() const
Get the classical bits.
Definition Operations.h:213
void AllocateBits(size_t numBits)
Allocate more bits.
Definition Operations.h:159
ExecuteResults & res
Definition NetworkJob.h:311
bool optimiseMultipleShotsExecution
Definition NetworkJob.h:321
static bool IsOptimisableForMultipleShots(Simulators::SimulatorType t, size_t curCnt)
Definition NetworkJob.h:303
const Simulators::SimulatorType simType
Definition NetworkJob.h:317
std::string maxBondDim
Definition NetworkJob.h:326
const size_t curCnt
Definition NetworkJob.h:312
std::vector< bool > executedGates
Definition NetworkJob.h:323
typename Circuits::Circuit< Time >::ExecuteResults ExecuteResults
Definition NetworkJob.h:23
const size_t nrResultCbits
Definition NetworkJob.h:315
const size_t nrCbits
Definition NetworkJob.h:314
ExecuteJob(const std::shared_ptr< Circuits::Circuit< Time > > &c, ExecuteResults &r, size_t cnt, size_t nq, size_t nc, size_t ncr, Simulators::SimulatorType t, Simulators::SimulationType m, std::mutex &mut)
Definition NetworkJob.h:27
const std::shared_ptr< Circuits::Circuit< Time > > dcirc
Definition NetworkJob.h:310
std::shared_ptr< Simulators::ISimulator > optSim
Definition NetworkJob.h:322
std::mutex & resultsMutex
Definition NetworkJob.h:319
const size_t nrQubits
Definition NetworkJob.h:313
std::string mpsSample
Definition NetworkJob.h:328
const Simulators::SimulationType method
Definition NetworkJob.h:318
std::string singularValueThreshold
Definition NetworkJob.h:327
size_t GetJobCount() const
Definition NetworkJob.h:308
static std::shared_ptr< ISimulator > CreateSimulator(SimulatorType t=SimulatorType::kQCSim, SimulationType method=SimulationType::kMatrixProductState)
Create a quantum computing simulator.
Definition Factory.cpp:77
SimulationType
The type of simulation.
Definition State.h:79
@ kStatevector
statevector simulation type
@ kMatrixProductState
matrix product state simulation type
SimulatorType
The type of simulator.
Definition State.h:63
@ kQiskitAer
qiskit aer simulator type