Skip to content

Commit 7df37b4

Browse files
maliasadidime10
authored andcommitted
Revert #259
1 parent 2827d2c commit 7df37b4

12 files changed

+207
-242
lines changed

runtime/Makefile

+2-2
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ ENABLE_WARNINGS?=ON
1212
ENABLE_LIGHTNING_KOKKOS?=OFF
1313
ENABLE_OPENQASM?=OFF
1414
BUILD_QIR_STDLIB_FROM_SRC?=OFF
15-
# TODO: Update to latest_release after v0.33.0
16-
LIGHTNING_GIT_TAG_VALUE=master
15+
# TODO: remove after lightning monorepo upgrade
16+
LIGHTNING_GIT_TAG_VALUE?=v0.31.0
1717
LIGHTNING_KOKKOS_GIT_TAG_VALUE?=latest_release
1818
NPROC?=$(shell python -c "import os; print(os.cpu_count())")
1919

runtime/README.rst

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ The directory is structured as follows:
3030
- `extensions <https://github.com/PennyLaneAI/catalyst/tree/main/runtime/extensions>`_:
3131
A collection of extensions for backend simulators to fit into the
3232
`QIR programming model <https://github.com/qir-alliance/qir-spec/blob/main/specification/v0.1/4_Quantum_Runtime.md#qubits>`_.
33-
The `StateVectorLQubitDynamic <https://github.com/PennyLaneAI/catalyst/tree/main/runtime/extensions/StateVectorLQubitDynamic.hpp>`_
33+
The `StateVectorDynamicCPU <https://github.com/PennyLaneAI/catalyst/tree/main/runtime/extensions/StateVectorDynamicCPU.hpp>`_
3434
class extends the state-vector class of `Pennylane-Lightning <https://github.com/PennyLaneAI/pennylane-lightning>`_ providing
3535
dynamic allocation and deallocation of qubits.
3636

runtime/extensions/CMakeLists.txt

+1-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
44
include(FetchContent)
55

66
set(LIGHTNING_GIT_TAG "master" CACHE STRING "GIT_TAG value to build Lightning")
7-
set(source_files "StateVectorLQubitDynamic.cpp")
7+
set(source_files "StateVectorDynamicCPU.cpp")
88
FetchContent_Declare(
99
pennylane_lightning
1010
GIT_REPOSITORY https://github.com/PennyLaneAI/pennylane-lightning.git
@@ -29,7 +29,6 @@ if(ENABLE_LIGHTNING_KOKKOS)
2929
GIT_TAG ${LIGHTNING_KOKKOS_GIT_TAG}
3030
)
3131

32-
set(PL_BACKEND "lightning_qubit")
3332
set(PLKOKKOS_ENABLE_PYTHON OFF CACHE BOOL "Enable compilation of the Python bindings")
3433
FetchContent_MakeAvailable(pennylane_lightning_kokkos)
3534

runtime/extensions/StateVectorLQubitDynamic.cpp renamed to runtime/extensions/StateVectorDynamicCPU.cpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15-
#include "StateVectorLQubitDynamic.hpp"
15+
#include "StateVectorDynamicCPU.hpp"
1616

1717
// explicit instantiation
18-
template class Pennylane::LightningQubit::StateVectorLQubitDynamic<float>;
19-
template class Pennylane::LightningQubit::StateVectorLQubitDynamic<double>;
18+
template class Pennylane::StateVectorDynamicCPU<float>;
19+
template class Pennylane::StateVectorDynamicCPU<double>;

runtime/extensions/StateVectorLQubitDynamic.hpp renamed to runtime/extensions/StateVectorDynamicCPU.hpp

+84-111
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
14-
#pragma once
1514

1615
#include <numeric>
1716
#include <utility>
@@ -23,22 +22,11 @@
2322

2423
#include "Error.hpp"
2524

26-
#include <StateVectorLQubit.hpp>
25+
#include <StateVectorCPU.hpp>
2726

2827
#include <iostream>
2928

