24 explicit GpuMPO(
const std::shared_ptr<GpuLibrary>& lib,
int device = -1)
25 : lib(lib), obj(
nullptr) {
27 auto lock = lib->LockInitialization();
28 if (lib->SetGpuDevice(device == -1 ? lib->GetCreationDevice() : device))
29 obj = lib->CreateMPO();
33 int GetGpuDevice()
const {
return lib ? lib->MPOGetGpuId(obj) : -1; }
35 GpuMPO(
const std::shared_ptr<GpuLibrary>& lib,
void* obj)
36 : lib(lib), obj(obj) {}
38 GpuMPO(
const GpuMPO&) =
delete;
39 GpuMPO& operator=(
const GpuMPO&) =
delete;
40 ~GpuMPO() {
if (lib && obj) lib->DestroyMPO(obj); }
42 bool Create(
unsigned int n) {
return lib->MPOCreate(obj, n); }
43 bool CreateWithState(
unsigned int n,
const double* state) {
44 return lib->MPOCreateWithState(obj, n, state);
46 bool CreateWithBasisState(
unsigned int n,
unsigned long long state) {
47 return lib->MPOCreateWithBasisState(obj, n, state);
49 bool CreateWithBasisStateBits(
unsigned int n,
50 const std::vector<unsigned char>& stateBits) {
51 return lib->MPOCreateWithBasisStateBits(obj, n, stateBits.data());
53 bool CreateWithMixtureOfBasisStates(
55 const std::vector<std::pair<unsigned long long, double>>& mixture) {
56 std::vector<unsigned long long> states;
57 std::vector<double> weights;
58 states.reserve(mixture.size());
59 weights.reserve(mixture.size());
60 for (
const auto& [state, weight] : mixture) {
61 states.push_back(state);
62 weights.push_back(weight);
64 return lib->MPOCreateWithMixtureOfBasisStates(
65 obj, n, states.data(), weights.data(),
66 static_cast<int>(states.size()));
68 bool CreateWithMixtureOfBasisStatesBits(
69 unsigned int n,
const std::vector<unsigned char>& stateBitsFlat,
70 const std::vector<double>& weights) {
71 return lib->MPOCreateWithMixtureOfBasisStatesBits(
72 obj, n, stateBitsFlat.data(), weights.data(),
73 static_cast<int>(weights.size()));
76 if (!lib->MPOReset(obj))
77 throw std::runtime_error(
"GPU matrix-product-operator reset failed");
79 bool SetSeed(uint64_t seed) {
return lib->MPOSetSeed(obj, seed); }
80 bool SetInitialQubitsMap(
const std::vector<long long int>& initialMap) {
81 return lib->MPOSetInitialQubitsMap(obj, initialMap);
83 bool SetUseOptimalMeetingPosition(
bool useOptimalMeetingPosition) {
84 return lib->MPOSetUseOptimalMeetingPosition(obj, useOptimalMeetingPosition);
86 bool GetUseOptimalMeetingPosition()
const {
87 return lib->MPOGetUseOptimalMeetingPosition(obj);
89 bool SetCallbackContext(
void* context) {
90 return lib->MPOSetCallbackContext(obj, context);
92 bool SetMeetingPositionCallback(
93 int64_t (*callback)(
void*,
const int64_t*)) {
94 return lib->MPOSetMeetingPositionCallback(obj, callback);
96 bool SetBondDimensionsCallback(
void (*callback)(
void*,
const int64_t*)) {
97 return lib->MPOSetBondDimensionsCallback(obj, callback);
99 bool IsCreated()
const {
return lib->MPOIsCreated(obj); }
100 void SetDataType(
bool useDouble) {
101 if (!lib->MPOSetDataType(obj, useDouble))
102 throw std::runtime_error(
103 "GPU matrix-product-operator precision configuration failed");
105 void SetCutoff(
double singularValueThreshold) {
106 lib->MPOSetCutoff(obj, singularValueThreshold);
108 double GetCutoff()
const {
return lib->MPOGetCutoff(obj); }
111 bool SetTruncationMode(
int mode) {
112 return lib->MPOSetTruncationMode(obj, mode);
114 int GetTruncationMode()
const {
return lib->MPOGetTruncationMode(obj); }
115 bool SetGesvdJ(
bool enable) {
return lib->MPOSetGesvdJ(obj, enable); }
116 bool GetGesvdJ()
const {
return lib->MPOGetGesvdJ(obj); }
118 bool SetGesvdP(
bool enable) {
119 return obj && lib->MPOSetGesvdP(obj, enable);
121 bool GetGesvdP()
const {
return lib->MPOGetGesvdP(obj); }
122 bool SetGesvdR(
bool enable) {
123 return obj && lib->MPOSetGesvdR(obj, enable);
125 bool GetGesvdR()
const {
return lib->MPOGetGesvdR(obj); }
126 int GetLastSvdAlgo()
const {
return lib->MPOGetLastSvdAlgo(obj); }
128 void SetMaxExtent(
long int chi) { lib->MPOSetMaxExtent(obj, chi); }
129 long int GetMaxExtent()
const {
return lib->MPOGetMaxExtent(obj); }
130 std::vector<long long int> GetBondDimensions(
size_t nrQubits)
const {
131 if (nrQubits < 2)
return {};
132 std::vector<long long int> bondDims(nrQubits - 1);
133 if (!lib->MPOGetBondDimensions(obj, bondDims.data()))
return {};
136 void ReCanonicalize(
int centerSite = 0) {
137 if (!lib->MPOReCanonicalize(obj, centerSite))
throw std::runtime_error(
"GPU MPO canonicalization failed");
139 void Trim(
double cutoff = -1.,
long int maxExtent = -1,
int centerSite = 0) {
140 if (!lib->MPOTrim(obj, cutoff, maxExtent, centerSite))
throw std::runtime_error(
"GPU MPO trim failed");
142 bool Measure(
unsigned int q) {
return lib->MPOMeasureQubitCollapse(obj, q); }
143 bool MeasureNoCollapse(
unsigned int q) {
return lib->MPOMeasureQubitNoCollapse(obj, q); }
144 bool MeasureQubits(std::vector<int>& qubits, std::vector<int>& bits,
bool collapse =
true) {
145 if (qubits.size() != bits.size())
throw std::invalid_argument(
"Measurement vectors must have equal size");
146 return collapse ? lib->MPOMeasureQubitsCollapse(obj, qubits.data(), bits.data(),
static_cast<int>(bits.size()))
147 : lib->MPOMeasureQubitsNoCollapse(obj, qubits.data(), bits.data(),
static_cast<int>(bits.size()));
149 unsigned long long MeasureAll(
bool collapse =
true) {
return collapse ? lib->MPOMeasureAllQubitsCollapse(obj) : lib->MPOMeasureAllQubitsNoCollapse(obj); }
150 bool Sample(
unsigned int nSamples,
long int* samples,
unsigned int nBits,
152 return lib->MPOSample(obj, nSamples, samples, nBits, bitOrdering);
154 bool SampleAll(
unsigned int shots,
long int* samples) {
155 return lib->MPOSampleAll(obj, shots, samples);
158 return lib->MPOBasisStateProbability(obj, outcome);
160 std::complex<double> GetElement(
long long row,
long long col)
const {
161 double re = 0., im = 0.;
162 if (!lib->MPOGetElement(obj, row, col, &re, &im))
throw std::runtime_error(
"GPU MPO element query failed");
166 if (!lib->MPOAllProbabilities(obj, probabilities))
167 throw std::runtime_error(
168 "GPU matrix-product-operator probability enumeration failed");
170 double ExpectationValue(
const std::string& pauli)
const {
171 return lib->MPOExpectationValue(obj, pauli.c_str(), pauli.size());
173 double QubitProbability0(
unsigned int q)
const {
return lib->MPOQubitProbability0(obj, q); }
174 double Trace()
const {
return lib->MPOTrace(obj); }
175 double Purity()
const {
return lib->MPOPurity(obj); }
176 double HermiticityResidual()
const {
return lib->MPOHermiticityResidual(obj); }
177 bool IsHermitian(
double eps = 1e-10)
const {
return lib->MPOIsHermitian(obj, eps); }
178 double TraceOfSquare()
const {
return lib->MPOTraceOfSquare(obj); }
179 void RestoreTrace() {
if (!lib->MPORestoreTrace(obj))
throw std::runtime_error(
"GPU MPO trace restoration failed"); }
180 void Hermitize() {
if (!lib->MPOHermitize(obj))
throw std::runtime_error(
"GPU MPO hermitization failed"); }
181 bool SetKrausCompletenessCheck(
int mode) {
return lib->MPOSetKrausCompletenessCheck(obj, mode); }
182 int GetKrausCompletenessCheck()
const {
return lib->MPOGetKrausCompletenessCheck(obj); }
183 std::vector<std::complex<double>> PartialTrace(
const std::vector<int>& qubits)
const {
184 const size_t dim =
size_t{1} << qubits.size();
185 std::vector<double> raw(2 * dim * dim);
186 if (!lib->MPOPartialTrace(obj, qubits.data(),
static_cast<int>(qubits.size()), raw.data()))
throw std::runtime_error(
"GPU MPO partial trace failed");
187 std::vector<std::complex<double>> result(dim * dim);
188 for (
size_t i = 0; i < result.size(); ++i) result[i] = {raw[2*i], raw[2*i+1]};
191 std::complex<double> HilbertSchmidtOverlap(
const GpuMPO& other)
const {
192 double re = 0., im = 0.;
193 if (!lib->MPOHilbertSchmidtOverlap(obj, other.obj, &re, &im))
throw std::runtime_error(
"GPU MPO overlap failed");
196 double FidelityWithStatevector(
const double* state)
const {
198 if (!lib->MPOFidelityWithStatevector(obj, state, &result))
throw std::runtime_error(
"GPU MPO fidelity failed");
202 if (!lib->MPOSaveState(obj))
203 throw std::runtime_error(
"GPU matrix-product-operator state save failed");
206 if (!lib->MPORestoreState(obj))
207 throw std::runtime_error(
208 "GPU matrix-product-operator state restore failed");
210 void CleanSavedState() {
211 if (!lib->MPOCleanSavedState(obj))
212 throw std::runtime_error(
213 "GPU matrix-product-operator saved-state cleanup failed");
215 std::unique_ptr<GpuMPO> Clone()
const {
216 void* cloned = lib->MPOClone(obj);
217 if (!cloned)
return nullptr;
218 return std::make_unique<GpuMPO>(lib, cloned);
220 bool ApplyKraus(
const std::vector<int>& qubits,
int count,
221 const double* operators) {
222 return lib->MPOApplyKraus(obj, qubits.size(), qubits.data(), count,
225 bool ApplyOneQubitMatrix(
int qubit,
const double* matrixInterleaved) {
226 return lib->MPOApplyOneQubitMatrix(obj, qubit, matrixInterleaved);
228 bool ApplyTwoQubitMatrix(
int qubit1,
int qubit2,
229 const double* matrixInterleaved) {
230 return lib->MPOApplyTwoQubitMatrix(obj, qubit1, qubit2,
234#define GPU_MPO_CHECK(call, name) \
237 throw std::runtime_error("GPU matrix-product-operator " name \
240#define GPU_MPO_GATE1(name) \
241 void name(int q) { GPU_MPO_CHECK(lib->MPO##name(obj, q), #name); }
242#define GPU_MPO_GATE2(name) \
243 void name(int a, int b) { GPU_MPO_CHECK(lib->MPO##name(obj, a, b), #name); }
244#define GPU_MPO_ROT1(name) \
245 void name(int q, double x) { \
246 GPU_MPO_CHECK(lib->MPO##name(obj, q, x), #name); \
248#define GPU_MPO_ROT2(name) \
249 void name(int a, int b, double x) { \
250 GPU_MPO_CHECK(lib->MPO##name(obj, a, b, x), #name); \
253 GPU_MPO_ROT1(ApplyBitFlipNoise) GPU_MPO_ROT1(ApplyPhaseFlipNoise)
254 GPU_MPO_ROT1(ApplyDepolarizingNoise) GPU_MPO_ROT1(ApplyAmplitudeDamping)
255 GPU_MPO_ROT1(ApplyPhaseDamping) GPU_MPO_GATE1(ApplyNonSelectiveMeasurement)
262 void ApplyU(
int q,
double a,
double b,
double c,
double d) {
263 GPU_MPO_CHECK(lib->MPOApplyU(obj, q, a, b, c, d),
"ApplyU");
270 void ApplyCU(
int a,
int b,
double c,
double d,
double e,
double f) {
271 GPU_MPO_CHECK(lib->MPOApplyCU(obj, a, b, c, d, e, f),
"ApplyCU");
280 GpuDeviceContext lib;
int ApplyK(void *sim, int qubit)
double Probability(void *sim, unsigned long long int outcome)
int RestoreState(void *sim)
int ApplyRx(void *sim, int qubit, double theta)
int ApplyReset(void *sim, const unsigned long int *qubits, unsigned long int nrQubits)
int ApplyX(void *sim, int qubit)
int ApplyU(void *sim, int qubit, double theta, double phi, double lambda, double gamma)
int ApplyCRy(void *sim, int controlQubit, int targetQubit, double theta)
int ApplyTDG(void *sim, int qubit)
int ApplyCSXDG(void *sim, int controlQubit, int targetQubit)
int ApplyS(void *sim, int qubit)
int ApplyCX(void *sim, int controlQubit, int targetQubit)
int ApplyCRz(void *sim, int controlQubit, int targetQubit, double theta)
double * AllProbabilities(void *sim)
unsigned long long int MeasureNoCollapse(void *sim)
int ApplyCP(void *sim, int controlQubit, int targetQubit, double theta)
int ApplySXDG(void *sim, int qubit)
int ApplySDG(void *sim, int qubit)
unsigned long long int Measure(void *sim, const unsigned long int *qubits, unsigned long int nrQubits)
int ApplyY(void *sim, int qubit)
int ApplyZ(void *sim, int qubit)
int ApplyH(void *sim, int qubit)
int ApplyCY(void *sim, int controlQubit, int targetQubit)
int ApplyCU(void *sim, int controlQubit, int targetQubit, double theta, double phi, double lambda, double gamma)
int ApplySwap(void *sim, int qubit1, int qubit2)
int ApplyRy(void *sim, int qubit, double theta)
int ApplyP(void *sim, int qubit, double theta)
int ApplyCH(void *sim, int controlQubit, int targetQubit)
int ApplySX(void *sim, int qubit)
int ApplyCZ(void *sim, int controlQubit, int targetQubit)
int ApplyRz(void *sim, int qubit, double theta)
int ApplyT(void *sim, int qubit)
int ApplyCRx(void *sim, int controlQubit, int targetQubit, double theta)
int ApplyCSX(void *sim, int controlQubit, int targetQubit)