diff --git a/.github/workflows/cpp-linter.yml b/.github/workflows/cpp-linter.yml index 3ef8ecb..4e56c8d 100644 --- a/.github/workflows/cpp-linter.yml +++ b/.github/workflows/cpp-linter.yml @@ -39,7 +39,7 @@ jobs: echo $CXX $CC --version $CXX --version - cmake -S . -B build -DBUILD_DD_EVAL_TESTS=ON + cmake -S . -B build -DBUILD_DD_EVAL_TESTS=ON -DBUILD_DD_EVAL_BENCHMARKS=ON - name: Run cpp-linter uses: cpp-linter/cpp-linter-action@v2 diff --git a/CMakeLists.txt b/CMakeLists.txt index 00f41fa..d2ba4e3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -34,3 +34,10 @@ if(BUILD_DD_EVAL_TESTS) include(GoogleTest) add_subdirectory(test) endif() + +option(BUILD_DD_EVAL_BENCHMARKS "Also build benchmarks for DDEval project") +if(BUILD_DD_EVAL_BENCHMARKS) + enable_testing() + include(GoogleTest) + add_subdirectory(benchmarks) +endif() diff --git a/benchmarks/CMakeLists.txt b/benchmarks/CMakeLists.txt new file mode 100644 index 0000000..3530f02 --- /dev/null +++ b/benchmarks/CMakeLists.txt @@ -0,0 +1,16 @@ +if(NOT TARGET gtest OR NOT TARGET gmock) + # Prevent overriding the parent project's compiler/linker settings on Windows + set(gtest_force_shared_crt # cmake-lint: disable=C0103 + ON + CACHE BOOL "" FORCE) + + # store path to googletest in variable + set(GTEST_PATH "extern/ddsim/extern/qfr/extern/dd_package/extern/googletest") + add_subdirectory("${PROJECT_SOURCE_DIR}/${GTEST_PATH}" "${GTEST_PATH}" + EXCLUDE_FROM_ALL) +endif() + +package_add_test( + ${PROJECT_NAME}_sim_benchmark ${PROJECT_NAME} benchmark_simexec_qpe.cpp + benchmark_simexec_ghz.cpp benchmark_simexec_bernstein.cpp + benchmark_simexec_grover.cpp) diff --git a/benchmarks/benchmark_simexec_bernstein.cpp b/benchmarks/benchmark_simexec_bernstein.cpp new file mode 100644 index 0000000..308c721 --- /dev/null +++ b/benchmarks/benchmark_simexec_bernstein.cpp @@ -0,0 +1,60 @@ +#include "QuantumComputation.hpp" +#include "algorithms/BernsteinVazirani.hpp" +#include "executors/CircuitSimulatorExecutor.hpp" +#include "executors/HybridSimulatorExecutor.hpp" +#include "executors/StochasticNoiseSimulatorExecutor.hpp" +#include "tasks/SimulationTask.hpp" + +#include "gtest/gtest.h" + +TEST(SimExecBenchmarkBerstein, HybridSimulatorAmplitudeExec) { + auto hybridSimulatorAmplitudeExecutor = + std::make_unique(); + std::size_t const n = 25; + auto qc = std::make_unique(n, false); + SimulationTask const simulationTask(std::move(qc)); + const auto result = hybridSimulatorAmplitudeExecutor->execute(simulationTask); + std::cout << result << "\n"; + EXPECT_TRUE(result["construction_time"].get() + + result["execution_time"].get() > + 1000000); + EXPECT_TRUE(result["construction_time"].get() + + result["execution_time"].get() < + 300000000); +} + +TEST(SimExecBenchmarkBerstein, HybridSimulatorDDExec) { + auto hybridSimulatorDDExecutor = std::make_unique(); + hybridSimulatorDDExecutor->setRunAmplitude(false); + hybridSimulatorDDExecutor->setRunDd(true); + std::size_t const n = 40; + auto qc = std::make_unique(n, false); + SimulationTask const simulationTask(std::move(qc)); + const auto result = hybridSimulatorDDExecutor->execute(simulationTask); + std::cout << result << "\n"; + EXPECT_TRUE(result["construction_time"].get() + + result["execution_time"].get() > + 1000000); + EXPECT_TRUE(result["construction_time"].get() + + result["execution_time"].get() < + 300000000); +} + +TEST(SimExecBenchmarkBerstein, StochasticNoiseSimulatorExec) { + auto stochasticNoiseSimulatorExecutor = + std::make_unique(); + std::size_t const n = 30; + auto qc = std::make_unique(n, false); + SimulationTask const simulationTask(std::move(qc)); + const auto result = stochasticNoiseSimulatorExecutor->execute(simulationTask); + std::cout << result << "\n"; + EXPECT_TRUE(result["construction_time"].get() + + result["execution_time"].get() > + 1000000); + EXPECT_TRUE(result["construction_time"].get() + + result["execution_time"].get() < + 300000000); +} + +// Gives "C++ exception with description "Unsupported non-unitary functionality +// 'Rst '." thrown in the test body." when run in dynamic diff --git a/benchmarks/benchmark_simexec_ghz.cpp b/benchmarks/benchmark_simexec_ghz.cpp new file mode 100644 index 0000000..7f3c47f --- /dev/null +++ b/benchmarks/benchmark_simexec_ghz.cpp @@ -0,0 +1,39 @@ +#include "QuantumComputation.hpp" +#include "algorithms/Entanglement.hpp" +#include "executors/CircuitSimulatorExecutor.hpp" +#include "executors/DeterministicNoiseSimExecutor.hpp" +#include "executors/HybridSimulatorExecutor.hpp" +#include "tasks/SimulationTask.hpp" + +#include "gtest/gtest.h" + +TEST(SimExecBenchmarkGHZ, HybridSimulatorAmplitudeExec) { + auto hybridSimulatorAmplitudeExecutor = + std::make_unique(); + auto qc = std::make_unique(25); + SimulationTask const simulationTask(std::move(qc)); + const auto result = hybridSimulatorAmplitudeExecutor->execute(simulationTask); + std::cout << result << "\n"; + EXPECT_TRUE(result["construction_time"].get() + + result["execution_time"].get() > + 1000000); + EXPECT_TRUE(result["construction_time"].get() + + result["execution_time"].get() < + 300000000); +} + +TEST(SimExecBenchmarkGHZ, DeterministicNoiseSimExec) { + auto deterministicNoiseSimulatorExecutor = + std::make_unique(); + auto qc = std::make_unique(20); + SimulationTask const simulationTask(std::move(qc)); + const auto result = + deterministicNoiseSimulatorExecutor->execute(simulationTask); + std::cout << result << "\n"; + EXPECT_TRUE(result["construction_time"].get() + + result["execution_time"].get() > + 1000000); + EXPECT_TRUE(result["construction_time"].get() + + result["execution_time"].get() < + 300000000); +} diff --git a/benchmarks/benchmark_simexec_grover.cpp b/benchmarks/benchmark_simexec_grover.cpp new file mode 100644 index 0000000..4d2c211 --- /dev/null +++ b/benchmarks/benchmark_simexec_grover.cpp @@ -0,0 +1,56 @@ +#include "QuantumComputation.hpp" +#include "algorithms/Grover.hpp" +#include "executors/CircuitSimulatorExecutor.hpp" +#include "executors/UnitarySimulatorExecutor.hpp" +#include "tasks/SimulationTask.hpp" + +#include "gtest/gtest.h" + +TEST(SimExecBenchmarkGrover, CircuitSimulatorExec) { + auto circuitSimulatorExecutor = std::make_unique(); + std::size_t const n = 25; + auto qc = std::make_unique(n); + SimulationTask const simulationTask(std::move(qc)); + const auto result = circuitSimulatorExecutor->execute(simulationTask); + std::cout << result << "\n"; + EXPECT_TRUE(result["construction_time"].get() + + result["execution_time"].get() > + 1000000); + EXPECT_TRUE(result["construction_time"].get() + + result["execution_time"].get() < + 300000000); +} + +TEST(SimExecBenchmarkGrover, UnitarySimSequentialExec) { + auto unitarySimSequentialExecutor = + std::make_unique(); + unitarySimSequentialExecutor->setRecursive(false); + unitarySimSequentialExecutor->setSequential(true); + std::size_t const n = 22; + auto qc = std::make_unique(n); + SimulationTask const simulationTask(std::move(qc)); + const auto result = unitarySimSequentialExecutor->execute(simulationTask); + std::cout << result << "\n"; + EXPECT_TRUE(result["construction_time"].get() + + result["execution_time"].get() > + 1000000); + EXPECT_TRUE(result["construction_time"].get() + + result["execution_time"].get() < + 300000000); +} + +TEST(SimExecBenchmarkGrover, UnitarySimRecursiveExec) { + auto unitarySimRecursiveExecutor = + std::make_unique(); + std::size_t const n = 22; + auto qc = std::make_unique(n); + SimulationTask const simulationTask(std::move(qc)); + const auto result = unitarySimRecursiveExecutor->execute(simulationTask); + std::cout << result << "\n"; + EXPECT_TRUE(result["construction_time"].get() + + result["execution_time"].get() > + 1000000); + EXPECT_TRUE(result["construction_time"].get() + + result["execution_time"].get() < + 300000000); +} diff --git a/benchmarks/benchmark_simexec_qpe.cpp b/benchmarks/benchmark_simexec_qpe.cpp new file mode 100644 index 0000000..b9b068e --- /dev/null +++ b/benchmarks/benchmark_simexec_qpe.cpp @@ -0,0 +1,39 @@ +#include "algorithms/QPE.hpp" +#include "executors/CircuitSimulatorExecutor.hpp" +#include "executors/UnitarySimulatorExecutor.hpp" +#include "tasks/SimulationTask.hpp" + +#include "gtest/gtest.h" + +// QPE fails from n=65 on in ComplexTable line 151. See if later versions of the +// dd package can fix this. + +TEST(SimExecBenchmarkQPE, CircuitSimulatorExec) { + auto circuitSimulatorExecutor = std::make_unique(); + std::size_t const n = 65; + auto qc = std::make_unique(n, true, false); + SimulationTask const simulationTask(std::move(qc)); + EXPECT_DEATH(circuitSimulatorExecutor->execute(simulationTask), "Assertion"); +} + +TEST(SimExecBenchmarkQPE, UnitarySimRecursiveExec) { + auto unitarySimRecursiveExecutor = + std::make_unique(); + std::size_t const n = 65; + auto qc = std::make_unique(n, true, false); + SimulationTask const simulationTask(std::move(qc)); + EXPECT_DEATH(unitarySimRecursiveExecutor->execute(simulationTask), + "Assertion"); +} + +TEST(SimExecBenchmarkQPE, UnitarySimSequentialExec) { + auto unitarySimSequentialExecutor = + std::make_unique(); + unitarySimSequentialExecutor->setRecursive(false); + unitarySimSequentialExecutor->setSequential(true); + std::size_t const n = 65; + auto qc = std::make_unique(n, true, false); + SimulationTask const simulationTask(std::move(qc)); + EXPECT_DEATH(unitarySimSequentialExecutor->execute(simulationTask), + "Assertion"); +} diff --git a/extern/ddsim b/extern/ddsim index cd26ed9..d4a57ae 160000 --- a/extern/ddsim +++ b/extern/ddsim @@ -1 +1 @@ -Subproject commit cd26ed904162d154200af1ddee53d0ae28e19618 +Subproject commit d4a57ae91fc7884c7c646f5c58a28ecac4ba387b diff --git a/include/Executor.hpp b/include/Executor.hpp index 4879301..49b8f8c 100644 --- a/include/Executor.hpp +++ b/include/Executor.hpp @@ -1,5 +1,9 @@ #pragma once +namespace constants { +const int GLOBAL_SEED = 15; +} + #include "Task.hpp" #include diff --git a/include/SimulationExecutor.hpp b/include/SimulationExecutor.hpp new file mode 100644 index 0000000..d84833d --- /dev/null +++ b/include/SimulationExecutor.hpp @@ -0,0 +1,40 @@ +#pragma once + +#include "Executor.hpp" +#include "QuantumComputation.hpp" +#include "Simulator.hpp" +#include "tasks/SimulationTask.hpp" + +template class SimulationExecutor : public Executor { + // static_assert(std::is_base_of_v, S>); + // How to use this while disregarding the template parameter of the + // Simulator class? +public: + virtual std::unique_ptr + constructSimulator(std::unique_ptr& qc) = 0; + + virtual json runSimulator(std::unique_ptr simulator) = 0; + + json execute(const SimulationTask& task) override { + auto qc = std::make_unique(task.getQc()->clone()); + auto const constructionStart = std::chrono::steady_clock::now(); + auto simulator = constructSimulator(qc); + auto const executionStart = std::chrono::steady_clock::now(); + + json result = runSimulator(std::move(simulator)); + auto const executionStop = std::chrono::steady_clock::now(); + // Add memory usage + + auto const constructionTime = + std::chrono::duration_cast( + executionStart - constructionStart); + auto const execTime = std::chrono::duration_cast( + executionStop - executionStart); + result["construction_time"] = constructionTime.count(); + result["execution_time"] = execTime.count(); + result["executor"] = getIdentifier(); + result["task"] = task.getIdentifier(); + + return result; + }; +}; diff --git a/include/executors/CircuitSimulatorExecutor.hpp b/include/executors/CircuitSimulatorExecutor.hpp index 10987af..461e1ae 100644 --- a/include/executors/CircuitSimulatorExecutor.hpp +++ b/include/executors/CircuitSimulatorExecutor.hpp @@ -1,13 +1,16 @@ #pragma once -#include "Executor.hpp" -#include "tasks/SimulationTask.hpp" +#include "CircuitSimulator.hpp" +#include "SimulationExecutor.hpp" -class CircuitSimulatorExecutor : public Executor { +class CircuitSimulatorExecutor : public SimulationExecutor> { public: - json execute(const SimulationTask& task) override; - [[nodiscard]] std::string getIdentifier() const override { return "circuit_simulator"; }; + + std::unique_ptr> + constructSimulator(std::unique_ptr& qc) override; + + json runSimulator(std::unique_ptr> simulator) override; }; diff --git a/include/executors/DeterministicNoiseSimExecutor.hpp b/include/executors/DeterministicNoiseSimExecutor.hpp new file mode 100644 index 0000000..978d17c --- /dev/null +++ b/include/executors/DeterministicNoiseSimExecutor.hpp @@ -0,0 +1,18 @@ +#pragma once + +#include "DeterministicNoiseSimulator.hpp" +#include "SimulationExecutor.hpp" + +class DeterministicNoiseSimExecutor + : public SimulationExecutor> { +public: + [[nodiscard]] std::string getIdentifier() const override { + return "deterministic_noise_simulator"; + } + + std::unique_ptr> + constructSimulator(std::unique_ptr& qc) override; + + json runSimulator( + std::unique_ptr> simulator) override; +}; diff --git a/include/executors/HybridSimulatorExecutor.hpp b/include/executors/HybridSimulatorExecutor.hpp new file mode 100644 index 0000000..f392b7b --- /dev/null +++ b/include/executors/HybridSimulatorExecutor.hpp @@ -0,0 +1,33 @@ +#pragma once + +#include "HybridSchrodingerFeynmanSimulator.hpp" +#include "SimulationExecutor.hpp" + +class HybridSimulatorExecutor + : public SimulationExecutor> { +public: + [[nodiscard]] std::string getIdentifier() const override { + if (runDD) { + return "hybrid_schrodinger_feynman_simulator_dd"; + } + return "hybrid_schrodinger_feynman_simulator_amplitude"; + }; + + std::unique_ptr> + constructSimulator(std::unique_ptr& qc) override; + + json runSimulator( + std::unique_ptr> simulator) override; + + [[nodiscard]] bool isRunAmplitude() const { return runAmplitude; } + + void setRunAmplitude(bool run) { runAmplitude = run; } + + [[nodiscard]] bool isRunDd() const { return runDD; } + + void setRunDd(bool run) { runDD = run; } + +private: + bool runAmplitude = true; + bool runDD = false; +}; diff --git a/include/executors/StochasticNoiseSimulatorExecutor.hpp b/include/executors/StochasticNoiseSimulatorExecutor.hpp new file mode 100644 index 0000000..53d25e2 --- /dev/null +++ b/include/executors/StochasticNoiseSimulatorExecutor.hpp @@ -0,0 +1,18 @@ +#pragma once + +#include "SimulationExecutor.hpp" +#include "StochasticNoiseSimulator.hpp" + +class StochasticNoiseSimulatorExecutor + : public SimulationExecutor> { +public: + [[nodiscard]] std::string getIdentifier() const override { + return "stochastic_noise_simulator"; + }; + + std::unique_ptr> + constructSimulator(std::unique_ptr& qc) override; + + json + runSimulator(std::unique_ptr> simulator) override; +}; diff --git a/include/executors/UnitarySimulatorExecutor.hpp b/include/executors/UnitarySimulatorExecutor.hpp new file mode 100644 index 0000000..c2af4a3 --- /dev/null +++ b/include/executors/UnitarySimulatorExecutor.hpp @@ -0,0 +1,31 @@ +#pragma once + +#include "SimulationExecutor.hpp" +#include "UnitarySimulator.hpp" + +class UnitarySimulatorExecutor : public SimulationExecutor> { +public: + std::unique_ptr> + constructSimulator(std::unique_ptr& qc) override; + + json runSimulator(std::unique_ptr> simulator) override; + + [[nodiscard]] std::string getIdentifier() const override { + if (sequential) { + return "unitary_simulator_sequential"; + } + return "unitary_simulator_recursive"; + }; + + [[nodiscard]] bool isSequential() const { return sequential; } + + void setSequential(bool run) { sequential = run; } + + [[nodiscard]] bool isRecursive() const { return recursive; } + + void setRecursive(bool run) { recursive = run; } + +private: + bool sequential = false; + bool recursive = true; +}; diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 9dce18f..02314b3 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -10,16 +10,24 @@ if(NOT TARGET ${PROJECT_NAME}) add_library( ${PROJECT_NAME} ${PROJECT_SOURCE_DIR}/include/Executor.hpp + ${PROJECT_SOURCE_DIR}/include/SimulationExecutor.hpp ${PROJECT_SOURCE_DIR}/include/executors/CircuitSimulatorExecutor.hpp ${PROJECT_SOURCE_DIR}/include/executors/AlternatingVerificationExecutor.hpp + ${PROJECT_SOURCE_DIR}/include/executors/HybridSimulatorExecutor.hpp + ${PROJECT_SOURCE_DIR}/include/executors/DeterministicNoiseSimExecutor.hpp + ${PROJECT_SOURCE_DIR}/include/executors/StochasticNoiseSimulatorExecutor.hpp + ${PROJECT_SOURCE_DIR}/include/executors/UnitarySimulatorExecutor.hpp ${PROJECT_SOURCE_DIR}/include/Task.hpp ${PROJECT_SOURCE_DIR}/include/tasks/SimulationTask.hpp ${PROJECT_SOURCE_DIR}/include/tasks/VerificationTask.hpp executors/CircuitSimulatorExecutor.cpp executors/AlternatingVerificationExecutor.cpp + executors/HybridSimulatorExecutor.cpp + executors/DeterministicNoiseSimExecutor.cpp + executors/StochasticNoiseSimulatorExecutor.cpp + executors/UnitarySimulatorExecutor.cpp tasks/SimulationTask.cpp tasks/VerificationTask.cpp) - # set include directories target_include_directories( ${PROJECT_NAME} PUBLIC ${PROJECT_SOURCE_DIR}/include diff --git a/src/executors/CircuitSimulatorExecutor.cpp b/src/executors/CircuitSimulatorExecutor.cpp index 367989a..7fcd3d7 100644 --- a/src/executors/CircuitSimulatorExecutor.cpp +++ b/src/executors/CircuitSimulatorExecutor.cpp @@ -1,30 +1,18 @@ #include "executors/CircuitSimulatorExecutor.hpp" -#include "CircuitSimulator.hpp" +std::unique_ptr> +CircuitSimulatorExecutor::constructSimulator( + std::unique_ptr& qc) { + auto circuitSimulator = std::make_unique>( + std::move(qc), constants::GLOBAL_SEED); -json CircuitSimulatorExecutor::execute(const SimulationTask& task) { - json result; - auto const constructionStart = std::chrono::steady_clock::now(); - - auto qc = std::make_unique(task.getQc()->clone()); - auto circuitSimulator = std::make_unique>(std::move(qc)); - - auto const executionStart = std::chrono::steady_clock::now(); - - result["measurement_results"] = circuitSimulator->simulate(1024U); - // Add memory usage - - auto const executionStop = std::chrono::steady_clock::now(); - auto const constructionTime = - std::chrono::duration_cast(executionStart - - constructionStart); - auto const execTime = std::chrono::duration_cast( - executionStop - executionStart); - result["construction_time"] = constructionTime.count(); - result["execution_time"] = execTime.count(); - - result["executor"] = getIdentifier(); - result["task"] = task.getIdentifier(); + return circuitSimulator; +} +json CircuitSimulatorExecutor::runSimulator( + std::unique_ptr> simulator) { + json result; + auto results = simulator->simulate(1024U); + result["measurement_results"] = results; return result; } diff --git a/src/executors/DeterministicNoiseSimExecutor.cpp b/src/executors/DeterministicNoiseSimExecutor.cpp new file mode 100644 index 0000000..6f3c6b3 --- /dev/null +++ b/src/executors/DeterministicNoiseSimExecutor.cpp @@ -0,0 +1,18 @@ +#include "executors/DeterministicNoiseSimExecutor.hpp" + +std::unique_ptr> +DeterministicNoiseSimExecutor::constructSimulator( + std::unique_ptr& qc) { + auto deterministicNoiseSimulator = + std::make_unique>(std::move(qc), + constants::GLOBAL_SEED); + return deterministicNoiseSimulator; +} + +json DeterministicNoiseSimExecutor::runSimulator( + std::unique_ptr> simulator) { + json result; + auto results = simulator->deterministicSimulate(); + result["measurement_results"] = results; + return result; +} diff --git a/src/executors/HybridSimulatorExecutor.cpp b/src/executors/HybridSimulatorExecutor.cpp new file mode 100644 index 0000000..fb50867 --- /dev/null +++ b/src/executors/HybridSimulatorExecutor.cpp @@ -0,0 +1,24 @@ +#include "executors/HybridSimulatorExecutor.hpp" + +std::unique_ptr> +HybridSimulatorExecutor::constructSimulator( + std::unique_ptr& qc) { + std::unique_ptr> hybridSimulator; + if (this->isRunAmplitude()) { + hybridSimulator = std::make_unique>( + std::move(qc), ApproximationInfo{}, constants::GLOBAL_SEED); + } else { + hybridSimulator = std::make_unique>( + std::move(qc), ApproximationInfo{}, constants::GLOBAL_SEED, + HybridSchrodingerFeynmanSimulator<>::Mode::DD); + } + return hybridSimulator; +} + +json HybridSimulatorExecutor::runSimulator( + std::unique_ptr> simulator) { + json result; + auto results = simulator->simulate(1024U); + result["measurement_results"] = results; + return result; +} diff --git a/src/executors/StochasticNoiseSimulatorExecutor.cpp b/src/executors/StochasticNoiseSimulatorExecutor.cpp new file mode 100644 index 0000000..53d3165 --- /dev/null +++ b/src/executors/StochasticNoiseSimulatorExecutor.cpp @@ -0,0 +1,17 @@ +#include "executors/StochasticNoiseSimulatorExecutor.hpp" + +std::unique_ptr> +StochasticNoiseSimulatorExecutor::constructSimulator( + std::unique_ptr& qc) { + auto stochasticNoiseSimulator = std::make_unique>( + std::move(qc), 1, 1, constants::GLOBAL_SEED); + return stochasticNoiseSimulator; +} + +json StochasticNoiseSimulatorExecutor::runSimulator( + std::unique_ptr> simulator) { + json result; + auto results = simulator->simulate(1024U); + result["measurement_results"] = results; + return result; +} diff --git a/src/executors/UnitarySimulatorExecutor.cpp b/src/executors/UnitarySimulatorExecutor.cpp new file mode 100644 index 0000000..66a9abf --- /dev/null +++ b/src/executors/UnitarySimulatorExecutor.cpp @@ -0,0 +1,26 @@ +#include "executors/UnitarySimulatorExecutor.hpp" + +std::unique_ptr> +UnitarySimulatorExecutor::constructSimulator( + std::unique_ptr& qc) { + std::unique_ptr> unitarySimulator; + if (this->recursive) { + unitarySimulator = std::make_unique>( + std::move(qc), ApproximationInfo{}, constants::GLOBAL_SEED); + } else { + unitarySimulator = std::make_unique>( + std::move(qc), ApproximationInfo{}, constants::GLOBAL_SEED, + UnitarySimulator<>::Mode::Sequential); + } + return unitarySimulator; +} + +json UnitarySimulatorExecutor::runSimulator( + std::unique_ptr> simulator) { + json result; + simulator->construct(); + result["final_node_count"] = simulator->getFinalNodeCount(); + result["max_node_count"] = simulator->getMaxNodeCount(); + result["unitary_execution_time"] = simulator->getConstructionTime(); + return result; +} diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index d51742c..b945610 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -13,5 +13,15 @@ configure_file(${CMAKE_SOURCE_DIR}/test/sim_circuits.json ${CMAKE_CURRENT_BINARY_DIR}/sim_circuits.json COPYONLY) configure_file(${CMAKE_SOURCE_DIR}/test/ver_circuits.json ${CMAKE_CURRENT_BINARY_DIR}/ver_circuits.json COPYONLY) -package_add_test(${PROJECT_NAME}_sim_test ${PROJECT_NAME} test_simexec.cpp) +package_add_test( + ${PROJECT_NAME}_sim_test + ${PROJECT_NAME} + test_simexec_simple.cpp + test_circ_sim_exec.cpp + test_deter_noise_sim_exec.cpp + test_stoch_noise_sim_exec.cpp + test_hybrid_sim_exec.cpp + test_hybrid_sim_exec_dd.cpp + test_uni_sim_exec.cpp + test_uni_sim_exec_seq.cpp) package_add_test(${PROJECT_NAME}_ver_test ${PROJECT_NAME} test_qcecexec.cpp) diff --git a/test/sim_circuits.json b/test/sim_circuits.json index dd73f45..8249d25 100644 --- a/test/sim_circuits.json +++ b/test/sim_circuits.json @@ -4,7 +4,7 @@ "circuit": "OPENQASM 2.0;include \"qelib1.inc\";qreg q[2];x q[0];x q[1];\n" }, { - "description": "two_qubit_circuit_with_h_z_controlled_x_swap", - "circuit": "OPENQASM 2.0;include \"qelib1.inc\";qreg q[2];cx q[0], q[1];h q[0];z q[0];h q[0];swap q[0], q[1];\n" + "description": "two_qubit_circuit_with_h_z_controlled_x", + "circuit": "OPENQASM 2.0;include \"qelib1.inc\";qreg q[2];cx q[0], q[1];h q[0];z q[0];h q[0];\n" } ] diff --git a/test/test_circ_sim_exec.cpp b/test/test_circ_sim_exec.cpp new file mode 100644 index 0000000..909184f --- /dev/null +++ b/test/test_circ_sim_exec.cpp @@ -0,0 +1,105 @@ +#include "algorithms/BernsteinVazirani.hpp" +#include "algorithms/Entanglement.hpp" +#include "algorithms/Grover.hpp" +#include "algorithms/QPE.hpp" +#include "algorithms/RandomCliffordCircuit.hpp" +#include "algorithms/WState.hpp" +#include "executors/CircuitSimulatorExecutor.hpp" + +#include "gtest/gtest.h" + +class CircSimExecTest : public testing::Test { +protected: + void TearDown() override {} + void SetUp() override {} +}; + +TEST_F(CircSimExecTest, GHZ) { + auto circuitSimulatorExecutor = std::make_unique(); + std::size_t const n = 5; + auto qc = std::make_unique(n); + SimulationTask const simulationTask(std::move(qc)); + const auto result = circuitSimulatorExecutor->execute(simulationTask); + std::cout << result << "\n"; +} + +TEST_F(CircSimExecTest, BernsteinVazirani) { + auto circSimExec = std::make_unique(); + std::size_t const n = 3; + auto qc = std::make_unique(n, false); + SimulationTask const simulationTask(std::move(qc)); + const auto result = circSimExec->execute(simulationTask); + std::cout << result << "\n"; +} + +TEST_F(CircSimExecTest, BernsteinVaziraniDyn) { + auto circSimExecDyn = std::make_unique(); + std::size_t const n = 4; + auto qc = std::make_unique(n, true); + SimulationTask const simulationTask(std::move(qc)); + const auto result = circSimExecDyn->execute(simulationTask); + std::cout << result << "\n"; +} + +TEST_F(CircSimExecTest, QPEExact) { + auto circuitSimulatorExecutor = std::make_unique(); + std::size_t const n = 3; + auto qc = std::make_unique(n, true, false); + SimulationTask const simulationTask(std::move(qc)); + const auto result = circuitSimulatorExecutor->execute(simulationTask); + std::cout << result << "\n"; +} + +TEST_F(CircSimExecTest, QPEInexact) { + auto circuitSimulatorExecutor = std::make_unique(); + std::size_t const n = 4; + auto qc = std::make_unique(n, false, false); + SimulationTask const simulationTask(std::move(qc)); + const auto result = circuitSimulatorExecutor->execute(simulationTask); + std::cout << result << "\n"; +} + +TEST_F(CircSimExecTest, QPEExactDyn) { + auto circuitSimulatorExecutor = std::make_unique(); + std::size_t const n = 5; + auto qc = std::make_unique(n, true, true); + SimulationTask const simulationTask(std::move(qc)); + const auto result = circuitSimulatorExecutor->execute(simulationTask); + std::cout << result << "\n"; +} + +TEST_F(CircSimExecTest, QPEInexactDyn) { + auto circuitSimulatorExecutor = std::make_unique(); + std::size_t const n = 4; + auto qc = std::make_unique(n, false, true); + SimulationTask const simulationTask(std::move(qc)); + const auto result = circuitSimulatorExecutor->execute(simulationTask); + std::cout << result << "\n"; +} + +TEST_F(CircSimExecTest, Grover) { + auto circuitSimulatorExecutor = std::make_unique(); + std::size_t const n = 7; + auto qc = std::make_unique(n); + SimulationTask const simulationTask(std::move(qc)); + const auto result = circuitSimulatorExecutor->execute(simulationTask); + std::cout << result << "\n"; +} + +TEST_F(CircSimExecTest, RandomCliffordCircuit) { + auto circuitSimulatorExecutor = std::make_unique(); + std::size_t const n = 7; + auto qc = std::make_unique(n); + SimulationTask const simulationTask(std::move(qc)); + const auto result = circuitSimulatorExecutor->execute(simulationTask); + std::cout << result << "\n"; +} + +TEST_F(CircSimExecTest, WState) { + auto circuitSimulatorExecutor = std::make_unique(); + std::size_t const n = 6; + auto qc = std::make_unique(n); + SimulationTask const simulationTask(std::move(qc)); + const auto result = circuitSimulatorExecutor->execute(simulationTask); + std::cout << result << "\n"; +} diff --git a/test/test_deter_noise_sim_exec.cpp b/test/test_deter_noise_sim_exec.cpp new file mode 100644 index 0000000..d28e759 --- /dev/null +++ b/test/test_deter_noise_sim_exec.cpp @@ -0,0 +1,43 @@ +#include "algorithms/BernsteinVazirani.hpp" +#include "algorithms/Entanglement.hpp" +#include "algorithms/RandomCliffordCircuit.hpp" +#include "algorithms/WState.hpp" +#include "executors/DeterministicNoiseSimExecutor.hpp" + +#include "gtest/gtest.h" + +// Failed for BV, QPE and Grover with error message "Unsupported non-unitary +// functionality: "meas"" + +class DeterNoiseSimExecTest : public testing::Test { +protected: + void TearDown() override {} + void SetUp() override {} +}; + +TEST_F(DeterNoiseSimExecTest, GHZ) { + auto simulator = std::make_unique(); + std::size_t const n = 5; + auto qc = std::make_unique(n); + SimulationTask const simulationTask(std::move(qc)); + const auto result = simulator->execute(simulationTask); + std::cout << result << "\n"; +} + +TEST_F(DeterNoiseSimExecTest, RandomCliffordCircuit) { + auto simulator = std::make_unique(); + std::size_t const n = 7; + auto qc = std::make_unique(n); + SimulationTask const simulationTask(std::move(qc)); + const auto result = simulator->execute(simulationTask); + std::cout << result << "\n"; +} + +TEST_F(DeterNoiseSimExecTest, WState) { + auto simulator = std::make_unique(); + std::size_t const n = 6; + auto qc = std::make_unique(n); + SimulationTask const simulationTask(std::move(qc)); + const auto result = simulator->execute(simulationTask); + std::cout << result << "\n"; +} diff --git a/test/test_hybrid_sim_exec.cpp b/test/test_hybrid_sim_exec.cpp new file mode 100644 index 0000000..87230c3 --- /dev/null +++ b/test/test_hybrid_sim_exec.cpp @@ -0,0 +1,71 @@ +#include "algorithms/BernsteinVazirani.hpp" +#include "algorithms/Entanglement.hpp" +#include "algorithms/Grover.hpp" +#include "algorithms/QPE.hpp" +#include "algorithms/WState.hpp" +#include "executors/HybridSimulatorExecutor.hpp" + +#include "gtest/gtest.h" + +// Failed for RandomCliffordCircuit with error message "Only StandardOperations +// are supported for now." + +class HybridSimExecTest : public testing::Test { +protected: + void TearDown() override {} + void SetUp() override {} +}; + +TEST_F(HybridSimExecTest, GHZ) { + auto simulator = std::make_unique(); + std::size_t const n = 5; + auto qc = std::make_unique(n); + SimulationTask const simulationTask(std::move(qc)); + const auto result = simulator->execute(simulationTask); + std::cout << result << "\n"; +} + +TEST_F(HybridSimExecTest, BernsteinVazirani) { + auto simulator = std::make_unique(); + std::size_t const n = 3; + auto qc = std::make_unique(n, false); + SimulationTask const simulationTask(std::move(qc)); + const auto result = simulator->execute(simulationTask); + std::cout << result << "\n"; +} + +TEST_F(HybridSimExecTest, QPEExact) { + auto simulator = std::make_unique(); + std::size_t const n = 3; + auto qc = std::make_unique(n, true, false); + SimulationTask const simulationTask(std::move(qc)); + const auto result = simulator->execute(simulationTask); + std::cout << result << "\n"; +} + +TEST_F(HybridSimExecTest, QPEInexact) { + auto simulator = std::make_unique(); + std::size_t const n = 4; + auto qc = std::make_unique(n, false, false); + SimulationTask const simulationTask(std::move(qc)); + const auto result = simulator->execute(simulationTask); + std::cout << result << "\n"; +} + +TEST_F(HybridSimExecTest, Grover) { + auto simulator = std::make_unique(); + std::size_t const n = 2; + auto qc = std::make_unique(n); + SimulationTask const simulationTask(std::move(qc)); + const auto result = simulator->execute(simulationTask); + std::cout << result << "\n"; +} + +TEST_F(HybridSimExecTest, WState) { + auto simulator = std::make_unique(); + std::size_t const n = 6; + auto qc = std::make_unique(n); + SimulationTask const simulationTask(std::move(qc)); + const auto result = simulator->execute(simulationTask); + std::cout << result << "\n"; +} diff --git a/test/test_hybrid_sim_exec_dd.cpp b/test/test_hybrid_sim_exec_dd.cpp new file mode 100644 index 0000000..61e31b0 --- /dev/null +++ b/test/test_hybrid_sim_exec_dd.cpp @@ -0,0 +1,83 @@ +#include "algorithms/BernsteinVazirani.hpp" +#include "algorithms/Entanglement.hpp" +#include "algorithms/Grover.hpp" +#include "algorithms/QPE.hpp" +#include "algorithms/WState.hpp" +#include "executors/HybridSimulatorExecutor.hpp" + +#include "gtest/gtest.h" + +// Failed for RandomCliffordCircuit with error message "Only StandardOperations +// are supported for now." + +class HybridSimExecTestDD : public testing::Test { +protected: + void TearDown() override {} + void SetUp() override {} +}; + +TEST_F(HybridSimExecTestDD, GHZ) { + auto simulator = std::make_unique(); + simulator->setRunAmplitude(false); + simulator->setRunDd(true); + std::size_t const n = 5; + auto qc = std::make_unique(n); + SimulationTask const simulationTask(std::move(qc)); + const auto result = simulator->execute(simulationTask); + std::cout << result << "\n"; +} + +TEST_F(HybridSimExecTestDD, BernsteinVazirani) { + auto simulator = std::make_unique(); + simulator->setRunAmplitude(false); + simulator->setRunDd(true); + std::size_t const n = 3; + auto qc = std::make_unique(n, false); + SimulationTask const simulationTask(std::move(qc)); + const auto result = simulator->execute(simulationTask); + std::cout << result << "\n"; +} + +TEST_F(HybridSimExecTestDD, QPEExact) { + auto simulator = std::make_unique(); + simulator->setRunAmplitude(false); + simulator->setRunDd(true); + std::size_t const n = 3; + auto qc = std::make_unique(n, true, false); + SimulationTask const simulationTask(std::move(qc)); + const auto result = simulator->execute(simulationTask); + std::cout << result << "\n"; +} + +TEST_F(HybridSimExecTestDD, QPEInexact) { + auto simulator = std::make_unique(); + simulator->setRunAmplitude(false); + simulator->setRunDd(true); + std::size_t const n = 4; + auto qc = std::make_unique(n, false, false); + SimulationTask const simulationTask(std::move(qc)); + const auto result = simulator->execute(simulationTask); + std::cout << result << "\n"; +} + +TEST_F(HybridSimExecTestDD, Grover) { + auto simulator = std::make_unique(); + simulator->setRunAmplitude(false); + simulator->setRunDd(true); + std::size_t const n = 2; + auto qc = std::make_unique(n); + SimulationTask const simulationTask(std::move(qc)); + const auto result = simulator->execute(simulationTask); + std::cout << result << "\n"; +} + +TEST_F(HybridSimExecTestDD, WState) { + auto simulator = std::make_unique(); + simulator->setRunAmplitude(false); + simulator->setRunDd(true); + std::size_t const n = 6; + auto qc = std::make_unique(n); + SimulationTask const simulationTask(std::move(qc)); + const auto result = simulator->execute(simulationTask); + std::cout << result << "\n"; +} diff --git a/test/test_simexec.cpp b/test/test_simexec.cpp deleted file mode 100644 index 4f740cd..0000000 --- a/test/test_simexec.cpp +++ /dev/null @@ -1,62 +0,0 @@ -#include "QuantumComputation.hpp" -#include "executors/CircuitSimulatorExecutor.hpp" -#include "tasks/SimulationTask.hpp" - -#include "gtest/gtest.h" - -struct TestConfigurationDDSIM { - // given input - std::string description; - std::string circuit; -}; - -// NOLINTNEXTLINE (readability-identifier-naming) -inline void from_json(const nlohmann::json& j, TestConfigurationDDSIM& test) { - test.description = j.at("description").get(); - test.circuit = j.at("circuit").get(); -} - -namespace { -std::vector getTests(const std::string& path) { - std::ifstream input(path); - nlohmann::json j; - input >> j; - return j; -} -} // namespace - -class DDSIMExecTest : public ::testing::TestWithParam { -protected: - void SetUp() override { - test = GetParam(); - std::stringstream ss(test.circuit); - - auto qc = std::make_unique(); - qc->import(ss, qc::Format::OpenQASM); - std::cout << "Circuit:\n" << *qc; - - simulationTask = SimulationTask(std::move(qc)); - circuitSimulatorExecutor = std::make_unique(); - } - - SimulationTask simulationTask; - std::unique_ptr circuitSimulatorExecutor; - TestConfigurationDDSIM test; -}; - -INSTANTIATE_TEST_SUITE_P( - Circuits, DDSIMExecTest, testing::ValuesIn(getTests("sim_circuits.json")), - [](const testing::TestParamInfo& inf) { - return inf.param.description; - }); - -TEST_P(DDSIMExecTest, Tests) { - const auto result = circuitSimulatorExecutor->execute(simulationTask); - std::cout << "Results:\n" << result.dump(2U) << std::endl; - - ASSERT_TRUE(result.contains("measurement_results")); - EXPECT_TRUE(result.contains("construction_time")); - EXPECT_TRUE(result.contains("execution_time")); - EXPECT_TRUE(result.contains("executor")); - EXPECT_TRUE(result.contains("task")); -} diff --git a/test/test_simexec_bernstein.cpp b/test/test_simexec_bernstein.cpp new file mode 100644 index 0000000..c92190c --- /dev/null +++ b/test/test_simexec_bernstein.cpp @@ -0,0 +1,42 @@ +#include "QuantumComputation.hpp" +#include "algorithms/BernsteinVazirani.hpp" +#include "executors/CircuitSimulatorExecutor.hpp" +#include "executors/HybridSimulatorExecutor.hpp" +#include "executors/StochasticNoiseSimulatorExecutor.hpp" +#include "tasks/SimulationTask.hpp" + +#include "gtest/gtest.h" + +TEST(SimExecTestBerstein, HybridSimulatorAmplitudeExec) { + auto hybridSimulatorAmplitudeExecutor = + std::make_unique(); + std::size_t const n = 3; + auto qc = std::make_unique(n, false); + SimulationTask const simulationTask(std::move(qc)); + const auto result = hybridSimulatorAmplitudeExecutor->execute(simulationTask); + std::cout << result << "\n"; +} + +TEST(SimExecTestBerstein, HybridSimulatorDDExec) { + auto hybridSimulatorDDExecutor = std::make_unique(); + hybridSimulatorDDExecutor->setRunAmplitude(false); + hybridSimulatorDDExecutor->setRunDd(true); + std::size_t const n = 8; + auto qc = std::make_unique(n, false); + SimulationTask const simulationTask(std::move(qc)); + const auto result = hybridSimulatorDDExecutor->execute(simulationTask); + std::cout << result << "\n"; +} + +TEST(SimExecTestBerstein, StochasticNoiseSimulatorExec) { + auto stochasticNoiseSimulatorExecutor = + std::make_unique(); + std::size_t const n = 5; + auto qc = std::make_unique(n, false); + SimulationTask const simulationTask(std::move(qc)); + const auto result = stochasticNoiseSimulatorExecutor->execute(simulationTask); + std::cout << result << "\n"; +} + +// Gives "C++ exception with description "Unsupported non-unitary functionality +// 'Rst '." thrown in the test body." when run in dynamic diff --git a/test/test_simexec_ghz.cpp b/test/test_simexec_ghz.cpp new file mode 100644 index 0000000..8c3a26c --- /dev/null +++ b/test/test_simexec_ghz.cpp @@ -0,0 +1,39 @@ +#include "QuantumComputation.hpp" +#include "algorithms/Entanglement.hpp" +#include "executors/CircuitSimulatorExecutor.hpp" +#include "executors/DeterministicNoiseSimExecutor.hpp" +#include "executors/HybridSimulatorExecutor.hpp" +#include "tasks/SimulationTask.hpp" + +#include "gtest/gtest.h" + +// Other executors excluded because 128 qubits still have under 1s execution +// time + +TEST(SimExecTestGHZ, DeterministicNoiseSimExec) { + auto deterministicNoiseSimExecutor = + std::make_unique(); + auto qc = std::make_unique(5); + SimulationTask const simulationTask(std::move(qc)); + const auto result = deterministicNoiseSimExecutor->execute(simulationTask); + std::cout << result << "\n"; +} + +TEST(SimExecTestGHZ, HybridSimulatorAmplitudeExec) { + auto hybridSimulatorAmplitudeExecutor = + std::make_unique(); + auto qc = std::make_unique(10); + SimulationTask const simulationTask(std::move(qc)); + const auto result = hybridSimulatorAmplitudeExecutor->execute(simulationTask); + std::cout << result << "\n"; +} + +TEST(SimExecTestGHZ, HybridSimulatorDDExec) { + auto hybridSimulatorDDExecutor = std::make_unique(); + hybridSimulatorDDExecutor->setRunAmplitude(false); + hybridSimulatorDDExecutor->setRunDd(true); + auto qc = std::make_unique(8); + SimulationTask const simulationTask(std::move(qc)); + const auto result = hybridSimulatorDDExecutor->execute(simulationTask); + std::cout << result << "\n"; +} diff --git a/test/test_simexec_grover.cpp b/test/test_simexec_grover.cpp new file mode 100644 index 0000000..d4ca107 --- /dev/null +++ b/test/test_simexec_grover.cpp @@ -0,0 +1,38 @@ +#include "QuantumComputation.hpp" +#include "algorithms/Grover.hpp" +#include "executors/CircuitSimulatorExecutor.hpp" +#include "executors/UnitarySimulatorExecutor.hpp" +#include "tasks/SimulationTask.hpp" + +#include "gtest/gtest.h" + +TEST(SimExecTestGrover, CircuitSimulatorExec) { + auto circuitSimulatorExecutor = std::make_unique(); + std::size_t const n = 7; + auto qc = std::make_unique(n); + SimulationTask const simulationTask(std::move(qc)); + const auto result = circuitSimulatorExecutor->execute(simulationTask); + std::cout << result << "\n"; +} + +TEST(SimExecTestGrover, UnitarySimSequentialExec) { + auto unitarySimSequentialExecutor = + std::make_unique(); + unitarySimSequentialExecutor->setRecursive(false); + unitarySimSequentialExecutor->setSequential(true); + std::size_t const n = 3; + auto qc = std::make_unique(n); + SimulationTask const simulationTask(std::move(qc)); + const auto result = unitarySimSequentialExecutor->execute(simulationTask); + std::cout << result << "\n"; +} + +TEST(SimExecTestGrover, UnitarySimRecursiveExec) { + auto unitarySimRecursiveExecutor = + std::make_unique(); + std::size_t const n = 4; + auto qc = std::make_unique(n); + SimulationTask const simulationTask(std::move(qc)); + const auto result = unitarySimRecursiveExecutor->execute(simulationTask); + std::cout << result << "\n"; +} diff --git a/test/test_simexec_simple.cpp b/test/test_simexec_simple.cpp new file mode 100644 index 0000000..6149159 --- /dev/null +++ b/test/test_simexec_simple.cpp @@ -0,0 +1,154 @@ +#include "executors/CircuitSimulatorExecutor.hpp" +#include "executors/DeterministicNoiseSimExecutor.hpp" +#include "executors/HybridSimulatorExecutor.hpp" +#include "executors/StochasticNoiseSimulatorExecutor.hpp" +#include "executors/UnitarySimulatorExecutor.hpp" +#include "tasks/SimulationTask.hpp" + +#include "gtest/gtest.h" + +struct TestConfigurationDDSIM { + // given input + std::string description; + std::string circuit; +}; + +// NOLINTNEXTLINE (readability-identifier-naming) +inline void from_json(const nlohmann::json& j, TestConfigurationDDSIM& test) { + test.description = j.at("description").get(); + test.circuit = j.at("circuit").get(); +} + +namespace { +std::vector getTests(const std::string& path) { + std::ifstream input(path); + nlohmann::json j; + input >> j; + return j; +} +} // namespace + +class DDSIMExecTest : public ::testing::TestWithParam { +protected: + void SetUp() override { + test = GetParam(); + std::stringstream ss(test.circuit); + + auto qc = std::make_unique(); + qc->import(ss, qc::Format::OpenQASM); + std::cout << "Circuit:\n" << *qc; + + simulationTask = SimulationTask(std::move(qc)); + } + + SimulationTask simulationTask; + TestConfigurationDDSIM test; +}; + +INSTANTIATE_TEST_SUITE_P( + Circuits, DDSIMExecTest, testing::ValuesIn(getTests("sim_circuits.json")), + [](const testing::TestParamInfo& inf) { + return inf.param.description; + }); + +TEST_P(DDSIMExecTest, CircuitSimulatorExec) { + std::unique_ptr circuitSimulatorExecutor = + std::make_unique(); + const auto result = circuitSimulatorExecutor->execute(simulationTask); + std::cout << "Results:\n" << result.dump(2U) << std::endl; + + ASSERT_TRUE(result.contains("measurement_results")); + EXPECT_TRUE(result.contains("construction_time")); + EXPECT_TRUE(result.contains("execution_time")); + EXPECT_TRUE(result.contains("executor")); + EXPECT_TRUE(result.contains("task")); +} + +TEST_P(DDSIMExecTest, DeterministicNoiseSimExec) { + std::unique_ptr deterministicNoiseSimExecutor = + std::make_unique(); + const auto result = deterministicNoiseSimExecutor->execute(simulationTask); + std::cout << "Results:\n" << result.dump(2U) << std::endl; + + ASSERT_TRUE(result.contains("measurement_results")); + EXPECT_TRUE(result.contains("construction_time")); + EXPECT_TRUE(result.contains("execution_time")); + EXPECT_TRUE(result.contains("executor")); + EXPECT_TRUE(result.contains("task")); +} + +TEST_P(DDSIMExecTest, HybridSimulatorAmplitudeExec) { + std::unique_ptr hybridSimulatorAmplitudeExecutor = + std::make_unique(); + ASSERT_TRUE(hybridSimulatorAmplitudeExecutor->isRunAmplitude()); + const auto result = hybridSimulatorAmplitudeExecutor->execute(simulationTask); + std::cout << "Results:\n" << result.dump(2U) << std::endl; + + ASSERT_TRUE(result.contains("measurement_results")); + EXPECT_TRUE(result.contains("construction_time")); + EXPECT_TRUE(result.contains("execution_time")); + EXPECT_TRUE(result.contains("executor")); + EXPECT_TRUE(result.contains("task")); +} + +TEST_P(DDSIMExecTest, HybridSimulatorDDExec) { + std::unique_ptr hybridSimulatorDDExecutor = + std::make_unique(); + hybridSimulatorDDExecutor->setRunAmplitude(false); + hybridSimulatorDDExecutor->setRunDd(true); + + const auto result = hybridSimulatorDDExecutor->execute(simulationTask); + std::cout << "Results:\n" << result.dump(2U) << std::endl; + + ASSERT_TRUE(result.contains("measurement_results")); + ASSERT_TRUE(result["executor"] == + ("hybrid_schrodinger_feynman_simulator_dd")); + EXPECT_TRUE(result.contains("construction_time")); + EXPECT_TRUE(result.contains("execution_time")); + EXPECT_TRUE(result.contains("executor")); + EXPECT_TRUE(result.contains("task")); +} + +TEST_P(DDSIMExecTest, StochasticNoiseSimExec) { + std::unique_ptr + stochasticNoiseSimulatorExecutor = + std::make_unique(); + const auto result = stochasticNoiseSimulatorExecutor->execute(simulationTask); + std::cout << "Results:\n" << result.dump(2U) << std::endl; + + ASSERT_TRUE(result.contains("measurement_results")); + EXPECT_TRUE(result.contains("construction_time")); + EXPECT_TRUE(result.contains("execution_time")); + EXPECT_TRUE(result.contains("executor")); + EXPECT_TRUE(result.contains("task")); +} + +TEST_P(DDSIMExecTest, UnitarySimRecursiveExec) { + std::unique_ptr unitarySimRecursiveExecutor = + std::make_unique(); + const auto result = unitarySimRecursiveExecutor->execute(simulationTask); + std::cout << "Results:\n" << result.dump(2U) << std::endl; + + ASSERT_TRUE(result.contains("final_node_count")); + ASSERT_TRUE(result.contains("max_node_count")); + EXPECT_TRUE(result.contains("unitary_execution_time")); + EXPECT_TRUE(result.contains("executor")); + EXPECT_TRUE(result.contains("task")); +} + +TEST_P(DDSIMExecTest, UnitarySimSequentialExec) { + std::unique_ptr unitarySimSequentialExecutor = + std::make_unique(); + unitarySimSequentialExecutor->setRecursive(false); + unitarySimSequentialExecutor->setSequential(true); + + const auto result = unitarySimSequentialExecutor->execute(simulationTask); + std::cout << "Results:\n" << result.dump(2U) << std::endl; + + ASSERT_TRUE(result.contains("final_node_count")); + ASSERT_TRUE(result.contains("max_node_count")); + ASSERT_TRUE(result["executor"] == ("unitary_simulator_sequential")); + EXPECT_TRUE(result.contains("unitary_execution_time")); + EXPECT_TRUE(result.contains("executor")); + EXPECT_TRUE(result.contains("task")); +} diff --git a/test/test_stoch_noise_sim_exec.cpp b/test/test_stoch_noise_sim_exec.cpp new file mode 100644 index 0000000..d140a8c --- /dev/null +++ b/test/test_stoch_noise_sim_exec.cpp @@ -0,0 +1,78 @@ +#include "algorithms/BernsteinVazirani.hpp" +#include "algorithms/Entanglement.hpp" +#include "algorithms/Grover.hpp" +#include "algorithms/QPE.hpp" +#include "algorithms/RandomCliffordCircuit.hpp" +#include "algorithms/WState.hpp" +#include "executors/StochasticNoiseSimulatorExecutor.hpp" + +#include "gtest/gtest.h" + +class StochNoiseSimExecTest : public testing::Test { +protected: + void TearDown() override {} + void SetUp() override {} +}; + +TEST_F(StochNoiseSimExecTest, GHZ) { + auto simulator = std::make_unique(); + std::size_t const n = 5; + auto qc = std::make_unique(n); + SimulationTask const simulationTask(std::move(qc)); + const auto result = simulator->execute(simulationTask); + std::cout << result << "\n"; +} + +TEST_F(StochNoiseSimExecTest, BernsteinVazirani) { + auto simulator = std::make_unique(); + std::size_t const n = 3; + auto qc = std::make_unique(n, false); + SimulationTask const simulationTask(std::move(qc)); + const auto result = simulator->execute(simulationTask); + std::cout << result << "\n"; +} + +TEST_F(StochNoiseSimExecTest, QPEExact) { + auto simulator = std::make_unique(); + std::size_t const n = 3; + auto qc = std::make_unique(n, true, false); + SimulationTask const simulationTask(std::move(qc)); + const auto result = simulator->execute(simulationTask); + std::cout << result << "\n"; +} + +TEST_F(StochNoiseSimExecTest, QPEInexact) { + auto simulator = std::make_unique(); + std::size_t const n = 4; + auto qc = std::make_unique(n, false, false); + SimulationTask const simulationTask(std::move(qc)); + const auto result = simulator->execute(simulationTask); + std::cout << result << "\n"; +} + +TEST_F(StochNoiseSimExecTest, Grover) { + auto simulator = std::make_unique(); + std::size_t const n = 7; + auto qc = std::make_unique(n); + SimulationTask const simulationTask(std::move(qc)); + const auto result = simulator->execute(simulationTask); + std::cout << result << "\n"; +} + +TEST_F(StochNoiseSimExecTest, RandomCliffordCircuit) { + auto simulator = std::make_unique(); + std::size_t const n = 7; + auto qc = std::make_unique(n); + SimulationTask const simulationTask(std::move(qc)); + const auto result = simulator->execute(simulationTask); + std::cout << result << "\n"; +} + +TEST_F(StochNoiseSimExecTest, WState) { + auto simulator = std::make_unique(); + std::size_t const n = 6; + auto qc = std::make_unique(n); + SimulationTask const simulationTask(std::move(qc)); + const auto result = simulator->execute(simulationTask); + std::cout << result << "\n"; +} diff --git a/test/test_uni_sim_exec.cpp b/test/test_uni_sim_exec.cpp new file mode 100644 index 0000000..ac53254 --- /dev/null +++ b/test/test_uni_sim_exec.cpp @@ -0,0 +1,102 @@ +#include "algorithms/BernsteinVazirani.hpp" +#include "algorithms/Entanglement.hpp" +#include "algorithms/Grover.hpp" +#include "algorithms/QFT.hpp" +#include "algorithms/QPE.hpp" +#include "algorithms/RandomCliffordCircuit.hpp" +#include "algorithms/WState.hpp" +#include "executors/UnitarySimulatorExecutor.hpp" + +#include "gtest/gtest.h" + +class UniSimExecTest : public testing::Test { +protected: + void TearDown() override {} + void SetUp() override {} +}; + +TEST_F(UniSimExecTest, GHZ) { + auto unitarySimulatorExecutor = std::make_unique(); + std::size_t const n = 5; + auto qc = std::make_unique(n); + SimulationTask const simulationTask(std::move(qc)); + const auto result = unitarySimulatorExecutor->execute(simulationTask); + std::cout << result << "\n"; +} + +TEST_F(UniSimExecTest, BernsteinVazirani) { + auto unitarySimulatorExecutor = std::make_unique(); + std::size_t const n = 3; + auto qc = std::make_unique(n, false); + SimulationTask const simulationTask(std::move(qc)); + const auto result = unitarySimulatorExecutor->execute(simulationTask); + std::cout << result << "\n"; +} + +TEST_F(UniSimExecTest, QPEExact) { + auto unitarySimulatorExecutor = std::make_unique(); + std::size_t const n = 3; + auto qc = std::make_unique(n, true, false); + SimulationTask const simulationTask(std::move(qc)); + const auto result = unitarySimulatorExecutor->execute(simulationTask); + std::cout << result << "\n"; +} + +TEST_F(UniSimExecTest, QPEInexact) { + auto unitarySimulatorExecutor = std::make_unique(); + std::size_t const n = 4; + auto qc = std::make_unique(n, false, false); + SimulationTask const simulationTask(std::move(qc)); + const auto result = unitarySimulatorExecutor->execute(simulationTask); + std::cout << result << "\n"; +} + +TEST_F(UniSimExecTest, QFT) { + auto unitarySimulatorExecutor = std::make_unique(); + std::size_t const n = 4; + auto qc = std::make_unique(n); + SimulationTask const simulationTask(std::move(qc)); + const auto result = unitarySimulatorExecutor->execute(simulationTask); + std::cout << result << "\n"; +} + +TEST_F(UniSimExecTest, QFTNonZeroInput) { + auto unitarySimulatorExecutor = std::make_unique(); + std::size_t const n = 5; + auto statePrepQFT = qc::QuantumComputation(n); + auto actualQft = qc::QFT(n); + statePrepQFT.emplace_back(actualQft.asCompoundOperation()); + qc::CircuitOptimizer::flattenOperations(statePrepQFT); + std::unique_ptr qft( + new qc::QuantumComputation(std::move(statePrepQFT))); + SimulationTask const simulationTask(std::move(qft)); + const auto result = unitarySimulatorExecutor->execute(simulationTask); + std::cout << result << "\n"; +} + +TEST_F(UniSimExecTest, Grover) { + auto unitarySimulatorExecutor = std::make_unique(); + std::size_t const n = 7; + auto qc = std::make_unique(n); + SimulationTask const simulationTask(std::move(qc)); + const auto result = unitarySimulatorExecutor->execute(simulationTask); + std::cout << result << "\n"; +} + +TEST_F(UniSimExecTest, RandomCliffordCircuit) { + auto unitarySimulatorExecutor = std::make_unique(); + std::size_t const n = 7; + auto qc = std::make_unique(n); + SimulationTask const simulationTask(std::move(qc)); + const auto result = unitarySimulatorExecutor->execute(simulationTask); + std::cout << result << "\n"; +} + +TEST_F(UniSimExecTest, WState) { + auto unitarySimulatorExecutor = std::make_unique(); + std::size_t const n = 6; + auto qc = std::make_unique(n); + SimulationTask const simulationTask(std::move(qc)); + const auto result = unitarySimulatorExecutor->execute(simulationTask); + std::cout << result << "\n"; +} diff --git a/test/test_uni_sim_exec_seq.cpp b/test/test_uni_sim_exec_seq.cpp new file mode 100644 index 0000000..e8094da --- /dev/null +++ b/test/test_uni_sim_exec_seq.cpp @@ -0,0 +1,120 @@ +#include "algorithms/BernsteinVazirani.hpp" +#include "algorithms/Entanglement.hpp" +#include "algorithms/Grover.hpp" +#include "algorithms/QFT.hpp" +#include "algorithms/QPE.hpp" +#include "algorithms/RandomCliffordCircuit.hpp" +#include "algorithms/WState.hpp" +#include "executors/UnitarySimulatorExecutor.hpp" + +#include "gtest/gtest.h" + +class UniSimExecTestSeq : public testing::Test { +protected: + void TearDown() override {} + void SetUp() override {} +}; + +TEST_F(UniSimExecTestSeq, GHZ) { + auto unitarySimulatorExecutor = std::make_unique(); + unitarySimulatorExecutor->setRecursive(false); + unitarySimulatorExecutor->setSequential(true); + std::size_t const n = 5; + auto qc = std::make_unique(n); + SimulationTask const simulationTask(std::move(qc)); + const auto result = unitarySimulatorExecutor->execute(simulationTask); + std::cout << result << "\n"; +} + +TEST_F(UniSimExecTestSeq, BernsteinVazirani) { + auto unitarySimulatorExecutor = std::make_unique(); + unitarySimulatorExecutor->setRecursive(false); + unitarySimulatorExecutor->setSequential(true); + std::size_t const n = 3; + auto qc = std::make_unique(n, false); + SimulationTask const simulationTask(std::move(qc)); + const auto result = unitarySimulatorExecutor->execute(simulationTask); + std::cout << result << "\n"; +} + +TEST_F(UniSimExecTestSeq, QPEExact) { + auto unitarySimulatorExecutor = std::make_unique(); + unitarySimulatorExecutor->setRecursive(false); + unitarySimulatorExecutor->setSequential(true); + std::size_t const n = 3; + auto qc = std::make_unique(n, true, false); + SimulationTask const simulationTask(std::move(qc)); + const auto result = unitarySimulatorExecutor->execute(simulationTask); + std::cout << result << "\n"; +} + +TEST_F(UniSimExecTestSeq, QPEInexact) { + auto unitarySimulatorExecutor = std::make_unique(); + unitarySimulatorExecutor->setRecursive(false); + unitarySimulatorExecutor->setSequential(true); + std::size_t const n = 4; + auto qc = std::make_unique(n, false, false); + SimulationTask const simulationTask(std::move(qc)); + const auto result = unitarySimulatorExecutor->execute(simulationTask); + std::cout << result << "\n"; +} + +TEST_F(UniSimExecTestSeq, QFT) { + auto unitarySimulatorExecutor = std::make_unique(); + unitarySimulatorExecutor->setRecursive(false); + unitarySimulatorExecutor->setSequential(true); + std::size_t const n = 4; + auto qc = std::make_unique(n); + SimulationTask const simulationTask(std::move(qc)); + const auto result = unitarySimulatorExecutor->execute(simulationTask); + std::cout << result << "\n"; +} + +TEST_F(UniSimExecTestSeq, QFTNonZeroInput) { + auto unitarySimulatorExecutor = std::make_unique(); + unitarySimulatorExecutor->setRecursive(false); + unitarySimulatorExecutor->setSequential(true); + std::size_t const n = 5; + auto statePrepQFT = qc::QuantumComputation(n); + auto actualQft = qc::QFT(n); + statePrepQFT.emplace_back(actualQft.asCompoundOperation()); + qc::CircuitOptimizer::flattenOperations(statePrepQFT); + std::unique_ptr qft( + new qc::QuantumComputation(std::move(statePrepQFT))); + SimulationTask const simulationTask(std::move(qft)); + const auto result = unitarySimulatorExecutor->execute(simulationTask); + std::cout << result << "\n"; +} + +TEST_F(UniSimExecTestSeq, Grover) { + auto unitarySimulatorExecutor = std::make_unique(); + unitarySimulatorExecutor->setRecursive(false); + unitarySimulatorExecutor->setSequential(true); + std::size_t const n = 7; + auto qc = std::make_unique(n); + SimulationTask const simulationTask(std::move(qc)); + const auto result = unitarySimulatorExecutor->execute(simulationTask); + std::cout << result << "\n"; +} + +TEST_F(UniSimExecTestSeq, RandomCliffordCircuit) { + auto unitarySimulatorExecutor = std::make_unique(); + unitarySimulatorExecutor->setRecursive(false); + unitarySimulatorExecutor->setSequential(true); + std::size_t const n = 7; + auto qc = std::make_unique(n); + SimulationTask const simulationTask(std::move(qc)); + const auto result = unitarySimulatorExecutor->execute(simulationTask); + std::cout << result << "\n"; +} + +TEST_F(UniSimExecTestSeq, WState) { + auto unitarySimulatorExecutor = std::make_unique(); + unitarySimulatorExecutor->setRecursive(false); + unitarySimulatorExecutor->setSequential(true); + std::size_t const n = 6; + auto qc = std::make_unique(n); + SimulationTask const simulationTask(std::move(qc)); + const auto result = unitarySimulatorExecutor->execute(simulationTask); + std::cout << result << "\n"; +}