30-
namespace {
31-
using Pennylane::Util::AlignedAllocator;
32-
using Pennylane::Util::bestCPUMemoryModel;
33-
using Pennylane::Util::exp2;
34-
using Pennylane::Util::isPerfectPowerOf2;
35-
using Pennylane::Util::log2PerfectPower;
36-
using Pennylane::Util::ONE;
37-
using Pennylane::Util::squaredNorm;
38-
using Pennylane::Util::ZERO;
39-
} // namespace
40-
41-
namespace Pennylane::LightningQubit {
29+
namespace Pennylane {
4230
/**
4331
* @brief State-vector dynamic class.
4432
*
@@ -47,16 +35,15 @@ namespace Pennylane::LightningQubit {
4735
* quantum circuit simulation.
4836
*
4937
*/
50-
template <class fp_t = double>
51-
class StateVectorLQubitDynamic : public StateVectorLQubit<fp_t, StateVectorLQubitDynamic<fp_t>> {
38+
template <class PrecisionT = double>
39+
class StateVectorDynamicCPU : public StateVectorCPU<PrecisionT, StateVectorDynamicCPU<PrecisionT>> {
5240
public:
53-
using PrecisionT = fp_t;
54-
using ComplexT = std::complex<PrecisionT>;
55-
using MemoryStorageT = Pennylane::Util::MemoryStorageLocation::Internal;
41+
using BaseType = StateVectorCPU<PrecisionT, StateVectorDynamicCPU<PrecisionT>>;
42+
43+
using ComplexPrecisionT = std::complex<PrecisionT>;
5644

5745
private:
58-
using BaseType = StateVectorLQubit<PrecisionT, StateVectorLQubitDynamic<PrecisionT>>;
59-
std::vector<ComplexT, AlignedAllocator<ComplexT>> data_;
46+
std::vector<ComplexPrecisionT, Util::AlignedAllocator<ComplexPrecisionT>> data_;
6047

6148
static constexpr PrecisionT epsilon_ = std::numeric_limits<PrecisionT>::epsilon() * 100;
6249

@@ -75,23 +62,25 @@ class StateVectorLQubitDynamic : public StateVectorLQubit<fp_t, StateVectorLQubi
7562
{
7663
for (size_t i = 0; i < distance; i++) {
7764
*second++ = std::move(*first);
78-
*first = ZERO<PrecisionT>();
65+
*first = Util::ZERO<PrecisionT>();
7966
first++;
8067
}
8168
return second;
8269
}
8370

84-
inline void _scalar_mul_data(std::vector<ComplexT, AlignedAllocator<ComplexT>> &data,
85-
ComplexT scalar)
71+
inline void _scalar_mul_data(
72+
std::vector<ComplexPrecisionT, Util::AlignedAllocator<ComplexPrecisionT>> &data,
73+
ComplexPrecisionT scalar)
8674
{
8775
std::transform(data.begin(), data.end(), data.begin(),
88-
[scalar](const ComplexT &elem) { return elem * scalar; });
76+
[scalar](const ComplexPrecisionT &elem) { return elem * scalar; });
8977
}
9078

91-
inline void _normalize_data(std::vector<ComplexT, AlignedAllocator<ComplexT>> &data)
79+
inline void
80+
_normalize_data(std::vector<ComplexPrecisionT, Util::AlignedAllocator<ComplexPrecisionT>> &data)
9281
{
93-
_scalar_mul_data(data,
94-
ONE<PrecisionT>() / std::sqrt(squaredNorm(data.data(), data.size())));
82+
_scalar_mul_data(data, Util::ONE<PrecisionT>() /
83+
std::sqrt(Util::squaredNorm(data.data(), data.size())));
9584
}
9685

9786
public:
@@ -102,29 +91,28 @@ class StateVectorLQubitDynamic : public StateVectorLQubit<fp_t, StateVectorLQubi
10291
* @param threading Threading option the statevector to use
10392
* @param memory_model Memory model the statevector will use
10493
*/
105-
explicit StateVectorLQubitDynamic(size_t num_qubits,
106-
Threading threading = Threading::SingleThread,
107-
CPUMemoryModel memory_model = bestCPUMemoryModel())
94+
explicit StateVectorDynamicCPU(size_t num_qubits, Threading threading = Threading::SingleThread,
95+
CPUMemoryModel memory_model = bestCPUMemoryModel())
10896
: BaseType{num_qubits, threading, memory_model},
109-
data_{exp2(num_qubits), ZERO<PrecisionT>(),
110-
getAllocator<ComplexT>( // LCOV_EXCL_LINE
97+
data_{Util::exp2(num_qubits), Util::ZERO<PrecisionT>(),
98+
getAllocator<ComplexPrecisionT>( // LCOV_EXCL_LINE
11199
this->memory_model_)}
112100
{
113-
data_[0] = ONE<PrecisionT>();
101+
data_[0] = Util::ONE<PrecisionT>();
114102
}
115103

116104
/**
117105
* @brief Construct a statevector from another statevector
118106
*
119-
* @tparam OtherDerived A derived type of StateVectorLQubit to use for
107+
* @tparam OtherDerived A derived type of StateVectorCPU to use for
120108
* construction.
121109
* @param other Another statevector to construct the statevector from
122110
*/
123111
template <class OtherDerived>
124-
explicit StateVectorLQubitDynamic(const StateVectorLQubit<PrecisionT, OtherDerived> &other)
112+
explicit StateVectorDynamicCPU(const StateVectorCPU<PrecisionT, OtherDerived> &other)
125113
: BaseType(other.getNumQubits(), other.threading(), other.memoryModel()),
126114
data_{other.getData(), other.getData() + other.getLength(),
127-
getAllocator<ComplexT>(this->memory_model_)}
115+
getAllocator<ComplexPrecisionT>(this->memory_model_)}
128116
{
129117
}
130118

@@ -136,13 +124,14 @@ class StateVectorLQubitDynamic : public StateVectorLQubit<fp_t, StateVectorLQubi
136124
* @param threading Threading option the statevector to use
137125
* @param memory_model Memory model the statevector will use
138126
*/
139-
StateVectorLQubitDynamic(const ComplexT *other_data, size_t other_size,
140-
Threading threading = Threading::SingleThread,
141-
CPUMemoryModel memory_model = bestCPUMemoryModel())
142-
: BaseType(log2PerfectPower(other_size), threading, memory_model),
143-
data_{other_data, other_data + other_size, getAllocator<ComplexT>(this->memory_model_)}
127+
StateVectorDynamicCPU(const ComplexPrecisionT *other_data, size_t other_size,
128+
Threading threading = Threading::SingleThread,
129+
CPUMemoryModel memory_model = bestCPUMemoryModel())
130+
: BaseType(Util::log2PerfectPower(other_size), threading, memory_model),
131+
data_{other_data, other_data + other_size,
132+
getAllocator<ComplexPrecisionT>(this->memory_model_)}
144133
{
145-
PL_ABORT_IF_NOT(isPerfectPowerOf2(other_size),
134+
PL_ABORT_IF_NOT(Util::isPerfectPowerOf2(other_size),
146135
"The size of provided data must be a power of 2.");
147136
}
148137

@@ -156,79 +145,34 @@ class StateVectorLQubitDynamic : public StateVectorLQubit<fp_t, StateVectorLQubi
156145
* @param memory_model Memory model the statevector will use
157146
*/
158147
template <class Alloc>
159-
explicit StateVectorLQubitDynamic(const std::vector<std::complex<PrecisionT>, Alloc> &other,
160-
Threading threading = Threading::SingleThread,
161-
CPUMemoryModel memory_model = bestCPUMemoryModel())
162-
: StateVectorLQubitDynamic(other.data(), other.size(), threading, memory_model)
148+
explicit StateVectorDynamicCPU(const std::vector<std::complex<PrecisionT>, Alloc> &other,
149+
Threading threading = Threading::SingleThread,
150+
CPUMemoryModel memory_model = bestCPUMemoryModel())
151+
: StateVectorDynamicCPU(other.data(), other.size(), threading, memory_model)
163152
{
164153
}
165154

166-
StateVectorLQubitDynamic(const StateVectorLQubitDynamic &rhs) = default;
167-
StateVectorLQubitDynamic(StateVectorLQubitDynamic &&) noexcept = default;
168-
169-
StateVectorLQubitDynamic &operator=(const StateVectorLQubitDynamic &) = default;
170-
StateVectorLQubitDynamic &operator=(StateVectorLQubitDynamic &&) noexcept = default;
171-
172-
~StateVectorLQubitDynamic() = default;
173-
174-
/**
175-
* @brief Set the number of qubits represented by the statevector data.
176-
*
177-
* @return std::size_t
178-
*/
179-
void setNumQubits(size_t qubits) noexcept { this->num_qubits_ = qubits; }
180-
181-
/**
182-
* @brief Get underlying C-style data of the state-vector.
183-
*/
184-
[[nodiscard]] auto getData() -> ComplexT * { return data_.data(); }
185-
186-
/**
187-
* @brief Get underlying C-style data of the state-vector.
188-
*/
189-
[[nodiscard]] auto getData() const -> const ComplexT * { return data_.data(); }
155+
StateVectorDynamicCPU(const StateVectorDynamicCPU &rhs) = default;
156+
StateVectorDynamicCPU(StateVectorDynamicCPU &&) noexcept = default;
190157

191-
/**
192-
* @brief Get underlying data vector.
193-
*/
194-
[[nodiscard]] auto getDataVector() -> std::vector<ComplexT, AlignedAllocator<ComplexT>> &
195-
{
196-
return data_;
197-
}
198-
199-
/**
200-
* @brief Get underlying data vector.
201-
*/
202-
[[nodiscard]] auto getDataVector() const
203-
-> const std::vector<ComplexT, AlignedAllocator<ComplexT>> &
204-
{
205-
return data_;
206-
}
158+
StateVectorDynamicCPU &operator=(const StateVectorDynamicCPU &) = default;
159+
StateVectorDynamicCPU &operator=(StateVectorDynamicCPU &&) noexcept = default;
207160

208-
/**
209-
* @brief Update data of the class to new_data
210-
*
211-
* @param new_data data pointer to new data.
212-
* @param new_size size of underlying data storage.
213-
*/
214-
void updateData(const ComplexT *new_data, size_t new_size)
215-
{
216-
PL_ASSERT(data_.size() == new_size);
217-
std::copy(new_data, new_data + new_size, data_.data());
218-
}
161+
~StateVectorDynamicCPU() = default;
219162

220163
/**
221164
* @brief Update data of the class to new_data
222165
*
223166
* @tparam Alloc Allocator type of std::vector to use for updating data.
224167
* @param new_data std::vector contains data.
225168
*/
226-
template <class Alloc> void updateData(const std::vector<ComplexT, Alloc> &new_data)
169+
template <class Alloc> void updateData(const std::vector<ComplexPrecisionT, Alloc> &new_data)
227170
{
228-
updateData(new_data.data(), new_data.size());
171+
assert(data_.size() == new_data.size());
172+
std::copy(new_data.data(), new_data.data() + new_data.size(), data_.data());
229173
}
230174

231-
AlignedAllocator<ComplexT> allocator() const { return data_.get_allocator(); }
175+
Util::AlignedAllocator<ComplexPrecisionT> allocator() const { return data_.get_allocator(); }
232176

233177
[[nodiscard]] auto isValidWire(size_t wire) -> bool { return wire < this->getNumQubits(); }
234178

@@ -240,9 +184,9 @@ class StateVectorLQubitDynamic : public StateVectorLQubit<fp_t, StateVectorLQubi
240184
* matrix after tracing out the complement of qubit `wire`.
241185
*
242186
* @param wire Index of the wire.
243-
* @return ComplexT
187+
* @return ComplexPrecisionT
244188
*/
245-
auto getSubsystemPurity(size_t wire) -> ComplexT
189+
auto getSubsystemPurity(size_t wire) -> ComplexPrecisionT
246190
{
247191
PL_ABORT_IF_NOT(isValidWire(wire), "Invalid wire: The wire must be in the range of wires");
248192

@@ -257,11 +201,11 @@ class StateVectorLQubitDynamic : public StateVectorLQubit<fp_t, StateVectorLQubi
257201

258202
// The resulting 2x2 reduced density matrix of the complement system to
259203
// qubit `wire`.
260-
std::vector<ComplexT> rho(4, {0, 0});
204+
std::vector<ComplexPrecisionT> rho(4, {0, 0});
261205

262206
for (uint8_t i = 0; i < 2; i++) {
263207
for (uint8_t j = 0; j < 2; j++) {
264-
ComplexT sum{0, 0};
208+
ComplexPrecisionT sum{0, 0};
265209
for (size_t k = 0; k < (sv_size / 2); k++) {
266210
size_t idx_wire_0 = (/* upper_bits: */ (upper_mask & k) << 1UL) +
267211
/* lower_bits: */ (lower_mask & k);
@@ -278,7 +222,7 @@ class StateVectorLQubitDynamic : public StateVectorLQubit<fp_t, StateVectorLQubi
278222
}
279223

280224
// Compute/Return the trace of rho**2
281-
return (rho[0] * rho[0]) + (ComplexT{2, 0} * rho[1] * rho[2]) + (rho[3] * rho[3]);
225+
return (rho[0] * rho[0]) + (ComplexPrecisionT{2, 0} * rho[1] * rho[2]) + (rho[3] * rho[3]);
282226
}
283227

284228
/**
@@ -290,7 +234,7 @@ class StateVectorLQubitDynamic : public StateVectorLQubit<fp_t, StateVectorLQubi
290234
*/
291235
[[nodiscard]] auto checkSubsystemPurity(size_t wire, double eps = epsilon_) -> bool
292236
{
293-
ComplexT purity = getSubsystemPurity(wire);
237+
ComplexPrecisionT purity = getSubsystemPurity(wire);
294238
return (std::abs(1.0 - purity.real()) < eps) && (purity.imag() < eps);
295239
}
296240

@@ -335,8 +279,9 @@ class StateVectorLQubitDynamic : public StateVectorLQubit<fp_t, StateVectorLQubi
335279
// Check if the reduced state-vector is the first-half
336280
bool is_first_half = false;
337281
for (auto src = dst; src < data_.end(); std::advance(src, 2 * distance)) {
338-
is_first_half = std::any_of(src, src + static_cast<long long>(distance),
339-
[](ComplexT &e) { return e != ZERO<PrecisionT>(); });
282+
is_first_half =
283+
std::any_of(src, src + static_cast<long long>(distance),
284+
[](ComplexPrecisionT &e) { return e != Util::ZERO<PrecisionT>(); });
340285
if (is_first_half) {
341286
break;
342287
}
@@ -366,8 +311,36 @@ class StateVectorLQubitDynamic : public StateVectorLQubit<fp_t, StateVectorLQubi
366311
this->setNumQubits(0);
367312

368313
// the init state-vector
369-
data_.push_back(ONE<PrecisionT>());
314+
data_.push_back(Util::ONE<PrecisionT>());
315+
}
316+
317+
/**
318+
* @brief Get underlying C-style data of the state-vector.
319+
*/
320+
[[nodiscard]] auto getData() -> ComplexPrecisionT * { return data_.data(); }
321+
322+
/**
323+
* @brief Get underlying C-style data of the state-vector.
324+
*/
325+
[[nodiscard]] auto getData() const -> const ComplexPrecisionT * { return data_.data(); }
326+
327+
/**
328+
* @brief Get underlying data vector.
329+
*/
330+
[[nodiscard]] auto getDataVector()
331+
-> std::vector<ComplexPrecisionT, Util::AlignedAllocator<ComplexPrecisionT>> &
332+
{
333+
return data_;
334+
}
335+
336+
/**
337+
* @brief Get underlying data vector.
338+
*/
339+
[[nodiscard]] auto getDataVector() const
340+
-> const std::vector<ComplexPrecisionT, Util::AlignedAllocator<ComplexPrecisionT>> &
341+
{
342+
return data_;
370343
}
371344
};
372345

373-
} // namespace Pennylane::LightningQubit
346+
} // namespace Pennylane

runtime/lib/backend/common/Utils.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
#include "UtilKokkos.hpp"
3131
#endif
3232

33-
#if __has_include("StateVectorLQubitDynamic.hpp")
33+
#if __has_include("StateVectorDynamicCPU.hpp")
3434
#include "Util.hpp"
3535
#endif
3636

0 commit comments

Comments
 (0)