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