diff --git a/CMakeLists.txt b/CMakeLists.txt
index 3349581b..56eaa95e 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -2,14 +2,13 @@ cmake_minimum_required(VERSION 3.14...3.19)
project(ddsim
LANGUAGES CXX
- VERSION 1.3.0
+ VERSION 1.4.0
DESCRIPTION "DDSIM - A JKQ quantum simulator based on decision diagrams"
)
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
option(COVERAGE "Configure for coverage report generation")
option(GENERATE_POSITION_INDEPENDENT_CODE "Generate position independent code")
-option(TEST_WITH_SANITIZERS "Run test with ASAN and UBSAN")
set(default_build_type "Release")
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
diff --git a/LICENSE b/LICENSE
index 1bb1f8bf..975d8e1b 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,6 +1,6 @@
MIT License
-Copyright (c) 2020 Stefan Hillmich, Lukas Burgholzer, Robert Wille
+Copyright (c) 2021 Stefan Hillmich, Lukas Burgholzer, Thomas Grurl, and Robert Wille
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/README.md b/README.md
index bde58650..a6938304 100644
--- a/README.md
+++ b/README.md
@@ -10,8 +10,6 @@
A tool for quantum circuit simulation by the [Institute for Integrated Circuits](https://iic.jku.at/eda/) at the [Johannes Kepler University Linz](https://jku.at)
and a part of the [JKQ toolset](https://github.com/iic-jku/jkq).
-Developers: Stefan Hillmich, Lukas Burgholzer, Thomas Grurl, and Robert Wille.
-
The tool builds upon [our quantum functionality representation (QFR)](https://github.com/iic-jku/qfr.git) which in turns builds on [our decision diagram (DD) package](https://github.com/iic-jku/dd_package.git).
For more information, on our work on quantum circuit simulation please visit [iic.jku.at/eda/research/quantum_simulation](https://iic.jku.at/eda/research/quantum_simulation) or, for more information on our work on noise-aware quantum circuit simulation, please visit [iic.jku.at/eda/research/noise_aware_simulation](https://iic.jku.at/eda/research/noise_aware_simulation).
@@ -59,7 +57,7 @@ The following additional algorithms are integrated in [QFR](https://github.com/i
For details on the available methods we refer to [iic.jku.at/eda/research/quantum_simulation](https://iic.jku.at/eda/research/quantum_simulation).
-The simulator is based on [[1]](https://iic.jku.at/files/eda/2018_tcad_advanced_simulation_quantum_computation.pdf) and can either be used as a **standalone executable** with command-line interface, or as a **library** for the incorporation in other projects.
+The simulator is based on the references listed below and can either be used as a **standalone executable** with command-line interface, or as a **library** for the incorporation in other projects.
## System Requirements
@@ -114,29 +112,26 @@ The standalone executable is launched in the following way, showing available op
```commandline
$ ./ddsim_simple --help
JKQ DDSIM by https://iic.jku.at/eda/ -- Allowed options:
--h [ --help ] produce help message
---seed arg (=0) seed for random number generator (default zero is possibly directly used as seed!)
---shots arg (=0) number of measurements (if the algorithm does not contain non-unitary gates, weak simulation is used)
---display_vector display the state vector
---ps print simulation stats (applied gates, sim. time, and maximal size of the DD)
---verbose Causes some simulators to print additional information to STDERR
---benchmark print simulation stats in a single CSV style line (overrides --ps and suppresses most other output, please don't rely on the format across versions)
---simulate_file arg simulate a quantum circuit given by file (detection by the file extension)
---simulate_qft arg simulate Quantum Fourier Transform for given number of qubits
---simulate_ghz arg simulate state preparation of GHZ state for given number of qubits
---step_fidelity arg (=1) target fidelity for each approximation run (>=1 = disable approximation)
---steps arg (=1) number of approximation steps
---initial_reorder arg (=0) Try to find a good initial variable order (0=None, 1=Most affected qubits to the top, 2=Most affected targets to the top)
---dynamic_reorder arg (=0) Apply reordering strategy during simulation (0=None, 1=Sifting, 2=Move2Top)
---post_reorder arg (=0) Apply a reordering strategy after simulation (0=None, 1=Sifting)
---simulate_grover arg simulate Grover's search for given number of qubits with random oracle
---simulate_grover_emulated arg simulate Grover's search for given number of qubits with random oracle and emulation
---simulate_grover_oracle_emulated arg simulate Grover's search for given number of qubits with given oracle and emulation
---simulate_shor arg simulate Shor's algorithm factoring this number
---simulate_shor_coprime arg (=0) coprime number to use with Shor's algorithm (zero randomly generates a coprime)
---simulate_shor_no_emulation Force Shor simulator to do modular exponentiation instead of using emulation (you'll usually want emulation)
---simulate_fast_shor arg simulate Shor's algorithm factoring this number with intermediate measurements
---simulate_fast_shor_coprime arg (=0) coprime number to use with Shor's algorithm (zero randomly generates a coprime)
+ -h [ --help ] produce help message
+ --seed arg (=0) seed for random number generator (default zero is possibly directly used as seed!)
+ --shots arg (=0) number of measurements (if the algorithm does not contain non-unitary gates, weak simulation is used)
+ --pv display the state vector as list of pairs (real and imaginary parts)
+ --ps print simulation stats (applied gates, sim. time, and maximal size of the DD)
+ --pm print measurement results
+ --verbose Causes some simulators to print additional information to STDERR
+ --simulate_file arg simulate a quantum circuit given by file (detection by the file extension)
+ --simulate_qft arg simulate Quantum Fourier Transform for given number of qubits
+ --simulate_ghz arg simulate state preparation of GHZ state for given number of qubits
+ --step_fidelity arg (=1) target fidelity for each approximation run (>=1 = disable approximation)
+ --steps arg (=1) number of approximation steps
+ --simulate_grover arg simulate Grover's search for given number of qubits with random oracle
+ --simulate_grover_emulated arg simulate Grover's search for given number of qubits with random oracle and emulation
+ --simulate_grover_oracle_emulated arg simulate Grover's search for given number of qubits with given oracle and emulation
+ --simulate_shor arg simulate Shor's algorithm factoring this number
+ --simulate_shor_coprime arg (=0) coprime number to use with Shor's algorithm (zero randomly generates a coprime)
+ --simulate_shor_no_emulation Force Shor simulator to do modular exponentiation instead of using emulation (you'll usually want emulation)
+ --simulate_fast_shor arg simulate Shor's algorithm factoring this number with intermediate measurements
+ --simulate_fast_shor_coprime arg (=0) coprime number to use with Shor's algorithm (zero randomly generates a coprime)
```
@@ -145,42 +140,25 @@ The output is JSON-formatted as shown below (with hopefully intuitive naming).
```commandline
$ cmake -DCMAKE_BUILD_TYPE=Release -S . -B build
$ cmake --build build --config Release --target ddsim_simple
-$ ./build/ddsim_simple --simulate_ghz 4 --display_vector --shots 1000 --ps
+$ ./build/ddsim_simple --simulate_ghz 4 --shots 1000 --ps --pm
{
- "measurements": {
+ "measurement_results": {
"0000": 484,
"1111": 516
},
- "state_vector": [
- +0.707107+0i,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- 0,
- +0.707107+0i
- ],
- "non_zero_entries": 2,
"statistics": {
- "simulation_time": 0.000104,
- "measurement_time": 0.000104,
- "benchmark": "",
- "shots": 1000,
- "distinct_results": 2,
- "n_qubits": 4,
"applied_gates": 4,
+ "approximation_runs": "0",
+ "benchmark": "entanglement_4",
+ "distinct_results": 2,
+ "final_fidelity": "1.000000",
"max_nodes": 9,
- "path_of_least_resistance": "1111",
- "seed": 0
+ "n_qubits": 4,
+ "seed": "0",
+ "shots": 1000,
+ "simulation_time": 0.00013726699398830533,
+ "single_shots": "1",
+ "step_fidelity": "1.000000"
}
}
```
@@ -226,72 +204,50 @@ $ cmake --build build --config Release --target ddsim_noise_aware
The simulator provides a help function which is called in the following way:
```commandline
-$ ./build/ddsim_noise_aware --help
+$ ./build/ddsim_noise_aware -h
JKQ DDSIM by https://iic.jku.at/eda/ -- Allowed options:
-h [ --help ] produce help message
- --seed arg (=0) seed for random number generator
- (default zero is possibly directly used
- as seed!)
- --shots arg (=0) number of measurements (if the
- algorithm does not contain non-unitary
- gates, weak simulation is used)
- --display_vector display the state vector
- --ps print simulation stats (applied gates,
- sim. time, and maximal size of the DD)
- --verbose Causes some simulators to print
- additional information to STDERR
- --benchmark print simulation stats in a single CSV
- style line (overrides --ps and
- suppresses most other output, please
- don't rely on the format across
- versions)
- --simulate_file arg simulate a quantum circuit given by
- file (detection by the file extension)
- .
- .
- .
- --noise_effects arg Noise effects (A (=amplitude damping),D
- (=depolarization),P (=phase flip)) in
- the form of a character string
- describing the noise effects (default="
- ")
- --noise_prob arg Probability for applying noise
- (default=0.001)
- --confidence arg Confidence in the error bound of the
- stochastic simulation (default= 0.05)
- --error_bound arg Error bound of the stochastic
- simulation (default=0.1)
- --stoch_runs arg (=0) Number of stochastic runs. When the
- value is 0 the value is calculated
- using the confidence, error_bound and
- number of tracked properties. (default
- = 0)
- --properties arg Comma separated list of tracked
- properties. Note that -1 is the
- fidelity and "-" can be used to specify
- a range. (default="0-1000")
+ --seed arg (=0) seed for random number generator (default zero is possibly directly used as seed!)
+ --pm print measurements
+ --ps print simulation stats (applied gates, sim. time, and maximal size of the DD)
+ --verbose Causes some simulators to print additional information to STDERR
+ --simulate_file arg simulate a quantum circuit given by file (detection by the file extension)
+ --step_fidelity arg (=1) target fidelity for each approximation run (>=1 = disable approximation)
+ --steps arg (=1) number of approximation steps
+ --noise_effects arg (=APD) Noise effects (A (=amplitude damping),D (=depolarization),P (=phase flip)) in the form of a character string describing the noise effects
+ --noise_prob arg (=0.001) Probability for applying noise
+ --confidence arg (=0.05) Confidence in the error bound of the stochastic simulation
+ --error_bound arg (=0.1) Error bound of the stochastic simulation
+ --stoch_runs arg (=0) Number of stochastic runs. When the value is 0 the value is calculated using the confidence, error_bound and number of tracked properties.
+ --properties arg (=-3-1000) Comma separated list of tracked properties. Note that -1 is the fidelity and "-" can be used to specify a range.
+
+Process finished with exit code 0
+
```
An example run, with amplitude damping, phase flip, and depolarization error (each with a probability of 0.1% whenever a gate is applied) looks like this:
```commandline
-$ ./build/ddsim_noise_aware --noise_effects APD --stoch_runs 10000 --noise_prob 0.001 --simulate_file /home/user/adder4.qasm
-Conducting perfect run ...
-Conducting 10000 runs using 4 cores ...
-Starting 4 threads
-Calculating amplitudes from all runs ...
-Probabilities are ... (probabilities < 0.001 are omitted)
-state=|0000> proba=0.00975488
-state=|0001> proba=0.00784512
-state=|0100> proba=0.00175135
-state=|0101> proba=0.00194865
-state=|0110> proba=0.00404999
-state=|1000> proba=0.0229565
-state=|1001> proba=0.937243
-state=|1011> proba=0.00229939
-state=|1100> proba=0.00215185
-state=|1101> proba=0.00284815
-state=|1110> proba=0.00505003
+$ ./build/ddsim_noise_aware --ps --noise_effects APD --stoch_runs 10000 --noise_prob 0.001 --simulate_file adder4.qasm
+{
+ "statistics": {
+ "applied_gates": 23,
+ "approximation_runs": "0.000000",
+ "benchmark": "stoch_APD_adder_n4",
+ "final_fidelity": "0.937343",
+ "max_nodes": 10,
+ "mean_stoch_run_time": "0.015796",
+ "n_qubits": 4,
+ "parallel_instances": "28",
+ "perfect_run_time": "0.000066",
+ "seed": "0",
+ "simulation_time": 5.911194324493408,
+ "step_fidelity": "1.000000",
+ "stoch_runs": 10000,
+ "stoch_wall_time": "5.911118",
+ "threads": 28
+ }
+}
```
## Running Tests
@@ -329,7 +285,9 @@ If you use our tool for your research, we will be thankful if you refer to it by
-[1] A. Zulehner and R. Wille, “Advanced Simulation of Quantum Computations,” Transactions on CAD of Integrated Circuits and Systems (TCAD), vol. 38, no. 5, pp. 848–859, 2019
+
+ [1] A. Zulehner and R. Wille, “Advanced Simulation of Quantum Computations,” Transactions on CAD of Integrated Circuits and Systems (TCAD), vol. 38, no. 5, pp. 848–859, 2019
+
```bibtex
@article{zulehner2019advanced,
@@ -346,7 +304,29 @@ If you use our tool for your research, we will be thankful if you refer to it by
-[2] T. Grurl, R. Kueng, J. Fuß, and R. Wille, “Stochastic Quantum Circuit Simulation Using Decision Diagrams,” in Design, Automation and Test in Europe (DATE), 2021
+
+ [2] S. Hillmich, I. L. Markov, and R. Wille, “Just Like the Real Thing: Fast Weak Simulation of Quantum Computation,” in Design Automation Conference (DAC), 2020
+
+
+```bibtex
+@inproceedings{DBLP:conf/dac/HillmichMW20,
+ author = {Stefan Hillmich and
+ Igor L. Markov and
+ Robert Wille},
+ title = {Just Like the Real Thing: {F}ast Weak Simulation of Quantum Computation},
+ booktitle = {Design Automation Conference},
+ publisher = {{IEEE}},
+ year = {2020}
+}
+```
+
+
+
+
+
+
+ [3] T. Grurl, R. Kueng, J. Fuß, and R. Wille, “Stochastic Quantum Circuit Simulation Using Decision Diagrams,” in Design, Automation and Test in Europe (DATE), 2021
+
```bibtex
@inproceedings{Grurl2020,
@@ -361,4 +341,24 @@ If you use our tool for your research, we will be thankful if you refer to it by
+
+
+ [4] S. Hillmich, R. Kueng, I. L. Markov, and R. Wille, "As Accurate as Needed, as Efficient as Possible: Approximations in DD-based Quantum Circuit Simulation," in Design, Automation and Test in Europe (DATE), 2021
+
+
+```bibtex
+@inproceedings{DBLP:conf/date/HillmichKMW21,
+ author = {Stefan Hillmich and
+ Richard Kueng and
+ Igor L. Markov and
+ Robert Wille},
+ title = {As Accurate as Needed, as Efficient as Possible: Approximations in DD-based Quantum Circuit Simulation},
+ booktitle = {Design, Automation and Test in Europe},
+ year = {2021}
+}
+```
+
+
+
+
diff --git a/apps/CMakeLists.txt b/apps/CMakeLists.txt
index be14dc24..4b0cb805 100644
--- a/apps/CMakeLists.txt
+++ b/apps/CMakeLists.txt
@@ -20,10 +20,17 @@ macro(add_sim_executable APPNAME)
set_target_properties(${PROJECT_NAME}_${APPNAME} PROPERTIES EXPORT_NAME ${PROJECT_NAME}_${APPNAME})
endmacro()
-if (Boost_FOUND)
+set(THREADS_PREFER_PTHREAD_FLAG ON)
+find_package( Threads )
+link_libraries( Threads::Threads)
+
+if(Boost_FOUND)
add_sim_executable(simple Boost::program_options)
add_sim_executable(primebases Boost::program_options)
-
+ if(Threads_FOUND)
+ add_sim_executable(noise_aware Boost::program_options )
+ # target_link_libraries(${PROJECT_NAME}_noise_aware PUBLIC Threads::Threads)
+ endif()
else ()
message(WARNING "Did not find Boost! Commandline interface will not be an available target!")
endif ()
diff --git a/apps/noise_aware.cpp b/apps/noise_aware.cpp
new file mode 100644
index 00000000..d3e8dff1
--- /dev/null
+++ b/apps/noise_aware.cpp
@@ -0,0 +1,110 @@
+#include "StochasticNoiseSimulator.hpp"
+#include "nlohmann/json.hpp"
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+namespace nl = nlohmann;
+
+int main(int argc, char** argv) {
+ namespace po = boost::program_options;
+ unsigned long long seed;
+
+ po::options_description description("JKQ DDSIM by https://iic.jku.at/eda/ -- Allowed options");
+ // clang-format off
+ description.add_options()
+ ("help,h", "produce help message")
+ ("seed", po::value(&seed)->default_value(0), "seed for random number generator (default zero is possibly directly used as seed!)")
+ ("pm", "print measurements")
+ ("ps", "print simulation stats (applied gates, sim. time, and maximal size of the DD)")
+ ("verbose", "Causes some simulators to print additional information to STDERR")
+
+ ("simulate_file", po::value(), "simulate a quantum circuit given by file (detection by the file extension)")
+ ("step_fidelity", po::value()->default_value(1.0), "target fidelity for each approximation run (>=1 = disable approximation)")
+ ("steps", po::value()->default_value(1), "number of approximation steps")
+
+ ("noise_effects", po::value()->default_value("APD"), "Noise effects (A (=amplitude damping),D (=depolarization),P (=phase flip)) in the form of a character string describing the noise effects (default=\"APD\")")
+ ("noise_prob", po::value()->default_value(0.001), "Probability for applying noise (default=0.001)")
+ ("confidence", po::value()->default_value(0.05), "Confidence in the error bound of the stochastic simulation (default= 0.05)")
+ ("error_bound", po::value()->default_value(0.1), "Error bound of the stochastic simulation (default=0.1)")
+ ("stoch_runs", po::value()->default_value(0), "Number of stochastic runs. When the value is 0 the value is calculated using the confidence, error_bound and number of tracked properties. (default = 0)")
+ ("properties", po::value()->default_value("-3-1000"), R"(Comma separated list of tracked properties. Note that -1 is the fidelity and "-" can be used to specify a range. (default="-3-1000"))")
+ ;
+ // clang-format on
+ po::variables_map vm;
+ try {
+ po::store(po::parse_command_line(argc, argv, description), vm);
+
+ if (vm.count("help")) {
+ std::cout << description;
+ return 0;
+ }
+ po::notify(vm);
+ } catch (const po::error& e) {
+ std::cerr << "[ERROR] " << e.what() << "! Try option '--help' for available commandline options.\n";
+ std::exit(1);
+ }
+
+ std::unique_ptr quantumComputation;
+ std::unique_ptr ddsim{nullptr};
+
+ if (vm.count("simulate_file")) {
+ const std::string fname = vm["simulate_file"].as();
+ quantumComputation = std::make_unique(fname);
+ ddsim = std::make_unique(quantumComputation,
+ vm["steps"].as(),
+ vm["step_fidelity"].as(),
+ seed);
+ } else {
+ std::cerr << "Did not find anything to simulate. See help below.\n"
+ << description << "\n";
+ std::exit(1);
+ }
+
+ if (quantumComputation && quantumComputation->getNqubits() > 100) {
+ std::clog << "[WARNING] Quantum computation contains quite many qubits. You're jumping into the deep end.\n";
+ }
+
+ ddsim->setNoiseEffects(vm["noise_effects"].as());
+ ddsim->setAmplitudeDampingProbability(vm["noise_prob"].as());
+ ddsim->stoch_confidence = vm["confidence"].as();
+ ddsim->setRecordedProperties(vm["properties"].as());
+ ddsim->stoch_error_margin = vm["error_bound"].as();
+ ddsim->stochastic_runs = vm["stoch_runs"].as();
+
+ auto t1 = std::chrono::steady_clock::now();
+
+ const std::map measurement_results = ddsim->StochSimulate();
+
+ auto t2 = std::chrono::steady_clock::now();
+
+ std::chrono::duration duration_simulation = t2 - t1;
+
+ nl::json output_obj;
+
+ if (vm.count("ps")) {
+ output_obj["statistics"] = {
+ {"simulation_time", duration_simulation.count()},
+ {"benchmark", ddsim->getName()},
+ {"stoch_runs", ddsim->stochastic_runs},
+ {"threads", ddsim->max_instances},
+ {"n_qubits", +ddsim->getNumberOfQubits()},
+ {"applied_gates", ddsim->getNumberOfOps()},
+ {"max_nodes", ddsim->getMaxNodeCount()},
+ {"seed", ddsim->getSeed()},
+ };
+
+ for (const auto& item: ddsim->AdditionalStatistics()) {
+ output_obj["statistics"][item.first] = item.second;
+ }
+ }
+
+ if (vm.count("pm")) {
+ output_obj["measurement_results"] = measurement_results;
+ }
+ std::cout << std::setw(2) << output_obj << std::endl;
+}
diff --git a/apps/simple.cpp b/apps/simple.cpp
index 4e0e9b1c..e00b556d 100644
--- a/apps/simple.cpp
+++ b/apps/simple.cpp
@@ -3,16 +3,19 @@
#include "ShorFastSimulator.hpp"
#include "ShorSimulator.hpp"
#include "Simulator.hpp"
+#include "algorithms/Entanglement.hpp"
+#include "algorithms/Grover.hpp"
+#include "algorithms/QFT.hpp"
+#include "nlohmann/json.hpp"
-#include
-#include
-#include
#include
#include
#include
#include
#include
+namespace nl = nlohmann;
+
int main(int argc, char** argv) {
namespace po = boost::program_options;
// variables initialized by boost program_options default values
@@ -24,30 +27,31 @@ int main(int argc, char** argv) {
ApproximationInfo::ApproximationWhen approx_when;
po::options_description description("JKQ DDSIM by https://iic.jku.at/eda/ -- Allowed options");
- description.add_options()("help,h", "produce help message")("seed", po::value<>(&seed)->default_value(0),
- "seed for random number generator (default zero is possibly directly used as seed!)")("shots", po::value<>(&shots)->default_value(0),
- "number of measurements (if the algorithm does not contain non-unitary gates, weak simulation is used)")("display_vector", "display the state vector")("ps", "print simulation stats (applied gates, sim. time, and maximal size of the DD)")("verbose", "Causes some simulators to print additional information to STDERR")("benchmark",
- "print simulation stats in a single CSV style line (overrides --ps and suppresses most other output, please don't rely on the format across versions)")
-
- ("simulate_file", po::value(),
- "simulate a quantum circuit given by file (detection by the file extension)")("simulate_qft", po::value(), "simulate Quantum Fourier Transform for given number of qubits")("simulate_ghz", po::value(),
- "simulate state preparation of GHZ state for given number of qubits")("step_fidelity", po::value<>(&step_fidelity)->default_value(1.0),
- "target fidelity for each approximation run (>=1 = disable approximation)")("steps", po::value<>(&approx_steps)->default_value(1), "number of approximation steps")("approx_when", po::value<>(&approx_when)->default_value(ApproximationInfo::FidelityDriven),
- "approximation method ('fidelity' (default) or 'memory'")("approx_state",
- "do excessive approximation runs at the end of the simulation to see how the quantum state behaves")
-
- ("simulate_grover", po::value(),
- "simulate Grover's search for given number of qubits with random oracle")("simulate_grover_emulated", po::value(),
- "simulate Grover's search for given number of qubits with random oracle and emulation")("simulate_grover_oracle_emulated", po::value(),
- "simulate Grover's search for given number of qubits with given oracle and emulation")
-
- ("simulate_shor", po::value(), "simulate Shor's algorithm factoring this number")("simulate_shor_coprime", po::value()->default_value(0),
- "coprime number to use with Shor's algorithm (zero randomly generates a coprime)")("simulate_shor_no_emulation",
- "Force Shor simulator to do modular exponentiation instead of using emulation (you'll usually want emulation)")
-
- ("simulate_fast_shor", po::value(),
- "simulate Shor's algorithm factoring this number with intermediate measurements")("simulate_fast_shor_coprime", po::value()->default_value(0),
- "coprime number to use with Shor's algorithm (zero randomly generates a coprime)");
+ // clang-format off
+ description.add_options()
+ ("help,h", "produce help message")
+ ("seed", po::value<>(&seed)->default_value(0), "seed for random number generator (default zero is possibly directly used as seed!)")
+ ("shots", po::value<>(&shots)->default_value(0), "number of measurements (if the algorithm does not contain non-unitary gates, weak simulation is used)")
+ ("pv", "display the state vector")
+ ("ps", "print simulation stats (applied gates, sim. time, and maximal size of the DD)")
+ ("pm", "print measurement results")
+ ("verbose", "Causes some simulators to print additional information to STDERR")
+ ("simulate_file", po::value(), "simulate a quantum circuit given by file (detection by the file extension)")
+ ("simulate_qft", po::value(), "simulate Quantum Fourier Transform for given number of qubits")
+ ("simulate_ghz", po::value(), "simulate state preparation of GHZ state for given number of qubits")
+ ("step_fidelity", po::value<>(&step_fidelity)->default_value(1.0), "target fidelity for each approximation run (>=1 = disable approximation)")
+ ("steps", po::value<>(&approx_steps)->default_value(1), "number of approximation steps")
+ ("approx_when", po::value<>(&approx_when)->default_value(ApproximationInfo::FidelityDriven), "approximation method ('fidelity' (default) or 'memory'")
+ ("approx_state", "do excessive approximation runs at the end of the simulation to see how the quantum state behaves")
+ ("simulate_grover", po::value(), "simulate Grover's search for given number of qubits with random oracle")
+ ("simulate_grover_emulated", po::value(), "simulate Grover's search for given number of qubits with random oracle and emulation")
+ ("simulate_grover_oracle_emulated", po::value(), "simulate Grover's search for given number of qubits with given oracle and emulation")
+ ("simulate_shor", po::value(), "simulate Shor's algorithm factoring this number")
+ ("simulate_shor_coprime", po::value()->default_value(0), "coprime number to use with Shor's algorithm (zero randomly generates a coprime)")
+ ("simulate_shor_no_emulation", "Force Shor simulator to do modular exponentiation instead of using emulation (you'll usually want emulation)")
+ ("simulate_fast_shor", po::value(), "simulate Shor's algorithm factoring this number with intermediate measurements")
+ ("simulate_fast_shor_coprime", po::value()->default_value(0),"coprime number to use with Shor's algorithm (zero randomly generates a coprime)");
+ // clang-format on
po::variables_map vm;
try {
po::store(po::parse_command_line(argc, argv, description), vm);
@@ -184,69 +188,32 @@ int main(int argc, char** argv) {
}
}
- if (vm.count("benchmark")) {
- auto more_info = ddsim->AdditionalStatistics();
- std::cout << ddsim->getName() << ", "
- << ddsim->getNumberOfQubits() << ", "
- << std::fixed << duration_simulation.count() << std::defaultfloat << ", "
- << more_info["single_shots"] << ","
- << more_info["approximation_runs"] << ","
- << more_info["final_fidelity"] << ", "
- << more_info["coprime_a"] << ", "
- << more_info["sim_result"] << ", "
- << more_info["polr_result"] << ", "
- << ddsim->getSeed() << ", "
- << ddsim->getNumberOfOps() << ", "
- << ddsim->getMaxNodeCount()
- << "\n";
- return 0;
- }
-
- std::cout << "{\n";
+ nl::json output_obj;
- if (!m.empty()) {
- std::cout << " \"measurements\": {";
- bool first_element = true;
- for (const auto& element: m) {
- std::cout << (first_element ? "" : ",") << "\n \"" << element.first << "\": " << element.second;
- first_element = false;
- }
- std::cout << "\n },\n";
+ if (vm.count("pm")) {
+ output_obj["measurement_results"] = m;
}
- if (vm.count("display_vector")) {
- std::cout << " \"state_vector\": [";
-
- bool first_element = true;
- unsigned long long non_zero_entries = 0;
- for (const auto& element: ddsim->getVector()) {
- if (element.r != 0 || element.i != 0) {
- non_zero_entries++;
- std::cout << (first_element ? "" : ",") << "\n " << std::showpos << element.r << element.i << "i"
- << std::noshowpos;
- } else {
- std::cout << (first_element ? "" : ",") << "\n 0";
- }
- first_element = false;
- }
- std::cout << "\n ],\n";
- std::cout << " \"non_zero_entries\": " << non_zero_entries << ",\n";
+
+ if (vm.count("pv")) {
+ output_obj["state_vector"] = ddsim->getVectorPair();
}
if (vm.count("ps")) {
- std::cout << " \"statistics\": {\n"
- << " \"simulation_time\": " << std::fixed << duration_simulation.count() << std::defaultfloat
- << ",\n"
- << " \"benchmark\": \"" << ddsim->getName() << "\",\n"
- << " \"shots\": " << shots << ",\n"
- << " \"distinct_results\": " << m.size() << ",\n"
- << " \"n_qubits\": " << ddsim->getNumberOfQubits() << ",\n"
- << " \"applied_gates\": " << ddsim->getNumberOfOps() << ",\n"
- << " \"max_nodes\": " << ddsim->getMaxNodeCount() << ",\n";
+ output_obj["statistics"] = {
+ {"simulation_time", duration_simulation.count()},
+ {"benchmark", ddsim->getName()},
+ {"n_qubits", +ddsim->getNumberOfQubits()},
+ {"applied_gates", ddsim->getNumberOfOps()},
+ {"max_nodes", ddsim->getMaxNodeCount()},
+ {"shots", shots},
+ {"distinct_results", m.size()},
+ {"seed", ddsim->getSeed()},
+ };
+
for (const auto& item: ddsim->AdditionalStatistics()) {
- std::cout << " \"" << item.first << "\": \"" << item.second << "\",\n";
+ output_obj["statistics"][item.first] = item.second;
}
- std::cout << " \"seed\": " << ddsim->getSeed() << "\n"
- << " },\n";
}
- std::cout << " \"dummy\": 0\n}\n"; // trailing element to make json printout easier
+
+ std::cout << std::setw(2) << output_obj << std::endl;
}
diff --git a/extern/qfr b/extern/qfr
index d420683f..7bb2681a 160000
--- a/extern/qfr
+++ b/extern/qfr
@@ -1 +1 @@
-Subproject commit d420683fb9e18a522d60d318f6e9311886acd051
+Subproject commit 7bb2681a3fcecd42f7440fb352ce86900cf0fcb4
diff --git a/include/Simulator.hpp b/include/Simulator.hpp
index 327daeb3..74cba7bc 100644
--- a/include/Simulator.hpp
+++ b/include/Simulator.hpp
@@ -45,6 +45,8 @@ class Simulator {
[[nodiscard]] std::vector getVector() const;
+ [[nodiscard]] std::vector> getVectorPair() const;
+
[[nodiscard]] std::size_t getActiveNodeCount() const { return dd->vUniqueTable.getActiveNodeCount(); }
[[nodiscard]] std::size_t getMaxNodeCount() const { return dd->vUniqueTable.getMaxActiveNodes(); }
diff --git a/include/StochasticNoiseSimulator.hpp b/include/StochasticNoiseSimulator.hpp
new file mode 100644
index 00000000..87ff3324
--- /dev/null
+++ b/include/StochasticNoiseSimulator.hpp
@@ -0,0 +1,142 @@
+#ifndef DDSIM_STOCHASTICNOISESIMULATOR_HPP
+#define DDSIM_STOCHASTICNOISESIMULATOR_HPP
+
+#include "QuantumComputation.hpp"
+#include "Simulator.hpp"
+
+#include
+#include