14#ifndef _QCSIM_PAULI_PROPAGATOR_H
15#define _QCSIM_PAULI_PROPAGATOR_H 1
17#include "PauliPropagator.h"
18#include "../Circuit/Circuit.h"
24 void ApplyP(
int qubit,
double lambda) { ApplyRZ(qubit, lambda); }
26 void ApplyT(
int qubit) { ApplyRZ(qubit, M_PI_4); }
28 void ApplyTDG(
int qubit) { ApplyRZ(qubit, -M_PI_4); }
30 void ApplyU(
int qubit,
double theta,
double phi,
double lambda,
32 ApplyRZ(qubit, lambda);
33 ApplyRY(qubit, theta);
37 void ApplyCH(
int controlQubit,
int targetQubit) {
40 ApplyCX(controlQubit, targetQubit);
43 ApplyCX(controlQubit, targetQubit);
51 void ApplyCU(
int controlQubit,
int targetQubit,
double theta,
double phi,
52 double lambda,
double gamma = 0.0) {
53 if (gamma != 0.0)
ApplyP(controlQubit, gamma);
55 const double lambdaPlusPhiHalf = 0.5 * (lambda + phi);
56 const double halfTheta = 0.5 * theta;
57 ApplyP(targetQubit, 0.5 * (lambda - phi));
58 ApplyP(controlQubit, lambdaPlusPhiHalf);
59 ApplyCX(controlQubit, targetQubit);
60 ApplyU(targetQubit, -halfTheta, 0, -lambdaPlusPhiHalf);
61 ApplyCX(controlQubit, targetQubit);
62 ApplyU(targetQubit, halfTheta, phi, 0);
65 void ApplyCRX(
int controlQubit,
int targetQubit,
double angle) {
66 const double halfAngle = angle * 0.5;
69 ApplyCX(controlQubit, targetQubit);
70 ApplyRZ(targetQubit, -halfAngle);
71 ApplyCX(controlQubit, targetQubit);
72 ApplyRZ(targetQubit, halfAngle);
76 void ApplyCRY(
int controlQubit,
int targetQubit,
double angle) {
77 const double halfAngle = angle * 0.5;
78 ApplyRY(targetQubit, halfAngle);
79 ApplyCX(controlQubit, targetQubit);
80 ApplyRY(targetQubit, -halfAngle);
81 ApplyCX(controlQubit, targetQubit);
84 void ApplyCRZ(
int controlQubit,
int targetQubit,
double angle) {
85 const double halfAngle = angle * 0.5;
87 ApplyRZ(targetQubit, halfAngle);
88 ApplyCX(controlQubit, targetQubit);
89 ApplyRZ(targetQubit, -halfAngle);
90 ApplyCX(controlQubit, targetQubit);
93 void ApplyCP(
int controlQubit,
int targetQubit,
double lambda) {
94 const double halfAngle = lambda * 0.5;
95 ApplyP(controlQubit, halfAngle);
96 ApplyCX(controlQubit, targetQubit);
97 ApplyP(targetQubit, -halfAngle);
98 ApplyCX(controlQubit, targetQubit);
99 ApplyP(targetQubit, halfAngle);
102 void ApplyCS(
int controlQubit,
int targetQubit) {
105 ApplyCX(controlQubit, targetQubit);
107 ApplyCX(controlQubit, targetQubit);
111 ApplyCX(controlQubit, targetQubit);
113 ApplyCX(controlQubit, targetQubit);
120 ApplyCS(controlQubit, targetQubit);
130 void ApplyCSwap(
int controlQubit,
int targetQubit1,
int targetQubit2) {
131 const int q1 = controlQubit;
132 const int q2 = targetQubit1;
133 const int q3 = targetQubit2;
150 void ApplyCCX(
int controlQubit1,
int controlQubit2,
int targetQubit) {
151 const int q1 = controlQubit1;
152 const int q2 = controlQubit2;
153 const int q3 = targetQubit;
162 std::unique_ptr<QcsimPauliPropagator>
Clone()
const {
163 auto clone = std::make_unique<QcsimPauliPropagator>();
164 clone->SetNrQubits(GetNrQubits());
165 clone->SetPauliWeightThreshold(GetPauliWeightThreshold());
166 clone->SetBatchSize(GetBatchSize());
167 clone->SetBatchSizeForSum(GetBatchSizeForSum());
168 clone->SetCoefficientThreshold(GetCoefficientThreshold());
169 clone->SetParallelThreshold(GetParallelThreshold());
170 clone->SetParallelThresholdForSum(GetParallelThresholdForSum());
171 clone->SetStepsBetweenDeduplication(StepsBetweenDeduplication());
172 clone->SetStepsBetweenTrims(StepsBetweenTrims());
173 clone->SetOperations(GetOperations());
174 clone->SetSavePosition(GetSavePosition());
175 if (IsParallelEnabled()) clone->EnableParallel();
182 size_t nrQubitsSampled,
size_t samples) {
183 return samples *
GetCost(circuit) * exp2(nrQubitsSampled - 1);
187 if (!circuit)
return 0.0;
190 double doublingCost = 1;
195 for (
int pos =
static_cast<int>(circuit->size()) - 1; pos >= 0; --pos) {
196 const std::shared_ptr<Circuits::IOperation<>>& op = (*circuit)[pos];
197 cost += GetOpCost(circuit, op, pos) * doublingCost;
198 doublingCost *= GetOpMultiplication(op);
202 cost += doublingCost;
211 if (!circuit || !op || pos < 0 || pos >=
static_cast<int>(circuit->size()))
220 if (pos == 0)
return 1.;
222 const auto& prevOp = (*circuit)[pos - 1];
223 return 1. + GetOpCost(circuit, prevOp, pos - 1);
227 if (pos == 0)
return 1.5;
228 const auto& prevOp = (*circuit)[pos - 1];
229 return 1.5 + GetOpCost(circuit, prevOp, pos - 1);
231 const auto conditionalGate =
232 std::static_pointer_cast<Circuits::ConditionalGate<>>(op);
233 return GetOpCost(circuit, conditionalGate->GetOperation(), pos);
234 }
else if (op->GetType() ==
236 const auto conditionalMeasurement =
237 std::static_pointer_cast<Circuits::ConditionalMeasurement<>>(op);
238 return GetOpCost(circuit, conditionalMeasurement->GetOperation(), pos);
243 const auto gate = std::static_pointer_cast<Circuits::IQuantumGate<>>(op);
245 switch (gate->GetGateType()) {
324 static double GetOpMultiplication(
334 const auto conditionalGate =
335 std::static_pointer_cast<Circuits::ConditionalGate<>>(op);
336 return GetOpMultiplication(conditionalGate->GetOperation());
337 }
else if (op->GetType() ==
344 const auto gate = std::static_pointer_cast<Circuits::IQuantumGate<>>(op);
345 switch (gate->GetGateType()) {
int ApplyX(void *sim, int qubit)
int ApplyS(void *sim, int qubit)
int ApplyCX(void *sim, int controlQubit, int targetQubit)
int ApplySDG(void *sim, int qubit)
int ApplyH(void *sim, int qubit)
Circuit class for holding the sequence of operations.
void ApplyCH(int controlQubit, int targetQubit)
void ApplyCU(int controlQubit, int targetQubit, double theta, double phi, double lambda, double gamma=0.0)
std::unique_ptr< QcsimPauliPropagator > Clone() const
static double GetSamplingCost(const std::shared_ptr< Circuits::Circuit<> > &circuit, size_t nrQubitsSampled, size_t samples)
void ApplyCRZ(int controlQubit, int targetQubit, double angle)
void ApplyCRY(int controlQubit, int targetQubit, double angle)
static double GetCost(const std::shared_ptr< Circuits::Circuit<> > &circuit)
void ApplyP(int qubit, double lambda)
void ApplyCP(int controlQubit, int targetQubit, double lambda)
void ApplyU(int qubit, double theta, double phi, double lambda, double gamma=0.0)
void ApplyCSXDAG(int controlQubit, int targetQubit)
void ApplyCSDAG(int controlQubit, int targetQubit)
void ApplyCSX(int controlQubit, int targetQubit)
void ApplyCSwap(int controlQubit, int targetQubit1, int targetQubit2)
void ApplyCS(int controlQubit, int targetQubit)
void ApplyCCX(int controlQubit1, int controlQubit2, int targetQubit)
void ApplyCRX(int controlQubit, int targetQubit, double angle)
@ 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 ...