6
6
#pragma once
7
7
8
8
#include " StateType.hpp"
9
- #include " algorithms/RandomCliffordCircuit.hpp"
10
- #include " dd/DDDefinitions.hpp"
11
- #include " dd/DDpackageConfig.hpp"
12
- #include " dd/Package.hpp"
9
+ #include " checker/dd/DDPackageConfigs.hpp"
13
10
#include " dd/Package_fwd.hpp"
14
- #include " dd/Simulation.hpp" // IWYU pragma: keep
15
11
16
- #include < array>
17
12
#include < cassert>
18
- #include < cmath>
19
13
#include < cstddef>
20
- #include < cstdint>
21
- #include < limits>
22
14
#include < random>
23
- #include < tuple>
24
15
#include < unordered_set>
25
- #include < vector>
26
16
27
17
namespace ec {
28
18
class StateGenerator {
@@ -32,143 +22,24 @@ class StateGenerator {
32
22
}
33
23
StateGenerator () : StateGenerator(0U ) {}
34
24
35
- template <class Config = dd::DDPackageConfig>
36
25
qc::VectorDD
37
- generateRandomState (dd::Package<Config>& dd, const std::size_t totalQubits,
38
- const std::size_t ancillaryQubits = 0U ,
39
- const StateType type = StateType::ComputationalBasis) {
40
- switch (type) {
41
- case ec::StateType::Random1QBasis:
42
- return generateRandom1QBasisState (dd, totalQubits, ancillaryQubits);
43
- case ec::StateType::Stabilizer:
44
- return generateRandomStabilizerState (dd, totalQubits, ancillaryQubits);
45
- default :
46
- return generateRandomComputationalBasisState (dd, totalQubits,
47
- ancillaryQubits);
48
- }
49
- }
26
+ generateRandomState (dd::Package<SimulationDDPackageConfig>& dd,
27
+ std::size_t totalQubits, std::size_t ancillaryQubits = 0U ,
28
+ StateType type = StateType::ComputationalBasis);
50
29
51
- template <class Config = dd::DDPackageConfig>
52
30
qc::VectorDD generateRandomComputationalBasisState (
53
- dd::Package<Config>& dd, const std::size_t totalQubits,
54
- const std::size_t ancillaryQubits = 0U ) {
55
- // determine how many qubits truly are random
56
- const std::size_t randomQubits = totalQubits - ancillaryQubits;
57
- std::vector<bool > stimulusBits (totalQubits, false );
58
-
59
- // check if there still is a unique computational basis state
60
- if (constexpr auto bitwidth = std::numeric_limits<std::uint64_t >::digits;
61
- randomQubits <= (bitwidth - 1U )) {
62
- const auto maxStates = static_cast <std::uint64_t >(1U ) << randomQubits;
63
- assert (generatedComputationalBasisStates.size () != maxStates);
64
- // generate a unique computational basis state
65
- std::uniform_int_distribution<std::uint64_t > distribution (0U ,
66
- maxStates - 1U );
67
- auto [randomState, success] =
68
- generatedComputationalBasisStates.insert (distribution (mt));
69
- while (!success) {
70
- std::tie (randomState, success) =
71
- generatedComputationalBasisStates.insert (distribution (mt));
72
- }
31
+ dd::Package<SimulationDDPackageConfig>& dd, std::size_t totalQubits,
32
+ std::size_t ancillaryQubits = 0U );
73
33
74
- // generate the bitvector corresponding to the random state
75
- for (std::size_t i = 0U ; i < randomQubits; ++i) {
76
- if ((*randomState & (static_cast <std::uint64_t >(1U ) << i)) != 0U ) {
77
- stimulusBits[i] = true ;
78
- }
79
- }
80
- } else {
81
- // check how many numbers are needed for each random state
82
- const auto nr = static_cast <std::size_t >(
83
- std::ceil (static_cast <double >(randomQubits) / bitwidth));
84
- // generate enough random numbers
85
- std::vector<std::mt19937_64::result_type> randomNumbers (nr, 0U );
86
- for (auto i = 0U ; i < nr; ++i) {
87
- randomNumbers[i] = mt ();
88
- }
89
- // generate the corresponding bitvector
90
- for (std::size_t i = 0U ; i < randomQubits; ++i) {
91
- if ((randomNumbers[i / bitwidth] &
92
- (static_cast <std::uint_least64_t >(1U ) << (i % bitwidth))) != 0U ) {
93
- stimulusBits[i] = true ;
94
- }
95
- }
96
- }
97
-
98
- // return the appropriate decision diagram
99
- return dd.makeBasisState (totalQubits, stimulusBits);
100
- }
101
-
102
- template <class Config = dd::DDPackageConfig>
103
34
qc::VectorDD
104
- generateRandom1QBasisState (dd::Package<Config>& dd,
105
- const std::size_t totalQubits,
106
- const std::size_t ancillaryQubits = 0U ) {
107
- // determine how many qubits truly are random
108
- const std::size_t randomQubits = totalQubits - ancillaryQubits;
109
-
110
- // choose a random basis state for each qubit
111
- auto randomBasisState =
112
- std::vector<dd::BasisStates>(totalQubits, dd::BasisStates::zero);
113
- for (std::size_t i = 0U ; i < randomQubits; ++i) {
114
- switch (random1QBasisDistribution (mt)) {
115
- case static_cast <std::size_t >(dd::BasisStates::zero):
116
- randomBasisState[i] = dd::BasisStates::zero;
117
- break ;
118
- case static_cast <std::size_t >(dd::BasisStates::one):
119
- randomBasisState[i] = dd::BasisStates::one;
120
- break ;
121
- case static_cast <std::size_t >(dd::BasisStates::plus):
122
- randomBasisState[i] = dd::BasisStates::plus;
123
- break ;
124
- case static_cast <std::size_t >(dd::BasisStates::minus):
125
- randomBasisState[i] = dd::BasisStates::minus;
126
- break ;
127
- case static_cast <std::size_t >(dd::BasisStates::right):
128
- randomBasisState[i] = dd::BasisStates::right;
129
- break ;
130
- case static_cast <std::size_t >(dd::BasisStates::left):
131
- randomBasisState[i] = dd::BasisStates::left;
132
- break ;
133
- default :
134
- break ;
135
- }
136
- }
137
-
138
- // return the appropriate decision diagram
139
- return dd.makeBasisState (totalQubits, randomBasisState);
140
- }
35
+ generateRandom1QBasisState (dd::Package<SimulationDDPackageConfig>& dd,
36
+ std::size_t totalQubits,
37
+ std::size_t ancillaryQubits = 0U );
141
38
142
- template <class Config = dd::DDPackageConfig>
143
39
qc::VectorDD
144
- generateRandomStabilizerState (dd::Package<Config>& dd,
145
- const std::size_t totalQubits,
146
- const std::size_t ancillaryQubits = 0U ) {
147
- // determine how many qubits truly are random
148
- const std::size_t randomQubits = totalQubits - ancillaryQubits;
149
-
150
- // generate a random Clifford circuit with appropriate depth
151
- auto rcs = qc::RandomCliffordCircuit (
152
- randomQubits,
153
- static_cast <std::size_t >(std::round (std::log2 (randomQubits))), mt ());
154
-
155
- // generate the associated stabilizer state by simulating the Clifford
156
- // circuit
157
- auto stabilizer = simulate (&rcs, dd.makeZeroState (randomQubits), dd);
158
-
159
- // decrease the ref count right after so that it stays correct later on
160
- dd.decRef (stabilizer);
161
-
162
- // add |0> edges for all the ancillary qubits
163
- auto initial = stabilizer;
164
- for (std::size_t p = randomQubits; p < totalQubits; ++p) {
165
- initial = dd.makeDDNode (static_cast <dd::Qubit>(p),
166
- std::array{initial, qc::VectorDD::zero ()});
167
- }
168
-
169
- // return the resulting decision diagram
170
- return initial;
171
- }
40
+ generateRandomStabilizerState (dd::Package<SimulationDDPackageConfig>& dd,
41
+ std::size_t totalQubits,
42
+ std::size_t ancillaryQubits = 0U );
172
43
173
44
void seedGenerator (std::size_t s);
174
45
0 commit comments