Skip to content

Commit e182d63

Browse files
Fix a bug in the generator of DoubleExcitationPlus (#298)
* Fix applyGeneratorDoubleExcitationPlus * Auto update version * Improve generator tests * Format * Update workflow Co-authored-by: Dev version update bot <[email protected]>
1 parent a113c30 commit e182d63

File tree

5 files changed

+68
-55
lines changed

5 files changed

+68
-55
lines changed

.github/workflows/wheel_win_x86_64.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ jobs:
1919
matrix:
2020
os: [windows-latest]
2121
py_version: ["3.7", "3.8", "3.9", "3.10"]
22-
name: ${{ matrix.os }}
22+
name: ${{ matrix.os }} (Python ${{ matrix.py_version}})
2323
runs-on: ${{ matrix.os }}
2424

2525
steps:

pennylane_lightning/_version.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,4 @@
1616
Version number (major.minor.patch[-label])
1717
"""
1818

19-
__version__ = "0.24.0-dev11"
19+
__version__ = "0.24.0-dev12"

pennylane_lightning/src/gates/Constant.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -179,10 +179,10 @@ namespace Pennylane::Gates::Constant {
179179
std::pair<GateOperation, size_t>{GateOperation::SingleExcitationMinus, 2},
180180
std::pair<GateOperation, size_t>{GateOperation::SingleExcitationPlus, 2},
181181
std::pair<GateOperation, size_t>{GateOperation::Toffoli, 3},
182+
std::pair<GateOperation, size_t>{GateOperation::CSWAP, 3},
182183
std::pair<GateOperation, size_t>{GateOperation::DoubleExcitation, 4},
183184
std::pair<GateOperation, size_t>{GateOperation::DoubleExcitationMinus, 4},
184185
std::pair<GateOperation, size_t>{GateOperation::DoubleExcitationPlus, 4},
185-
std::pair<GateOperation, size_t>{GateOperation::CSWAP, 3},
186186
};
187187

188188
/**

pennylane_lightning/src/gates/cpu_kernels/QChemGateImplementations.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -411,7 +411,7 @@ auto GateImplementationsPI::applyGeneratorDoubleExcitationPlus(
411411
for (const size_t &externalIndex : externalIndices) {
412412
std::complex<PrecisionT> *shiftedState = arr + externalIndex;
413413
for (const size_t &i : indices) {
414-
shiftedState[indices[i]] *= -1;
414+
shiftedState[i] *= -1;
415415
}
416416

417417
shiftedState[indices[i0]] *= -Util::IMAG<PrecisionT>();

pennylane_lightning/src/tests/Test_GateImplementations_Generator.cpp

+64-51
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,13 @@ template <size_t gntr_idx> constexpr auto generatorGatePairsIter() {
6161
}
6262
}
6363

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+
6471
/**
6572
* @brief Array of all generator operations with the corresponding gate
6673
* operations.
@@ -70,87 +77,93 @@ constexpr static auto generator_gate_pairs =
7077

7178
template <class PrecisionT, class ParamT, class GateImplementation,
7279
GeneratorOperation gntr_op, class RandomEngine>
73-
void testGeneratorForGate(RandomEngine &re, size_t num_qubits, bool inverse) {
80+
void testGeneratorForGate(RandomEngine &re, bool inverse) {
7481
using ComplexPrecisionT = std::complex<PrecisionT>;
75-
constexpr auto I = Util::IMAG<PrecisionT>();
82+
constexpr static auto I = Util::IMAG<PrecisionT>();
7683

77-
constexpr auto eps = PrecisionT{1e-3}; // For finite difference
84+
constexpr static auto eps = PrecisionT{1e-3}; // For finite difference
7885

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;
8191

8292
DYNAMIC_SECTION("Test generator of " << gate_name << " for kernel "
8393
<< 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}));
99135
}
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}));
121136
}
122137
}
123138
template <typename PrecisionT, typename ParamT, class GateImplementation,
124139
size_t gntr_idx, class RandomEngine>
125-
void testAllGeneratorForKernel(RandomEngine &re, size_t num_qubits) {
140+
void testAllGeneratorForKernel(RandomEngine &re) {
126141
if constexpr (gntr_idx <
127142
GateImplementation::implemented_generators.size()) {
128143
constexpr auto gntr_op =
129144
GateImplementation::implemented_generators[gntr_idx];
130145
testGeneratorForGate<PrecisionT, ParamT, GateImplementation, gntr_op>(
131-
re, num_qubits, false);
146+
re, false);
132147
testGeneratorForGate<PrecisionT, ParamT, GateImplementation, gntr_op>(
133-
re, num_qubits, true);
148+
re, true);
134149
testAllGeneratorForKernel<PrecisionT, ParamT, GateImplementation,
135-
gntr_idx + 1>(re, num_qubits);
150+
gntr_idx + 1>(re);
136151
} else {
137152
static_cast<void>(re);
138-
static_cast<void>(num_qubits);
139153
}
140154
}
141155

142156
template <typename PrecisionT, typename ParamT, class TypeList,
143157
class RandomEngine>
144-
void testAllGeneratorsAndKernels(RandomEngine &re, size_t num_qubits) {
158+
void testAllGeneratorsAndKernels(RandomEngine &re) {
145159
if constexpr (!std::is_same_v<TypeList, void>) {
146160
using GateImplementation = typename TypeList::Type;
147161
testAllGeneratorForKernel<PrecisionT, ParamT, GateImplementation, 0>(
148-
re, num_qubits);
162+
re);
149163
testAllGeneratorsAndKernels<PrecisionT, ParamT,
150-
typename TypeList::Next>(re, num_qubits);
164+
typename TypeList::Next>(re);
151165
} else {
152166
static_cast<void>(re);
153-
static_cast<void>(num_qubits);
154167
}
155168
}
156169

@@ -161,5 +174,5 @@ TEMPLATE_TEST_CASE("Test all generators of all kernels",
161174

162175
std::mt19937 re{1337};
163176

164-
testAllGeneratorsAndKernels<PrecisionT, ParamT, TestKernels>(re, 4);
177+
testAllGeneratorsAndKernels<PrecisionT, ParamT, TestKernels>(re);
165178
}

0 commit comments

Comments
 (0)