34template <
typename Time = Types::time_type>
class ExecuteJob
62 ConfigureTrajectoryArithmetic();
68 threadBudget.Limit(SimulatorThreadLimit());
73 PrepareCircuitForExecution();
78 const bool hasMeasurementsOnlyAtEnd = !
dcirc->HasOpsAfterMeasurements();
82 size_t curMaxBondDimLocal = 0;
91 if (!hasMeasurementsOnlyAtEnd &&
curCnt > 1)
104 optSim->GetConfiguration(
"sampling_policy") ==
"reproducible_v1")
106 threadBudget.Limit(SimulatorThreadLimit());
112 if (optimiseMultipleShots)
118 network->GetMPSOptimizeSwaps())
126 if (!hasMeasurementsOnlyAtEnd &&
curCnt > 1)
131 network->GetMPSOptimizeSwaps())
133 auto circ = std::static_pointer_cast<Circuits::Circuit<Time>>(
dcirc->Clone());
134 circ->ConvertForCutting();
135 optSim->SetUpcomingGates(circ->GetOperations());
140 std::shared_ptr<Circuits::MeasurementOperation<Time>> measurementsOp;
144 if (optimiseMultipleShots && hasMeasurementsOnlyAtEnd)
146 bool isQiskitAer =
false;
153 measurementsOp =
dcirc->GetLastMeasurements(executed, isQiskitAer);
154 const auto &qbits = measurementsOp->GetQubits();
172 if (optimiseMultipleShots && (specialOptimizationForStatevector || hasMeasurementsOnlyAtEnd))
174 const auto &qbits = measurementsOp->GetQubits();
176 const auto sampleres =
optSim->SampleCountsMany(qbits,
curCnt);
178 AccumulateSamples(*measurementsOp, sampleres, state, localRes);
181 for (
const auto &r : localRes)
182 res[r.first] += r.second;
191 const auto shotCircuit =
dcirc;
192 for (
size_t i = 0; i <
curCnt; ++i)
200 if (optimiseMultipleShots)
205 optSim->SetGatesCounter(0);
207 dcirc->ExecuteMeasurements(
optSim, state, executed, &curMaxBondDimLocal);
211 dcirc->ExecuteBD(
optSim, state, &curMaxBondDimLocal);
215 optSim->SetGatesCounter(0);
228 for (
const auto &r : localRes)
229 res[r.first] += r.second;
240 ConfigureTrajectoryArithmetic();
241 PrepareCircuitForExecution();
246 const bool hasMeasurementsOnlyAtEnd = !
dcirc->HasOpsAfterMeasurements();
252 optSim->SetMultithreading(
true);
264 if (optimiseMultipleShots)
270 network->GetMPSOptimizeSwaps())
277 if (!hasMeasurementsOnlyAtEnd &&
curCnt > 1)
285 bool needToExecuteGates =
true;
290 needToExecuteGates =
false;
294 if (needToExecuteGates && optimiseMultipleShots)
299 network->GetMPSOptimizeSwaps())
306 if (!hasMeasurementsOnlyAtEnd &&
curCnt > 1)
313 network->GetMPSOptimizeSwaps())
326 network->GetMPSOptimizeSwaps())
328 auto circ = std::static_pointer_cast<Circuits::Circuit<Time>>(
dcirc->Clone());
329 circ->ConvertForCutting();
330 optSim->SetUpcomingGates(circ->GetOperations());
340 optSim->SetMultithreading(
true);
348 if (optimiseMultipleShots)
353 network->GetMPSOptimizeSwaps())
360 if (!hasMeasurementsOnlyAtEnd &&
curCnt > 1)
367 std::shared_ptr<Circuits::MeasurementOperation<Time>> measurementsOp;
371 if (optimiseMultipleShots && hasMeasurementsOnlyAtEnd)
373 bool isQiskitAer =
false;
380 measurementsOp =
dcirc->GetLastMeasurements(executed, isQiskitAer);
381 const auto &qbits = measurementsOp->GetQubits();
393 if (optimiseMultipleShots && (specialOptimizationForStatevector || hasMeasurementsOnlyAtEnd))
395 const auto &qbits = measurementsOp->GetQubits();
397 const auto sampleres =
optSim->SampleCountsMany(qbits,
curCnt);
399 AccumulateSamples(*measurementsOp, sampleres, state,
res);
405 for (
size_t i = 0; i <
curCnt; ++i)
407 if (optimiseMultipleShots)
412 optSim->SetGatesCounter(0);
422 optSim->SetGatesCounter(0);
446 void ConfigureTrajectoryArithmetic()
451 optSim->
Configure(
"reproducible_trajectory",
config.GetConfiguration(
"reproducible_trajectory").c_str());
454 class ScopedInternalThreads
457 explicit ScopedInternalThreads(
int threads)
462 void Limit(
int threads)
468 previous = omp_get_max_threads();
469 omp_set_num_threads(threads);
476 ~ScopedInternalThreads()
480 omp_set_num_threads(previous);
490 int SimulatorThreadLimit()
const
492#if defined(_OPENMP) && defined(_MSC_VER) && !defined(__clang__) && !defined(_OPENMP_LLVM_RUNTIME)
500 template <
class Samples>
501 void AccumulateSamples(Circuits::MeasurementOperation<Time> &measurement,
const Samples &samples, Circuits::OperationState &state,
ExecuteResults &target)
503 auto add = [&](
const auto &sample) {
504 const auto &[bits, count] = sample;
505 const size_t draws = measurement.
HasReadout() ? count : 1;
506 for (
size_t i = 0; i < draws; ++i)
511 target[output] += measurement.
HasReadout() ? 1 : count;
515 if (measurement.
HasReadout() &&
optSim->GetConfiguration(
"sampling_policy") ==
"reproducible_v1")
519 std::vector<const typename Samples::value_type *> ordered;
520 ordered.reserve(samples.size());
521 for (
const auto &sample : samples)
522 ordered.push_back(&sample);
523 std::sort(ordered.begin(), ordered.end(), [](
auto a,
auto b) { return a->first < b->first; });
524 for (
const auto *sample : ordered)
528 for (
const auto &sample : samples)
532 void PrepareCircuitForExecution()
537 const uint64_t defaultSeed =
539 dcirc =
dcirc->CloneForExecution(stream, defaultSeed);
542 void OptimizeMPSInitialQubitsMap(std::shared_ptr<Simulators::ISimulator> &sim, std::shared_ptr<Circuits::Circuit<Time>> &
dcirc,
size_t nrQubits)
const
546 (
network->GetInitialQubitsMapOptimization() ||
network->GetMPSOptimizeSwaps()) && sim->SupportsMPSSwapOptimization() &&
547 !
dcirc->HasCompositeOperations())
552 if (
network->GetMPSOptimizationQubitsNumberThreshold() <= routedQubits)
554 const auto bondDimThreshold =
network->GetMPSOptimizationBondDimensionThreshold();
556 config.IsSet(
"matrix_product_operator_max_bond_dimension")
557 ?
"matrix_product_operator_max_bond_dimension"
558 :
"matrix_product_state_max_bond_dimension");
560 if (maxBondDimValue == 0 ||
static_cast<int>(bondDimThreshold) <= maxBondDimValue)
563 dcirc->ConvertForCutting();
564 auto layers =
dcirc->ToMultipleQubitsLayersNoClone();
568 dcirc->SetOperations(ordered->GetOperations());
569 sim->SetUpcomingGates(
dcirc->GetOperations());
570 if (sim->IsGateFusionEnabled() && !sim->GetUpcomingRoutingOperations().empty())
572 Circuits::Circuit<Time> routingCircuit;
573 for (
const auto &op : sim->GetUpcomingRoutingOperations())
580 dummySim.SetSwapGatesRelabelQubits(sim->SwapGatesRelabelQubits());
581 dummySim.setGrowthFactorGate(
network->getGrowthFactorGate());
582 dummySim.setGrowthFactorSwap(
network->getGrowthFactorSwap());
583 if (maxBondDimValue != 0)
586 dummySim.SetMaxBondDimension(
593 if (
network->GetInitialQubitsMapOptimization())
595 const auto optimalMap = dummySim.ComputeOptimalQubitsMap(layers);
596 sim->SetInitialQubitsMap(optimalMap);
599 if (
network->GetMPSOptimizeSwaps())
601 int lookaheadDepthLocal =
network->GetLookaheadDepth();
603 if (lookaheadDepthLocal == std::numeric_limits<int>::max())
605 double avgTwoQubitGatesPerLayer = 0.0;
606 for (
const auto &layer : layers)
608 int twoQubitGates = 0;
609 for (
const auto &op : layer->GetOperations())
611 if (op->AffectedQubits().size() >= 2)
616 avgTwoQubitGatesPerLayer += twoQubitGates;
619 avgTwoQubitGatesPerLayer /= layers.size();
621 int lookaheadVal =
static_cast<int>(4. * avgTwoQubitGatesPerLayer);
622 if (lookaheadVal > 15)
625 lookaheadDepthLocal = layers.size() < 8 || routedQubits <= 10 ? 0
626 : layers.size() < 15 ?
static_cast<int>(lookaheadVal)
627 : layers.size() < 25 ? static_cast<int>(1.5 * lookaheadVal)
631 int lookaheadHeuristicDepthLocal =
network->GetLookaheadDepthWithHeuristic();
633 if (lookaheadHeuristicDepthLocal == std::numeric_limits<int>::max())
634 lookaheadHeuristicDepthLocal = layers.size() < 8 || routedQubits <= 10 ? 0 : lookaheadDepthLocal - 1;
636 if (lookaheadHeuristicDepthLocal < 0)
637 lookaheadHeuristicDepthLocal = 0;
639 sim->SetUseOptimalMeetingPosition(
true);
640 if (
network->GetLookaheadDepth() == std::numeric_limits<int>::max())
641 sim->SetAutomaticLookaheadDepth(lookaheadDepthLocal);
643 sim->SetLookaheadDepth(lookaheadDepthLocal);
644 sim->SetLookaheadDepthWithHeuristic(lookaheadHeuristicDepthLocal);
645 sim->setGrowthFactorGate(
network->getGrowthFactorGate());
646 sim->setGrowthFactorSwap(
network->getGrowthFactorSwap());
651 sim->SetUpcomingGates(
dcirc->GetOperations());
659 std::shared_ptr<Circuits::Circuit<Time>>
dcirc;
679 std::shared_ptr<Simulators::ISimulator>
optSim;
688 std::shared_ptr<Network::INetwork<Time>>
network;