18#ifndef __EXECUTION_COST_H_
19#define __EXECUTION_COST_H_
74 return static_cast<double>(
nrQubits);
92 throw std::out_of_range(
"Invalid index for CircuitInfo field");
142 return static_cast<double>(
runtime);
144 throw std::out_of_range(
"Invalid index for ExecutionInfo field");
157 const double opOrder = exp2(nrQubits);
160 for (
const auto &op : *circuit)
162 const auto affectedQubits = op->AffectedQubits();
164 cost += opOrder * affectedQubits.size();
166 cost += 2. * opOrder * affectedQubits.size();
169 if (affectedQubits.size() == 1)
171 else if (affectedQubits.size() == 2)
173 else if (affectedQubits.size() == 3)
174 cost += 16 * opOrder;
181 const double twoQubitOpOrder = pow(maxBondDim, 3);
182 const double oneQubitOpOrder = pow(maxBondDim, 2);
185 for (
const auto &op : *circuit)
187 const auto affectedQubits = op->AffectedQubits();
201 cost += twoQubitOpOrder * affectedQubits.size() * nrQubits / 2.;
204 if (affectedQubits.size() == 1)
205 cost += oneQubitOpOrder;
206 else if (affectedQubits.size() == 2)
209 cost += twoQubitOpOrder * nrQubits / 3.;
210 else if (affectedQubits.size() == 3)
213 cost += twoQubitOpOrder * nrQubits * 2;
220 const double measOrder = pow(nrQubits, 2);
221 const double opOrder =
static_cast<double>(nrQubits);
224 for (
const auto &op : *circuit)
226 const auto affectedQubits = op->AffectedQubits();
229 cost += measOrder * affectedQubits.size();
231 cost += opOrder * affectedQubits.size();
238 double doublingCost = 1;
240 for (
const auto &op : *circuit)
242 if (op->IsBranching())
245 const auto affectedQubits = op->AffectedQubits();
248 cost += doublingCost * affectedQubits.size();
251 if (affectedQubits.size() == 1)
252 cost += doublingCost;
253 else if (affectedQubits.size() == 2)
254 cost += doublingCost * 2;
255 else if (affectedQubits.size() == 3)
256 cost += doublingCost * 4;
265 return std::numeric_limits<double>::infinity();
273 const bool hasMeasurementsInTheMiddle = circuit->HasOpsAfterMeasurements();
274 const std::vector<bool> executedOps = circuit->ExecuteNonMeasurements(
nullptr, dummyState);
276 const size_t dif = circuit->size() - executedOps.size();
283 const double opOrder = exp2(nrQubits);
286 for (
size_t i = 0; i < circuit->size(); ++i)
288 if (i >= dif && !executedOps[i - dif])
291 const auto &op = (*circuit)[i];
292 const auto affectedQubits = op->AffectedQubits();
294 cost += opOrder * affectedQubits.size();
296 cost += 2. * opOrder * affectedQubits.size();
299 if (affectedQubits.size() == 1)
301 else if (affectedQubits.size() == 2)
303 else if (affectedQubits.size() == 3)
304 cost += 16 * opOrder;
314 if (hasMeasurementsInTheMiddle)
316 double samplingCost = 0;
317 for (
size_t i = dif; i < circuit->size(); ++i)
319 if (executedOps[i - dif])
322 const auto &op = (*circuit)[i];
323 const auto affectedQubits = op->AffectedQubits();
325 samplingCost += opOrder * affectedQubits.size();
327 samplingCost += 2. * opOrder * affectedQubits.size();
330 if (affectedQubits.size() == 1)
331 samplingCost += opOrder;
332 else if (affectedQubits.size() == 2)
333 samplingCost += 4 * opOrder;
334 else if (affectedQubits.size() == 3)
335 samplingCost += 16 * opOrder;
339 samplingCost += opOrder * nrQubitsSampled;
341 return cost + samplingCost * samples;
345 return cost + 30 * opOrder + samples * nrQubits;
349 const double oneQubitOpOrder =
static_cast<double>(maxBondDim * maxBondDim);
350 const double twoQubitOpOrder =
static_cast<double>(oneQubitOpOrder * maxBondDim);
353 for (
size_t i = 0; i < circuit->size(); ++i)
355 if (i >= dif && !executedOps[i - dif])
358 const auto &op = (*circuit)[i];
359 const auto affectedQubits = op->AffectedQubits();
373 cost += twoQubitOpOrder * affectedQubits.size() * nrQubits / 2.;
376 if (affectedQubits.size() == 1)
377 cost += oneQubitOpOrder;
378 else if (affectedQubits.size() == 2)
381 cost += twoQubitOpOrder * nrQubits / 3.;
382 else if (affectedQubits.size() == 3)
385 cost += twoQubitOpOrder * nrQubits * 2;
389 if (hasMeasurementsInTheMiddle)
391 double samplingCost = 0;
392 for (
size_t i = dif; i < circuit->size(); ++i)
394 if (executedOps[i - dif])
397 const auto &op = (*circuit)[i];
398 const auto affectedQubits = op->AffectedQubits();
401 samplingCost += twoQubitOpOrder * affectedQubits.size() * nrQubits / 2.;
404 if (affectedQubits.size() == 1)
405 samplingCost += oneQubitOpOrder;
406 else if (affectedQubits.size() == 2)
409 samplingCost += twoQubitOpOrder * nrQubits / 3.;
410 else if (affectedQubits.size() == 3)
413 samplingCost += twoQubitOpOrder * nrQubits * 2;
417 samplingCost += twoQubitOpOrder * nrQubits * nrQubits;
419 return cost + samplingCost * samples;
429 return cost + samples * twoQubitOpOrder * nrQubits * nrQubits;
433 const double measOrder = pow(nrQubits, 2);
434 const double opOrder =
static_cast<double>(nrQubits);
437 for (
size_t i = 0; i < circuit->size(); ++i)
439 if (i >= dif && !executedOps[i - dif])
442 const auto &op = (*circuit)[i];
443 const auto affectedQubits = op->AffectedQubits();
446 cost += measOrder * affectedQubits.size();
448 cost += opOrder * affectedQubits.size();
451 if (hasMeasurementsInTheMiddle)
453 double samplingCost = 0;
454 for (
size_t i = dif; i < circuit->size(); ++i)
456 if (executedOps[i - dif])
459 const auto &op = (*circuit)[i];
460 const auto affectedQubits = op->AffectedQubits();
463 samplingCost += measOrder * affectedQubits.size();
465 samplingCost += opOrder * affectedQubits.size();
468 samplingCost += measOrder * nrQubitsSampled;
470 return cost + samplingCost * samples;
480 return cost + samples * measOrder * nrQubitsSampled;
485 double doublingCost = 1;
486 for (
size_t i = 0; i < circuit->size(); ++i)
488 if (i >= dif && !executedOps[i - dif])
490 const auto &op = (*circuit)[i];
491 if (op->IsBranching())
494 const auto affectedQubits = op->AffectedQubits();
497 cost += doublingCost * affectedQubits.size();
500 if (affectedQubits.size() == 1)
501 cost += doublingCost;
502 else if (affectedQubits.size() == 2)
503 cost += doublingCost * 2;
504 else if (affectedQubits.size() == 3)
505 cost += doublingCost * 4;
509 if (hasMeasurementsInTheMiddle)
511 double samplingCost = 0;
512 for (
size_t i = dif; i < circuit->size(); ++i)
514 if (executedOps[i - dif])
517 const auto &op = (*circuit)[i];
518 if (op->IsBranching())
521 const auto affectedQubits = op->AffectedQubits();
525 samplingCost += doublingCost * affectedQubits.size();
528 if (affectedQubits.size() == 1)
529 samplingCost += doublingCost;
530 else if (affectedQubits.size() == 2)
531 samplingCost += doublingCost * 2;
532 else if (affectedQubits.size() == 3)
533 samplingCost += doublingCost * 4;
537 samplingCost += doublingCost * nrQubitsSampled;
539 return cost + samplingCost * samples;
543 return cost + 30 * doublingCost + samples * nrQubits;
548 return std::numeric_limits<double>::infinity();
561 for (
char c : pauliString)
563 if (c ==
'X' || c ==
'x' || c ==
'Y' || c ==
'y' || c ==
'Z' || c ==
'z')
569 const double opOrder = exp2(nrQubits);
573 cost += opOrder * (pauliCnt + 1);
579 const double twoQubitOpOrder = pow(maxBondDim, 3);
580 const double oneQubitOpOrder = pow(maxBondDim, 2);
584 cost += oneQubitOpOrder * pauliCnt + nrQubits * twoQubitOpOrder;
590 cost += nrQubits * nrQubits;
595 double doublingCost = 1;
596 for (
const auto &op : *circuit)
598 if (op->IsBranching())
601 cost += 4 * doublingCost * pauliCnt;
606 return std::numeric_limits<double>::infinity();
609 static std::shared_ptr<Circuits::Circuit<>>
GenerateRandomCircuit(
size_t nrQubits,
size_t depth,
double measureInsideProbability = 0.,
610 size_t nrMeasAtEnd = 0,
bool isClifford =
false,
size_t nrNonCliffordGatesLimit = 0,
611 size_t nrBranchingGatesLimit = 0)
613 auto circuit = std::make_shared<Circuits::Circuit<>>();
614 std::random_device rdev;
615 std::mt19937 rng(rdev());
616 std::uniform_real_distribution<double> dist(0.0, 1.0);
617 std::uniform_real_distribution<double> paramDist(-2 * M_PI, 2 * M_PI);
618 std::uniform_int_distribution<Types::qubit_t> qubitDist(0, nrQubits - 1);
623 std::vector<Types::qubit_t> qubits(nrQubits);
624 std::iota(qubits.begin(), qubits.end(), 0);
626 size_t nrNonCliffordGates = 0;
627 if (nrNonCliffordGatesLimit == 0 && !isClifford)
628 nrNonCliffordGatesLimit = depth;
630 size_t nrBranchingGates = 0;
631 if (nrBranchingGatesLimit == 0)
632 nrBranchingGatesLimit = depth;
634 for (
size_t i = 0; i < depth; ++i)
636 if (dist(rng) < measureInsideProbability)
639 std::vector<std::pair<Types::qubit_t, size_t>> qs = {{q, q}};
644 std::shuffle(qubits.begin(), qubits.end(), rng);
645 const auto q1 = qubits[0];
646 const auto q2 = qubits[1];
647 const auto q3 = qubits[2];
652 auto param1 = paramDist(rng);
653 auto param2 = paramDist(rng);
654 auto param3 = paramDist(rng);
655 auto param4 = paramDist(rng);
660 while (!theGate->IsClifford())
667 if (!theGate->IsClifford())
668 ++nrNonCliffordGates;
669 if (theGate->IsBranching())
672 if (nrNonCliffordGates > nrNonCliffordGatesLimit)
677 while (!theGate->IsClifford())
682 --nrNonCliffordGates;
685 if (nrBranchingGates > nrBranchingGatesLimit)
691 while (theGate->IsBranching())
699 circuit->AddOperation(theGate);
702 std::shuffle(circuit->begin(), circuit->end(), rng);
706 if (nrMeasAtEnd > nrQubits)
707 nrMeasAtEnd = nrQubits;
708 std::shuffle(qubits.begin(), qubits.end(), rng);
710 for (
size_t i = 0; i < nrMeasAtEnd; ++i)
712 std::vector<std::pair<Types::qubit_t, size_t>> qs = {{qubits[i], i}};
723 auto sim =
GetSimulator(simType, method, nrQubits, maxBondDim);
726 auto start = std::chrono::high_resolution_clock::now();
727 for (
size_t i = 0; i < nrReps; ++i)
728 circuit->Execute(sim, dummyState);
729 auto end = std::chrono::high_resolution_clock::now();
730 return std::chrono::duration<double>(end - start).count();
734 const std::shared_ptr<
Circuits::Circuit<>> &circuit,
size_t nrQubitsSampled,
size_t nrSamples,
size_t nrReps,
737 auto sim =
GetSimulator(simType, method, nrQubits, maxBondDim);
740 if (nrQubitsSampled > nrQubits)
741 nrQubitsSampled = nrQubits;
743 std::iota(qubitsSampled.begin(), qubitsSampled.end(), 0);
745 const bool hasMeasurementsInTheMiddle = circuit->HasOpsAfterMeasurements();
747 auto start = std::chrono::high_resolution_clock::now();
749 if (hasMeasurementsInTheMiddle)
751 for (
size_t i = 0; i < nrReps; ++i)
753 const auto executedOps = circuit->ExecuteNonMeasurements(sim, dummyState);
756 for (
size_t sample = 0; sample < nrSamples; ++sample)
758 circuit->ExecuteMeasurements(sim, dummyState, executedOps);
764 for (
size_t i = 0; i < nrReps; ++i)
766 circuit->Execute(sim, dummyState);
767 sim->SampleCountsMany(qubitsSampled, nrSamples);
770 auto end = std::chrono::high_resolution_clock::now();
772 return std::chrono::duration<double>(end - start).count();
776 const std::shared_ptr<
Circuits::Circuit<>> &circuit,
const std::string &pauliString,
size_t nrReps,
779 auto sim =
GetSimulator(simType, method, nrQubits, maxBondDim);
781 auto start = std::chrono::high_resolution_clock::now();
782 for (
size_t i = 0; i < nrReps; ++i)
784 circuit->Execute(sim, dummyState);
785 sim->ExpectationValue(pauliString);
787 auto end = std::chrono::high_resolution_clock::now();
788 return std::chrono::duration<double>(end - start).count();
797 const auto strVal = std::to_string(maxBondDim);
798 sim->Configure(
"matrix_product_state_max_bond_dimension", strVal.c_str());
800 sim->AllocateQubits(nrQubits);
801 sim->SetMultithreading(
false);
810 info.
nrQubits = circuit->GetMaxQubitIndex() + 1;
812 const bool hasMeasurementsInTheMiddle = circuit->HasOpsAfterMeasurements();
813 const std::vector<bool> executedOps = circuit->ExecuteNonMeasurements(
nullptr, dummyState);
815 const size_t dif = circuit->size() - executedOps.size();
818 for (
const auto &op : *circuit)
820 const auto affectedQubits = op->AffectedQubits();
823 if (hasMeasurementsInTheMiddle)
831 if (affectedQubits.size() == 1)
834 if (i < dif || executedOps[i - dif])
837 else if (affectedQubits.size() == 2)
840 if (i < dif || executedOps[i - dif])
843 else if (affectedQubits.size() == 3)
846 if (i < dif || executedOps[i - dif])
856 static std::vector<ExecutionInfo>
ReadLog(
const std::string &logFilePath)
858 std::vector<ExecutionInfo> executionInfos;
860 std::ifstream logFile(logFilePath);
861 if (!logFile.is_open())
863 std::cerr <<
"Failed to open log file: " << logFilePath << std::endl;
864 return executionInfos;
869 while (std::getline(logFile, line))
871 std::stringstream ss(line);
874 std::getline(ss, value,
',');
876 std::getline(ss, value,
',');
878 std::getline(ss, value,
',');
880 std::getline(ss, value,
',');
882 std::getline(ss, value,
',');
884 std::getline(ss, value,
',');
886 std::getline(ss, value,
',');
888 std::getline(ss, value,
',');
890 std::getline(ss, value,
',');
893 std::getline(ss, value,
',');
895 std::getline(ss, value,
',');
897 std::getline(ss, value,
',');
899 std::getline(ss, value,
',');
902 std::getline(ss, value,
',');
904 std::getline(ss, value,
',');
905 info.
runtime = std::stod(value);
910 executionInfos.push_back(std::move(info));
913 std::random_device rdev;
914 std::mt19937 rng(rdev());
915 std::shuffle(executionInfos.begin(), executionInfos.end(), rng);
917 return executionInfos;
921 size_t nrMaxQubits,
size_t stepQubits,
size_t depthMin,
size_t depthMax,
size_t stepDepth,
922 double measureInsideProbability,
size_t nrMeasAtEndMin,
size_t nrMeasAtEndMax,
size_t stepMeasAtEnd,
923 size_t nrRandomCircuitsPerConfig,
const std::string &logFilePath,
size_t startBondDim = 16,
size_t endBondDim = 16)
926 int nrNonCliffordGates =
static_cast<int>(depthMax);
927 int nrBranchingGates =
static_cast<int>(depthMax);
932 nrNonCliffordGates = 1;
936 nrNonCliffordGates = 0;
940 nrBranchingGates = 8;
943 std::cout <<
"Benchmarking execution for simType: " <<
static_cast<int>(simType) <<
", method: " <<
static_cast<int>(method) << std::endl;
947 for (
size_t nrQubits = nrMinQubits; nrQubits <= nrMaxQubits; nrQubits += stepQubits)
949 std::cout <<
" Qubits: " << nrQubits << std::endl;
950 for (
size_t depth = depthMin; depth <= depthMax; depth += stepDepth)
952 std::cout <<
" Depth: " << depth << std::endl;
953 for (
size_t nrMeasAtEnd = nrMeasAtEndMin; nrMeasAtEnd <= std::min(nrMeasAtEndMax, nrQubits); nrMeasAtEnd += stepMeasAtEnd)
955 std::cout <<
" Measurements at end: " << nrMeasAtEnd << std::endl;
956 for (
size_t i = 0; i < nrRandomCircuitsPerConfig; ++i)
958 std::cout <<
" Random circuit: " << i + 1 <<
"/" << nrRandomCircuitsPerConfig << std::endl;
960 isClifford = !isClifford;
963 GenerateRandomCircuit(nrQubits, depth, measureInsideProbability, nrMeasAtEnd, isClifford, nrNonCliffordGates, nrBranchingGates);
965 for (
size_t maxBondDim = startBondDim; maxBondDim <= endBondDim; maxBondDim *= 2)
978 pauli.resize(nrQubits);
979 std::random_device rd;
980 std::mt19937 g(rd());
981 std::uniform_int_distribution<int> dist(0, 3);
983 for (
size_t i = 0; i < nrQubits; ++i)
985 const int v = dist(g);
1007 size_t nrMaxQubits,
size_t stepQubits,
size_t depthMin,
size_t depthMax,
size_t stepDepth,
1008 size_t nrRandomCircuitsPerConfig,
const std::string &logFilePath,
size_t startBondDim = 16,
1009 size_t endBondDim = 16)
1012 int nrNonCliffordGates =
static_cast<int>(depthMax);
1013 int nrBranchingGates =
static_cast<int>(depthMax);
1018 nrNonCliffordGates = 1;
1022 nrNonCliffordGates = 0;
1026 nrBranchingGates = 8;
1030 std::cout <<
"Benchmarking Pauli expectation for simType: " <<
static_cast<int>(simType) <<
", method: " <<
static_cast<int>(method) << std::endl;
1032 for (
size_t nrQubits = nrMinQubits; nrQubits <= nrMaxQubits; nrQubits += stepQubits)
1034 std::cout <<
" Qubits: " << nrQubits << std::endl;
1035 for (
size_t depth = depthMin; depth <= depthMax; depth += stepDepth)
1037 std::cout <<
" Depth: " << depth << std::endl;
1038 for (
size_t i = 0; i < nrRandomCircuitsPerConfig; ++i)
1041 isClifford = !isClifford;
1043 const auto circuit =
GenerateRandomCircuit(nrQubits, depth, 0., 0, isClifford, nrNonCliffordGates, nrBranchingGates);
1046 std::cout <<
" Random circuit: " << i + 1 <<
"/" << nrRandomCircuitsPerConfig <<
" Pauli string: " << pauliString << std::endl;
1047 for (
size_t maxBondDim = startBondDim; maxBondDim <= endBondDim; maxBondDim *= 2)
1049 std::cout <<
" Max bond dimension: " << maxBondDim << std::endl;
1058 size_t nrMaxQubits,
size_t stepQubits,
size_t depthMin,
size_t depthMax,
size_t stepDepth,
size_t nrMeasAtEndMin,
1059 size_t nrMeasAtEndMax,
size_t stepMeasAtEnd,
size_t nrSamplesMin,
size_t nrSamplesMax,
size_t multiplierSamples,
1060 size_t nrRandomCircuitsPerConfig,
const std::string &logFilePath,
size_t startBondDim = 16,
size_t endBondDim = 16)
1063 int nrNonCliffordGates =
static_cast<int>(depthMax);
1064 int nrBranchingGates =
static_cast<int>(depthMax);
1068 nrNonCliffordGates = 1;
1072 nrNonCliffordGates = 0;
1076 nrBranchingGates = 8;
1080 std::cout <<
"Benchmarking sampling for simType: " <<
static_cast<int>(simType) <<
", method: " <<
static_cast<int>(method) << std::endl;
1082 for (
size_t nrQubits = nrMinQubits; nrQubits <= nrMaxQubits; nrQubits += stepQubits)
1084 std::cout <<
" Qubits: " << nrQubits << std::endl;
1085 for (
size_t depth = depthMin; depth <= depthMax; depth += stepDepth)
1087 std::cout <<
" Depth: " << depth << std::endl;
1088 for (
size_t nrSamples = nrSamplesMin; nrSamples <= nrSamplesMax; nrSamples *= multiplierSamples)
1090 std::cout <<
" Samples: " << nrSamples << std::endl;
1091 for (
size_t i = 0; i < nrRandomCircuitsPerConfig; ++i)
1094 isClifford = !isClifford;
1095 const auto circuit =
GenerateRandomCircuit(nrQubits, depth, 0., 0, isClifford, nrNonCliffordGates, nrBranchingGates);
1096 for (
size_t nrQubitsSampled = nrQubits; nrQubitsSampled >= 1; nrQubitsSampled /= 2)
1098 std::cout <<
" Random circuit: " << i + 1 <<
"/" << nrRandomCircuitsPerConfig <<
" Qubits sampled: " << nrQubitsSampled
1100 for (
size_t maxBondDim = startBondDim; maxBondDim <= endBondDim; maxBondDim *= 2)
1116 const double executionTime =
MeasureExecutionTime(simType, method, info.nrQubits, circuit, nrReps, maxBondDim) / nrReps;
1118 std::stringstream ss;
1120 ss << info.nrQubits <<
"," << info.nrOneQubitOps <<
"," << info.nrTwoQubitOps <<
"," << info.nrThreeQubitOps <<
"," << info.nrMiddleMeasurementOps
1121 <<
"," << info.nrEndMeasurementOps <<
"," << info.nrOneQubitOpsExecutedOnce <<
"," << info.nrTwoQubitOpsExecutedOnce <<
","
1122 << info.nrThreeQubitOpsExecutedOnce <<
","
1123 <<
"0,0," << maxBondDim <<
","
1124 <<
"0," << estimatedCost <<
"," << executionTime;
1130 const std::shared_ptr<
Circuits::Circuit<>> &circuit,
size_t nrQubitsSampled,
size_t nrSamples,
size_t nrReps,
1134 const double estimatedCost =
EstimateSamplingCost(method, info.nrQubits, nrQubitsSampled, nrSamples, circuit, maxBondDim);
1135 const double samplingTime =
MeasureSamplingTime(simType, method, info.nrQubits, circuit, nrQubitsSampled, nrSamples, nrReps, maxBondDim) / nrReps;
1136 std::stringstream ss;
1137 ss << info.nrQubits <<
"," << info.nrOneQubitOps <<
"," << info.nrTwoQubitOps <<
"," << info.nrThreeQubitOps <<
"," << info.nrMiddleMeasurementOps
1138 <<
"," << info.nrEndMeasurementOps <<
"," << info.nrOneQubitOpsExecutedOnce <<
"," << info.nrTwoQubitOpsExecutedOnce <<
","
1139 << info.nrThreeQubitOpsExecutedOnce <<
"," << nrSamples <<
"," << nrQubitsSampled <<
"," << maxBondDim <<
","
1140 <<
"0," << estimatedCost <<
"," << samplingTime;
1145 const std::shared_ptr<
Circuits::Circuit<>> &circuit,
const std::string &pauliString,
size_t nrReps,
1149 info.nrQubits = std::max(info.nrQubits, pauliString.size());
1151 const double expectationTime =
MeasurePauliExpectationTime(simType, method, info.nrQubits, circuit, pauliString, nrReps, maxBondDim) / nrReps;
1153 size_t cntPauli = 0;
1154 for (
char c : pauliString)
1156 if (c ==
'X' || c ==
'x' || c ==
'Y' || c ==
'y' || c ==
'Z' || c ==
'z')
1160 std::stringstream ss;
1161 ss << info.nrQubits <<
"," << info.nrOneQubitOps <<
"," << info.nrTwoQubitOps <<
"," << info.nrThreeQubitOps <<
"," << info.nrMiddleMeasurementOps
1162 <<
"," << info.nrEndMeasurementOps <<
"," << info.nrOneQubitOpsExecutedOnce <<
"," << info.nrTwoQubitOpsExecutedOnce <<
","
1163 << info.nrThreeQubitOpsExecutedOnce <<
","
1164 <<
"0,0," << maxBondDim <<
"," << cntPauli <<
"," << estimatedCost <<
"," << expectationTime;
1168 static std::shared_ptr<Utils::MultipleLinearRegression>
GetRegressor(
const std::string &logFilePath,
const std::vector<size_t> &featureIndices)
1170 const auto executionInfos =
ReadLog(logFilePath);
1172 std::vector<std::vector<double>> features;
1173 features.reserve(executionInfos.size());
1175 std::vector<double> targetValues;
1176 targetValues.reserve(executionInfos.size());
1178 for (
const auto &info : executionInfos)
1180 std::vector<double> featureVector(featureIndices.size());
1181 for (
size_t i = 0; i < featureVector.size(); ++i)
1182 featureVector[i] = info.getFieldValue(featureIndices[i]);
1183 features.push_back(std::move(featureVector));
1185 targetValues.push_back(info.runtime);
1188 auto regressor = std::make_shared<Utils::MultipleLinearRegression>();
1189 regressor->SetSamples(features, targetValues);
static const std::shared_ptr< IQuantumGate< Time > > CreateGate(QuantumGateType type, size_t q1, size_t q2=0, size_t q3=0, double param1=0, double param2=0, double param3=0, double param4=0)
Construct a quantum gate.
Circuit class for holding the sequence of operations.
Measurement operation class.
The state class that stores the classical state of a quantum circuit execution.
static std::shared_ptr< Circuits::Circuit<> > GenerateRandomCircuit(size_t nrQubits, size_t depth, double measureInsideProbability=0., size_t nrMeasAtEnd=0, bool isClifford=false, size_t nrNonCliffordGatesLimit=0, size_t nrBranchingGatesLimit=0)
static double MeasureSamplingTime(Simulators::SimulatorType simType, Simulators::SimulationType method, size_t nrQubits, const std::shared_ptr< Circuits::Circuit<> > &circuit, size_t nrQubitsSampled, size_t nrSamples, size_t nrReps, size_t maxBondDim)
static void BenchmarkAndLogPauliExpectation(Simulators::SimulatorType simType, Simulators::SimulationType method, size_t nrReps, size_t nrMinQubits, size_t nrMaxQubits, size_t stepQubits, size_t depthMin, size_t depthMax, size_t stepDepth, size_t nrRandomCircuitsPerConfig, const std::string &logFilePath, size_t startBondDim=16, size_t endBondDim=16)
static double MeasureExecutionTime(Simulators::SimulatorType simType, Simulators::SimulationType method, size_t nrQubits, const std::shared_ptr< Circuits::Circuit<> > &circuit, size_t nrReps, size_t maxBondDim)
static void BenchmarkAndLogPauliExpectation(Simulators::SimulatorType simType, Simulators::SimulationType method, const std::shared_ptr< Circuits::Circuit<> > &circuit, const std::string &pauliString, size_t nrReps, size_t maxBondDim, Utils::LogFile &log)
static void BenchmarkAndLogSampling(Simulators::SimulatorType simType, Simulators::SimulationType method, size_t nrReps, size_t nrMinQubits, size_t nrMaxQubits, size_t stepQubits, size_t depthMin, size_t depthMax, size_t stepDepth, size_t nrMeasAtEndMin, size_t nrMeasAtEndMax, size_t stepMeasAtEnd, size_t nrSamplesMin, size_t nrSamplesMax, size_t multiplierSamples, size_t nrRandomCircuitsPerConfig, const std::string &logFilePath, size_t startBondDim=16, size_t endBondDim=16)
static double MeasurePauliExpectationTime(Simulators::SimulatorType simType, Simulators::SimulationType method, size_t nrQubits, const std::shared_ptr< Circuits::Circuit<> > &circuit, const std::string &pauliString, size_t nrReps, size_t maxBondDim)
static std::shared_ptr< Utils::MultipleLinearRegression > GetRegressor(const std::string &logFilePath, const std::vector< size_t > &featureIndices)
static std::shared_ptr< Simulators::ISimulator > GetSimulator(Simulators::SimulatorType simType, Simulators::SimulationType method, size_t nrQubits, size_t maxBondDim)
static double EstimatePauliExpectationCost(const std::string &pauliString, Simulators::SimulationType method, size_t nrQubits, const std::shared_ptr< Circuits::Circuit<> > &circuit, size_t maxBondDim)
static void BenchmarkAndLogSampling(Simulators::SimulatorType simType, Simulators::SimulationType method, const std::shared_ptr< Circuits::Circuit<> > &circuit, size_t nrQubitsSampled, size_t nrSamples, size_t nrReps, size_t maxBondDim, Utils::LogFile &log)
static double EstimateSamplingCost(Simulators::SimulationType method, size_t nrQubits, size_t nrQubitsSampled, size_t samples, const std::shared_ptr< Circuits::Circuit<> > &circuit, size_t maxBondDim)
static std::string GeneratePauliString(size_t nrQubits)
static double EstimateExecutionCost(Simulators::SimulationType method, size_t nrQubits, const std::shared_ptr< Circuits::Circuit<> > &circuit, size_t maxBondDim)
static CircuitInfo GetCircuitInfo(const std::shared_ptr< Circuits::Circuit<> > &circuit)
static void BenchmarkAndLogExecution(Simulators::SimulatorType simType, Simulators::SimulationType method, const std::shared_ptr< Circuits::Circuit<> > &circuit, size_t nrReps, size_t maxBondDim, Utils::LogFile &log)
static std::vector< ExecutionInfo > ReadLog(const std::string &logFilePath)
static void BenchmarkAndLogExecution(Simulators::SimulatorType simType, Simulators::SimulationType method, size_t nrReps, size_t nrMinQubits, size_t nrMaxQubits, size_t stepQubits, size_t depthMin, size_t depthMax, size_t stepDepth, double measureInsideProbability, size_t nrMeasAtEndMin, size_t nrMeasAtEndMax, size_t stepMeasAtEnd, size_t nrRandomCircuitsPerConfig, const std::string &logFilePath, size_t startBondDim=16, size_t endBondDim=16)
static double GetSamplingCost(const std::shared_ptr< Circuits::Circuit<> > &circuit, size_t nrQubitsSampled, size_t samples)
static double GetCost(const std::shared_ptr< Circuits::Circuit<> > &circuit)
static MAESTRO_FACTORY_EXPORT std::shared_ptr< ISimulator > CreateSimulator(SimulatorType t=SimulatorType::kQCSim, SimulationType method=SimulationType::kMatrixProductState)
Create a quantum computing simulator.
void Log(const std::string &message)
QuantumGateType
The type of quantum gates.
@ kConditionalGate
conditional gate, similar with gate, but conditioned on something from 'OperationState'
@ kConditionalMeasurement
conditional measurement, similar with measurement, but conditioned on something from 'OperationState'
@ kMeasurement
measurement, result in 'OperationState'
@ kGate
the usual quantum gate, result stays in simulator's state
@ kReset
reset, no result in 'state', just apply measurement, then apply not on all qubits that were measured ...
@ kQuantumChannel
a non-unitary CPTP operation on the simulator state
SimulationType
The type of simulation.
@ kStatevector
statevector simulation type
@ kMatrixProductState
matrix product state simulation type
@ kStabilizer
Clifford gates simulation type.
@ kPauliPropagator
Pauli propagator simulation type.
@ kPathIntegral
Path integral simulation type.
SimulatorType
The type of simulator.
std::vector< qubit_t > qubits_vector
The type of a vector of qubits.
uint_fast64_t qubit_t
The type of a qubit.
size_t nrTwoQubitOpsExecutedOnce
CircuitInfo(const CircuitInfo &other)=default
size_t nrEndMeasurementOps
size_t nrOneQubitOpsExecutedOnce
size_t nrThreeQubitOpsExecutedOnce
CircuitInfo & operator=(const CircuitInfo &other)=default
size_t nrMiddleMeasurementOps
double getFieldValue(size_t index) const
ExecutionInfo(const CircuitInfo &circuitInfo)
ExecutionInfo & operator=(const ExecutionInfo &other)=default
double getFieldValue(size_t index) const
ExecutionInfo(const ExecutionInfo &other)=default
ExecutionInfo & operator=(const CircuitInfo &circuitInfo)