Maestro 0.3.1
Unified interface for quantum circuit simulation
Loading...
Searching...
No Matches
NetworkJob.h
Go to the documentation of this file.
1
10
11#pragma once
12
13#ifndef _NETWORK_JOB_H
14#define _NETWORK_JOB_H
15
16#include "../Types.h"
18
20
21#include "Network.h"
22
23#include "Configuration.h"
24
25namespace Network {
26
27template <typename Time = Types::time_type>
29 public:
31
32 ExecuteJob() = delete;
33
34 explicit ExecuteJob(const std::shared_ptr<Circuits::Circuit<Time>> &c,
35 ExecuteResults &r, size_t cnt, size_t nq, size_t nc,
36 size_t ncr, Simulators::SimulatorType t,
37 Simulators::SimulationType m, std::mutex &mut)
38 : dcirc(c),
39 res(r),
40 curCnt(cnt),
41 nrQubits(nq),
42 nrCbits(nc),
43 nrResultCbits(ncr),
44 simType(t),
45 method(m),
46 resultsMutex(mut) {}
47
48 void DoWork() {
49 if (curCnt == 0) return;
50
52 state.AllocateBits(nrCbits);
53
54 const bool hasMeasurementsOnlyAtEnd = !dcirc->HasOpsAfterMeasurements();
55 const bool optimiseMultipleShots = optimiseMultipleShotsExecution;
56 const bool specialOptimizationForStatevector =
57 optimiseMultipleShots &&
59 hasMeasurementsOnlyAtEnd;
60 const bool specialOptimizationForMPS =
61 optimiseMultipleShots &&
63 hasMeasurementsOnlyAtEnd;
64
65 dcirc = dcirc->RemoveExecutedOperations(executedGates);
66
67 size_t curMaxBondDimLocal = 0;
68
69 if (!optSim) {
71 if (!optSim) return;
72 config.ApplyConfigurationToSimulator(optSim);
73
74 optSim->AllocateQubits(nrQubits);
75 optSim->Initialize();
76
77 OptimizeMPSInitialQubitsMap(optSim, dcirc, nrQubits);
78
79 if (optimiseMultipleShots) {
80 executedGates = dcirc->ExecuteNonMeasurements(optSim, state, &curMaxBondDimLocal);
81
82 if (!specialOptimizationForStatevector && !specialOptimizationForMPS &&
83 curCnt > 1)
84 optSim->SaveState();
85
86 dcirc = dcirc->RemoveExecutedOperations(executedGates);
88 network->GetMPSOptimizeSwaps()) {
89 //auto circ = std::static_pointer_cast<Circuits::Circuit<Time>>(dcirc->Clone());
90 //circ->ConvertForCutting();
91 optSim->SetUpcomingGates(dcirc->GetOperations());
92 }
93 }
94 } else if (method == Simulators::SimulationType::kMatrixProductState && network->GetMPSOptimizeSwaps()) {
95 auto circ =
96 std::static_pointer_cast<Circuits::Circuit<Time>>(dcirc->Clone());
97 circ->ConvertForCutting();
98 optSim->SetUpcomingGates(circ->GetOperations());
99 }
100
101 std::shared_ptr<Circuits::MeasurementOperation<Time>> measurementsOp;
102
103 const std::vector<bool> executed = std::move(executedGates);
104
105 if (optimiseMultipleShots && hasMeasurementsOnlyAtEnd) {
106 bool isQiskitAer = false;
107#ifndef NO_QISKIT_AER
109 isQiskitAer = true;
110 }
111#endif
112 measurementsOp = dcirc->GetLastMeasurements(executed, isQiskitAer);
113 const auto &qbits = measurementsOp->GetQubits();
114 if (qbits.empty()) {
115 auto bits = state.GetAllBits();
116 bits.resize(nrResultCbits, false);
117
118 const std::lock_guard lock(resultsMutex);
119 res[bits] += curCnt;
120
121 if (curMaxBondDim && curMaxBondDimLocal > *curMaxBondDim)
122 *curMaxBondDim = curMaxBondDimLocal;
123
124 return;
125 }
126 }
127
128 ExecuteResults localRes;
129
130 if (optimiseMultipleShots &&
131 (specialOptimizationForStatevector || hasMeasurementsOnlyAtEnd)) {
132 const auto &qbits = measurementsOp->GetQubits();
133
134 const auto sampleres = optSim->SampleCountsMany(qbits, curCnt);
135
136 for (const auto &[mstate, cnt] : sampleres) {
137 measurementsOp->SetStateFromSample(mstate, state);
138
139 auto bits = state.GetAllBits();
140 bits.resize(nrResultCbits, false);
141
142 localRes[bits] += cnt;
143
144 state.Reset();
145 }
146
147 const std::lock_guard lock(resultsMutex);
148 for (const auto &r : localRes) res[r.first] += r.second;
149
150 if (curMaxBondDim && curMaxBondDimLocal > *curMaxBondDim)
151 *curMaxBondDim = curMaxBondDimLocal;
152
153 return;
154 }
155
156 const auto curCnt1 = curCnt > 0 ? curCnt - 1 : 0;
157 for (size_t i = 0; i < curCnt; ++i) {
158 if (optimiseMultipleShots) {
159 if (i > 0) {
160 optSim->RestoreState();
161 optSim->SetGatesCounter(0);
162 }
163 dcirc->ExecuteMeasurements(optSim, state, executed, &curMaxBondDimLocal);
164 } else {
165 dcirc->ExecuteBD(optSim, state, &curMaxBondDimLocal);
166 if (i < curCnt1) {
167 optSim->Reset();
168 optSim->SetGatesCounter(0);
169 }
170 }
171
172 auto bits = state.GetAllBits();
173 bits.resize(nrResultCbits, false);
174
175 ++localRes[bits];
176
177 state.Reset();
178 }
179
180 const std::lock_guard lock(resultsMutex);
181 for (const auto &r : localRes) res[r.first] += r.second;
182
183 if (curMaxBondDim && curMaxBondDimLocal > *curMaxBondDim)
184 *curMaxBondDim = curMaxBondDimLocal;
185 }
186
188 if (curCnt == 0) return;
189
191 state.AllocateBits(nrCbits);
192
193 const bool hasMeasurementsOnlyAtEnd = !dcirc->HasOpsAfterMeasurements();
194 const bool optimiseMultipleShots = optimiseMultipleShotsExecution;
195 const bool specialOptimizationForStatevector =
196 optimiseMultipleShots &&
198 hasMeasurementsOnlyAtEnd;
199 const bool specialOptimizationForMPS =
200 optimiseMultipleShots &&
202 hasMeasurementsOnlyAtEnd;
203
204
205 if (optSim) {
206 optSim->SetMultithreading(true);
207
208 if (optSim->GetNumberOfQubits() != nrQubits) {
209 optSim->Clear();
210 config.ApplyConfigurationToSimulator(optSim);
211
212 optSim->AllocateQubits(nrQubits);
213 optSim->Initialize();
214
215 OptimizeMPSInitialQubitsMap(optSim, dcirc, nrQubits);
216
217 if (optimiseMultipleShots) {
218 executedGates = dcirc->ExecuteNonMeasurements(optSim, state, curMaxBondDim);
219
220 if (!specialOptimizationForStatevector &&
221 !specialOptimizationForMPS && curCnt > 1)
222 optSim->SaveState();
223 dcirc = dcirc->RemoveExecutedOperations(executedGates);
225 network->GetMPSOptimizeSwaps()) {
226 //auto circ = std::static_pointer_cast<Circuits::Circuit<Time>>(dcirc->Clone());
227 //circ->ConvertForCutting();
228 optSim->SetUpcomingGates(dcirc->GetOperations());
229 }
230 }
231 } else if (executedGates.size() == dcirc->size()) {
232 // special case for when the simulator is passed from the network
233 // and no gates were executed yet
234 bool needToExecuteGates = true;
235 for (const bool val : executedGates) {
236 if (val) {
237 needToExecuteGates = false;
238 break;
239 }
240 }
241 if (needToExecuteGates && optimiseMultipleShots) {
242 executedGates = dcirc->ExecuteNonMeasurements(optSim, state, curMaxBondDim);
243 if (!specialOptimizationForStatevector &&
244 !specialOptimizationForMPS && curCnt > 1)
245 optSim->SaveState();
246 dcirc = dcirc->RemoveExecutedOperations(executedGates);
248 network->GetMPSOptimizeSwaps()) {
249 //auto circ = std::static_pointer_cast<Circuits::Circuit<Time>>(dcirc->Clone());
250 //circ->ConvertForCutting();
251 optSim->SetUpcomingGates(dcirc->GetOperations());
252 }
253 } else {
254 dcirc = dcirc->RemoveExecutedOperations(executedGates);
256 network->GetMPSOptimizeSwaps()) {
257 //auto circ = std::static_pointer_cast<Circuits::Circuit<Time>>(dcirc->Clone());
258 //circ->ConvertForCutting();
259 optSim->SetUpcomingGates(dcirc->GetOperations());
260 }
261 }
262 } else {
263 dcirc = dcirc->RemoveExecutedOperations(executedGates);
265 network->GetMPSOptimizeSwaps()) {
266 auto circ =
267 std::static_pointer_cast<Circuits::Circuit<Time>>(dcirc->Clone());
268 circ->ConvertForCutting();
269 optSim->SetUpcomingGates(circ->GetOperations());
270 }
271 }
272 } else {
274 if (!optSim) return;
275
276 optSim->SetMultithreading(true);
277 config.ApplyConfigurationToSimulator(optSim);
278
279 optSim->AllocateQubits(nrQubits);
280 optSim->Initialize();
281
282 OptimizeMPSInitialQubitsMap(optSim, dcirc, nrQubits);
283
284 if (optimiseMultipleShots) {
285 executedGates = dcirc->ExecuteNonMeasurements(optSim, state, curMaxBondDim);
286
287 if (!specialOptimizationForStatevector && !specialOptimizationForMPS &&
288 curCnt > 1)
289 optSim->SaveState();
290
291 dcirc = dcirc->RemoveExecutedOperations(executedGates);
292 if (method == Simulators::SimulationType::kMatrixProductState && network->GetMPSOptimizeSwaps()) {
293 //auto circ = std::static_pointer_cast<Circuits::Circuit<Time>>(dcirc->Clone());
294 //circ->ConvertForCutting();
295 optSim->SetUpcomingGates(dcirc->GetOperations());
296 }
297 }
298 }
299
300 std::shared_ptr<Circuits::MeasurementOperation<Time>> measurementsOp;
301
302 const std::vector<bool> executed = std::move(executedGates);
303
304 if (optimiseMultipleShots && hasMeasurementsOnlyAtEnd) {
305 bool isQiskitAer = false;
306#ifndef NO_QISKIT_AER
308 isQiskitAer = true;
309 }
310#endif
311 measurementsOp = dcirc->GetLastMeasurements(executed, isQiskitAer);
312 const auto &qbits = measurementsOp->GetQubits();
313 if (qbits.empty()) {
314 auto bits = state.GetAllBits();
315 bits.resize(nrResultCbits, false);
316
317 res[bits] += curCnt;
318
319 return;
320 }
321 }
322
323 if (optimiseMultipleShots &&
324 (specialOptimizationForStatevector || hasMeasurementsOnlyAtEnd)) {
325 const auto &qbits = measurementsOp->GetQubits();
326
327 const auto sampleres = optSim->SampleCountsMany(qbits, curCnt);
328
329 for (const auto &[mstate, cnt] : sampleres) {
330 measurementsOp->SetStateFromSample(mstate, state);
331
332 auto bits = state.GetAllBits();
333 bits.resize(nrResultCbits, false);
334
335 res[bits] += cnt;
336
337 state.Reset();
338 }
339
340 return;
341 }
342
343 const auto curCnt1 = curCnt > 0 ? curCnt - 1 : 0;
344 for (size_t i = 0; i < curCnt; ++i) {
345 if (optimiseMultipleShots) {
346 if (i > 0) {
347 optSim->RestoreState();
348 optSim->SetGatesCounter(0);
349 }
350 dcirc->ExecuteMeasurements(optSim, state, executed, curMaxBondDim);
351 } else {
352 dcirc->ExecuteBD(optSim, state, curMaxBondDim);
353 if (i < curCnt1) {
354 optSim->Reset(); // leave the simulator state for the last iteration
355 optSim->SetGatesCounter(0);
356 }
357 }
358
359 auto bits = state.GetAllBits();
360 bits.resize(nrResultCbits, false);
361
362 ++res[bits];
363
364 state.Reset();
365 }
366 }
367
369 size_t curCnt) {
370 return curCnt > 1;
371 }
372
373 size_t GetJobCount() const { return curCnt; }
374
375private:
376 void OptimizeMPSInitialQubitsMap(
377 std::shared_ptr<Simulators::ISimulator> &sim,
378 std::shared_ptr<Circuits::Circuit<Time>> &dcirc, size_t nrQubits) const {
379 if (sim->GetSimulationType() ==
381 (network->GetInitialQubitsMapOptimization() ||
382 network->GetMPSOptimizeSwaps()) &&
383 sim->SupportsMPSSwapOptimization()) {
384 if (network->GetMPSOptimizationQubitsNumberThreshold() <= nrQubits) {
385 const auto bondDimThreshold =
386 network->GetMPSOptimizationBondDimensionThreshold();
387 const auto maxBondDimValue =
388 config.GetConfigurationAsInt("matrix_product_state_max_bond_dimension");
389
390 if (maxBondDimValue == 0 ||
391 static_cast<int>(bondDimThreshold) <= maxBondDimValue) {
392 // need to be sure the circuit is correctly converted
393 dcirc->ConvertForCutting(); // convert the three qubit gates
394 auto layers = dcirc->ToMultipleQubitsLayersNoClone();
395
397 dummySim.setGrowthFactorGate(network->getGrowthFactorGate());
398 dummySim.setGrowthFactorSwap(network->getGrowthFactorSwap());
399 if (maxBondDimValue != 0)
400 dummySim.SetMaxBondDimension(maxBondDimValue);
401
402 if (network->GetInitialQubitsMapOptimization()) {
403 const auto optimalMap = dummySim.ComputeOptimalQubitsMap(layers);
404 sim->SetInitialQubitsMap(optimalMap);
405 }
406
408
409 if (network->GetMPSOptimizeSwaps()) {
410 // TODO: come up with something better!
411 int lookaheadDepthLocal = network->GetLookaheadDepth();
412
413 if (lookaheadDepthLocal == std::numeric_limits<int>::max()) {
414 double avgTwoQubitGatesPerLayer = 0.0;
415 for (const auto &layer : layers) {
416 int twoQubitGates = 0;
417 for (const auto &op : layer->GetOperations()) {
418 if (op->AffectedQubits().size() >= 2) {
419 ++twoQubitGates;
420 }
421 }
422 avgTwoQubitGatesPerLayer += twoQubitGates;
423 }
424 avgTwoQubitGatesPerLayer /= layers.size();
425
426 int lookaheadVal =
427 static_cast<int>(4. * avgTwoQubitGatesPerLayer);
428 if (lookaheadVal > 15) lookaheadVal = 15;
429
430 lookaheadDepthLocal =
431 layers.size() < 8 || nrQubits <= 10 ? 0
432 : layers.size() < 15 ? static_cast<int>(lookaheadVal)
433 : layers.size() < 25 ? static_cast<int>(1.5 * lookaheadVal)
434 : 2 * lookaheadVal;
435 }
436
437 int lookaheadHeuristicDepthLocal =
438 network->GetLookaheadDepthWithHeuristic();
439
440 if (lookaheadHeuristicDepthLocal == std::numeric_limits<int>::max())
441 lookaheadHeuristicDepthLocal =
442 layers.size() < 10 || nrQubits <= 10 ? 0
443 : layers.size() < 20
444 ? lookaheadDepthLocal - 1
445 : lookaheadDepthLocal - 2;
446
447 if (lookaheadHeuristicDepthLocal < 0)
448 lookaheadHeuristicDepthLocal = 0;
449
450 sim->SetUseOptimalMeetingPosition(true);
451 sim->SetLookaheadDepth(lookaheadDepthLocal);
452 sim->SetLookaheadDepthWithHeuristic(lookaheadHeuristicDepthLocal);
453 sim->setGrowthFactorGate(network->getGrowthFactorGate());
454 sim->setGrowthFactorSwap(network->getGrowthFactorSwap());
455 sim->SetUpcomingGates(dcirc->GetOperations());
456 }
457 }
458 }
459 }
460 }
461
462public:
463 std::shared_ptr<Circuits::Circuit<Time>> dcirc;
465 const size_t curCnt;
466 const size_t nrQubits;
467 const size_t nrCbits;
468 const size_t nrResultCbits;
469
472 std::mutex &resultsMutex;
473
475 std::shared_ptr<Simulators::ISimulator> optSim;
476 std::vector<bool> executedGates;
477
478 // relevant only if the simulator is not passed or the simulator doesn't have the proper number of qubits,
479 // otherwise the simulator is already configured
481
482 std::shared_ptr<Network::INetwork<Time>> network;
483 size_t* curMaxBondDim = nullptr;
484};
485
486} // namespace Network
487
488#endif // ! _NETWORK_JOB_H
Circuit class for holding the sequence of operations.
Definition Circuit.h:48
std::unordered_map< std::vector< bool >, size_t > ExecuteResults
The results of the execution of the circuit.
Definition Circuit.h:50
static std::shared_ptr< Circuits::Circuit< Time > > LayersToCircuit(const std::vector< std::shared_ptr< Circuits::Circuit< Time > > > &layers)
Converts the layers back to a circuit.
Definition Circuit.h:2474
The state class that stores the classical state of a quantum circuit execution.
Definition Operations.h:65
void Reset(bool value=false)
Set the classical bits with the specified value.
Definition Operations.h:246
const std::vector< bool > & GetAllBits() const
Get the classical bits.
Definition Operations.h:216
void AllocateBits(size_t numBits)
Allocate more bits.
Definition Operations.h:162
ExecuteResults & res
Definition NetworkJob.h:464
bool optimiseMultipleShotsExecution
Definition NetworkJob.h:474
static bool IsOptimisableForMultipleShots(Simulators::SimulatorType t, size_t curCnt)
Definition NetworkJob.h:368
const Simulators::SimulatorType simType
Definition NetworkJob.h:470
const size_t curCnt
Definition NetworkJob.h:465
std::vector< bool > executedGates
Definition NetworkJob.h:476
typename Circuits::Circuit< Time >::ExecuteResults ExecuteResults
Definition NetworkJob.h:30
std::shared_ptr< Network::INetwork< Time > > network
Definition NetworkJob.h:482
const size_t nrResultCbits
Definition NetworkJob.h:468
const size_t nrCbits
Definition NetworkJob.h:467
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:34
std::shared_ptr< Simulators::ISimulator > optSim
Definition NetworkJob.h:475
std::shared_ptr< Circuits::Circuit< Time > > dcirc
Definition NetworkJob.h:463
std::mutex & resultsMutex
Definition NetworkJob.h:472
const size_t nrQubits
Definition NetworkJob.h:466
const Simulators::SimulationType method
Definition NetworkJob.h:471
Configuration< Time > config
Definition NetworkJob.h:480
size_t GetJobCount() const
Definition NetworkJob.h:373
static std::shared_ptr< ISimulator > CreateSimulator(SimulatorType t=SimulatorType::kQCSim, SimulationType method=SimulationType::kMatrixProductState)
Create a quantum computing simulator.
Definition Factory.cpp:173
SimulationType
The type of simulation.
Definition State.h:98
@ kStatevector
statevector simulation type
Definition State.h:99
@ kMatrixProductState
matrix product state simulation type
Definition State.h:100
SimulatorType
The type of simulator.
Definition State.h:72
@ kQiskitAer
qiskit aer simulator type
Definition State.h:74