Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

assignment: add ISWAP functionality and unit tests #749

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions pennylane_lightning/core/src/gates/Constant.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ using GateView = typename std::pair<GateOperation, std::string_view>;
GateView{GateOperation::IsingYY, "IsingYY"},
GateView{GateOperation::IsingZZ, "IsingZZ"},
GateView{GateOperation::SWAP, "SWAP"},
GateView{GateOperation::ISWAP, "ISWAP"},
GateView{GateOperation::ControlledPhaseShift, "ControlledPhaseShift"},
GateView{GateOperation::CRX, "CRX"},
GateView{GateOperation::CRY, "CRY"},
Expand Down Expand Up @@ -217,6 +218,7 @@ using GateNWires = typename std::pair<GateOperation, std::size_t>;
GateNWires{GateOperation::CY, 2},
GateNWires{GateOperation::CZ, 2},
GateNWires{GateOperation::SWAP, 2},
GateNWires{GateOperation::ISWAP, 2},
GateNWires{GateOperation::IsingXX, 2},
GateNWires{GateOperation::IsingXY, 2},
GateNWires{GateOperation::IsingYY, 2},
Expand Down Expand Up @@ -331,6 +333,7 @@ using GateNParams = typename std::pair<GateOperation, std::size_t>;
GateNParams{GateOperation::CY, 0},
GateNParams{GateOperation::CZ, 0},
GateNParams{GateOperation::SWAP, 0},
GateNParams{GateOperation::ISWAP, 0},
GateNParams{GateOperation::IsingXX, 1},
GateNParams{GateOperation::IsingXY, 1},
GateNParams{GateOperation::IsingYY, 1},
Expand Down
1 change: 1 addition & 0 deletions pennylane_lightning/core/src/gates/GateOperation.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ enum class GateOperation : uint32_t {
CY,
CZ,
SWAP,
ISWAP,
IsingXX,
IsingXY,
IsingYY,
Expand Down
19 changes: 19 additions & 0 deletions pennylane_lightning/core/src/gates/Gates.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,23 @@ static constexpr auto getSWAP() -> std::vector<ComplexT<T>> {
ONE<ComplexT, T>()};
}

/**
* @brief Create a matrix representation of the ISWAP gate data in row-major
* format.
*
* @tparam ComplexT Complex class.
* @tparam T Required precision of gate (`float` or `double`).
* @return constexpr std::vector<ComplexT<T>> Return constant expression
* of ISWAP gate data.
*/
template <template <typename...> class ComplexT, typename T>
static constexpr auto getISWAP(const bool inverse = false) -> std::vector<ComplexT<T>> {
return {ONE<ComplexT, T>(), ZERO<ComplexT, T>(), ZERO<ComplexT, T>(), ZERO<ComplexT, T>(),
ZERO<ComplexT, T>(), ZERO<ComplexT, T>(), ((inverse) ? -IMAG<ComplexT, T>() : IMAG<ComplexT, T>()), ZERO<ComplexT, T>(),
ZERO<ComplexT, T>(), ((inverse) ? -IMAG<ComplexT, T>() : IMAG<ComplexT, T>()), ZERO<ComplexT, T>(), ZERO<ComplexT, T>(),
ZERO<ComplexT, T>(), ZERO<ComplexT, T>(), ZERO<ComplexT, T>(), ONE<ComplexT, T>()};
}

