diff --git a/include/algorithms/WState.hpp b/include/algorithms/WState.hpp new file mode 100644 index 000000000..cd879c7a0 --- /dev/null +++ b/include/algorithms/WState.hpp @@ -0,0 +1,10 @@ +#pragma once + +#include + +namespace qc { +class WState : public QuantumComputation { +public: + explicit WState(Qubit nq); +}; +} // namespace qc diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 8d1b64966..2c6fcc9bb 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -28,6 +28,7 @@ if(NOT TARGET ${PROJECT_NAME}) ${PROJECT_SOURCE_DIR}/include/algorithms/QFT.hpp ${PROJECT_SOURCE_DIR}/include/algorithms/QPE.hpp ${PROJECT_SOURCE_DIR}/include/algorithms/RandomCliffordCircuit.hpp + ${PROJECT_SOURCE_DIR}/include/algorithms/WState.hpp ${PROJECT_SOURCE_DIR}/include/CircuitOptimizer.hpp ${PROJECT_SOURCE_DIR}/include/Definitions.hpp ${PROJECT_SOURCE_DIR}/include/operations/Expression.hpp @@ -50,6 +51,7 @@ if(NOT TARGET ${PROJECT_NAME}) algorithms/QFT.cpp algorithms/QPE.cpp algorithms/RandomCliffordCircuit.cpp + algorithms/WState.cpp CircuitOptimizer.cpp operations/Expression.cpp operations/NonUnitaryOperation.cpp diff --git a/src/algorithms/WState.cpp b/src/algorithms/WState.cpp new file mode 100644 index 000000000..db2800ae5 --- /dev/null +++ b/src/algorithms/WState.cpp @@ -0,0 +1,25 @@ +#include "algorithms/WState.hpp" + +namespace qc { +void fGate(QuantumComputation& qc, const Qubit i, const Qubit j, const Qubit k, + const Qubit n) { + const auto theta = std::acos(std::sqrt(1.0 / static_cast(k - n + 1))); + qc.ry(j, -theta); + qc.z(j, qc::Control{i}); + qc.ry(j, theta); +} + +WState::WState(const Qubit nq) : QuantumComputation(nq) { + name = "wstate_" + std::to_string(nq); + + x(nq - 1); + + for (Qubit m = 1; m < nq; m++) { + fGate(*this, nq - m, nq - m - 1, nq, m); + } + + for (Qubit k = nq - 1; k > 0; k--) { + x(k, qc::Control{k - 1}); + } +} +} // namespace qc diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 8af5d51ad..fabbc7b1f 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -25,7 +25,8 @@ package_add_test( algorithms/test_entanglement.cpp algorithms/test_grcs.cpp algorithms/test_random_clifford.cpp - algorithms/test_qpe.cpp) + algorithms/test_qpe.cpp + algorithms/test_wstate.cpp) package_add_test( ${PROJECT_NAME}-test-zx diff --git a/test/algorithms/test_wstate.cpp b/test/algorithms/test_wstate.cpp new file mode 100644 index 000000000..c076b8378 --- /dev/null +++ b/test/algorithms/test_wstate.cpp @@ -0,0 +1,42 @@ +#include "algorithms/WState.hpp" +#include "dd/Simulation.hpp" + +#include "gtest/gtest.h" +#include +#include + +class WState : public testing::TestWithParam {}; + +std::vector generateWStateStrings(const std::size_t length) { + std::vector result; + result.reserve(length); + for (std::size_t i = 0U; i < length; ++i) { + auto binaryString = std::string(length, '0'); + binaryString[i] = '1'; + result.emplace_back(binaryString); + } + return result; +} + +INSTANTIATE_TEST_SUITE_P( + WState, WState, testing::Range(1U, 128U, 7U), + [](const testing::TestParamInfo& inf) { + // Generate names for test cases + const auto nqubits = inf.param; + std::stringstream ss{}; + ss << nqubits << "_qubits"; + return ss.str(); + }); + +TEST_P(WState, FunctionTest) { + const auto nq = GetParam(); + + auto qc = qc::WState(nq); + auto dd = std::make_unique>(qc.getNqubits()); + const std::size_t shots = 1024; + const auto measurements = + simulate(&qc, dd->makeZeroState(qc.getNqubits()), dd, shots); + for (const auto& result : generateWStateStrings(nq)) { + EXPECT_TRUE(measurements.find(result) != measurements.end()); + } +}