Maestro 0.3.11
Unified interface for quantum circuit simulation
Loading...
Searching...
No Matches
GpuMPO.h
Go to the documentation of this file.
1
4#pragma once
5
6#ifndef _GPU_MPO_H_
7#define _GPU_MPO_H_
8
9#ifdef __linux__
10
11#include <cmath>
12#include <complex>
13#include <limits>
14#include <memory>
15#include <stdexcept>
16#include <string>
17#include <unordered_map>
18#include <utility>
19#include <vector>
20
22#include "GpuDeviceContext.h"
23
24namespace Simulators
25{
26
27class GpuMPO
28{
29 public:
30 explicit GpuMPO(const std::shared_ptr<GpuLibrary> &lib, int device = -1) : lib(lib), obj(nullptr)
31 {
32 if (lib)
33 {
34 auto lock = lib->LockInitialization();
35 if (lib->SetGpuDevice(device == -1 ? lib->GetCreationDevice() : device))
36 obj = lib->CreateMPO();
37 }
38 }
39
40 int GetGpuDevice() const
41 {
42 return lib ? lib->MPOGetGpuId(obj) : -1;
43 }
44
45 GpuMPO(const std::shared_ptr<GpuLibrary> &lib, void *obj) : lib(lib), obj(obj)
46 {
47 }
48
49 GpuMPO() = delete;
50 GpuMPO(const GpuMPO &) = delete;
51 GpuMPO &operator=(const GpuMPO &) = delete;
52
53 ~GpuMPO()
54 {
55 if (lib && obj)
56 lib->DestroyMPO(obj);
57 }
58
59 bool Create(unsigned int n)
60 {
61 return lib->MPOCreate(obj, n);
62 }
63
64 bool CreateWithState(unsigned int n, const double *state)
65 {
66 return lib->MPOCreateWithState(obj, n, state);
67 }
68
69 bool CreateWithBasisState(unsigned int n, unsigned long long state)
70 {
71 return lib->MPOCreateWithBasisState(obj, n, state);
72 }
73
74 bool CreateWithBasisStateBits(unsigned int n, const std::vector<unsigned char> &stateBits)
75 {
76 return lib->MPOCreateWithBasisStateBits(obj, n, stateBits.data());
77 }
78
79 bool CreateWithMixtureOfBasisStates(unsigned int n, const std::vector<std::pair<unsigned long long, double>> &mixture)
80 {
81 std::vector<unsigned long long> states;
82 std::vector<double> weights;
83 states.reserve(mixture.size());
84 weights.reserve(mixture.size());
85 for (const auto &[state, weight] : mixture)
86 {
87 states.push_back(state);
88 weights.push_back(weight);
89 }
90 return lib->MPOCreateWithMixtureOfBasisStates(obj, n, states.data(), weights.data(), static_cast<int>(states.size()));
91 }
92
93 bool CreateWithMixtureOfBasisStatesBits(unsigned int n, const std::vector<unsigned char> &stateBitsFlat, const std::vector<double> &weights)
94 {
95 return lib->MPOCreateWithMixtureOfBasisStatesBits(obj, n, stateBitsFlat.data(), weights.data(), static_cast<int>(weights.size()));
96 }
97
98 void Reset()
99 {
100 if (!lib->MPOReset(obj))
101 throw std::runtime_error("GPU matrix-product-operator reset failed");
102 }
103
104 bool SetSeed(uint64_t seed)
105 {
106 return lib->MPOSetSeed(obj, seed);
107 }
108
109 bool SetInitialQubitsMap(const std::vector<long long int> &initialMap)
110 {
111 return lib->MPOSetInitialQubitsMap(obj, initialMap);
112 }
113
114 bool SetUseOptimalMeetingPosition(bool useOptimalMeetingPosition)
115 {
116 return lib->MPOSetUseOptimalMeetingPosition(obj, useOptimalMeetingPosition);
117 }
118
119 bool GetUseOptimalMeetingPosition() const
120 {
121 return lib->MPOGetUseOptimalMeetingPosition(obj);
122 }
123
124 std::vector<long long> GetQubitsMap() const
125 {
126 std::vector<long long> map(lib->MPOGetNrQubits(obj));
127 if (!lib->MPOGetQubitsMap(obj, map.data(), static_cast<int>(map.size())))
128 return {};
129 return map;
130 }
131
132 bool SetCallbackContext(void *context)
133 {
134 return lib->MPOSetCallbackContext(obj, context);
135 }
136
137 bool SetMeetingPositionCallback(int64_t (*callback)(void *, const int64_t *))
138 {
139 return lib->MPOSetMeetingPositionCallback(obj, callback);
140 }
141
142 bool SetBondDimensionsCallback(void (*callback)(void *, const int64_t *))
143 {
144 return lib->MPOSetBondDimensionsCallback(obj, callback);
145 }
146
147 void InstallBondSummary(void (*summary)(void *, int64_t), void (*full)(void *, const int64_t *))
148 {
149 const bool ok = lib->HasMPOBondSummary() ? lib->MPOSetBondDimensionSummaryCallback(obj, summary) : SetBondDimensionsCallback(full);
150 if (!ok)
151 throw std::runtime_error("GPU MPO bond callback installation failed");
152 }
153
154 std::vector<double> ExpectationValues(const std::vector<std::string> &paulis) const
155 {
156 TensorQueries::PauliBatch batch(paulis);
157 std::vector<double> values(paulis.size());
158 if (paulis.empty())
159 return values;
160 if (lib->HasMPOExpectationValues())
161 {
162 if (!lib->MPOExpectationValues(obj, TensorQueries::Count(paulis.size()), batch.strings.data(), batch.lengths.data(), values.data()))
163 throw std::runtime_error("GPU MPO batch expectation failed");
164 }
165 else
166 {
167 for (size_t i = 0; i < paulis.size(); ++i)
168 values[i] = ExpectationValueComplex(paulis[i]).real();
169 }
170 return values;
171 }
172
173 std::vector<std::complex<double>> ExpectationValuesComplex(const std::vector<std::string> &paulis, bool normalized = true) const
174 {
175 TensorQueries::PauliBatch batch(paulis);
176 std::vector<std::complex<double>> values(paulis.size());
177 if (paulis.empty())
178 return values;
179 if (lib->HasMPOExpectationValuesComplex())
180 {
181 std::vector<double> re(paulis.size()), im(paulis.size());
182 if (!lib->MPOExpectationValuesComplex(obj, TensorQueries::Count(paulis.size()), batch.strings.data(), batch.lengths.data(), normalized, re.data(),
183 im.data()))
184 throw std::runtime_error("GPU MPO complex batch expectation failed");
185 for (size_t i = 0; i < paulis.size(); ++i)
186 values[i] = {re[i], im[i]};
187 }
188 else
189 {
190 for (size_t i = 0; i < paulis.size(); ++i)
191 values[i] = ExpectationValueComplex(paulis[i], normalized);
192 }
193 return values;
194 }
195
196 bool IsCreated() const
197 {
198 return lib->MPOIsCreated(obj);
199 }
200
201 bool IsDoublePrecision() const
202 {
203 return lib->MPOIsDoublePrecision(obj);
204 }
205
206 void SetDataType(bool useDouble)
207 {
208 if (!lib->MPOSetDataType(obj, useDouble))
209 throw std::runtime_error("GPU matrix-product-operator precision configuration failed");
210 }
211
212 void SetCutoff(double singularValueThreshold)
213 {
214 if (!lib->MPOSetCutoff(obj, singularValueThreshold))
215 throw std::runtime_error("GPU MPO cutoff configuration failed");
216 }
217
218 double GetCutoff() const
219 {
220 return lib->MPOGetCutoff(obj);
221 }
222
223 // mode: 0 = RelativeToMax, 1 = DiscardedWeight (default). See
224 // TruncationMode in the GPU library's lib/truncationmode.hpp.
225 bool SetTruncationMode(int mode)
226 {
227 return lib->MPOSetTruncationMode(obj, mode);
228 }
229
230 int GetTruncationMode() const
231 {
232 return lib->MPOGetTruncationMode(obj);
233 }
234
235 bool SetGesvdJ(bool enable)
236 {
237 return lib->MPOSetGesvdJ(obj, enable);
238 }
239
240 bool GetGesvdJ() const
241 {
242 return lib->MPOGetGesvdJ(obj);
243 }
244
245 // Enabling any of J/P/R clears the other two selectors in the plugin.
246 bool SetGesvdP(bool enable)
247 {
248 return obj && lib->MPOSetGesvdP(obj, enable);
249 }
250
251 bool GetGesvdP() const
252 {
253 return lib->MPOGetGesvdP(obj);
254 }
255
256 bool SetGesvdR(bool enable)
257 {
258 return obj && lib->MPOSetGesvdR(obj, enable);
259 }
260
261 bool GetGesvdR() const
262 {
263 return lib->MPOGetGesvdR(obj);
264 }
265
266 int GetLastSvdAlgo() const
267 {
268 return lib->MPOGetLastSvdAlgo(obj);
269 }
270
271 void SetMaxExtent(long int chi)
272 {
273 if (!lib->MPOSetMaxExtent(obj, chi))
274 throw std::runtime_error("GPU MPO bond cap configuration failed");
275 }
276
277 long int GetMaxExtent() const
278 {
279 return lib->MPOGetMaxExtent(obj);
280 }
281
282 std::vector<long long int> GetBondDimensions(size_t nrQubits) const
283 {
284 if (nrQubits < 2)
285 return {};
286 std::vector<long long int> bondDims(nrQubits - 1);
287 if (!lib->MPOGetBondDimensions(obj, bondDims.data()))
288 return {};
289 return bondDims;
290 }
291
292 void ReCanonicalize()
293 {
294 if (!lib->MPOReCanonicalize(obj))
295 throw std::runtime_error("GPU MPO canonicalization failed");
296 }
297
298 void Trim(double cutoff = -1., long int maxExtent = -1)
299 {
300 if (!lib->MPOTrim(obj, cutoff, maxExtent))
301 throw std::runtime_error("GPU MPO trim failed");
302 }
303
304 bool Measure(unsigned int q)
305 {
306 return lib->MPOMeasureQubitCollapse(obj, q);
307 }
308
309 bool MeasureNoCollapse(unsigned int q)
310 {
311 return lib->MPOMeasureQubitNoCollapse(obj, q);
312 }
313
314 bool MeasureQubits(std::vector<int> &qubits, std::vector<int> &bits, bool collapse = true)
315 {
316 if (qubits.size() != bits.size())
317 throw std::invalid_argument("Measurement vectors must have equal size");
318 return collapse ? lib->MPOMeasureQubitsCollapse(obj, qubits.data(), bits.data(), static_cast<int>(bits.size()))
319 : lib->MPOMeasureQubitsNoCollapse(obj, qubits.data(), bits.data(), static_cast<int>(bits.size()));
320 }
321
322 unsigned long long MeasureAll(bool collapse = true)
323 {
324 return collapse ? lib->MPOMeasureAllQubitsCollapse(obj) : lib->MPOMeasureAllQubitsNoCollapse(obj);
325 }
326
327 bool Sample(unsigned int nSamples, long int *samples, unsigned int nBits, int *bitOrdering)
328 {
329 return lib->MPOSample(obj, nSamples, samples, nBits, bitOrdering);
330 }
331
332 bool SampleAll(unsigned int shots, long int *samples)
333 {
334 return lib->MPOSampleAll(obj, shots, samples);
335 }
336
337 double Probability(long long outcome) const
338 {
339 return lib->MPOBasisStateProbability(obj, outcome);
340 }
341
342 std::complex<double> GetElement(long long row, long long col) const
343 {
344 double re = 0., im = 0.;
345 if (!lib->MPOGetElement(obj, row, col, &re, &im))
346 throw std::runtime_error("GPU MPO element query failed");
347 return {re, im};
348 }
349
350 void AllProbabilities(double *probabilities)
351 {
352 if (!lib->MPOAllProbabilities(obj, probabilities))
353 throw std::runtime_error("GPU matrix-product-operator probability enumeration failed");
354 }
355
356 double ExpectationValue(const std::string &pauli) const
357 {
358 return lib->MPOExpectationValue(obj, pauli.c_str(), pauli.size());
359 }
360
361 double QubitProbability0(unsigned int q) const
362 {
363 return lib->MPOQubitProbability0(obj, q);
364 }
365
366 double Trace() const
367 {
368 return lib->MPOTrace(obj);
369 }
370
371 double Purity() const
372 {
373 return lib->MPOPurity(obj);
374 }
375
376 double HermiticityResidual() const
377 {
378 return lib->MPOHermiticityResidual(obj);
379 }
380
381 bool IsHermitian(double eps = 1e-10) const
382 {
383 return lib->MPOIsHermitian(obj, eps);
384 }
385
386 double TraceOfSquare() const
387 {
388 return lib->MPOTraceOfSquare(obj);
389 }
390
391 void RestoreTrace()
392 {
393 if (!lib->MPORestoreTrace(obj))
394 throw std::runtime_error("GPU MPO trace restoration failed");
395 }
396
397 void Hermitize()
398 {
399 if (!lib->MPOHermitize(obj))
400 throw std::runtime_error("GPU MPO hermitization failed");
401 }
402
403 bool SetKrausCompletenessCheck(int mode)
404 {
405 return lib->MPOSetKrausCompletenessCheck(obj, mode);
406 }
407
408 int GetKrausCompletenessCheck() const
409 {
410 return lib->MPOGetKrausCompletenessCheck(obj);
411 }
412
413 std::vector<std::complex<double>> PartialTrace(const std::vector<int> &qubits) const
414 {
415 if (qubits.size() > 13)
416 throw std::invalid_argument("GPU MPO partial trace supports at most 13 qubits");
417 const size_t dim = size_t{1} << qubits.size();
418 std::vector<double> raw(2 * dim * dim);
419 if (!lib->MPOPartialTrace(obj, qubits.data(), static_cast<int>(qubits.size()), raw.data()))
420 throw std::runtime_error("GPU MPO partial trace failed");
421 std::vector<std::complex<double>> result(dim * dim);
422 for (size_t i = 0; i < result.size(); ++i)
423 result[i] = {raw[2 * i], raw[2 * i + 1]};
424 return result;
425 }
426
427 std::complex<double> HilbertSchmidtOverlap(const GpuMPO &other) const
428 {
429 double re = 0., im = 0.;
430 if (!lib->MPOHilbertSchmidtOverlap(obj, other.obj, &re, &im))
431 throw std::runtime_error("GPU MPO overlap failed");
432 return {re, im};
433 }
434
435 double FidelityWithStatevector(const double *state) const
436 {
437 double result = 0.;
438 if (!lib->MPOFidelityWithStatevector(obj, state, &result))
439 throw std::runtime_error("GPU MPO fidelity failed");
440 return result;
441 }
442
443 // Bit vectors are in logical-qubit order. Histogram entries instead follow
444 // the caller's qubit order (indices must be distinct).
445 double ProbabilityBits(const std::vector<unsigned char> &bits) const
446 {
447 ValidateBits(bits);
448 const double probability = lib->MPOBasisStateProbabilityBits(obj, bits.data());
449 if (!std::isfinite(probability))
450 throw std::runtime_error("GPU MPO probability requires a safely positive trace");
451 return probability;
452 }
453
454 std::complex<double> GetElementBits(const std::vector<unsigned char> &row, const std::vector<unsigned char> &col) const
455 {
456 ValidateBits(row);
457 ValidateBits(col);
458 double re = 0., im = 0.;
459 if (!lib->MPOGetElementBits(obj, row.data(), col.data(), &re, &im))
460 throw std::runtime_error("GPU MPO element query failed");
461 return {re, im};
462 }
463
464 std::complex<double> TraceComplex() const
465 {
466 double re = 0., im = 0.;
467 if (!lib->MPOTraceComplex(obj, &re, &im))
468 throw std::runtime_error("GPU MPO complex trace failed");
469 return {re, im};
470 }
471
472 std::complex<double> ExpectationValueComplex(const std::string &pauli, bool normalized = true) const
473 {
474 double re = 0., im = 0.;
475 const bool ok = normalized ? lib->MPOExpectationValueComplex(obj, pauli.c_str(), pauli.size(), &re, &im)
476 : lib->MPOUnnormalizedExpectationValue(obj, pauli.c_str(), pauli.size(), &re, &im);
477 if (!ok)
478 throw std::runtime_error("GPU MPO complex expectation failed");
479 return {re, im};
480 }
481
482 std::vector<std::complex<double>> GetDensityMatrix(bool normalized = true) const
483 {
484 const int n = lib->MPOGetNrQubits(obj);
485 if (n < 0 || n > 13)
486 throw std::invalid_argument("GPU MPO dense output supports at most 13 qubits");
487 const size_t count = size_t{1} << (2 * n);
488 std::vector<double> raw(2 * count);
489 const bool ok = normalized ? lib->MPOGetDensityMatrix(obj, raw.data()) : lib->MPOGetUnnormalizedDensityMatrix(obj, raw.data());
490 if (!ok)
491 throw std::runtime_error("GPU MPO density matrix query failed");
492 std::vector<std::complex<double>> result(count);
493 for (size_t i = 0; i < count; ++i)
494 result[i] = {raw[2 * i], raw[2 * i + 1]};
495 return result;
496 }
497
498 bool SetRestoreTraceAfterTruncation(bool enable)
499 {
500 return lib->MPOSetRestoreTraceAfterTruncation(obj, enable) == 1;
501 }
502
503 bool GetRestoreTraceAfterTruncation() const
504 {
505 return lib->MPOGetRestoreTraceAfterTruncation(obj) == 1;
506 }
507
508 bool SetHermitizeAfterTruncation(bool enable)
509 {
510 return lib->MPOSetHermitizeAfterTruncation(obj, enable) == 1;
511 }
512
513 bool GetHermitizeAfterTruncation() const
514 {
515 return lib->MPOGetHermitizeAfterTruncation(obj) == 1;
516 }
517
518 void MoveAtBeginningOfChain(const std::vector<int> &qubits)
519 {
520 if (!lib->MPOMoveAtBeginningOfChain(obj, qubits.data(), qubits.size()))
521 throw std::runtime_error("GPU MPO chain routing failed");
522 }
523
524 bool ApplyOperator(const std::vector<int> &qubits, const double *matrix, bool normalize = false)
525 {
526 return normalize ? lib->MPOApplyOperatorAndNormalize(obj, qubits.size(), qubits.data(), matrix) == 1
527 : lib->MPOApplyOperator(obj, qubits.size(), qubits.data(), matrix) == 1;
528 }
529
530 std::vector<unsigned char> SampleBits(unsigned int shots, const std::vector<int> &qubits)
531 {
532 if (!shots || qubits.empty())
533 return {};
534 if (qubits.size() > std::numeric_limits<unsigned int>::max() || qubits.size() > std::numeric_limits<size_t>::max() / shots)
535 throw std::length_error("GPU MPO sample buffer too large");
536 std::vector<unsigned char> result(size_t(shots) * qubits.size());
537 if (!lib->MPOSampleBits(obj, shots, qubits.size(), qubits.data(), result.data()))
538 throw std::runtime_error("GPU MPO bit sampling failed");
539 return result;
540 }
541
542 std::unordered_map<std::vector<bool>, int64_t> SampleHistogram(size_t shots, std::vector<unsigned int> qubits)
543 {
544 if (!shots || qubits.empty())
545 return {};
546 if (shots > std::numeric_limits<unsigned int>::max() || shots > static_cast<size_t>(std::numeric_limits<long int>::max()) ||
547 qubits.size() > static_cast<size_t>(std::numeric_limits<int>::max()))
548 throw std::invalid_argument("GPU MPO sampling size exceeds API limits");
549 using Map = std::unordered_map<std::vector<bool>, int64_t>;
550 auto deleter = [this](Map *map) { lib->MPOFreeMapForSample(map); };
551 std::unique_ptr<Map, decltype(deleter)> map(static_cast<Map *>(lib->MPOGetMapForSample()), deleter);
552 if (!map || !lib->MPOSampleHistogram(obj, shots, qubits.size(), qubits.data(), map.get()))
553 throw std::runtime_error("GPU MPO histogram sampling failed");
554 return *map;
555 }
556
557 void SaveState()
558 {
559 if (!lib->MPOSaveState(obj))
560 throw std::runtime_error("GPU matrix-product-operator state save failed");
561 }
562
563 void RestoreState()
564 {
565 if (!lib->MPORestoreState(obj))
566 throw std::runtime_error("GPU matrix-product-operator state restore failed");
567 }
568
569 void CleanSavedState()
570 {
571 if (!lib->MPOCleanSavedState(obj))
572 throw std::runtime_error("GPU matrix-product-operator saved-state cleanup failed");
573 }
574
575 std::unique_ptr<GpuMPO> Clone() const
576 {
577 void *cloned = lib->MPOClone(obj);
578 if (!cloned)
579 return nullptr;
580 return std::make_unique<GpuMPO>(lib, cloned);
581 }
582
583 bool ApplyKraus(const std::vector<int> &qubits, int count, const double *operators)
584 {
585 return lib->MPOApplyKraus(obj, qubits.size(), qubits.data(), count, operators);
586 }
587
588 bool ApplyOneQubitMatrix(int qubit, const double *matrixInterleaved)
589 {
590 return lib->MPOApplyOneQubitMatrix(obj, qubit, matrixInterleaved);
591 }
592
593 bool ApplyTwoQubitMatrix(int qubit1, int qubit2, const double *matrixInterleaved)
594 {
595 return lib->MPOApplyTwoQubitMatrix(obj, qubit1, qubit2, matrixInterleaved);
596 }
597
598#define GPU_MPO_CHECK(call, name) \
599 do \
600 { \
601 if (!(call)) \
602 throw std::runtime_error("GPU matrix-product-operator " name " failed"); \
603 } while (false)
604#define GPU_MPO_GATE1(name) \
605 void name(int q) \
606 { \
607 GPU_MPO_CHECK(lib->MPO##name(obj, q), #name); \
608 }
609#define GPU_MPO_GATE2(name) \
610 void name(int a, int b) \
611 { \
612 GPU_MPO_CHECK(lib->MPO##name(obj, a, b), #name); \
613 }
614#define GPU_MPO_ROT1(name) \
615 void name(int q, double x) \
616 { \
617 GPU_MPO_CHECK(lib->MPO##name(obj, q, x), #name); \
618 }
619#define GPU_MPO_ROT2(name) \
620 void name(int a, int b, double x) \
621 { \
622 GPU_MPO_CHECK(lib->MPO##name(obj, a, b, x), #name); \
623 }
624 GPU_MPO_GATE1(ApplyReset)
625
626 GPU_MPO_ROT1(ApplyBitFlipNoise)
627
628 GPU_MPO_ROT1(ApplyPhaseFlipNoise)
629
630 GPU_MPO_ROT1(ApplyDepolarizingNoise)
631
632 GPU_MPO_ROT1(ApplyAmplitudeDamping)
633
634 GPU_MPO_ROT1(ApplyPhaseDamping)
635
636 GPU_MPO_GATE1(ApplyNonSelectiveMeasurement)
637
638 GPU_MPO_GATE1(ApplyX)
639
640 GPU_MPO_GATE1(ApplyY)
641
642 GPU_MPO_GATE1(ApplyZ)
643
644 GPU_MPO_GATE1(ApplyH)
645
646 GPU_MPO_GATE1(ApplyS)
647
648 GPU_MPO_GATE1(ApplySDG)
649
650 GPU_MPO_GATE1(ApplyT)
651
652 GPU_MPO_GATE1(ApplyTDG)
653
654 GPU_MPO_GATE1(ApplySX)
655
656 GPU_MPO_GATE1(ApplySXDG)
657
658 GPU_MPO_GATE1(ApplyK)
659
660 GPU_MPO_ROT1(ApplyP) GPU_MPO_ROT1(ApplyRx) GPU_MPO_ROT1(ApplyRy) GPU_MPO_ROT1(ApplyRz) void ApplyU(int q, double a, double b, double c, double d)
661 {
662 GPU_MPO_CHECK(lib->MPOApplyU(obj, q, a, b, c, d), "ApplyU");
663 }
664
665 GPU_MPO_GATE2(ApplyCX)
666
667 GPU_MPO_GATE2(ApplyCY)
668
669 GPU_MPO_GATE2(ApplyCZ)
670
671 GPU_MPO_GATE2(ApplyCH)
672
673 GPU_MPO_GATE2(ApplyCSX)
674
675 GPU_MPO_GATE2(ApplyCSXDG)
676
677 GPU_MPO_ROT2(ApplyCP)
678
679 GPU_MPO_ROT2(ApplyCRx)
680
681 GPU_MPO_ROT2(ApplyCRy) GPU_MPO_ROT2(ApplyCRz) GPU_MPO_GATE2(ApplySwap) void ApplyCU(int a, int b, double c, double d, double e, double f)
682 {
683 GPU_MPO_CHECK(lib->MPOApplyCU(obj, a, b, c, d, e, f), "ApplyCU");
684 }
685
686#undef GPU_MPO_ROT2
687#undef GPU_MPO_ROT1
688#undef GPU_MPO_GATE2
689#undef GPU_MPO_GATE1
690#undef GPU_MPO_CHECK
691
692 private:
693 void ValidateBits(const std::vector<unsigned char> &bits) const
694 {
695 if (bits.size() != static_cast<size_t>(lib->MPOGetNrQubits(obj)))
696 throw std::invalid_argument("GPU MPO bit vector width " + std::to_string(bits.size()) + " does not match register width " +
697 std::to_string(lib->MPOGetNrQubits(obj)));
698 }
699
700 GpuDeviceContext lib;
701 void *obj = nullptr;
702};
703
704} // namespace Simulators
705#endif
706#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 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)
Bounded online routing based on current physical bond dimensions.