pennylane-qrack 0.10.9__py3-none-macosx_14_0_arm64.whl → 0.25.0__py3-none-macosx_14_0_arm64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of pennylane-qrack might be problematic. Click here for more details.
- pennylane_qrack/QrackAceDeviceConfig.toml +108 -0
- pennylane_qrack/QrackDeviceConfig.toml +85 -123
- pennylane_qrack/QrackStabilizerDeviceConfig.toml +99 -0
- pennylane_qrack/_version.py +2 -2
- pennylane_qrack/qrack_ace_device.py +447 -0
- pennylane_qrack/qrack_device.cpp +66 -44
- pennylane_qrack/qrack_device.py +50 -17
- pennylane_qrack/qrack_stabilizer_device.py +313 -0
- {pennylane_qrack-0.10.9.dist-info → pennylane_qrack-0.25.0.dist-info}/METADATA +7 -3
- pennylane_qrack-0.25.0.dist-info/RECORD +15 -0
- {pennylane_qrack-0.10.9.dist-info → pennylane_qrack-0.25.0.dist-info}/WHEEL +1 -1
- pennylane_qrack-0.25.0.dist-info/entry_points.txt +4 -0
- pennylane_qrack/CMakeCache.txt +0 -394
- pennylane_qrack/Makefile +0 -230
- pennylane_qrack/cmake_install.cmake +0 -78
- pennylane_qrack/libqrack_device.dylib +0 -0
- pennylane_qrack-0.10.9.dist-info/RECORD +0 -15
- pennylane_qrack-0.10.9.dist-info/entry_points.txt +0 -2
- {pennylane_qrack-0.10.9.dist-info → pennylane_qrack-0.25.0.dist-info}/LICENSE +0 -0
- {pennylane_qrack-0.10.9.dist-info → pennylane_qrack-0.25.0.dist-info}/top_level.txt +0 -0
pennylane_qrack/qrack_device.cpp
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
#define CL_HPP_TARGET_OPENCL_VERSION 300
|
|
7
7
|
#include "qrack/qfactory.hpp"
|
|
8
8
|
|
|
9
|
-
#define QSIM_CONFIG(numQubits) Qrack::CreateArrangedLayersFull(nw, md, sd, sh, bdt,
|
|
9
|
+
#define QSIM_CONFIG(numQubits) Qrack::CreateArrangedLayersFull(nw, md, sd, sh, bdt, pg, tn, hy, oc, numQubits, Qrack::ZERO_BCI, nullptr, Qrack::CMPLX_DEFAULT_ARG, false, true, hp, sp)
|
|
10
10
|
|
|
11
11
|
std::string trim(std::string s)
|
|
12
12
|
{
|
|
@@ -38,9 +38,13 @@ struct QrackDevice final : public Catalyst::Runtime::QuantumDevice {
|
|
|
38
38
|
bool md;
|
|
39
39
|
bool bdt;
|
|
40
40
|
bool oc;
|
|
41
|
+
bool pg;
|
|
42
|
+
bool hy;
|
|
41
43
|
bool hp;
|
|
44
|
+
bool sp;
|
|
42
45
|
bool nw;
|
|
43
46
|
size_t shots;
|
|
47
|
+
Qrack::real1_f noise_param;
|
|
44
48
|
Qrack::QInterfacePtr qsim;
|
|
45
49
|
std::map<QubitIdType, bitLenInt> qubit_map;
|
|
46
50
|
std::vector<QrackObservable> obs_cache;
|
|
@@ -184,8 +188,8 @@ struct QrackDevice final : public Catalyst::Runtime::QuantumDevice {
|
|
|
184
188
|
const Qrack::real1 omega = inverse ? -params[0U] : params[2U];
|
|
185
189
|
const Qrack::real1 cos0 = (Qrack::real1)cos(theta / 2);
|
|
186
190
|
const Qrack::real1 sin0 = (Qrack::real1)sin(theta / 2);
|
|
187
|
-
const Qrack::complex expP = exp(Qrack::I_CMPLX * (phi + omega)
|
|
188
|
-
const Qrack::complex expM = exp(Qrack::I_CMPLX * (phi - omega)
|
|
191
|
+
const Qrack::complex expP = exp(Qrack::I_CMPLX * (phi + omega) * HALF_R1);
|
|
192
|
+
const Qrack::complex expM = exp(Qrack::I_CMPLX * (phi - omega) * HALF_R1);
|
|
189
193
|
const Qrack::complex mtrx[4U]{
|
|
190
194
|
cos0 / expP, -sin0 * expM,
|
|
191
195
|
sin0 / expM, cos0 * expP
|
|
@@ -226,14 +230,12 @@ struct QrackDevice final : public Catalyst::Runtime::QuantumDevice {
|
|
|
226
230
|
QRACK_CONST Qrack::complex NEG_SQRTI_2_CMPLX(ZERO_R1, -Qrack::SQRT1_2_R1);
|
|
227
231
|
const Qrack::complex QBRTI_2_CMPLX(ZERO_R1, sqrt(Qrack::SQRT1_2_R1));
|
|
228
232
|
const Qrack::complex NEG_QBRTI_2_CMPLX(ZERO_R1, sqrt(-Qrack::SQRT1_2_R1));
|
|
229
|
-
QRACK_CONST Qrack::complex ONE_PLUS_I_DIV_2 = Qrack::complex((Qrack::real1)(ONE_R1 / 2), (Qrack::real1)(ONE_R1 / 2));
|
|
230
|
-
QRACK_CONST Qrack::complex ONE_MINUS_I_DIV_2 = Qrack::complex((Qrack::real1)(ONE_R1 / 2), (Qrack::real1)(-ONE_R1 / 2));
|
|
231
233
|
|
|
232
234
|
QRACK_CONST Qrack::complex pauliX[4U] = { Qrack::ZERO_CMPLX, Qrack::ONE_CMPLX, Qrack::ONE_CMPLX, Qrack::ZERO_CMPLX };
|
|
233
235
|
QRACK_CONST Qrack::complex pauliY[4U] = { Qrack::ZERO_CMPLX, NEG_I_CMPLX, Qrack::I_CMPLX, Qrack::ZERO_CMPLX };
|
|
234
236
|
QRACK_CONST Qrack::complex pauliZ[4U] = { Qrack::ONE_CMPLX, Qrack::ZERO_CMPLX, Qrack::ZERO_CMPLX, NEG_1_CMPLX };
|
|
235
|
-
QRACK_CONST Qrack::complex sqrtX[4U]{
|
|
236
|
-
QRACK_CONST Qrack::complex iSqrtX[4U]{
|
|
237
|
+
QRACK_CONST Qrack::complex sqrtX[4U]{ Qrack::HALF_I_HALF_CMPLX, Qrack::HALF_NEG_I_HALF_CMPLX, Qrack::HALF_NEG_I_HALF_CMPLX, Qrack::HALF_I_HALF_CMPLX };
|
|
238
|
+
QRACK_CONST Qrack::complex iSqrtX[4U]{ Qrack::HALF_NEG_I_HALF_CMPLX, Qrack::HALF_I_HALF_CMPLX, Qrack::HALF_I_HALF_CMPLX, Qrack::HALF_NEG_I_HALF_CMPLX };
|
|
237
239
|
QRACK_CONST Qrack::complex hadamard[4U]{ SQRT1_2_CMPLX, SQRT1_2_CMPLX, SQRT1_2_CMPLX, NEG_SQRT1_2_CMPLX };
|
|
238
240
|
|
|
239
241
|
if ((name == "PauliX") || (name == "CNOT") || (name == "Toffoli") || (name == "MultiControlledX")) {
|
|
@@ -348,8 +350,8 @@ struct QrackDevice final : public Catalyst::Runtime::QuantumDevice {
|
|
|
348
350
|
const Qrack::real1 omega = inverse ? -params[0U] : params[2U];
|
|
349
351
|
const Qrack::real1 cos0 = (Qrack::real1)cos(theta / 2);
|
|
350
352
|
const Qrack::real1 sin0 = (Qrack::real1)sin(theta / 2);
|
|
351
|
-
const Qrack::complex expP = exp(Qrack::I_CMPLX * (phi + omega)
|
|
352
|
-
const Qrack::complex expM = exp(Qrack::I_CMPLX * (phi - omega)
|
|
353
|
+
const Qrack::complex expP = exp(Qrack::I_CMPLX * (phi + omega) * HALF_R1);
|
|
354
|
+
const Qrack::complex expM = exp(Qrack::I_CMPLX * (phi - omega) * HALF_R1);
|
|
353
355
|
const Qrack::complex mtrx[4U]{
|
|
354
356
|
cos0 / expP, -sin0 * expM,
|
|
355
357
|
sin0 / expM, cos0 * expP
|
|
@@ -384,12 +386,16 @@ struct QrackDevice final : public Catalyst::Runtime::QuantumDevice {
|
|
|
384
386
|
, sh(true)
|
|
385
387
|
, tn(true)
|
|
386
388
|
, sd(true)
|
|
387
|
-
, md(
|
|
389
|
+
, md(false)
|
|
388
390
|
, bdt(false)
|
|
389
391
|
, oc(true)
|
|
392
|
+
, pg(true)
|
|
393
|
+
, hy(true)
|
|
390
394
|
, hp(false)
|
|
395
|
+
, sp(false)
|
|
391
396
|
, nw(false)
|
|
392
397
|
, shots(1U)
|
|
398
|
+
, noise_param(ZERO_R1_F)
|
|
393
399
|
, qsim(nullptr)
|
|
394
400
|
{
|
|
395
401
|
// Cut leading '{' and trailing '}'
|
|
@@ -405,11 +411,13 @@ struct QrackDevice final : public Catalyst::Runtime::QuantumDevice {
|
|
|
405
411
|
keyMap["'is_schmidt_decomposition_parallel'"] = 4;
|
|
406
412
|
keyMap["'is_qbdd'"] = 5;
|
|
407
413
|
keyMap["'is_gpu'"] = 6;
|
|
408
|
-
keyMap["'
|
|
409
|
-
keyMap["'
|
|
414
|
+
keyMap["'is_paged'"] = 7;
|
|
415
|
+
keyMap["'is_hybrid_cpu_gpu'"] = 8;
|
|
416
|
+
keyMap["'is_host_pointer'"] =9;
|
|
417
|
+
keyMap["'is_sparse'"] =10;
|
|
418
|
+
keyMap["'noise'"] = 11;
|
|
410
419
|
|
|
411
420
|
size_t pos;
|
|
412
|
-
Qrack::real1_f noiseParam = 0;
|
|
413
421
|
while ((pos = kwargs.find(":")) != std::string::npos) {
|
|
414
422
|
std::string key = trim(kwargs.substr(0, pos));
|
|
415
423
|
kwargs.erase(0, pos + 1U);
|
|
@@ -437,11 +445,20 @@ struct QrackDevice final : public Catalyst::Runtime::QuantumDevice {
|
|
|
437
445
|
oc = val;
|
|
438
446
|
break;
|
|
439
447
|
case 7:
|
|
440
|
-
|
|
448
|
+
pg = val;
|
|
441
449
|
break;
|
|
442
450
|
case 8:
|
|
443
|
-
|
|
444
|
-
|
|
451
|
+
hy = val;
|
|
452
|
+
break;
|
|
453
|
+
case 9:
|
|
454
|
+
hp = val;
|
|
455
|
+
break;
|
|
456
|
+
case 10:
|
|
457
|
+
sp = val;
|
|
458
|
+
break;
|
|
459
|
+
case 11:
|
|
460
|
+
noise_param = std::stof(value);
|
|
461
|
+
nw = noise_param > ZERO_R1;
|
|
445
462
|
break;
|
|
446
463
|
default:
|
|
447
464
|
break;
|
|
@@ -449,8 +466,8 @@ struct QrackDevice final : public Catalyst::Runtime::QuantumDevice {
|
|
|
449
466
|
}
|
|
450
467
|
|
|
451
468
|
qsim = QSIM_CONFIG(0U);
|
|
452
|
-
if (
|
|
453
|
-
qsim->SetNoiseParameter(
|
|
469
|
+
if (noise_param > ZERO_R1) {
|
|
470
|
+
qsim->SetNoiseParameter(noise_param);
|
|
454
471
|
}
|
|
455
472
|
}
|
|
456
473
|
|
|
@@ -472,8 +489,6 @@ struct QrackDevice final : public Catalyst::Runtime::QuantumDevice {
|
|
|
472
489
|
}
|
|
473
490
|
return ids;
|
|
474
491
|
}
|
|
475
|
-
[[nodiscard]] auto Zero() const -> Result override { return const_cast<Result>(&QRACK_RESULT_FALSE_CONST); }
|
|
476
|
-
[[nodiscard]] auto One() const -> Result override { return const_cast<Result>(&QRACK_RESULT_TRUE_CONST); }
|
|
477
492
|
auto Observable(ObsId id, const std::vector<std::complex<double>> &matrix,
|
|
478
493
|
const std::vector<QubitIdType> &wires) -> ObsIdType override
|
|
479
494
|
{
|
|
@@ -544,34 +559,30 @@ struct QrackDevice final : public Catalyst::Runtime::QuantumDevice {
|
|
|
544
559
|
// Deallocate
|
|
545
560
|
qsim->Dispose(id, 1U);
|
|
546
561
|
}
|
|
547
|
-
void
|
|
562
|
+
void ReleaseQubits(const std::vector<QubitIdType> &qubits) override
|
|
548
563
|
{
|
|
549
|
-
|
|
550
|
-
|
|
564
|
+
if (qubits.size() == qsim->GetQubitCount()) {
|
|
565
|
+
qsim = QSIM_CONFIG(0U);
|
|
566
|
+
return;
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
for (const QubitIdType& q : qubits) {
|
|
570
|
+
ReleaseQubit(q);
|
|
571
|
+
}
|
|
551
572
|
}
|
|
552
573
|
[[nodiscard]] auto GetNumQubits() const -> size_t override
|
|
553
574
|
{
|
|
554
575
|
return qsim->GetQubitCount();
|
|
555
576
|
}
|
|
556
|
-
void SetDeviceShots(size_t s) override {
|
|
577
|
+
void SetDeviceShots(size_t s) override {
|
|
578
|
+
if ((s > 1U) && (noise_param > ZERO_R1_F)) {
|
|
579
|
+
throw std::domain_error("Shots > 1 can't be simulated with noise on the Qrack back end! (Likely, you want to set mcm_method=\"one-shot\" on your qnode, with multiple shots.)");
|
|
580
|
+
}
|
|
581
|
+
shots = s;
|
|
582
|
+
}
|
|
557
583
|
[[nodiscard]] auto GetDeviceShots() const -> size_t override { return shots; }
|
|
558
584
|
void StartTapeRecording() override { tapeRecording = true; }
|
|
559
585
|
void StopTapeRecording() override { tapeRecording = false; }
|
|
560
|
-
void PrintState() override
|
|
561
|
-
{
|
|
562
|
-
const size_t numQubits = qsim->GetQubitCount();
|
|
563
|
-
const size_t maxQPower = (size_t)((uint64_t)qsim->GetMaxQPower());
|
|
564
|
-
const size_t maxLcv = maxQPower - 1U;
|
|
565
|
-
size_t idx = 0U;
|
|
566
|
-
std::cout << "*** State-Vector of Size " << maxQPower << " ***" << std::endl;
|
|
567
|
-
std::cout << "[";
|
|
568
|
-
std::unique_ptr<Qrack::complex> sv(new Qrack::complex[maxQPower]);
|
|
569
|
-
qsim->GetQuantumState(sv.get());
|
|
570
|
-
for (; idx < maxLcv; ++idx) {
|
|
571
|
-
std::cout << sv.get()[idx] << ", ";
|
|
572
|
-
}
|
|
573
|
-
std::cout << sv.get()[idx] << "]" << std::endl;
|
|
574
|
-
}
|
|
575
586
|
void NamedOperation(const std::string &name, const std::vector<double> ¶ms,
|
|
576
587
|
const std::vector<QubitIdType> &wires, bool inverse,
|
|
577
588
|
const std::vector<QubitIdType> &controlled_wires,
|
|
@@ -716,10 +727,14 @@ struct QrackDevice final : public Catalyst::Runtime::QuantumDevice {
|
|
|
716
727
|
}
|
|
717
728
|
}
|
|
718
729
|
}
|
|
719
|
-
void Sample(DataView<double, 2> &samples
|
|
730
|
+
void Sample(DataView<double, 2> &samples) override
|
|
720
731
|
{
|
|
721
732
|
RT_FAIL_IF(samples.size() != shots * qsim->GetQubitCount(), "Invalid size for the pre-allocated samples");
|
|
722
733
|
|
|
734
|
+
if ((shots > 1U) && (noise_param > ZERO_R1_F)) {
|
|
735
|
+
throw std::domain_error("Shots > 1 can't be simulated with noise on the Qrack back end! (Likely, you want to set mcm_method=\"one-shot\" on your qnode, with multiple shots.)");
|
|
736
|
+
}
|
|
737
|
+
|
|
723
738
|
if (shots == 1U) {
|
|
724
739
|
const bitCapInt rev_sample = qsim->MAll();
|
|
725
740
|
const bitLenInt numQubits = qsim->GetQubitCount();
|
|
@@ -741,10 +756,14 @@ struct QrackDevice final : public Catalyst::Runtime::QuantumDevice {
|
|
|
741
756
|
const std::map<bitCapInt, int> q_samples = qsim->MultiShotMeasureMask(qPowers, shots);
|
|
742
757
|
_SampleBody(qPowers.size(), q_samples, samples);
|
|
743
758
|
}
|
|
744
|
-
void PartialSample(DataView<double, 2> &samples, const std::vector<QubitIdType> &wires
|
|
759
|
+
void PartialSample(DataView<double, 2> &samples, const std::vector<QubitIdType> &wires) override
|
|
745
760
|
{
|
|
746
761
|
RT_FAIL_IF(samples.size() != shots * wires.size(), "Invalid size for the pre-allocated samples");
|
|
747
762
|
|
|
763
|
+
if ((shots > 1U) && (noise_param > ZERO_R1_F)) {
|
|
764
|
+
throw std::domain_error("Shots > 1 can't be simulated with noise on the Qrack back end! (Likely, you want to set mcm_method=\"one-shot\" on your qnode, with multiple shots.)");
|
|
765
|
+
}
|
|
766
|
+
|
|
748
767
|
auto &&dev_wires = getDeviceWires(wires);
|
|
749
768
|
|
|
750
769
|
if (shots == 1U) {
|
|
@@ -782,8 +801,7 @@ struct QrackDevice final : public Catalyst::Runtime::QuantumDevice {
|
|
|
782
801
|
}
|
|
783
802
|
}
|
|
784
803
|
}
|
|
785
|
-
void Counts(DataView<double, 1> &eigvals, DataView<int64_t, 1> &counts
|
|
786
|
-
size_t shots) override
|
|
804
|
+
void Counts(DataView<double, 1> &eigvals, DataView<int64_t, 1> &counts) override
|
|
787
805
|
{
|
|
788
806
|
const size_t numQubits = qsim->GetQubitCount();
|
|
789
807
|
const size_t numElements = 1U << numQubits;
|
|
@@ -817,7 +835,7 @@ struct QrackDevice final : public Catalyst::Runtime::QuantumDevice {
|
|
|
817
835
|
}
|
|
818
836
|
|
|
819
837
|
void PartialCounts(DataView<double, 1> &eigvals, DataView<int64_t, 1> &counts,
|
|
820
|
-
const std::vector<QubitIdType> &wires
|
|
838
|
+
const std::vector<QubitIdType> &wires) override
|
|
821
839
|
{
|
|
822
840
|
const size_t numQubits = wires.size();
|
|
823
841
|
const size_t numElements = 1U << numQubits;
|
|
@@ -825,6 +843,10 @@ struct QrackDevice final : public Catalyst::Runtime::QuantumDevice {
|
|
|
825
843
|
RT_FAIL_IF(eigvals.size() != numElements || counts.size() != numElements,
|
|
826
844
|
"Invalid size for the pre-allocated counts");
|
|
827
845
|
|
|
846
|
+
if ((shots > 1U) && (noise_param > ZERO_R1_F)) {
|
|
847
|
+
throw std::domain_error("Shots > 1 can't be simulated with noise on the Qrack back end! (Likely, you want to set mcm_method=\"one-shot\" on your qnode, with multiple shots.)");
|
|
848
|
+
}
|
|
849
|
+
|
|
828
850
|
auto &&dev_wires = getDeviceWires(wires);
|
|
829
851
|
|
|
830
852
|
std::map<bitCapInt, int> q_samples;
|
pennylane_qrack/qrack_device.py
CHANGED
|
@@ -14,7 +14,6 @@
|
|
|
14
14
|
"""
|
|
15
15
|
Base device class for PennyLane-Qrack.
|
|
16
16
|
"""
|
|
17
|
-
from collections import OrderedDict
|
|
18
17
|
from functools import reduce
|
|
19
18
|
import cmath, math
|
|
20
19
|
import os
|
|
@@ -24,14 +23,20 @@ import itertools as it
|
|
|
24
23
|
|
|
25
24
|
import numpy as np
|
|
26
25
|
|
|
27
|
-
|
|
26
|
+
# PennyLane v0.42 introduced the `exceptions` module and will raise
|
|
27
|
+
# deprecation warnings if they are imported from the top-level module.
|
|
28
|
+
|
|
29
|
+
# This ensures backwards compatibility with older versions of PennyLane.
|
|
30
|
+
try:
|
|
31
|
+
from pennylane.exceptions import DeviceError, QuantumFunctionError
|
|
32
|
+
except (ModuleNotFoundError, ImportError) as import_error:
|
|
33
|
+
from pennylane import DeviceError, QuantumFunctionError
|
|
34
|
+
|
|
28
35
|
from pennylane.devices import QubitDevice
|
|
29
36
|
from pennylane.ops import (
|
|
30
|
-
|
|
37
|
+
StatePrep,
|
|
31
38
|
BasisState,
|
|
32
39
|
QubitUnitary,
|
|
33
|
-
CRZ,
|
|
34
|
-
PhaseShift,
|
|
35
40
|
Adjoint,
|
|
36
41
|
)
|
|
37
42
|
from pennylane.wires import Wires
|
|
@@ -66,9 +71,9 @@ class QrackDevice(QubitDevice):
|
|
|
66
71
|
"PauliY": Pauli.PauliY,
|
|
67
72
|
"PauliZ": Pauli.PauliZ,
|
|
68
73
|
"Identity": Pauli.PauliI,
|
|
74
|
+
"Hadamard": None,
|
|
75
|
+
"Hermitian": None,
|
|
69
76
|
"Prod": None,
|
|
70
|
-
# "Hadamard": None,
|
|
71
|
-
# "Hermitian": None,
|
|
72
77
|
# "Sum": None,
|
|
73
78
|
# "SProd": None,
|
|
74
79
|
# "Exp": None,
|
|
@@ -141,7 +146,7 @@ class QrackDevice(QubitDevice):
|
|
|
141
146
|
"C(MultiControlledX)",
|
|
142
147
|
}
|
|
143
148
|
|
|
144
|
-
|
|
149
|
+
config_filepath = pathlib.Path(
|
|
145
150
|
os.path.dirname(sys.modules[__name__].__file__) + "/QrackDeviceConfig.toml"
|
|
146
151
|
)
|
|
147
152
|
|
|
@@ -151,14 +156,20 @@ class QrackDevice(QubitDevice):
|
|
|
151
156
|
isTensorNetwork = True
|
|
152
157
|
# Use Schmidt decomposition optimizations? (Default is "true")
|
|
153
158
|
isSchmidtDecompose = True
|
|
154
|
-
# Distribute Schmidt-decomposed qubit subsystems to multiple GPUs or accelerators, if available? (Default is "
|
|
155
|
-
isSchmidtDecomposeMulti =
|
|
159
|
+
# Distribute Schmidt-decomposed qubit subsystems to multiple GPUs or accelerators, if available? (Default is "False"; mismatched device capacities might hurt overall performance)
|
|
160
|
+
isSchmidtDecomposeMulti = False
|
|
156
161
|
# Use "quantum binary decision diagram" ("QBDD") methods? (Default is "false"; note that QBDD is CPU-only)
|
|
157
162
|
isBinaryDecisionTree = False
|
|
158
163
|
# Use GPU acceleration? (Default is "true")
|
|
159
164
|
isOpenCL = True
|
|
165
|
+
# Use multi-GPU (or "multi-page") acceleration? (Default is "true")
|
|
166
|
+
isPaged = True
|
|
167
|
+
# Use CPU/GPU method hybridization? (Default is "True")
|
|
168
|
+
isCpuGpuHybrid = True
|
|
160
169
|
# Allocate GPU buffer from general host heap? (Default is "false"; "true" might improve performance or reliability in certain cases, like if using an Intel HD as accelerator)
|
|
161
|
-
isHostPointer = False
|
|
170
|
+
isHostPointer = True if os.environ.get("PYQRACK_HOST_POINTER_DEFAULT_ON") else False
|
|
171
|
+
# For CPU-based simulation, use sparse state vectors (Default is "false")
|
|
172
|
+
isSparse = False
|
|
162
173
|
# Noise parameter. (Default is "0"; depolarizing noise intensity can also be controlled by "QRACK_GATE_DEPOLARIZATION" environment variable)
|
|
163
174
|
noise = 0
|
|
164
175
|
|
|
@@ -186,8 +197,14 @@ class QrackDevice(QubitDevice):
|
|
|
186
197
|
self.isBinaryDecisionTree = options["isBinaryDecisionTree"]
|
|
187
198
|
if "isOpenCL" in options:
|
|
188
199
|
self.isOpenCL = options["isOpenCL"]
|
|
200
|
+
if "isPaged" in options:
|
|
201
|
+
self.isPaged = options["isPaged"]
|
|
202
|
+
if "isCpuGpuHybrid" in options:
|
|
203
|
+
self.isCpuGpuHybrid = options["isCpuGpuHybrid"]
|
|
189
204
|
if "isHostPointer" in options:
|
|
190
205
|
self.isHostPointer = options["isHostPointer"]
|
|
206
|
+
if "isSparse" in options:
|
|
207
|
+
self.isSparse = options["isSparse"]
|
|
191
208
|
if "noise" in options:
|
|
192
209
|
self.noise = options["noise"]
|
|
193
210
|
if (self.noise != 0) and (shots is None):
|
|
@@ -201,9 +218,24 @@ class QrackDevice(QubitDevice):
|
|
|
201
218
|
isSchmidtDecompose=self.isSchmidtDecompose,
|
|
202
219
|
isBinaryDecisionTree=self.isBinaryDecisionTree,
|
|
203
220
|
isOpenCL=self.isOpenCL,
|
|
221
|
+
isCpuGpuHybrid=self.isCpuGpuHybrid,
|
|
204
222
|
isHostPointer=self.isHostPointer,
|
|
223
|
+
isSparse=self.isSparse,
|
|
205
224
|
noise=self.noise,
|
|
206
225
|
)
|
|
226
|
+
self.device_kwargs = {
|
|
227
|
+
"is_hybrid_stabilizer": self.isStabilizerHybrid,
|
|
228
|
+
"is_tensor_network": self.isTensorNetwork,
|
|
229
|
+
"is_schmidt_decompose": self.isSchmidtDecompose,
|
|
230
|
+
"is_schmidt_decompose_parallel": self.isSchmidtDecomposeMulti,
|
|
231
|
+
"is_qpdd": self.isBinaryDecisionTree,
|
|
232
|
+
"is_gpu": self.isOpenCL,
|
|
233
|
+
"is_paged": self.isPaged,
|
|
234
|
+
"is_hybrid_cpu_gpu": self.isCpuGpuHybrid,
|
|
235
|
+
"is_host_pointer": self.isHostPointer,
|
|
236
|
+
"is_sparse": self.isSparse,
|
|
237
|
+
"noise": self.noise,
|
|
238
|
+
}
|
|
207
239
|
self._circuit = []
|
|
208
240
|
|
|
209
241
|
def _reverse_state(self):
|
|
@@ -229,8 +261,8 @@ class QrackDevice(QubitDevice):
|
|
|
229
261
|
|
|
230
262
|
def _apply(self):
|
|
231
263
|
for op in self._circuit:
|
|
232
|
-
if isinstance(op,
|
|
233
|
-
self.
|
|
264
|
+
if isinstance(op, StatePrep):
|
|
265
|
+
self._apply_state_prep(op)
|
|
234
266
|
elif isinstance(op, BasisState):
|
|
235
267
|
self._apply_basis_state(op)
|
|
236
268
|
elif isinstance(op, QubitUnitary):
|
|
@@ -259,7 +291,7 @@ class QrackDevice(QubitDevice):
|
|
|
259
291
|
|
|
260
292
|
return state_vector.flatten()
|
|
261
293
|
|
|
262
|
-
def
|
|
294
|
+
def _apply_state_prep(self, op):
|
|
263
295
|
"""Initialize state with a state vector"""
|
|
264
296
|
wires = op.wires
|
|
265
297
|
input_state = op.parameters[0]
|
|
@@ -692,10 +724,11 @@ class QrackDevice(QubitDevice):
|
|
|
692
724
|
|
|
693
725
|
return self._samples
|
|
694
726
|
|
|
695
|
-
|
|
696
|
-
|
|
727
|
+
# QubitDevice.states_to_binary() doesn't work for >64qb. (Fix by Elara, the custom OpenAI GPT)
|
|
728
|
+
samples = self._state.measure_shots(list(range(self.num_wires - 1, -1, -1)), self.shots)
|
|
729
|
+
self._samples = np.array(
|
|
730
|
+
[list(format(b, f"0{self.num_wires}b")) for b in samples], dtype=np.int8
|
|
697
731
|
)
|
|
698
|
-
self._samples = QubitDevice.states_to_binary(samples, self.num_wires)
|
|
699
732
|
|
|
700
733
|
return self._samples
|
|
701
734
|
|