Skip to content

Commit

Permalink
merge from lk-control-base
Browse files Browse the repository at this point in the history
  • Loading branch information
josephleekl committed Nov 8, 2024
2 parents 82b0b85 + e89065f commit a2d6fe4
Show file tree
Hide file tree
Showing 5 changed files with 153 additions and 1 deletion.
2 changes: 1 addition & 1 deletion pennylane_lightning/core/_version.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,4 @@
Version number (major.minor.patch[-label])
"""

__version__ = "0.40.0-dev4"
__version__ = "0.40.0-dev6"
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ using Pennylane::LightningKokkos::Util::ControlBitPatterns;
using Pennylane::LightningKokkos::Util::generateBitPatterns;
using Pennylane::LightningKokkos::Util::parity_2_offset;
using Pennylane::LightningKokkos::Util::reverseWires;
using Pennylane::LightningKokkos::Util::ControlBitPatterns;
using Pennylane::LightningKokkos::Util::generateBitPatterns;
using Pennylane::LightningKokkos::Util::parity_2_offset;
using Pennylane::LightningKokkos::Util::reverseWires;
using Pennylane::LightningKokkos::Util::vector2view;
} // namespace
/// @endcond
Expand Down Expand Up @@ -82,6 +86,54 @@ class applyNC1Functor<PrecisionT, FuncT, true> {
}
};

template <class PrecisionT, class FuncT>
class applyNC1Functor<PrecisionT, FuncT, false> {

template <class PrecisionT, class FuncT, bool has_controls>
class applyNC1Functor {};

template <class PrecisionT, class FuncT>
class applyNC1Functor<PrecisionT, FuncT, true> {
using KokkosIntVector = Kokkos::View<std::size_t *>;

Kokkos::View<Kokkos::complex<PrecisionT> *> arr;
const FuncT core_function;
KokkosIntVector indices;
KokkosIntVector parity;
KokkosIntVector rev_wires;
KokkosIntVector rev_wire_shifts;

public:
template <class ExecutionSpace>
applyNC1Functor([[maybe_unused]] ExecutionSpace exec,
Kokkos::View<Kokkos::complex<PrecisionT> *> arr_,
std::size_t num_qubits,
const std::vector<std::size_t> &controlled_wires,
const std::vector<bool> &controlled_values,
const std::vector<std::size_t> &wires, FuncT core_function_)
: arr(arr_), core_function(core_function_) {

std::tie(parity, rev_wires) =
reverseWires(num_qubits, wires, controlled_wires);
std::vector<std::size_t> indices_ =
generateBitPatterns(wires, num_qubits);
ControlBitPatterns(indices_, num_qubits, controlled_wires,
controlled_values);
indices = vector2view(indices_);
Kokkos::parallel_for(
Kokkos::RangePolicy<ExecutionSpace>(
0, exp2(num_qubits - controlled_wires.size() - wires.size())),
*this);
}
KOKKOS_FUNCTION void operator()(const std::size_t k) const {
const std::size_t offset = parity_2_offset(parity, k);
const std::size_t i0 = indices(0B00);
const std::size_t i1 = indices(0B01);

core_function(arr, i0 + offset, i1 + offset);
}
};

template <class PrecisionT, class FuncT>
class applyNC1Functor<PrecisionT, FuncT, false> {

Expand Down Expand Up @@ -510,6 +562,7 @@ void applyNCRot(Kokkos::View<Kokkos::complex<PrecisionT> *> arr_,
const Kokkos::complex<PrecisionT> mat_0b01 = mat[0b01];
const Kokkos::complex<PrecisionT> mat_0b10 = mat[0b10];
const Kokkos::complex<PrecisionT> mat_0b11 = mat[0b11];
auto core_function =
auto core_function =
KOKKOS_LAMBDA(Kokkos::View<Kokkos::complex<PrecisionT> *> arr,
const std::size_t i0, const std::size_t i1) {
Expand Down Expand Up @@ -847,6 +900,8 @@ void applyCRZ(Kokkos::View<Kokkos::complex<PrecisionT> *> arr_,
const PrecisionT &angle = params[0];
const PrecisionT cos_angle = std::cos(angle * static_cast<PrecisionT>(0.5));
const PrecisionT sin_angle = std::sin(angle * static_cast<PrecisionT>(0.5));
const PrecisionT cos_angle = std::cos(angle * static_cast<PrecisionT>(0.5));
const PrecisionT sin_angle = std::sin(angle * static_cast<PrecisionT>(0.5));
const Kokkos::complex<PrecisionT> shift_0{
cos_angle, (inverse) ? sin_angle : -sin_angle};
const Kokkos::complex<PrecisionT> shift_1 = Kokkos::conj(shift_0);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -704,6 +704,45 @@ TEMPLATE_TEST_CASE("StateVectorKokkos::applyCSWAP",
}
}

TEMPLATE_TEST_CASE("StateVectorKokkos::applyCSWAP",
"[StateVectorKokkos_Nonparam]", float, double) {
{
using ComplexT = StateVectorKokkos<TestType>::ComplexT;
const std::size_t num_qubits = 3;

StateVectorKokkos<TestType> kokkos_sv{num_qubits};

kokkos_sv.applyOperations({{"Hadamard"}, {"PauliX"}}, {{0}, {1}},
{{false}, {false}});

auto ini_sv = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace{},
kokkos_sv.getView());

auto z = ComplexT{ZERO<TestType>()};
auto i = ComplexT{INVSQRT2<TestType>()};

SECTION("Apply using dispatcher") {
SECTION("CSWAP [0,1,2]|+10> -> |010> + |101>") {
const std::vector<ComplexT> expected_results = {z, z, i, z,
z, i, z, z};

StateVectorKokkos<TestType> svdat012{num_qubits};
Kokkos::deep_copy(svdat012.getView(), ini_sv);

svdat012.applyOperation("CSWAP", {0, 1, 2}, false);

auto sv012 = Kokkos::create_mirror_view_and_copy(
Kokkos::HostSpace{}, svdat012.getView());

for (std::size_t j = 0; j < exp2(num_qubits); j++) {
CHECK(imag(expected_results[j]) == Approx(imag(sv012[j])));
CHECK(real(expected_results[j]) == Approx(real(sv012[j])));
}
}
}
}
}

TEMPLATE_TEST_CASE("StateVectorKokkos::applyMultiQubitOp",
"[StateVectorKokkos_Nonparam][Inverse]", float, double) {
const bool inverse = GENERATE(true, false);
Expand Down Expand Up @@ -801,6 +840,7 @@ TEMPLATE_TEST_CASE("StateVectorKokkos::applyMultiQubitOp",
}
}

TEMPLATE_TEST_CASE("StateVectorKokkos::applyOperation Controlled",
TEMPLATE_TEST_CASE("StateVectorKokkos::applyOperation Controlled",
"[StateVectorKokkos_Nonparam]", float, double) {

Expand All @@ -823,6 +863,28 @@ TEMPLATE_TEST_CASE("StateVectorKokkos::applyOperation non-param "
const std::size_t wire = GENERATE(0, 1, 2, 3);
StateVectorKokkos<TestType> kokkos_sv{num_qubits};

using StateVectorT = StateVectorKokkos<TestType>;
using PrecisionT = StateVectorT::PrecisionT;
const std::size_t num_qubits = 3;
StateVectorKokkos<TestType> state_vector{num_qubits};
auto matrix = getIdentity<Kokkos::complex, PrecisionT>();
PL_REQUIRE_THROWS_MATCHES(
state_vector.applyOperation("XXX", {0}, {true}, {1}, false, {}, matrix),
LightningException, "Controlled matrix operation not yet supported");
}

TEMPLATE_TEST_CASE("StateVectorKokkos::applyOperation non-param "
"one-qubit with controls",
"[StateVectorKokkos_NonParam]", float, double) {
const bool inverse = GENERATE(true, false);
const std::size_t num_qubits = 4;
const std::size_t control = GENERATE(0, 1, 2, 3);
const std::size_t wire = GENERATE(0, 1, 2, 3);
StateVectorKokkos<TestType> kokkos_sv{num_qubits};

kokkos_sv.applyOperations(
{{"Hadamard"}, {"Hadamard"}, {"Hadamard"}, {"Hadamard"}},
{{0}, {1}, {2}, {3}}, {{false}, {false}, {false}, {false}});
kokkos_sv.applyOperations(
{{"Hadamard"}, {"Hadamard"}, {"Hadamard"}, {"Hadamard"}},
{{0}, {1}, {2}, {3}}, {{false}, {false}, {false}, {false}});
Expand All @@ -832,6 +894,35 @@ TEMPLATE_TEST_CASE("StateVectorKokkos::applyOperation non-param "
StateVectorKokkos<TestType> sv_gate{num_qubits};
StateVectorKokkos<TestType> sv_control{num_qubits};

SECTION("N-controlled PauliX ") {

if (control == wire) {
Kokkos::deep_copy(sv_control.getView(), ini_sv);

REQUIRE_THROWS_AS(sv_control.applyOperation(
"PauliX", std::vector<std::size_t>{control},
std::vector<bool>{true},
std::vector<std::size_t>{wire}),
LightningException);
}

if (control != wire) {
Kokkos::deep_copy(sv_gate.getView(), ini_sv);
Kokkos::deep_copy(sv_control.getView(), ini_sv);

sv_gate.applyOperation("CNOT", {control, wire}, inverse);
sv_control.applyOperation(
"PauliX", std::vector<std::size_t>{control},
std::vector<bool>{true}, std::vector<std::size_t>{wire});
auto sv_gate_host = Kokkos::create_mirror_view_and_copy(
Kokkos::HostSpace{}, sv_gate.getView());
auto sv_control_host = Kokkos::create_mirror_view_and_copy(
Kokkos::HostSpace{}, sv_control.getView());
auto ini_sv = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace{},
kokkos_sv.getView());
StateVectorKokkos<TestType> sv_gate{num_qubits};
StateVectorKokkos<TestType> sv_control{num_qubits};

SECTION("N-controlled PauliX ") {

if (control == wire) {
Expand Down
1 change: 1 addition & 0 deletions pennylane_lightning/lightning_kokkos/_state_vector.py
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,7 @@ def _apply_lightning(
elif isinstance(operation, qml.ops.Controlled) and not isinstance(

Check warning on line 287 in pennylane_lightning/lightning_kokkos/_state_vector.py

View check run for this annotation

Codecov / codecov/patch

pennylane_lightning/lightning_kokkos/_state_vector.py#L287

Added line #L287 was not covered by tests
operation.base, (qml.QubitUnitary, qml.BlockEncode, qml.MultiRZ)
): # apply n-controlled gate
# Kokkos does not support controlled gates except for GlobalPhase and single-qubit
# Kokkos does not support controlled gates except for GlobalPhase and single-qubit
self._apply_lightning_controlled(operation)
else: # apply gate as a matrix
Expand Down
5 changes: 5 additions & 0 deletions pennylane_lightning/lightning_kokkos/lightning_kokkos.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ PauliX = { properties = [ "invertible", "controllable", "differe
PauliY = { properties = [ "invertible", "controllable", "differentiable" ] }
PauliZ = { properties = [ "invertible", "controllable", "differentiable" ] }
PhaseShift = { properties = [ "invertible", "controllable", "differentiable" ] }
PauliX = { properties = [ "invertible", "controllable", "differentiable" ] }
PauliY = { properties = [ "invertible", "controllable", "differentiable" ] }
PauliZ = { properties = [ "invertible", "controllable", "differentiable" ] }
PhaseShift = { properties = [ "invertible", "controllable", "differentiable" ] }
QubitUnitary = { properties = [ "invertible", ] }
Rot = { properties = [ "invertible", "controllable" ] }
RX = { properties = [ "invertible", "controllable", "differentiable" ] }
Expand All @@ -40,6 +44,7 @@ S = { properties = [ "invertible", "controllable", "differe
SWAP = { properties = [ "invertible", "controllable", "differentiable" ] }
Toffoli = { properties = [ "invertible", "differentiable" ] }
T = { properties = [ "invertible", "controllable", "differentiable" ] }
T = { properties = [ "invertible", "controllable", "differentiable" ] }

# Operators that should be decomposed according to the algorithm used
# by PennyLane's device API.
Expand Down

0 comments on commit a2d6fe4

Please sign in to comment.