Maestro 0.3.1
Unified interface for quantum circuit simulation
Loading...
Searching...
No Matches
GpuDensityMatrix.h
Go to the documentation of this file.
1
4#pragma once
5
6#ifndef _GPU_DENSITY_MATRIX_H_
7#define _GPU_DENSITY_MATRIX_H_
8
9#ifdef __linux__
10
11#include <memory>
12#include <complex>
13#include <stdexcept>
14#include <string>
15#include <utility>
16#include <vector>
17
18#include "GpuDeviceContext.h"
19
20namespace Simulators {
21
22class GpuDensityMatrix {
23 public:
24 explicit GpuDensityMatrix(const std::shared_ptr<GpuLibrary>& lib, int device = -1)
25 : lib(lib), obj(nullptr) {
26 if (lib) {
27 auto lock = lib->LockInitialization();
28 if (lib->SetGpuDevice(device == -1 ? lib->GetCreationDevice() : device))
29 obj = lib->CreateDensityMatrix();
30 }
31 }
32
33 int GetGpuDevice() const { return lib ? lib->DMGetGpuId(obj) : -1; }
34
35 GpuDensityMatrix(const std::shared_ptr<GpuLibrary>& lib, void* obj)
36 : lib(lib), obj(obj) {}
37 GpuDensityMatrix() = delete;
38 GpuDensityMatrix(const GpuDensityMatrix&) = delete;
39 GpuDensityMatrix& operator=(const GpuDensityMatrix&) = delete;
40 ~GpuDensityMatrix() { if (lib && obj) lib->DestroyDensityMatrix(obj); }
41
42 bool Create(unsigned int n) { return lib->DMCreate(obj, n); }
43 bool CreateWithState(unsigned int n, const double* state) {
44 return lib->DMCreateWithState(obj, n, state);
45 }
46 bool CreateWithBasisState(unsigned int n, unsigned long long state) {
47 return lib->DMCreateWithBasisState(obj, n, state);
48 }
49 bool CreateWithMixtureOfBasisStates(
50 unsigned int n,
51 const std::vector<std::pair<unsigned long long, double>>& mixture) {
52 std::vector<unsigned long long> states;
53 std::vector<double> weights;
54 states.reserve(mixture.size());
55 weights.reserve(mixture.size());
56 for (const auto& [state, weight] : mixture) {
57 states.push_back(state);
58 weights.push_back(weight);
59 }
60 return lib->DMCreateWithMixtureOfBasisStates(
61 obj, n, states.data(), weights.data(),
62 static_cast<int>(states.size()));
63 }
64 void Reset() {
65 if (!lib->DMReset(obj))
66 throw std::runtime_error("GPU density-matrix reset failed");
67 }
68 bool SetSeed(uint64_t seed) { return lib->DMSetSeed(obj, seed); }
69 bool IsCreated() const { return lib->DMIsCreated(obj); }
70 void SetDataType(bool useDouble) {
71 if (!lib->DMSetDataType(obj, useDouble))
72 throw std::runtime_error(
73 "GPU density-matrix precision configuration failed");
74 }
75 bool Measure(unsigned int q) { return lib->DMMeasureQubitCollapse(obj, q); }
76 bool MeasureNoCollapse(unsigned int q) { return lib->DMMeasureQubitNoCollapse(obj, q); }
77 bool MeasureQubits(std::vector<int>& qubits, std::vector<int>& bits, bool collapse = true) {
78 if (qubits.size() != bits.size()) throw std::invalid_argument("Measurement vectors must have equal size");
79 return collapse ? lib->DMMeasureQubitsCollapse(obj, qubits.data(), bits.data(), static_cast<int>(bits.size()))
80 : lib->DMMeasureQubitsNoCollapse(obj, qubits.data(), bits.data(), static_cast<int>(bits.size()));
81 }
82 unsigned long long MeasureAll(bool collapse = true) { return collapse ? lib->DMMeasureAllQubitsCollapse(obj) : lib->DMMeasureAllQubitsNoCollapse(obj); }
83 bool Sample(unsigned int n, long int* samples, unsigned int nBits, int* order) { return lib->DMSample(obj, n, samples, nBits, order); }
84 bool SampleAll(unsigned int shots, long int* samples) {
85 return lib->DMSampleAll(obj, shots, samples);
86 }
87 double Probability(long long outcome) const {
88 return lib->DMBasisStateProbability(obj, outcome);
89 }
90 std::complex<double> GetElement(long long row, long long col) const {
91 double re = 0., im = 0.;
92 if (!lib->DMGetElement(obj, row, col, &re, &im)) throw std::runtime_error("GPU density-matrix element query failed");
93 return {re, im};
94 }
95 void AllProbabilities(double* probabilities) {
96 if (!lib->DMAllProbabilities(obj, probabilities))
97 throw std::runtime_error(
98 "GPU density-matrix probability enumeration failed");
99 }
100 double ExpectationValue(const std::string& pauli) const {
101 return lib->DMExpectationValue(obj, pauli.c_str(), pauli.size());
102 }
103 double QubitProbability0(unsigned int q) const { return lib->DMQubitProbability0(obj, q); }
104 double Trace() const { return lib->DMTrace(obj); }
105 double Purity() const { return lib->DMPurity(obj); }
106 bool IsHermitian(double eps = 1e-10) const { return lib->DMIsHermitian(obj, eps); }
107 std::vector<std::complex<double>> PartialTrace(const std::vector<int>& qubits) const {
108 const size_t dim = size_t{1} << qubits.size();
109 std::vector<double> raw(2 * dim * dim);
110 if (!lib->DMPartialTrace(obj, qubits.data(), static_cast<int>(qubits.size()), raw.data()))
111 throw std::runtime_error("GPU density-matrix partial trace failed");
112 std::vector<std::complex<double>> result(dim * dim);
113 for (size_t i = 0; i < result.size(); ++i) result[i] = {raw[2*i], raw[2*i+1]};
114 return result;
115 }
116 std::complex<double> HilbertSchmidtOverlap(const GpuDensityMatrix& other) const {
117 double re = 0., im = 0.;
118 if (!lib->DMHilbertSchmidtOverlap(obj, other.obj, &re, &im))
119 throw std::runtime_error("GPU density-matrix overlap failed");
120 return {re, im};
121 }
122 double FidelityWithStatevector(const double* state) const {
123 double result = 0.;
124 if (!lib->DMFidelityWithStatevector(obj, state, &result))
125 throw std::runtime_error("GPU density-matrix fidelity failed");
126 return result;
127 }
128 void SaveState() {
129 if (!lib->DMSaveState(obj))
130 throw std::runtime_error("GPU density-matrix state save failed");
131 }
132 void RestoreState() {
133 if (!lib->DMRestoreState(obj))
134 throw std::runtime_error("GPU density-matrix state restore failed");
135 }
136 void CleanSavedState() {
137 if (!lib->DMCleanSavedState(obj))
138 throw std::runtime_error("GPU density-matrix saved-state cleanup failed");
139 }
140 std::unique_ptr<GpuDensityMatrix> Clone() const {
141 void* cloned = lib->DMClone(obj);
142 if (!cloned) return nullptr;
143 return std::make_unique<GpuDensityMatrix>(lib, cloned);
144 }
145 bool ApplyKraus(const std::vector<int>& qubits, int count,
146 const double* operators) {
147 return lib->DMApplyKraus(obj, qubits.size(), qubits.data(), count,
148 operators);
149 }
150
151#define GPU_DM_CHECK(call, name) \
152 do { \
153 if (!(call)) \
154 throw std::runtime_error("GPU density-matrix " name " failed"); \
155 } while (false)
156#define GPU_DM_GATE1(name) \
157 void name(int q) { GPU_DM_CHECK(lib->DM##name(obj, q), #name); }
158#define GPU_DM_GATE2(name) \
159 void name(int a, int b) { GPU_DM_CHECK(lib->DM##name(obj, a, b), #name); }
160#define GPU_DM_ROT1(name) \
161 void name(int q, double x) { GPU_DM_CHECK(lib->DM##name(obj, q, x), #name); }
162#define GPU_DM_ROT2(name) \
163 void name(int a, int b, double x) { \
164 GPU_DM_CHECK(lib->DM##name(obj, a, b, x), #name); \
165 }
166 GPU_DM_GATE1(ApplyReset)
167 GPU_DM_ROT1(ApplyBitFlipNoise) GPU_DM_ROT1(ApplyPhaseFlipNoise)
168 GPU_DM_ROT1(ApplyDepolarizingNoise) GPU_DM_ROT1(ApplyAmplitudeDamping)
169 GPU_DM_ROT1(ApplyPhaseDamping) GPU_DM_GATE1(ApplyNonSelectiveMeasurement)
170 GPU_DM_GATE1(ApplyX) GPU_DM_GATE1(ApplyY) GPU_DM_GATE1(ApplyZ)
171 GPU_DM_GATE1(ApplyH) GPU_DM_GATE1(ApplyS) GPU_DM_GATE1(ApplySDG)
172 GPU_DM_GATE1(ApplyT) GPU_DM_GATE1(ApplyTDG) GPU_DM_GATE1(ApplySX)
173 GPU_DM_GATE1(ApplySXDG) GPU_DM_GATE1(ApplyK)
174 GPU_DM_ROT1(ApplyP) GPU_DM_ROT1(ApplyRx) GPU_DM_ROT1(ApplyRy)
175 GPU_DM_ROT1(ApplyRz)
176 void ApplyU(int q, double a, double b, double c, double d) {
177 GPU_DM_CHECK(lib->DMApplyU(obj, q, a, b, c, d), "ApplyU");
178 }
179 GPU_DM_GATE2(ApplyCX) GPU_DM_GATE2(ApplyCY) GPU_DM_GATE2(ApplyCZ)
180 GPU_DM_GATE2(ApplyCH) GPU_DM_GATE2(ApplyCSX) GPU_DM_GATE2(ApplyCSXDG)
181 GPU_DM_ROT2(ApplyCP) GPU_DM_ROT2(ApplyCRx) GPU_DM_ROT2(ApplyCRy)
182 GPU_DM_ROT2(ApplyCRz)
183 void ApplyCCX(int a, int b, int c) {
184 GPU_DM_CHECK(lib->DMApplyCCX(obj, a, b, c), "ApplyCCX");
185 }
186 GPU_DM_GATE2(ApplySwap)
187 void ApplyCSwap(int a, int b, int c) {
188 GPU_DM_CHECK(lib->DMApplyCSwap(obj, a, b, c), "ApplyCSwap");
189 }
190 void ApplyCU(int a, int b, double c, double d, double e, double f) {
191 GPU_DM_CHECK(lib->DMApplyCU(obj, a, b, c, d, e, f), "ApplyCU");
192 }
193#undef GPU_DM_ROT2
194#undef GPU_DM_ROT1
195#undef GPU_DM_GATE2
196#undef GPU_DM_GATE1
197#undef GPU_DM_CHECK
198
199 private:
200 GpuDeviceContext lib;
201 void* obj = nullptr;
202};
203
204} // namespace Simulators
205#endif
206#endif
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 ApplyCSwap(void *sim, int controlQubit, int qubit1, int qubit2)
int ApplyCCX(void *sim, int controlQubit1, int controlQubit2, int targetQubit)
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)
int SaveState(void *sim)