@@ -61,6 +61,13 @@ template <size_t gntr_idx> constexpr auto generatorGatePairsIter() {
61
61
}
62
62
}
63
63
64
+ constexpr auto minNumQubitsFor (GeneratorOperation gntr_op) -> size_t {
65
+ if (Util::array_has_elt (Constant::multi_qubit_generators, gntr_op)) {
66
+ return 1 ;
67
+ }
68
+ return Util::lookup (Constant::generator_wires, gntr_op);
69
+ }
70
+
64
71
/* *
65
72
* @brief Array of all generator operations with the corresponding gate
66
73
* operations.
@@ -70,87 +77,93 @@ constexpr static auto generator_gate_pairs =
70
77
71
78
template <class PrecisionT , class ParamT , class GateImplementation ,
72
79
GeneratorOperation gntr_op, class RandomEngine >
73
- void testGeneratorForGate (RandomEngine &re, size_t num_qubits, bool inverse) {
80
+ void testGeneratorForGate (RandomEngine &re, bool inverse) {
74
81
using ComplexPrecisionT = std::complex<PrecisionT>;
75
- constexpr auto I = Util::IMAG<PrecisionT>();
82
+ constexpr static auto I = Util::IMAG<PrecisionT>();
76
83
77
- constexpr auto eps = PrecisionT{1e-3 }; // For finite difference
84
+ constexpr static auto eps = PrecisionT{1e-3 }; // For finite difference
78
85
79
- constexpr auto gate_op = Util::lookup (generator_gate_pairs, gntr_op);
80
- constexpr auto gate_name = Util::lookup (Constant::gate_names, gate_op);
86
+ constexpr static auto gate_op = Util::lookup (generator_gate_pairs, gntr_op);
87
+ constexpr static auto gate_name =
88
+ Util::lookup (Constant::gate_names, gate_op);
89
+ constexpr static auto min_num_qubits = minNumQubitsFor (gntr_op);
90
+ constexpr static size_t max_num_qubits = 6 ;
81
91
82
92
DYNAMIC_SECTION (" Test generator of " << gate_name << " for kernel "
83
93
<< GateImplementation::name) {
84
- const auto wires = createWires (gate_op);
85
- const auto ini_st = createRandomState<PrecisionT>(re, num_qubits);
86
-
87
- auto gntr_func =
88
- GeneratorOpToMemberFuncPtr<PrecisionT, GateImplementation,
89
- gntr_op>::value;
90
- auto gate_func =
91
- GateOpToMemberFuncPtr<PrecisionT, ParamT, GateImplementation,
92
- gate_op>::value;
93
-
94
- /* Apply generator to gntr_st */
95
- auto gntr_st = ini_st;
96
- PrecisionT scale = gntr_func (gntr_st.data (), num_qubits, wires, false );
97
- if (inverse) {
98
- scale *= -1 ;
94
+ for (size_t num_qubits = min_num_qubits; num_qubits < max_num_qubits;
95
+ num_qubits++) {
96
+ const auto wires = createWires (gate_op);
97
+ const auto ini_st = createRandomState<PrecisionT>(re, num_qubits);
98
+
99
+ auto gntr_func =
100
+ GeneratorOpToMemberFuncPtr<PrecisionT, GateImplementation,
101
+ gntr_op>::value;
102
+ auto gate_func =
103
+ GateOpToMemberFuncPtr<PrecisionT, ParamT, GateImplementation,
104
+ gate_op>::value;
105
+
106
+ /* Apply generator to gntr_st */
107
+ auto gntr_st = ini_st;
108
+ PrecisionT scale =
109
+ gntr_func (gntr_st.data (), num_qubits, wires, false );
110
+ if (inverse) {
111
+ scale *= -1 ;
112
+ }
113
+ scaleVector (gntr_st, I * scale);
114
+
115
+ /* Compute the derivative of the unitary gate applied to ini_st
116
+ * using finite difference */
117
+
118
+ auto diff_st_1 = ini_st;
119
+ auto diff_st_2 = ini_st;
120
+
121
+ gate_func (diff_st_1.data (), num_qubits, wires, inverse, eps);
122
+ gate_func (diff_st_2.data (), num_qubits, wires, inverse, -eps);
123
+
124
+ std::vector<ComplexPrecisionT> gate_der_st (size_t {1U }
125
+ << num_qubits);
126
+
127
+ std::transform (
128
+ diff_st_1.cbegin (), diff_st_1.cend (), diff_st_2.cbegin (),
129
+ gate_der_st.begin (),
130
+ [](ComplexPrecisionT a, ComplexPrecisionT b) { return a - b; });
131
+
132
+ scaleVector (gate_der_st, static_cast <PrecisionT>(0.5 ) / eps);
133
+
134
+ REQUIRE (gntr_st == approx (gate_der_st).margin (PrecisionT{1e-3 }));
99
135
}
100
- scaleVector (gntr_st, I * scale);
101
-
102
- /* Compute the derivative of the unitary gate applied to ini_st using
103
- * finite difference */
104
-
105
- auto diff_st_1 = ini_st;
106
- auto diff_st_2 = ini_st;
107
-
108
- gate_func (diff_st_1.data (), num_qubits, wires, inverse, eps);
109
- gate_func (diff_st_2.data (), num_qubits, wires, inverse, -eps);
110
-
111
- std::vector<ComplexPrecisionT> gate_der_st (size_t {1U } << num_qubits);
112
-
113
- std::transform (
114
- diff_st_1.cbegin (), diff_st_1.cend (), diff_st_2.cbegin (),
115
- gate_der_st.begin (),
116
- [](ComplexPrecisionT a, ComplexPrecisionT b) { return a - b; });
117
-
118
- scaleVector (gate_der_st, static_cast <PrecisionT>(0.5 ) / eps);
119
-
120
- REQUIRE (gntr_st == approx (gate_der_st).margin (PrecisionT{1e-3 }));
121
136
}
122
137
}
123
138
template <typename PrecisionT, typename ParamT, class GateImplementation ,
124
139
size_t gntr_idx, class RandomEngine >
125
- void testAllGeneratorForKernel (RandomEngine &re, size_t num_qubits ) {
140
+ void testAllGeneratorForKernel (RandomEngine &re) {
126
141
if constexpr (gntr_idx <
127
142
GateImplementation::implemented_generators.size ()) {
128
143
constexpr auto gntr_op =
129
144
GateImplementation::implemented_generators[gntr_idx];
130
145
testGeneratorForGate<PrecisionT, ParamT, GateImplementation, gntr_op>(
131
- re, num_qubits, false );
146
+ re, false );
132
147
testGeneratorForGate<PrecisionT, ParamT, GateImplementation, gntr_op>(
133
- re, num_qubits, true );
148
+ re, true );
134
149
testAllGeneratorForKernel<PrecisionT, ParamT, GateImplementation,
135
- gntr_idx + 1 >(re, num_qubits );
150
+ gntr_idx + 1 >(re);
136
151
} else {
137
152
static_cast <void >(re);
138
- static_cast <void >(num_qubits);
139
153
}
140
154
}
141
155
142
156
template <typename PrecisionT, typename ParamT, class TypeList ,
143
157
class RandomEngine >
144
- void testAllGeneratorsAndKernels (RandomEngine &re, size_t num_qubits ) {
158
+ void testAllGeneratorsAndKernels (RandomEngine &re) {
145
159
if constexpr (!std::is_same_v<TypeList, void >) {
146
160
using GateImplementation = typename TypeList::Type;
147
161
testAllGeneratorForKernel<PrecisionT, ParamT, GateImplementation, 0 >(
148
- re, num_qubits );
162
+ re);
149
163
testAllGeneratorsAndKernels<PrecisionT, ParamT,
150
- typename TypeList::Next>(re, num_qubits );
164
+ typename TypeList::Next>(re);
151
165
} else {
152
166
static_cast <void >(re);
153
- static_cast <void >(num_qubits);
154
167
}
155
168
}
156
169
@@ -161,5 +174,5 @@ TEMPLATE_TEST_CASE("Test all generators of all kernels",
161
174
162
175
std::mt19937 re{1337 };
163
176
164
- testAllGeneratorsAndKernels<PrecisionT, ParamT, TestKernels>(re, 4 );
177
+ testAllGeneratorsAndKernels<PrecisionT, ParamT, TestKernels>(re);
165
178
}
0 commit comments