/**
* @brief Create a matrix representation of the CY gate data in row-major
* format.
Expand Down Expand Up @@ -1238,6 +1255,8 @@ std::vector<ComplexT<T>> getMatrix(const GateOperation gate_op,
return getCZ<ComplexT, T>();
case GateOperation::SWAP:
return getSWAP<ComplexT, T>();
case GateOperation::ISWAP:
return getISWAP<ComplexT, T>(inverse);
case GateOperation::ControlledPhaseShift:
return getControlledPhaseShift<ComplexT, T>((inverse) ? -params[0]
: params[0]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,26 @@ void applySWAP(Kokkos::View<Kokkos::complex<PrecisionT> *> arr_,
});
}

template <class ExecutionSpace, class PrecisionT>
void applyISWAP(Kokkos::View<Kokkos::complex<PrecisionT> *> arr_,
const std::size_t num_qubits,
const std::vector<std::size_t> &wires,
[[maybe_unused]] const bool inverse = false,
luotianwu marked this conversation as resolved.
Show resolved Hide resolved
[[maybe_unused]] const std::vector<PrecisionT> &params = {}) {
const PrecisionT s = (inverse) ? -1 : 1;
applyNC2Functor(
ExecutionSpace{}, arr_, num_qubits, wires,
KOKKOS_LAMBDA(Kokkos::View<Kokkos::complex<PrecisionT> *> arr,
[[maybe_unused]] const std::size_t i00,
const std::size_t i01, const std::size_t i10,
[[maybe_unused]] const std::size_t i11) {
const auto v0 = arr(i01);
const auto v1 = arr(i10);
arr(i01) = Kokkos::complex<PrecisionT>{-imag(v1) * s, real(v1) * s};
arr(i10) = Kokkos::complex<PrecisionT>{-imag(v0) * s, real(v0) * s};
});
}

template <class ExecutionSpace, class PrecisionT>
void applyControlledPhaseShift(Kokkos::View<Kokkos::complex<PrecisionT> *> arr_,
const std::size_t num_qubits,
Expand Down Expand Up @@ -1116,6 +1136,9 @@ void applyNamedOperation(const GateOperation gateop,
case GateOperation::SWAP:
applySWAP<ExecutionSpace>(arr_, num_qubits, wires, inverse, params);
return;
case GateOperation::ISWAP:
applyISWAP<ExecutionSpace>(arr_, num_qubits, wires, inverse, params);
return;
case GateOperation::ControlledPhaseShift:
applyControlledPhaseShift<ExecutionSpace>(arr_, num_qubits, wires,
inverse, params);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ TEMPLATE_TEST_CASE("StateVectorKokkos::applyMatrix/Param-Operation",
const bool inverse = GENERATE(false, true);
const std::string gate_name =
GENERATE("Identity", "PauliX", "PauliY", "PauliZ", "Hadamard", "S", "T",
"CNOT", "SWAP", "CY", "CZ", "CSWAP", "Toffoli");
"CNOT", "SWAP", "ISWAP","CY", "CZ", "CSWAP", "Toffoli");
{
auto gate_matrix = getMatrix<Kokkos::complex, PrecisionT>(
str_to_gates_.at(gate_name), {}, inverse);
Expand Down Expand Up @@ -521,6 +521,103 @@ TEMPLATE_TEST_CASE("StateVectorKokkos::applySWAP",
}
}


TEMPLATE_TEST_CASE("StateVectorKokkos::applyISWAP",
"[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>()};
auto j = ComplexT{IMAG<TestType>()} * i;

SECTION("Apply using dispatcher") {
SECTION("ISWAP 0,1 |+10>") {
const std::vector<ComplexT> expected_results = {z, z, z, z,
j, z, i, z};

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

svdat01.applyOperation("ISWAP", {0, 1}, false);
svdat10.applyOperation("ISWAP", {1, 0}, false);

auto sv01 = Kokkos::create_mirror_view_and_copy(
Kokkos::HostSpace{}, svdat01.getView());
auto sv10 = Kokkos::create_mirror_view_and_copy(
Kokkos::HostSpace{}, svdat10.getView());

for (std::size_t j = 0; j < exp2(num_qubits); j++) {
CHECK(imag(expected_results[j]) == Approx(imag(sv01[j])));
CHECK(real(expected_results[j]) == Approx(real(sv01[j])));
CHECK(imag(expected_results[j]) == Approx(imag(sv10[j])));
CHECK(real(expected_results[j]) == Approx(real(sv10[j])));
}
}
SECTION("ISWAP 0,2 |+10>") {
const std::vector<ComplexT> expected_results = {z, z, i, j,
z, z, z, z};

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

svdat02.applyOperation("ISWAP", {0, 2}, false);
svdat20.applyOperation("ISWAP", {2, 0}, false);

auto sv02 = Kokkos::create_mirror_view_and_copy(
Kokkos::HostSpace{}, svdat02.getView());
auto sv20 = Kokkos::create_mirror_view_and_copy(
Kokkos::HostSpace{}, svdat20.getView());

for (std::size_t j = 0; j < exp2(num_qubits); j++) {
CHECK(imag(expected_results[j]) == Approx(imag(sv02[j])));
CHECK(real(expected_results[j]) == Approx(real(sv02[j])));
CHECK(imag(expected_results[j]) == Approx(imag(sv20[j])));
CHECK(real(expected_results[j]) == Approx(real(sv20[j])));
}
}
SECTION("ISWAP 1,2 |+10>") {
const std::vector<ComplexT> expected_results = {z, j, z, z,
z, j, z, z};

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

svdat12.applyOperation("ISWAP", {1, 2}, false);
svdat21.applyOperation("ISWAP", {2, 1}, false);

auto sv12 = Kokkos::create_mirror_view_and_copy(
Kokkos::HostSpace{}, svdat12.getView());
auto sv21 = Kokkos::create_mirror_view_and_copy(
Kokkos::HostSpace{}, svdat21.getView());

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


TEMPLATE_TEST_CASE("StateVectorKokkos::applyCZ", "[StateVectorKokkos_Nonparam]",
float, double) {
{
Expand Down
Loading