From 2541fdbcbba598dbb53a51199e194be325ebad71 Mon Sep 17 00:00:00 2001 From: Jan Drewniok <97012901+Drewniok@users.noreply.github.com> Date: Sat, 7 Sep 2024 07:11:58 +0200 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20Extended=20BDL=20input=20iterator?= =?UTF-8?q?=20to=20support=20different=20SiDB=20input=20representations=20?= =?UTF-8?q?(#521)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * :sparkles: Added an option to decide how input patterns are implemented in terms of perturber placement. * :alembic: add experiment for temperature simulation. * :memo: Update pyfiction docstrings Signed-off-by: GitHub Actions * 🎨 Incorporated pre-commit fixes * :memo: update docu. * 🎨 Incorporated pre-commit fixes * :memo: small fix. * :art: small fix. * :art: small fix to avoid window compile issue. * :memo: Update pyfiction docstrings Signed-off-by: GitHub Actions * :rotating_light: implement clang-tidy warning. * 🎨 Incorporated pre-commit fixes * :memo: update docu. * :art: small fix. * :art: small fix. * :memo: Update pyfiction docstrings Signed-off-by: GitHub Actions * :art: implement Marcel's feedback. * 🎨 Incorporated pre-commit fixes * :memo: Update pyfiction docstrings Signed-off-by: GitHub Actions * :memo: add changelog entry. * :memo: fix changelog entry. --------- Signed-off-by: GitHub Actions Co-authored-by: GitHub Actions Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .../algorithms/iter/bdl_input_iterator.hpp | 28 ++- .../simulation/sidb/critical_temperature.hpp | 8 +- .../simulation/sidb/is_operational.hpp | 8 +- .../pyfiction/pybind11_mkdoc_docstrings.hpp | 80 ++++++--- .../test_displacement_robustness_domain.py | 4 +- cli/cmd/simulation/temp.hpp | 16 +- docs/algorithms/iterators.rst | 2 + docs/changelog.rst | 10 ++ docs/publications.rst | 6 +- .../runtime_analysis.cpp | 2 +- ...itical_temperature_simulation_bestagon.cpp | 70 ++++++++ .../critical_temperature_simulation_siqad.cpp | 67 +++++++ .../algorithms/iter/bdl_input_iterator.hpp | 65 ++++++- .../physical_design/design_sidb_gates.hpp | 1 + .../sidb/calculate_energy_and_state_type.hpp | 1 + .../simulation/sidb/critical_temperature.hpp | 63 ++++--- .../simulation/sidb/is_operational.hpp | 66 ++++--- .../sidb/random_sidb_layout_generator.hpp | 2 +- .../is_sidb_gate_design_impossible.hpp | 10 +- include/fiction/utils/truth_table_utils.hpp | 4 +- .../simulation/sidb/critical_temperature.cpp | 149 +++++++++++----- .../sidb/displacement_robustness_domain.cpp | 114 ++++++------ .../simulation/sidb/is_operational.cpp | 50 ++++++ .../algorithms/simulation/sidb/quickexact.cpp | 4 +- test/utils/blueprints/layout_blueprints.hpp | 166 +++++++++++++++++- 25 files changed, 765 insertions(+), 231 deletions(-) rename experiments/sidb_simulation/{ => electrostatic_ground_state}/runtime_analysis.cpp (99%) create mode 100644 experiments/sidb_simulation/temperature/critical_temperature_simulation_bestagon.cpp create mode 100644 experiments/sidb_simulation/temperature/critical_temperature_simulation_siqad.cpp diff --git a/bindings/pyfiction/include/pyfiction/algorithms/iter/bdl_input_iterator.hpp b/bindings/pyfiction/include/pyfiction/algorithms/iter/bdl_input_iterator.hpp index 45dbe7fda..8a0ab7bdf 100644 --- a/bindings/pyfiction/include/pyfiction/algorithms/iter/bdl_input_iterator.hpp +++ b/bindings/pyfiction/include/pyfiction/algorithms/iter/bdl_input_iterator.hpp @@ -32,8 +32,8 @@ void bdl_input_iterator(pybind11::module& m, const std::string& lattice) py::class_>(m, fmt::format("bdl_input_iterator_{}", lattice).c_str(), DOC(fiction_bdl_input_iterator)) - .def(py::init(), "lyt"_a, - "params"_a = fiction::detect_bdl_pairs_params{}, DOC(fiction_bdl_input_iterator_bdl_input_iterator)) + .def(py::init(), "lyt"_a, + "params"_a = fiction::bdl_input_iterator_params{}, DOC(fiction_bdl_input_iterator_bdl_input_iterator)) .def( "__next__", [](fiction::bdl_input_iterator& self) -> Lyt& @@ -102,6 +102,30 @@ void bdl_input_iterator(pybind11::module& m, const std::string& lattice) inline void bdl_input_iterator(pybind11::module& m) { + namespace py = pybind11; + using namespace py::literals; + + /** + * Input BDL configuration + */ + py::enum_(m, "input_bdl_configuration") + .value("PERTURBER_ABSENCE_ENCODED", + fiction::bdl_input_iterator_params::input_bdl_configuration::PERTURBER_ABSENCE_ENCODED, + DOC(fiction_bdl_input_iterator_params_input_bdl_configuration_PERTURBER_ABSENCE_ENCODED)) + .value("PERTURBER_DISTANCE_ENCODED", + fiction::bdl_input_iterator_params::input_bdl_configuration::PERTURBER_DISTANCE_ENCODED, + DOC(fiction_bdl_input_iterator_params_input_bdl_configuration_PERTURBER_DISTANCE_ENCODED)); + + /** + * BDL input iterator parameters. + */ + py::class_(m, "bdl_input_iterator_params") + .def(py::init<>()) + .def_readwrite("input_bdl_config", &fiction::bdl_input_iterator_params::input_bdl_config, + DOC(fiction_bdl_input_iterator_params_input_bdl_config)) + .def_readwrite("bdl_pairs_params", &fiction::bdl_input_iterator_params::bdl_pairs_params, + DOC(fiction_bdl_input_iterator_params_bdl_pairs_params)); + // NOTE be careful with the order of the following calls! Python will resolve the first matching overload! detail::bdl_input_iterator(m, "100"); diff --git a/bindings/pyfiction/include/pyfiction/algorithms/simulation/sidb/critical_temperature.hpp b/bindings/pyfiction/include/pyfiction/algorithms/simulation/sidb/critical_temperature.hpp index e2e60e8e2..c28979678 100644 --- a/bindings/pyfiction/include/pyfiction/algorithms/simulation/sidb/critical_temperature.hpp +++ b/bindings/pyfiction/include/pyfiction/algorithms/simulation/sidb/critical_temperature.hpp @@ -67,11 +67,9 @@ inline void critical_temperature(pybind11::module& m) .def("report", &fiction::critical_temperature_stats::report, DOC(fiction_critical_temperature_stats_report)) .def_readonly("algorithm_name", &fiction::critical_temperature_stats::algorithm_name, DOC(fiction_critical_temperature_stats_algorithm_name)) - .def_readonly("critical_temperature", &fiction::critical_temperature_stats::critical_temperature, - DOC(fiction_critical_temperature_stats_critical_temperature)) .def_readonly("num_valid_lyt", &fiction::critical_temperature_stats::num_valid_lyt, DOC(fiction_critical_temperature_stats_num_valid_lyt)) - .def_readonly("energy_between_ground_state_and_first_erroneous", + .def_readonly("is_ground_state_transparent", &fiction::critical_temperature_stats::energy_between_ground_state_and_first_erroneous, DOC(fiction_critical_temperature_stats_energy_between_ground_state_and_first_erroneous)) @@ -91,8 +89,8 @@ inline void critical_temperature(pybind11::module& m) DOC(fiction_critical_temperature_params_confidence_level)) .def_readwrite("max_temperature", &fiction::critical_temperature_params::max_temperature, DOC(fiction_critical_temperature_params_max_temperature)) - .def_readwrite("bdl_params", &fiction::critical_temperature_params::bdl_params, - DOC(fiction_critical_temperature_params_bdl_params)); + .def_readwrite("input_bdl_iterator_params", &fiction::critical_temperature_params::input_bdl_iterator_params, + DOC(fiction_critical_temperature_params_input_bdl_iterator_params)); // NOTE be careful with the order of the following calls! Python will resolve the first matching overload! diff --git a/bindings/pyfiction/include/pyfiction/algorithms/simulation/sidb/is_operational.hpp b/bindings/pyfiction/include/pyfiction/algorithms/simulation/sidb/is_operational.hpp index eed84bd03..c408ad5c6 100644 --- a/bindings/pyfiction/include/pyfiction/algorithms/simulation/sidb/is_operational.hpp +++ b/bindings/pyfiction/include/pyfiction/algorithms/simulation/sidb/is_operational.hpp @@ -30,7 +30,7 @@ void is_operational(pybind11::module& m) "params"_a = fiction::is_operational_params{}, DOC(fiction_is_operational)); m.def("operational_input_patterns", &fiction::operational_input_patterns, "lyt"_a, "spec"_a, - "params"_a = fiction::is_operational_params{}, DOC(fiction_is_operational)); + "params"_a = fiction::is_operational_params{}, DOC(fiction_operational_input_patterns)); } } // namespace detail @@ -47,11 +47,11 @@ inline void is_operational(pybind11::module& m) py::class_(m, "is_operational_params", DOC(fiction_is_operational_params)) .def(py::init<>()) .def_readwrite("simulation_parameters", &fiction::is_operational_params::simulation_parameters, - DOC(fiction_is_operational_params)) + DOC(fiction_is_operational_params_simulation_parameters)) .def_readwrite("sim_engine", &fiction::is_operational_params::sim_engine, DOC(fiction_is_operational_params_sim_engine)) - .def_readwrite("bdl_params", &fiction::is_operational_params::bdl_params, - DOC(fiction_is_operational_params_bdl_params)); + .def_readwrite("input_bdl_iterator_params", &fiction::is_operational_params::input_bdl_iterator_params, + DOC(fiction_is_operational_params_input_bdl_iterator_params)); // NOTE be careful with the order of the following calls! Python will resolve the first matching overload! diff --git a/bindings/pyfiction/include/pyfiction/pybind11_mkdoc_docstrings.hpp b/bindings/pyfiction/include/pyfiction/pybind11_mkdoc_docstrings.hpp index 4c7fecf43..b00c893ac 100644 --- a/bindings/pyfiction/include/pyfiction/pybind11_mkdoc_docstrings.hpp +++ b/bindings/pyfiction/include/pyfiction/pybind11_mkdoc_docstrings.hpp @@ -524,7 +524,7 @@ Parameter ``lyt``: The SiDB BDL layout to iterate over. Parameter ``params``: - Parameters for the BDL pair detection.)doc"; + Parameters for the BDL input iterator.)doc"; static const char *__doc_fiction_bdl_input_iterator_current_input_index = R"doc(The current input index. There are :math:`2^n` possible input states @@ -703,6 +703,38 @@ Parameter ``other``: The difference between the current input index and the given iterator ones.)doc"; +static const char *__doc_fiction_bdl_input_iterator_params = R"doc(Parameters for the BDL input iterator.)doc"; + +static const char *__doc_fiction_bdl_input_iterator_params_2 = R"doc(Parameters for the BDL input iterator.)doc"; + +static const char *__doc_fiction_bdl_input_iterator_params_bdl_pairs_params = R"doc(Parameters to detect BDL pairs.)doc"; + +static const char *__doc_fiction_bdl_input_iterator_params_input_bdl_config = +R"doc(The `input_bdl_config` member allows selection between different modes +for handling input BDLs.)doc"; + +static const char *__doc_fiction_bdl_input_iterator_params_input_bdl_configuration = +R"doc(This enum defines how BDL inputs are manipulated within the algorithm. +According to existing literature, there are two main approaches for +handling BDL inputs: + +1. A perturber is used to set the input to `1`, while the absence of a +perturber represents a `0` (as described in +https://ieeexplore.ieee.org/abstract/document/8963859). 2. An input of +`1` is generated by placing a perturber closer to the target, whereas +a `0` is produced by positioning the perturber farther away (as +described in https://dl.acm.org/doi/10.1145/3489517.3530525).)doc"; + +static const char *__doc_fiction_bdl_input_iterator_params_input_bdl_configuration_PERTURBER_ABSENCE_ENCODED = +R"doc(A perturber is used to set the input to `1`, while the absence of a +perturber represents a `0` (as described in +https://ieeexplore.ieee.org/abstract/document/8963859).)doc"; + +static const char *__doc_fiction_bdl_input_iterator_params_input_bdl_configuration_PERTURBER_DISTANCE_ENCODED = +R"doc(An input of `1` is generated by placing a perturber closer to the BDL +wire, whereas a `0` is produced by positioning the perturber farther +away (as described in https://dl.acm.org/doi/10.1145/3489517.3530525).)doc"; + static const char *__doc_fiction_bdl_input_iterator_set_all_inputs = R"doc(Sets all input cells of the layout according to the current input index. The input index is interpreted as a binary number, where the @@ -3075,8 +3107,6 @@ static const char *__doc_fiction_critical_temperature_params_alpha = R"doc(Alpha parameter for the *QuickSim* algorithm (only applicable if engine == APPROXIMATE).)doc"; -static const char *__doc_fiction_critical_temperature_params_bdl_params = R"doc(Parameters for the BDL pair detection algorithms.)doc"; - static const char *__doc_fiction_critical_temperature_params_confidence_level = R"doc(Probability threshold for ground state population. The temperature at which the simulation finds the ground state to be populated with a @@ -3086,6 +3116,8 @@ probability of erroneous calculations of the gate.)doc"; static const char *__doc_fiction_critical_temperature_params_engine = R"doc(Simulation mode to determine the *Critical Temperature*.)doc"; +static const char *__doc_fiction_critical_temperature_params_input_bdl_iterator_params = R"doc(Parameters for the BDL input iterator.)doc"; + static const char *__doc_fiction_critical_temperature_params_iteration_steps = R"doc(Number of iteration steps for the *QuickSim* algorithm (only applicable if engine == APPROXIMATE).)doc"; @@ -3116,8 +3148,6 @@ static const char *__doc_fiction_critical_temperature_stats_algorithm_name = R"doc(Name of the algorithm used to compute the physically valid charge distributions.)doc"; -static const char *__doc_fiction_critical_temperature_stats_critical_temperature = R"doc(*Critical Temperature* of the given layout (unit: K).)doc"; - static const char *__doc_fiction_critical_temperature_stats_energy_between_ground_state_and_first_erroneous = R"doc(Energy difference between the ground state and the first (erroneous) excited state (unit: meV).)doc"; @@ -4155,6 +4185,8 @@ static const char *__doc_fiction_detail_critical_temperature_impl = R"doc()doc"; static const char *__doc_fiction_detail_critical_temperature_impl_bii = R"doc(Iterator that iterates over all possible input states.)doc"; +static const char *__doc_fiction_detail_critical_temperature_impl_critical_temperature = R"doc(Critical temperature [K].)doc"; + static const char *__doc_fiction_detail_critical_temperature_impl_critical_temperature_impl = R"doc()doc"; static const char *__doc_fiction_detail_critical_temperature_impl_determine_critical_temperature = @@ -4164,23 +4196,6 @@ Parameter ``energy_state_type``: All energies of all physically valid charge distributions with the corresponding state type (i.e. transparent, erroneous).)doc"; -static const char *__doc_fiction_detail_critical_temperature_impl_energy_between_ground_state_and_first_erroneous = -R"doc(The energy difference between the ground state and the first erroneous -state is determined. Additionally, the state type of the ground state -is determined and returned. - -Parameter ``energy_and_state_type``: - All energies of all physically valid charge distributions with the - corresponding state type (i.e. transparent, erroneous). - -Parameter ``min_energy``: - Minimal energy of all physically valid charge distributions of a - given layout (unit: eV). - -Returns: - State type (i.e. transparent, erroneous) of the ground state is - returned.)doc"; - static const char *__doc_fiction_detail_critical_temperature_impl_gate_based_simulation = R"doc(*Gate-based Critical Temperature* Simulation of a SiDB layout for a given Boolean function. @@ -4198,6 +4213,23 @@ R"doc(Returns the critical temperature. Returns: The critical temperature (unit: K).)doc"; +static const char *__doc_fiction_detail_critical_temperature_impl_is_ground_state_transparent = +R"doc(The energy difference between the ground state and the first erroneous +state is determined. Additionally, the state type of the ground state +is determined and returned. + +Parameter ``energy_and_state_type``: + All energies of all physically valid charge distributions with the + corresponding state type (i.e. transparent, erroneous). + +Parameter ``min_energy``: + Minimal energy of all physically valid charge distributions of a + given layout (unit: eV). + +Returns: + State type (i.e. transparent, erroneous) of the ground state is + returned.)doc"; + static const char *__doc_fiction_detail_critical_temperature_impl_layout = R"doc(SiDB cell-level layout.)doc"; static const char *__doc_fiction_detail_critical_temperature_impl_non_gate_based_simulation = @@ -12562,7 +12594,7 @@ Parameter ``params``: static const char *__doc_fiction_is_operational_params = R"doc(Parameters for the `is_operational` algorithm.)doc"; -static const char *__doc_fiction_is_operational_params_bdl_params = R"doc(Parameters for the BDL pair detection algorithms.)doc"; +static const char *__doc_fiction_is_operational_params_input_bdl_iterator_params = R"doc(Parameters for the BDL input iterator.)doc"; static const char *__doc_fiction_is_operational_params_sim_engine = R"doc(The simulation engine to be used for the operational domain @@ -12616,7 +12648,7 @@ static const char *__doc_fiction_is_sidb_gate_design_impossible_params = R"doc(This struct contains parameters to determine if SiDB gate design is impossible.)doc"; -static const char *__doc_fiction_is_sidb_gate_design_impossible_params_detect_bdl_params = R"doc(Parameters used to determine BDL pairs.)doc"; +static const char *__doc_fiction_is_sidb_gate_design_impossible_params_input_bdl_iterator_params = R"doc(Parameters for the BDL input iterator.)doc"; static const char *__doc_fiction_is_sidb_gate_design_impossible_params_simulation_params = R"doc(All parameters for physical SiDB simulations.)doc"; diff --git a/bindings/pyfiction/test/algorithms/simulation/sidb/test_displacement_robustness_domain.py b/bindings/pyfiction/test/algorithms/simulation/sidb/test_displacement_robustness_domain.py index baafef2a3..4d5e0b284 100644 --- a/bindings/pyfiction/test/algorithms/simulation/sidb/test_displacement_robustness_domain.py +++ b/bindings/pyfiction/test/algorithms/simulation/sidb/test_displacement_robustness_domain.py @@ -30,8 +30,8 @@ def test_siqad_and_gate_100_lattice(self): params.displacement_variations = [1, 1] params.operational_params.simulation_parameters = sidb_simulation_parameters(2, -0.28) - params.operational_params.bdl_params.maximum_distance = 2.0 - params.operational_params.bdl_params.minimum_distance = 0.2 + params.operational_params.input_bdl_iterator_params.bdl_pairs_params.maximum_distance = 2.0 + params.operational_params.input_bdl_iterator_params.bdl_pairs_params.minimum_distance = 0.2 # only offset_coordinate(4, 5) and offset_coordinate(10,12) are affected by displacement params.fixed_sidbs = {offset_coordinate(0, 1), offset_coordinate(2, 3), offset_coordinate(20, 1), diff --git a/cli/cmd/simulation/temp.hpp b/cli/cmd/simulation/temp.hpp index 30f5db5f0..55b0087ec 100644 --- a/cli/cmd/simulation/temp.hpp +++ b/cli/cmd/simulation/temp.hpp @@ -68,6 +68,7 @@ class temp_command : public command { // reset statistics stats = {}; + ct = 0.0; if (params.confidence_level <= 0 || params.confidence_level > 1) { @@ -143,12 +144,12 @@ class temp_command : public command const auto tt_ptr = ts.current(); - fiction::critical_temperature_gate_based(*lyt_ptr, std::vector{*tt_ptr}, params, - &stats); + ct = fiction::critical_temperature_gate_based(*lyt_ptr, std::vector{*tt_ptr}, + params, &stats); } else { - fiction::critical_temperature_non_gate_based(*lyt_ptr, params, &stats); + ct = fiction::critical_temperature_non_gate_based(*lyt_ptr, params, &stats); } if (stats.num_valid_lyt == 0) @@ -159,8 +160,7 @@ class temp_command : public command else { env->out() << fmt::format("[i] critical temperature of {} is {}{} K", get_name(lyt_ptr), - (stats.critical_temperature == params.max_temperature ? "> " : ""), - stats.critical_temperature) + (ct == params.max_temperature ? "> " : ""), ct) << std::endl; if (stats.num_valid_lyt > 1) @@ -198,6 +198,10 @@ class temp_command : public command * Critical temperature statistics. */ fiction::critical_temperature_stats stats{}; + /** + * Critical temperature. + */ + double ct = 0.0; /** * Logs the resulting information in a log file. @@ -212,7 +216,7 @@ class temp_command : public command {"epsilon_r", stats.simulation_parameters.epsilon_r}, {"lambda_tf", stats.simulation_parameters.lambda_tf}, {"mu_minus", stats.simulation_parameters.mu_minus}}}, - {"Critical temperature", stats.critical_temperature}, + {"Critical temperature", ct}, {"Number of stable states", stats.num_valid_lyt}, {"Energy difference between ground state and first erroneous state", stats.energy_between_ground_state_and_first_erroneous}}; diff --git a/docs/algorithms/iterators.rst b/docs/algorithms/iterators.rst index 52422782f..47d41c181 100644 --- a/docs/algorithms/iterators.rst +++ b/docs/algorithms/iterators.rst @@ -23,6 +23,8 @@ BDL Input Iterator .. tab:: C++ **Header:** ``fiction/algorithms/iter/bdl_input_iterator.hpp`` + .. doxygenstruct:: fiction::bdl_input_iterator_params + :members: .. doxygenclass:: fiction::bdl_input_iterator :members: diff --git a/docs/changelog.rst b/docs/changelog.rst index dd70cf459..efc11047d 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -5,6 +5,16 @@ All notable changes to this project will be documented in this file. The format is based on `Keep a Changelog `_. +Unreleased``` +------------- + +Added +##### +- Experiments: + - Script to simulate the critical temperature of SiQAD and Bestagon gates +- Algorithms: + - Added support for different ways of implementing input information in SiDB technology to the BDL input iterator + v0.6.4 - 2024-08-30 ------------------- diff --git a/docs/publications.rst b/docs/publications.rst index c69caecb7..d9ce176ee 100644 --- a/docs/publications.rst +++ b/docs/publications.rst @@ -115,7 +115,7 @@ Furthermore, if you use any of the design automation algorithms, please consider year={2023} } - `QuickSim experiment script `_ + `QuickSim experiment script `_ * :ref:`QuickExact ` (``quickexact``): @@ -129,7 +129,7 @@ Furthermore, if you use any of the design automation algorithms, please consider year={2024} } - `QuickExact experiment script `_ + `QuickExact experiment script `_ * :ref:`Critical temperature simulation ` (``critical_temperature``): @@ -143,6 +143,8 @@ Furthermore, if you use any of the design automation algorithms, please consider year={2023} } + `Critical temperature experiment scripts `_ + * :ref:`Operational domain computation ` (``opdom``): .. code-block:: tex diff --git a/experiments/sidb_simulation/runtime_analysis.cpp b/experiments/sidb_simulation/electrostatic_ground_state/runtime_analysis.cpp similarity index 99% rename from experiments/sidb_simulation/runtime_analysis.cpp rename to experiments/sidb_simulation/electrostatic_ground_state/runtime_analysis.cpp index ee4b30bdd..20f8a23e0 100644 --- a/experiments/sidb_simulation/runtime_analysis.cpp +++ b/experiments/sidb_simulation/electrostatic_ground_state/runtime_analysis.cpp @@ -13,9 +13,9 @@ #include "fiction/types.hpp" #include "fiction/utils/truth_table_utils.hpp" #include "fiction_experiments.hpp" -#include "mockturtle/utils/stopwatch.hpp" #include +#include #include #include diff --git a/experiments/sidb_simulation/temperature/critical_temperature_simulation_bestagon.cpp b/experiments/sidb_simulation/temperature/critical_temperature_simulation_bestagon.cpp new file mode 100644 index 000000000..641ada4bf --- /dev/null +++ b/experiments/sidb_simulation/temperature/critical_temperature_simulation_bestagon.cpp @@ -0,0 +1,70 @@ +// +// Created by Jan Drewniok on 03.09.24. +// + +#include "fiction_experiments.hpp" + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +using namespace fiction; + +int main() // NOLINT +{ + experiments::experiment simulation_exp{ + "Benchmark", + "Gate Name", + "Critical Temperature [K]", + "E_{g,err} [meV]", + }; + + static const std::string folder = fmt::format("{}bestagon_gates_type_tags/", EXPERIMENTS_PATH); + + static const std::array>, 12> gates = { + std::make_pair("hourglass", create_double_wire_tt()), + std::make_pair("cx", create_crossing_wire_tt()), + std::make_pair("ha", create_half_adder_tt()), + std::make_pair("and", std::vector{create_and_tt()}), + std::make_pair("xor", std::vector{create_xor_tt()}), + std::make_pair("or", std::vector{create_or_tt()}), + std::make_pair("xnor", std::vector{create_xnor_tt()}), + std::make_pair("fo2", std::vector{create_fan_out_tt()}), + std::make_pair("nor", std::vector{create_nor_tt()}), + std::make_pair("nand", std::vector{create_nand_tt()}), + std::make_pair("inv", std::vector{create_not_tt()}), + std::make_pair("wire", std::vector{create_id_tt()})}; + + const sidb_simulation_parameters sim_params{2, -0.32}; + const critical_temperature_params ct_params{sim_params}; + + for (const auto& [gate, truth_table] : gates) + { + for (const auto& file : std::filesystem::directory_iterator(fmt::format("{}{}", folder, gate))) + { + const auto layout = read_sqd_layout(file.path().string()); + + critical_temperature_stats ct_stats{}; + + const auto ct = + critical_temperature_gate_based(layout, truth_table, ct_params, &ct_stats); + + simulation_exp(gate, ct, ct_stats.energy_between_ground_state_and_first_erroneous); + simulation_exp.save(); + simulation_exp.table(); + } + } + return EXIT_SUCCESS; +} diff --git a/experiments/sidb_simulation/temperature/critical_temperature_simulation_siqad.cpp b/experiments/sidb_simulation/temperature/critical_temperature_simulation_siqad.cpp new file mode 100644 index 000000000..0ba6959e8 --- /dev/null +++ b/experiments/sidb_simulation/temperature/critical_temperature_simulation_siqad.cpp @@ -0,0 +1,67 @@ +// +// Created by Jan Drewniok on 03.09.24. +// + +#include "fiction_experiments.hpp" + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +using namespace fiction; + +int main() // NOLINT +{ + experiments::experiment simulation_exp{ + "Benchmark", + "Gate Name", + "Critical Temperature [K]", + "E_{g,err} [meV]", + }; + + static const std::string folder = fmt::format("{}siqad_gates_type_tags/", EXPERIMENTS_PATH); + + static const std::array>, 5> gates = { + std::make_pair("and", std::vector{create_and_tt()}), + std::make_pair("nand", std::vector{create_nand_tt()}), + std::make_pair("xnor", std::vector{create_xnor_tt()}), + std::make_pair("xor", std::vector{create_xor_tt()}), std::make_pair("or", std::vector{create_or_tt()})}; + + const sidb_simulation_parameters sim_params{2, -0.28}; + critical_temperature_params ct_params{sim_params}; + + // this is how the gates are presented and simulated in "SiQAD: A Design and Simulation Tool for Atomic Silicon + // Quantum Dot Circuits\" by Samuel Sze Hang Ng, Jacob Retallick, Hsi Nien Chiu, Robert Lupoiu, Lucian Livadaru, + // Taleana Huff, Mohammad Rashidi, Wyatt Vine, Thomas Dienel, Robert A. Wolkow, and Konrad Walus in IEEE + // TRANSACTIONS ON NANOTECHNOLOGY, Volume 19, 2020. (https://ieeexplore.ieee.org/abstract/document/8963859) + ct_params.input_bdl_iterator_params.input_bdl_config = + bdl_input_iterator_params::input_bdl_configuration::PERTURBER_ABSENCE_ENCODED; + + for (const auto& [gate, truth_table] : gates) + { + for (const auto& file : std::filesystem::directory_iterator(fmt::format("{}{}", folder, gate))) + { + const auto layout = read_sqd_layout(file.path().string()); + + critical_temperature_stats ct_stats{}; + const auto ct = + critical_temperature_gate_based(layout, truth_table, ct_params, &ct_stats); + + simulation_exp(gate, ct, ct_stats.energy_between_ground_state_and_first_erroneous); + simulation_exp.save(); + simulation_exp.table(); + } + } + return EXIT_SUCCESS; +} diff --git a/include/fiction/algorithms/iter/bdl_input_iterator.hpp b/include/fiction/algorithms/iter/bdl_input_iterator.hpp index 51e15b5d5..79e5ee454 100644 --- a/include/fiction/algorithms/iter/bdl_input_iterator.hpp +++ b/include/fiction/algorithms/iter/bdl_input_iterator.hpp @@ -17,6 +17,43 @@ namespace fiction { +/** + * Parameters for the BDL input iterator. + */ +struct bdl_input_iterator_params +{ + /** + * This enum defines how BDL inputs are manipulated within the algorithm. + * According to existing literature, there are two main approaches for handling BDL inputs: + * + * 1. A perturber is used to set the input to `1`, while the absence of a perturber represents a `0` + * (as described in https://ieeexplore.ieee.org/abstract/document/8963859). + * 2. An input of `1` is generated by placing a perturber closer to the target, whereas a `0` is produced + * by positioning the perturber farther away (as described in https://dl.acm.org/doi/10.1145/3489517.3530525). + */ + enum class input_bdl_configuration : uint8_t + { + /** + * An input of `1` is generated by placing a perturber closer to the BDL wire, whereas a `0` is produced + * by positioning the perturber farther away (as described in https://dl.acm.org/doi/10.1145/3489517.3530525). + */ + PERTURBER_DISTANCE_ENCODED, + /** + * A perturber is used to set the input to `1`, while the absence of a perturber represents a `0` + * (as described in https://ieeexplore.ieee.org/abstract/document/8963859). + */ + PERTURBER_ABSENCE_ENCODED + }; + /** + * The `input_bdl_config` member allows selection between different modes for handling input BDLs. + */ + input_bdl_configuration input_bdl_config{input_bdl_configuration::PERTURBER_DISTANCE_ENCODED}; + /** + * Parameters to detect BDL pairs. + */ + detect_bdl_pairs_params bdl_pairs_params{}; +}; + /** * Iterator that iterates over all possible input states of a BDL layout. There are \f$2^n\f$ possible input states * for an \f$n\f$-input BDL layout, each with a unique input index. The input index is interpreted as a binary number, @@ -39,11 +76,13 @@ class bdl_input_iterator * BDL pairs. * * @param lyt The SiDB BDL layout to iterate over. - * @param params Parameters for the BDL pair detection. + * @param params Parameters for the BDL input iterator. */ - explicit bdl_input_iterator(const Lyt& lyt, const detect_bdl_pairs_params& params = {}) noexcept : + explicit bdl_input_iterator(const Lyt& lyt, + const bdl_input_iterator_params& params = bdl_input_iterator_params{}) noexcept : layout{lyt.clone()}, - input_pairs{detect_bdl_pairs(layout, sidb_technology::cell_type::INPUT, params)} + input_pairs{detect_bdl_pairs(layout, sidb_technology::cell_type::INPUT, params.bdl_pairs_params)}, + params{params} { static_assert(is_cell_level_layout_v, "Lyt is not a cell-level layout"); static_assert(has_sidb_technology_v, "Lyt is not an SiDB layout"); @@ -289,6 +328,10 @@ class bdl_input_iterator * The current input index. There are \f$2^n\f$ possible input states for an \f$n\f$-input BDL layout. */ uint64_t current_input_index{0ull}; + /** + * Parameters for the BDL input iterator. + */ + const bdl_input_iterator_params params; /** * Sets all input cells of the layout according to the current input index. The input index is interpreted as a @@ -310,9 +353,19 @@ class bdl_input_iterator } else { - // set input i to 0 - layout.assign_cell_type(input_i.upper, technology::cell_type::INPUT); - layout.assign_cell_type(input_i.lower, technology::cell_type::EMPTY); + if (params.input_bdl_config == + bdl_input_iterator_params::input_bdl_configuration::PERTURBER_DISTANCE_ENCODED) + { + // set input i to 0 + layout.assign_cell_type(input_i.upper, technology::cell_type::INPUT); + layout.assign_cell_type(input_i.lower, technology::cell_type::EMPTY); + } + else + { + // set input i to 0 + layout.assign_cell_type(input_i.upper, technology::cell_type::EMPTY); + layout.assign_cell_type(input_i.lower, technology::cell_type::EMPTY); + } } } } diff --git a/include/fiction/algorithms/physical_design/design_sidb_gates.hpp b/include/fiction/algorithms/physical_design/design_sidb_gates.hpp index 908f07ad8..820589baf 100644 --- a/include/fiction/algorithms/physical_design/design_sidb_gates.hpp +++ b/include/fiction/algorithms/physical_design/design_sidb_gates.hpp @@ -43,6 +43,7 @@ namespace fiction template struct design_sidb_gates_params { + // TODO (Jan Drewniok): After PR481 is merged, add bdl_input_iterator_params. /** * Selector for the different termination conditions for the SiDB gate design process. */ diff --git a/include/fiction/algorithms/simulation/sidb/calculate_energy_and_state_type.hpp b/include/fiction/algorithms/simulation/sidb/calculate_energy_and_state_type.hpp index 3067c1649..3a85791d5 100644 --- a/include/fiction/algorithms/simulation/sidb/calculate_energy_and_state_type.hpp +++ b/include/fiction/algorithms/simulation/sidb/calculate_energy_and_state_type.hpp @@ -72,6 +72,7 @@ calculate_energy_and_state_type(const sidb_energy_distribution& physical_constants::POP_STABILITY_ERR) { bool correct_output = true; + for (auto i = 0u; i < output_bdl_pairs.size(); i++) { if (static_cast(-charge_state_to_sign(valid_layout.get_charge_state( diff --git a/include/fiction/algorithms/simulation/sidb/critical_temperature.hpp b/include/fiction/algorithms/simulation/sidb/critical_temperature.hpp index 576cde678..246d8de10 100644 --- a/include/fiction/algorithms/simulation/sidb/critical_temperature.hpp +++ b/include/fiction/algorithms/simulation/sidb/critical_temperature.hpp @@ -76,9 +76,9 @@ struct critical_temperature_params */ double max_temperature{400}; /** - * Parameters for the BDL pair detection algorithms. + * Parameters for the BDL input iterator. */ - detect_bdl_pairs_params bdl_params{}; + bdl_input_iterator_params input_bdl_iterator_params{}; /** * Number of iteration steps for the *QuickSim* algorithm (only applicable if engine == APPROXIMATE). */ @@ -102,10 +102,6 @@ struct critical_temperature_stats * Name of the algorithm used to compute the physically valid charge distributions. */ std::string algorithm_name{}; - /** - * *Critical Temperature* of the given layout (unit: K). - */ - double critical_temperature{0}; /** * Number of physically valid charge configurations. */ @@ -121,8 +117,6 @@ struct critical_temperature_stats */ void report(std::ostream& out = std::cout) const { - out << fmt::format("Critical Temperature = {:.2f} K\n", critical_temperature); - if (num_valid_lyt != 0) { out << fmt::format("'# of physically valid charge configurations': {} | Energy between ground state and " @@ -149,13 +143,13 @@ class critical_temperature_impl layout{lyt}, params{ps}, stats{st}, - bii(bdl_input_iterator{layout, params.bdl_params}) + bii(bdl_input_iterator{layout, params.input_bdl_iterator_params}), + critical_temperature{ps.max_temperature} { stats.simulation_parameters = params.simulation_parameters; stats.algorithm_name = (params.engine == critical_temperature_params::simulation_engine::EXACT) ? "QuickExact" : "QuickSim"; - stats.critical_temperature = params.max_temperature; } /** @@ -169,14 +163,14 @@ class critical_temperature_impl { if (layout.is_empty()) { - stats.critical_temperature = 0.0; + critical_temperature = 0.0; return; } if (layout.num_cells() > 1) { - const auto output_bdl_pairs = - detect_bdl_pairs(layout, sidb_technology::cell_type::OUTPUT, params.bdl_params); + const auto output_bdl_pairs = detect_bdl_pairs(layout, sidb_technology::cell_type::OUTPUT, + params.input_bdl_iterator_params.bdl_pairs_params); // number of different input combinations for (auto i = 0u; i < spec.front().num_bits(); ++i, ++bii) @@ -184,7 +178,7 @@ class critical_temperature_impl // if positively charged SiDBs can occur, the SiDB layout is considered as non-operational if (can_positive_charges_occur(*bii, params.simulation_parameters)) { - stats.critical_temperature = 0.0; + critical_temperature = 0.0; return; } @@ -192,7 +186,7 @@ class critical_temperature_impl const auto sim_result = physical_simulation_of_layout(bii); if (sim_result.charge_distributions.empty()) { - stats.critical_temperature = 0.0; + critical_temperature = 0.0; return; } stats.num_valid_lyt = sim_result.charge_distributions.size(); @@ -201,14 +195,12 @@ class critical_temperature_impl const auto distribution = energy_distribution(sim_result.charge_distributions); // A label that indicates whether the state still fulfills the logic. - sidb_energy_and_state_type energy_state_type{}; - energy_state_type = calculate_energy_and_state_type(distribution, sim_result.charge_distributions, - output_bdl_pairs, spec, i); + const auto energy_state_type = calculate_energy_and_state_type( + distribution, sim_result.charge_distributions, output_bdl_pairs, spec, i); const auto min_energy = energy_state_type.cbegin()->first; - auto ground_state_is_transparent = - energy_between_ground_state_and_first_erroneous(energy_state_type, min_energy); + auto ground_state_is_transparent = is_ground_state_transparent(energy_state_type, min_energy); if (ground_state_is_transparent) { @@ -217,8 +209,8 @@ class critical_temperature_impl else { - stats.critical_temperature = 0.0; // If no ground state fulfills the logic, the Critical - // Temperature is zero. May be worth it to change µ_. + critical_temperature = 0.0; // If no ground state fulfills the logic, the Critical + // Temperature is zero. May be worth it to change µ_. } } } @@ -282,18 +274,18 @@ class critical_temperature_impl { // If the occupation probability of excited states exceeds the given threshold. if (occupation_probability_non_gate_based(distribution, temp) > (1 - params.confidence_level) && - (temp < stats.critical_temperature)) + (temp < critical_temperature)) { // The current temperature is stored as the critical temperature. - stats.critical_temperature = temp; + critical_temperature = temp; break; } - if (std::abs(temp - params.max_temperature) < 0.001 && (temp < stats.critical_temperature)) + if (std::abs(temp - params.max_temperature) < 0.001 && (temp < critical_temperature)) { // Maximal temperature is stored as the Critical Temperature. - stats.critical_temperature = params.max_temperature; + critical_temperature = params.max_temperature; } } } @@ -304,7 +296,7 @@ class critical_temperature_impl */ [[nodiscard]] double get_critical_temperature() const noexcept { - return stats.critical_temperature; + return critical_temperature; } private: @@ -317,10 +309,11 @@ class critical_temperature_impl * @param min_energy Minimal energy of all physically valid charge distributions of a given layout (unit: eV). * @return State type (i.e. transparent, erroneous) of the ground state is returned. */ - bool energy_between_ground_state_and_first_erroneous(const sidb_energy_and_state_type& energy_and_state_type, - const double min_energy) noexcept + bool is_ground_state_transparent(const sidb_energy_and_state_type& energy_and_state_type, + const double min_energy) noexcept { bool ground_state_is_transparent = false; + for (const auto& [energy, state_type] : energy_and_state_type) { // Check if there is at least one ground state that satisfies the logic (transparent). Round the energy @@ -364,16 +357,16 @@ class critical_temperature_impl { // If the occupation probability of erroneous states exceeds the given threshold... if (occupation_probability_gate_based(energy_state_type, temp) > (1 - params.confidence_level) && - (temp < stats.critical_temperature)) + (temp < critical_temperature)) { // The current temperature is stored as Critical Temperature. - stats.critical_temperature = temp; + critical_temperature = temp; break; } - if (std::abs(temp - params.max_temperature) < 0.001 && (temp < stats.critical_temperature)) + if (std::abs(temp - params.max_temperature) < 0.001 && (temp < critical_temperature)) { // Maximal temperature is stored as Critical Temperature. - stats.critical_temperature = params.max_temperature; + critical_temperature = params.max_temperature; } } } @@ -390,6 +383,10 @@ class critical_temperature_impl * Statistics. */ critical_temperature_stats& stats; + /** + * Critical temperature [K]. + */ + double critical_temperature; /** * Iterator that iterates over all possible input states. */ diff --git a/include/fiction/algorithms/simulation/sidb/is_operational.hpp b/include/fiction/algorithms/simulation/sidb/is_operational.hpp index 47afbbfae..70435c82a 100644 --- a/include/fiction/algorithms/simulation/sidb/is_operational.hpp +++ b/include/fiction/algorithms/simulation/sidb/is_operational.hpp @@ -8,6 +8,7 @@ #include "fiction/algorithms/iter/bdl_input_iterator.hpp" #include "fiction/algorithms/simulation/sidb/can_positive_charges_occur.hpp" #include "fiction/algorithms/simulation/sidb/detect_bdl_pairs.hpp" +#include "fiction/algorithms/simulation/sidb/determine_groundstate_from_simulation_results.hpp" #include "fiction/algorithms/simulation/sidb/energy_distribution.hpp" #include "fiction/algorithms/simulation/sidb/exhaustive_ground_state_simulation.hpp" #include "fiction/algorithms/simulation/sidb/quickexact.hpp" @@ -62,9 +63,9 @@ struct is_operational_params */ sidb_simulation_engine sim_engine{sidb_simulation_engine::QUICKEXACT}; /** - * Parameters for the BDL pair detection algorithms. + * Parameters for the BDL input iterator. */ - detect_bdl_pairs_params bdl_params{}; + bdl_input_iterator_params input_bdl_iterator_params{}; }; namespace detail @@ -95,8 +96,9 @@ class is_operational_impl layout{lyt}, truth_table{tt}, parameters{params}, - output_bdl_pairs(detect_bdl_pairs(layout, sidb_technology::cell_type::OUTPUT, parameters.bdl_params)), - bii(bdl_input_iterator{layout, parameters.bdl_params}) + output_bdl_pairs(detect_bdl_pairs(layout, sidb_technology::cell_type::OUTPUT, + parameters.input_bdl_iterator_params.bdl_pairs_params)), + bii(bdl_input_iterator{layout, parameters.input_bdl_iterator_params}) {} /** @@ -133,45 +135,39 @@ class is_operational_impl return operational_status::NON_OPERATIONAL; } - // find the ground state, which is the charge distribution with the lowest energy - const auto ground_state = std::min_element( - simulation_results.charge_distributions.cbegin(), simulation_results.charge_distributions.cend(), - [](const auto& lhs, const auto& rhs) { return lhs.get_system_energy() < rhs.get_system_energy(); }); - - // ground state is degenerate - if ((energy_distribution(simulation_results.charge_distributions).begin()->second) > 1) - { - return operational_status::NON_OPERATIONAL; - } + const auto ground_states = determine_groundstate_from_simulation_results(simulation_results); - // fetch the charge states of the output BDL pair - for (auto output = 0u; output < output_bdl_pairs.size(); output++) + for (const auto& gs : ground_states) { - const auto charge_state_output_upper = ground_state->get_charge_state(output_bdl_pairs[output].upper); - const auto charge_state_output_lower = ground_state->get_charge_state(output_bdl_pairs[output].lower); - - // if the output charge states are equal, the layout is not operational - if (charge_state_output_lower == charge_state_output_upper) + // fetch the charge states of the output BDL pair + for (auto output = 0u; output < output_bdl_pairs.size(); output++) { - return operational_status::NON_OPERATIONAL; - } + const auto charge_state_output_upper = gs.get_charge_state(output_bdl_pairs[output].upper); + const auto charge_state_output_lower = gs.get_charge_state(output_bdl_pairs[output].lower); - // if the expected output is 1, the expected charge states are (upper, lower) = (0, -1) - if (kitty::get_bit(truth_table[output], i)) - { - if (charge_state_output_upper != sidb_charge_state::NEUTRAL || - charge_state_output_lower != sidb_charge_state::NEGATIVE) + // if the output charge states are equal, the layout is not operational + if (charge_state_output_lower == charge_state_output_upper) { return operational_status::NON_OPERATIONAL; } - } - // if the expected output is 0, the expected charge states are (upper, lower) = (-1, 0) - else - { - if (charge_state_output_upper != sidb_charge_state::NEGATIVE || - charge_state_output_lower != sidb_charge_state::NEUTRAL) + + // if the expected output is 1, the expected charge states are (upper, lower) = (0, -1) + if (kitty::get_bit(truth_table[output], i)) { - return operational_status::NON_OPERATIONAL; + if (charge_state_output_upper != sidb_charge_state::NEUTRAL || + charge_state_output_lower != sidb_charge_state::NEGATIVE) + { + return operational_status::NON_OPERATIONAL; + } + } + // if the expected output is 0, the expected charge states are (upper, lower) = (-1, 0) + else + { + if (charge_state_output_upper != sidb_charge_state::NEGATIVE || + charge_state_output_lower != sidb_charge_state::NEUTRAL) + { + return operational_status::NON_OPERATIONAL; + } } } } diff --git a/include/fiction/algorithms/simulation/sidb/random_sidb_layout_generator.hpp b/include/fiction/algorithms/simulation/sidb/random_sidb_layout_generator.hpp index 79b1d5f3b..3027dad12 100644 --- a/include/fiction/algorithms/simulation/sidb/random_sidb_layout_generator.hpp +++ b/include/fiction/algorithms/simulation/sidb/random_sidb_layout_generator.hpp @@ -73,7 +73,7 @@ struct generate_random_sidb_layout_params * even impossible to find several unique (given by number_of_unique_generated_layouts) layouts. Therefore, this * parameter sets a limit for the maximum number of tries. */ - uint64_t maximal_attempts_for_multiple_layouts = 10E6; + uint64_t maximal_attempts_for_multiple_layouts = 1'000'000; }; /** diff --git a/include/fiction/technology/is_sidb_gate_design_impossible.hpp b/include/fiction/technology/is_sidb_gate_design_impossible.hpp index 89d6ae12e..340c744fa 100644 --- a/include/fiction/technology/is_sidb_gate_design_impossible.hpp +++ b/include/fiction/technology/is_sidb_gate_design_impossible.hpp @@ -30,9 +30,9 @@ struct is_sidb_gate_design_impossible_params */ sidb_simulation_parameters simulation_params{}; /** - * Parameters used to determine BDL pairs. + * Parameters for the BDL input iterator. */ - detect_bdl_pairs_params detect_bdl_params{}; + bdl_input_iterator_params input_bdl_iterator_params{}; }; /** * This function evaluates whether it is impossible to design an SiDB gate for a given truth table and a given skeleton @@ -59,12 +59,12 @@ template assert(skeleton_with_defects.num_pis() > 0 && "lyt needs input cells"); assert(skeleton_with_defects.num_pos() > 0 && "lyt needs output cells"); - const auto output_pairs = - detect_bdl_pairs(skeleton_with_defects, sidb_technology::cell_type::OUTPUT, params.detect_bdl_params); + const auto output_pairs = detect_bdl_pairs(skeleton_with_defects, sidb_technology::cell_type::OUTPUT, + params.input_bdl_iterator_params.bdl_pairs_params); assert(output_pairs.empty() == false && "lyt needs output BDL pairs"); - auto bdl_iter = bdl_input_iterator{skeleton_with_defects, params.detect_bdl_params}; + auto bdl_iter = bdl_input_iterator{skeleton_with_defects, params.input_bdl_iterator_params}; for (auto i = 0u; i < spec.front().num_bits(); ++i, ++bdl_iter) { diff --git a/include/fiction/utils/truth_table_utils.hpp b/include/fiction/utils/truth_table_utils.hpp index de2e18349..55f233dec 100644 --- a/include/fiction/utils/truth_table_utils.hpp +++ b/include/fiction/utils/truth_table_utils.hpp @@ -397,8 +397,8 @@ namespace fiction */ [[nodiscard]] inline std::vector create_half_adder_tt() noexcept { - static constexpr const char* truth_table_string1 = "1000"; // Output 1 - static constexpr const char* truth_table_string2 = "0110"; // Output 2 + static constexpr const char* truth_table_string1 = "0110"; // Output 1 + static constexpr const char* truth_table_string2 = "1000"; // Output 2 kitty::dynamic_truth_table table1{2}; // 2 input variables for Output 1 kitty::dynamic_truth_table table2{2}; // 2 input variables for Output 2 diff --git a/test/algorithms/simulation/sidb/critical_temperature.cpp b/test/algorithms/simulation/sidb/critical_temperature.cpp index bb0a51610..221f1a313 100644 --- a/test/algorithms/simulation/sidb/critical_temperature.cpp +++ b/test/algorithms/simulation/sidb/critical_temperature.cpp @@ -3,14 +3,12 @@ // #include -#include #include +#include "utils/blueprints/layout_blueprints.hpp" + #include #include -#include -#include -#include #include #include #include @@ -46,10 +44,11 @@ TEMPLATE_TEST_CASE("Test critical_temperature function", "[critical-temperature] params.iteration_steps = 0; params.alpha = 0.0; - critical_temperature_gate_based(lyt, std::vector{create_id_tt()}, params, &critical_stats); + const auto ct = + critical_temperature_gate_based(lyt, std::vector{create_id_tt()}, params, &critical_stats); CHECK(critical_stats.num_valid_lyt == 0); - CHECK(critical_stats.critical_temperature == 0.0); + CHECK(ct == 0.0); } SECTION("No SiDB") @@ -61,10 +60,10 @@ TEMPLATE_TEST_CASE("Test critical_temperature function", "[critical-temperature] params.iteration_steps = 80; params.alpha = 0.7; - critical_temperature_gate_based(lyt, std::vector{tt{}}, params, &critical_stats); + const auto ct = critical_temperature_gate_based(lyt, std::vector{tt{}}, params, &critical_stats); CHECK(critical_stats.num_valid_lyt == 0); - CHECK(critical_stats.critical_temperature == 0.0); + CHECK(ct == 0.0); } SECTION("Not working diagonal wire where positively charged SiDBs can occur") @@ -97,9 +96,9 @@ TEMPLATE_TEST_CASE("Test critical_temperature function", "[critical-temperature] params.iteration_steps = 80; params.alpha = 0.7; - critical_temperature_gate_based(lyt, std::vector{create_id_tt()}, params, &critical_stats); + const auto ct = critical_temperature_gate_based(lyt, std::vector{create_id_tt()}, params, &critical_stats); - CHECK(critical_stats.critical_temperature == 0.0); + CHECK(ct == 0.0); } SECTION("four SiDBs with two valid charge distributions, QuickExact") @@ -117,15 +116,15 @@ TEMPLATE_TEST_CASE("Test critical_temperature function", "[critical-temperature] params.iteration_steps = 80; params.alpha = 0.7; - critical_temperature_non_gate_based(lyt, params, &critical_stats); + const auto ct = critical_temperature_non_gate_based(lyt, params, &critical_stats); CHECK(critical_stats.num_valid_lyt == 2); CHECK_THAT(std::abs(critical_stats.energy_between_ground_state_and_first_erroneous), Catch::Matchers::WithinAbs(std::numeric_limits::infinity(), 0.01)); - CHECK(critical_stats.critical_temperature == 350); + CHECK(ct == 350); } - SECTION("Y-shaped SiDB AND gate") + SECTION("Y-shaped SiQAD AND gate") { lyt.assign_cell_type({0, 0, 1}, sidb_technology::cell_type::INPUT); lyt.assign_cell_type({2, 1, 1}, sidb_technology::cell_type::INPUT); @@ -153,11 +152,30 @@ TEMPLATE_TEST_CASE("Test critical_temperature function", "[critical-temperature] params.iteration_steps = 80; params.alpha = 0.7; - critical_temperature_gate_based(lyt, std::vector{create_and_tt()}, params, &critical_stats); + const auto ct = critical_temperature_gate_based(lyt, std::vector{create_and_tt()}, params, &critical_stats); + + CHECK_THAT(std::abs(critical_stats.energy_between_ground_state_and_first_erroneous), + Catch::Matchers::WithinAbs(std::numeric_limits::infinity(), 0.01)); + CHECK(ct == 350); + } + + SECTION("Y-shaped SiQAD OR gate") + { + const auto lyt_or_gate = blueprints::siqad_or_gate(); + + sim_params.mu_minus = -0.28; + + params.simulation_parameters = sim_params; + params.engine = critical_temperature_params::simulation_engine::EXACT; + params.input_bdl_iterator_params.input_bdl_config = + bdl_input_iterator_params::input_bdl_configuration::PERTURBER_ABSENCE_ENCODED; + + const auto ct = + critical_temperature_gate_based(lyt_or_gate, std::vector{create_or_tt()}, params, &critical_stats); CHECK_THAT(std::abs(critical_stats.energy_between_ground_state_and_first_erroneous), Catch::Matchers::WithinAbs(std::numeric_limits::infinity(), 0.01)); - CHECK(critical_stats.critical_temperature == 350); + CHECK(ct == 400); } SECTION("Bestagon AND gate, QuickExact") @@ -198,11 +216,11 @@ TEMPLATE_TEST_CASE("Test critical_temperature function", "[critical-temperature] params.iteration_steps = 80; params.alpha = 0.7; - critical_temperature_gate_based(lyt, std::vector{create_and_tt()}, params, &critical_stats); + const auto ct = critical_temperature_gate_based(lyt, std::vector{create_and_tt()}, params, &critical_stats); CHECK_THAT(std::abs(critical_stats.energy_between_ground_state_and_first_erroneous), Catch::Matchers::WithinAbs(26.02, 0.01)); - CHECK_THAT(std::abs(critical_stats.critical_temperature - 59.19), Catch::Matchers::WithinAbs(0.00, 0.01)); + CHECK_THAT(std::abs(ct - 59.19), Catch::Matchers::WithinAbs(0.00, 0.01)); } SECTION("Bestagon AND gate, QuickSim") @@ -243,9 +261,9 @@ TEMPLATE_TEST_CASE("Test critical_temperature function", "[critical-temperature] params.iteration_steps = 500; params.alpha = 0.6; - critical_temperature_gate_based(lyt, std::vector{create_and_tt()}, params, &critical_stats); + const auto ct = critical_temperature_gate_based(lyt, std::vector{create_and_tt()}, params, &critical_stats); - CHECK(critical_stats.critical_temperature > 0); + CHECK(ct > 0); } SECTION("Bestagon FO2 gate") @@ -285,11 +303,12 @@ TEMPLATE_TEST_CASE("Test critical_temperature function", "[critical-temperature] params.iteration_steps = 80; params.alpha = 0.7; - critical_temperature_gate_based(lyt, std::vector{create_fan_out_tt()}, params, &critical_stats); + const auto ct = + critical_temperature_gate_based(lyt, std::vector{create_fan_out_tt()}, params, &critical_stats); CHECK_THAT(std::abs(critical_stats.energy_between_ground_state_and_first_erroneous - 0.56), Catch::Matchers::WithinAbs(0.00, 0.01)); - CHECK_THAT(std::abs(critical_stats.critical_temperature - 1.46), Catch::Matchers::WithinAbs(0.00, 0.01)); + CHECK_THAT(std::abs(ct - 1.46), Catch::Matchers::WithinAbs(0.00, 0.01)); } SECTION("OR gate") @@ -325,9 +344,9 @@ TEMPLATE_TEST_CASE("Test critical_temperature function", "[critical-temperature] params.iteration_steps = 80; params.alpha = 0.7; - critical_temperature_gate_based(lyt, std::vector{create_or_tt()}, params, &critical_stats); + const auto ct = critical_temperature_gate_based(lyt, std::vector{create_or_tt()}, params, &critical_stats); - CHECK(critical_stats.critical_temperature < 350); + CHECK(ct < 350); } SECTION("Not working diagonal Wire") @@ -358,13 +377,13 @@ TEMPLATE_TEST_CASE("Test critical_temperature function", "[critical-temperature] params.iteration_steps = 80; params.alpha = 0.7; - critical_temperature_gate_based(lyt, std::vector{create_id_tt()}, params, &critical_stats); + const auto ct = critical_temperature_gate_based(lyt, std::vector{create_id_tt()}, params, &critical_stats); CHECK(critical_stats.algorithm_name == "QuickExact"); CHECK_THAT(std::abs(critical_stats.energy_between_ground_state_and_first_erroneous), Catch::Matchers::WithinAbs(305.95, 0.01)); - CHECK_THAT(std::abs(critical_stats.critical_temperature), Catch::Matchers::WithinAbs(0.00, 0.01)); + CHECK_THAT(std::abs(ct), Catch::Matchers::WithinAbs(0.00, 0.01)); } SECTION("nine SiDBs, QuickSim, non-gate-based") @@ -387,11 +406,11 @@ TEMPLATE_TEST_CASE("Test critical_temperature function", "[critical-temperature] params.iteration_steps = 500; params.alpha = 0.6; - critical_temperature_non_gate_based(lyt, params, &critical_stats); + const auto ct = critical_temperature_non_gate_based(lyt, params, &critical_stats); CHECK(critical_stats.algorithm_name == "QuickSim"); - CHECK_THAT(std::abs(critical_stats.critical_temperature), Catch::Matchers::WithinAbs(11.55, 0.01)); + CHECK_THAT(std::abs(ct), Catch::Matchers::WithinAbs(11.55, 0.01)); } } @@ -419,12 +438,13 @@ TEMPLATE_TEST_CASE("Test critical_temperature function, using offset coordinates params.iteration_steps = 0; params.alpha = 0.0; - critical_temperature_gate_based(lyt, std::vector{create_id_tt()}, params, &critical_stats); + const auto ct = + critical_temperature_gate_based(lyt, std::vector{create_id_tt()}, params, &critical_stats); CHECK(critical_stats.algorithm_name == "QuickSim"); CHECK(critical_stats.num_valid_lyt == 0); - CHECK(critical_stats.critical_temperature == 0.0); + CHECK(ct == 0.0); } SECTION("One SiDB") @@ -436,12 +456,12 @@ TEMPLATE_TEST_CASE("Test critical_temperature function, using offset coordinates params.iteration_steps = 80; params.alpha = 0.7; - critical_temperature_gate_based(lyt, std::vector{tt{}}, params, &critical_stats); + const auto ct = critical_temperature_gate_based(lyt, std::vector{tt{}}, params, &critical_stats); CHECK(critical_stats.algorithm_name == "QuickExact"); CHECK(critical_stats.num_valid_lyt == 0); - CHECK(critical_stats.critical_temperature == 0.0); + CHECK(ct == 0.0); } SECTION("Not working diagonal Wire where positively charged SiDBs can occur") @@ -474,8 +494,9 @@ TEMPLATE_TEST_CASE("Test critical_temperature function, using offset coordinates params.iteration_steps = 80; params.alpha = 0.7; - critical_temperature_gate_based(lyt, std::vector{create_id_tt()}, params, &critical_stats); - CHECK(critical_stats.critical_temperature == 0.0); + const auto ct = critical_temperature_gate_based(lyt, std::vector{create_id_tt()}, params, &critical_stats); + + CHECK(ct == 0.0); } SECTION("four SiDBs with two valid charge distributions, QuickExact") @@ -493,14 +514,14 @@ TEMPLATE_TEST_CASE("Test critical_temperature function, using offset coordinates params.iteration_steps = 80; params.alpha = 0.7; - critical_temperature_non_gate_based(lyt, params, &critical_stats); + const auto ct = critical_temperature_non_gate_based(lyt, params, &critical_stats); CHECK(critical_stats.algorithm_name == "QuickExact"); CHECK(critical_stats.num_valid_lyt == 2); CHECK_THAT(std::abs(critical_stats.energy_between_ground_state_and_first_erroneous), Catch::Matchers::WithinAbs(std::numeric_limits::infinity(), 0.01)); - CHECK(critical_stats.critical_temperature == 350); + CHECK(ct == 350); } SECTION("Y-shape SiDB AND gate") @@ -530,17 +551,17 @@ TEMPLATE_TEST_CASE("Test critical_temperature function, using offset coordinates params.iteration_steps = 80; params.alpha = 0.7; - critical_temperature_gate_based(lyt, std::vector{create_and_tt()}, params, &critical_stats); + const auto ct = critical_temperature_gate_based(lyt, std::vector{create_and_tt()}, params, &critical_stats); CHECK(critical_stats.algorithm_name == "QuickExact"); CHECK_THAT(std::abs(critical_stats.energy_between_ground_state_and_first_erroneous), Catch::Matchers::WithinAbs(std::numeric_limits::infinity(), 0.01)); - CHECK(critical_stats.critical_temperature == 350); + CHECK(ct == 350); } } -TEMPLATE_TEST_CASE("Critical temperature of Bestagon CX, QuickSim", "[critical-temperature], [quality]", +TEMPLATE_TEST_CASE("Critical temperature of Bestagon CX, QuickExact", "[critical-temperature], [quality]", sidb_100_cell_clk_lyt_siqad, cds_sidb_100_cell_clk_lyt_siqad) { TestType lyt{}; @@ -594,12 +615,56 @@ TEMPLATE_TEST_CASE("Critical temperature of Bestagon CX, QuickSim", "[critical-t params.engine = critical_temperature_params::simulation_engine::EXACT; params.confidence_level = 0.99; params.max_temperature = 350; - params.iteration_steps = 80; - params.alpha = 0.7; - critical_temperature_gate_based(lyt, std::vector{create_crossing_wire_tt()}, params, &critical_stats); + const auto ct = critical_temperature_gate_based(lyt, create_crossing_wire_tt(), params, &critical_stats); CHECK_THAT(std::fabs(critical_stats.energy_between_ground_state_and_first_erroneous - 0.32), Catch::Matchers::WithinAbs(0.00, 0.01)); - CHECK_THAT(std::abs(critical_stats.critical_temperature - 0.85), Catch::Matchers::WithinAbs(0.00, 0.01)); + CHECK_THAT(std::abs(ct - 0.85), Catch::Matchers::WithinAbs(0.00, 0.01)); +} + +TEMPLATE_TEST_CASE("Critical temperature of Bestagon double wire, QuickExact", "[critical-temperature], [quality]", + sidb_100_cell_clk_lyt_siqad, cds_sidb_100_cell_clk_lyt_siqad) +{ + const auto lyt_double_wire_gate = blueprints::bestagon_double_wire(); + + critical_temperature_params params{}; + const sidb_simulation_parameters sim_params{2, -0.32, 5.6, 5.0}; + + critical_temperature_stats critical_stats{}; + + params.simulation_parameters = sim_params; + params.engine = critical_temperature_params::simulation_engine::EXACT; + params.confidence_level = 0.99; + params.max_temperature = 350; + + const auto ct = + critical_temperature_gate_based(lyt_double_wire_gate, create_double_wire_tt(), params, &critical_stats); + + CHECK_THAT(std::fabs(critical_stats.energy_between_ground_state_and_first_erroneous - 10.717), + Catch::Matchers::WithinAbs(0.00, 0.01)); + CHECK_THAT(std::abs(ct - 24.18), Catch::Matchers::WithinAbs(0.00, 0.01)); +} + +TEMPLATE_TEST_CASE("Critical temperature of Bestagon half adder gate, QuickExact", "[critical-temperature], [quality]", + sidb_100_cell_clk_lyt_siqad, cds_sidb_100_cell_clk_lyt_siqad) +{ + const auto lyt_half_adder_gate = blueprints::bestagon_ha(); + + critical_temperature_params params{}; + const sidb_simulation_parameters sim_params{2, -0.32, 5.6, 5.0}; + + critical_temperature_stats critical_stats{}; + + params.simulation_parameters = sim_params; + params.engine = critical_temperature_params::simulation_engine::EXACT; + params.confidence_level = 0.99; + params.max_temperature = 350; + + const auto ct = + critical_temperature_gate_based(lyt_half_adder_gate, create_half_adder_tt(), params, &critical_stats); + + CHECK_THAT(std::fabs(critical_stats.energy_between_ground_state_and_first_erroneous - 0.15), + Catch::Matchers::WithinAbs(0.00, 0.01)); + CHECK_THAT(std::abs(ct - 0.40), Catch::Matchers::WithinAbs(0.00, 0.01)); } diff --git a/test/algorithms/simulation/sidb/displacement_robustness_domain.cpp b/test/algorithms/simulation/sidb/displacement_robustness_domain.cpp index 7374d7489..6d42b42ad 100644 --- a/test/algorithms/simulation/sidb/displacement_robustness_domain.cpp +++ b/test/algorithms/simulation/sidb/displacement_robustness_domain.cpp @@ -42,13 +42,13 @@ TEST_CASE("Determine the SiDB gate displacement robustness of the Y-shaped SiDB const auto lyt = blueprints::siqad_and_gate(); displacement_robustness_domain_params> params{}; - params.displacement_variations = {1, 1}; - params.operational_params.simulation_parameters = sidb_simulation_parameters{2, -0.28}; - params.operational_params.bdl_params.maximum_distance = 2.0; - params.operational_params.bdl_params.minimum_distance = 0.2; - params.fixed_sidbs = {{0, 0, 1}, {2, 1, 1}, {20, 0, 1}, {18, 1, 1}, {14, 3, 1}, - {16, 2, 1}, {10, 7, 0}, {10, 6, 0}, {10, 9, 1}, {4, 2, 1}}; - params.percentage_of_analyzed_displaced_layouts = 0.1; + params.displacement_variations = {1, 1}; + params.operational_params.simulation_parameters = sidb_simulation_parameters{2, -0.28}; + params.operational_params.input_bdl_iterator_params.bdl_pairs_params.maximum_distance = 2.0; + params.operational_params.input_bdl_iterator_params.bdl_pairs_params.minimum_distance = 0.2; + params.fixed_sidbs = {{0, 0, 1}, {2, 1, 1}, {20, 0, 1}, {18, 1, 1}, {14, 3, 1}, + {16, 2, 1}, {10, 7, 0}, {10, 6, 0}, {10, 9, 1}, {4, 2, 1}}; + params.percentage_of_analyzed_displaced_layouts = 0.1; params.analysis_mode = displacement_robustness_domain_params>::displacement_analysis_mode::RANDOM; params.dimer_policy = displacement_robustness_domain_params< @@ -75,8 +75,8 @@ TEST_CASE("Determine the SiDB gate displacement robustness of the Y-shaped SiDB params.displacement_variations = {0, 2}; params.dimer_policy = displacement_robustness_domain_params< cell>::dimer_displacement_policy::STAY_ON_ORIGINAL_DIMER; - params.operational_params.bdl_params.maximum_distance = 3.0; - params.operational_params.bdl_params.minimum_distance = 0.2; + params.operational_params.input_bdl_iterator_params.bdl_pairs_params.maximum_distance = 3.0; + params.operational_params.input_bdl_iterator_params.bdl_pairs_params.minimum_distance = 0.2; const auto robustness_domain = determine_displacement_robustness_domain(lyt, std::vector{create_and_tt()}, params, &stats); @@ -97,10 +97,10 @@ TEST_CASE("Determine the probability of fabricating an operational SiQAD Y-shape SECTION("only one displacement variation, SiQAD coordinate") { displacement_robustness_domain_params> params{}; - params.displacement_variations = {1, 0}; - params.operational_params.simulation_parameters = sidb_simulation_parameters{2, -0.28}; - params.operational_params.bdl_params.maximum_distance = 2.0; - params.operational_params.bdl_params.minimum_distance = 0.2; + params.displacement_variations = {1, 0}; + params.operational_params.simulation_parameters = sidb_simulation_parameters{2, -0.28}; + params.operational_params.input_bdl_iterator_params.bdl_pairs_params.maximum_distance = 2.0; + params.operational_params.input_bdl_iterator_params.bdl_pairs_params.minimum_distance = 0.2; const auto result = determine_probability_of_fabricating_operational_gate(lyt, std::vector{create_and_tt()}, params, 0.3); @@ -117,10 +117,10 @@ TEST_CASE("Determine the probability of fabricating an operational Bestagon AND SECTION("one displacement variation in x-direction") { displacement_robustness_domain_params> params{}; - params.displacement_variations = {1, 0}; - params.operational_params.simulation_parameters = sidb_simulation_parameters{2, -0.32}; - params.operational_params.bdl_params.maximum_distance = 2.0; - params.operational_params.bdl_params.minimum_distance = 0.2; + params.displacement_variations = {1, 0}; + params.operational_params.simulation_parameters = sidb_simulation_parameters{2, -0.32}; + params.operational_params.input_bdl_iterator_params.bdl_pairs_params.maximum_distance = 2.0; + params.operational_params.input_bdl_iterator_params.bdl_pairs_params.minimum_distance = 0.2; params.analysis_mode = displacement_robustness_domain_params>::displacement_analysis_mode::RANDOM; params.percentage_of_analyzed_displaced_layouts = 0.1; @@ -139,12 +139,12 @@ TEST_CASE("Determine the probability of fabricating an operational BDL wire with SECTION("one displacement variation in y-direction") { displacement_robustness_domain_params> params{}; - params.displacement_variations = {0, 1}; - params.operational_params.simulation_parameters = sidb_simulation_parameters{2, -0.32}; - params.operational_params.bdl_params.maximum_distance = 2.0; - params.operational_params.bdl_params.minimum_distance = 0.2; - params.dimer_policy = displacement_robustness_domain_params< - cell>::dimer_displacement_policy::STAY_ON_ORIGINAL_DIMER; + params.displacement_variations = {0, 1}; + params.operational_params.simulation_parameters = sidb_simulation_parameters{2, -0.32}; + params.operational_params.input_bdl_iterator_params.bdl_pairs_params.maximum_distance = 2.0; + params.operational_params.input_bdl_iterator_params.bdl_pairs_params.minimum_distance = 0.2; + params.dimer_policy = displacement_robustness_domain_params< + cell>::dimer_displacement_policy::STAY_ON_ORIGINAL_DIMER; params.analysis_mode = displacement_robustness_domain_params< cell>::displacement_analysis_mode::EXHAUSTIVE; @@ -171,12 +171,12 @@ TEST_CASE("Determine the probability of fabricating an operational BDL wire with SECTION("one displacement variation in x-direction") { displacement_robustness_domain_params> params{}; - params.displacement_variations = {1, 0}; - params.operational_params.simulation_parameters = sidb_simulation_parameters{2, -0.32}; - params.operational_params.bdl_params.maximum_distance = 2.0; - params.operational_params.bdl_params.minimum_distance = 0.2; - params.dimer_policy = displacement_robustness_domain_params< - cell>::dimer_displacement_policy::STAY_ON_ORIGINAL_DIMER; + params.displacement_variations = {1, 0}; + params.operational_params.simulation_parameters = sidb_simulation_parameters{2, -0.32}; + params.operational_params.input_bdl_iterator_params.bdl_pairs_params.maximum_distance = 2.0; + params.operational_params.input_bdl_iterator_params.bdl_pairs_params.minimum_distance = 0.2; + params.dimer_policy = displacement_robustness_domain_params< + cell>::dimer_displacement_policy::STAY_ON_ORIGINAL_DIMER; params.analysis_mode = displacement_robustness_domain_params< cell>::displacement_analysis_mode::EXHAUSTIVE; @@ -188,10 +188,10 @@ TEST_CASE("Determine the probability of fabricating an operational BDL wire with SECTION("one displacement variation in x-direction, random sampling") { displacement_robustness_domain_params> params{}; - params.displacement_variations = {1, 0}; - params.operational_params.simulation_parameters = sidb_simulation_parameters{2, -0.32}; - params.operational_params.bdl_params.maximum_distance = 2.0; - params.operational_params.bdl_params.minimum_distance = 0.2; + params.displacement_variations = {1, 0}; + params.operational_params.simulation_parameters = sidb_simulation_parameters{2, -0.32}; + params.operational_params.input_bdl_iterator_params.bdl_pairs_params.maximum_distance = 2.0; + params.operational_params.input_bdl_iterator_params.bdl_pairs_params.minimum_distance = 0.2; const auto result = determine_probability_of_fabricating_operational_gate(lyt, std::vector{create_id_tt()}, params, 0.0); @@ -201,10 +201,10 @@ TEST_CASE("Determine the probability of fabricating an operational BDL wire with SECTION("fabrication error rate p = 0.0") { displacement_robustness_domain_params> params{}; - params.displacement_variations = {0, 1}; - params.operational_params.simulation_parameters = sidb_simulation_parameters{2, -0.32}; - params.operational_params.bdl_params.maximum_distance = 2.0; - params.operational_params.bdl_params.minimum_distance = 0.2; + params.displacement_variations = {0, 1}; + params.operational_params.simulation_parameters = sidb_simulation_parameters{2, -0.32}; + params.operational_params.input_bdl_iterator_params.bdl_pairs_params.maximum_distance = 2.0; + params.operational_params.input_bdl_iterator_params.bdl_pairs_params.minimum_distance = 0.2; const auto result = determine_probability_of_fabricating_operational_gate(lyt, std::vector{create_id_tt()}, params, 0.0); @@ -222,12 +222,12 @@ TEST_CASE("Determine the probability of fabricating an operational BDL, offset c SECTION("one displacement variation in y-direction") { displacement_robustness_domain_params> params{}; - params.displacement_variations = {0, 1}; - params.operational_params.simulation_parameters = sidb_simulation_parameters{2, -0.32}; - params.operational_params.bdl_params.maximum_distance = 2.0; - params.operational_params.bdl_params.minimum_distance = 0.2; - params.dimer_policy = displacement_robustness_domain_params< - cell>::dimer_displacement_policy::STAY_ON_ORIGINAL_DIMER; + params.displacement_variations = {0, 1}; + params.operational_params.simulation_parameters = sidb_simulation_parameters{2, -0.32}; + params.operational_params.input_bdl_iterator_params.bdl_pairs_params.maximum_distance = 2.0; + params.operational_params.input_bdl_iterator_params.bdl_pairs_params.minimum_distance = 0.2; + params.dimer_policy = displacement_robustness_domain_params< + cell>::dimer_displacement_policy::STAY_ON_ORIGINAL_DIMER; params.analysis_mode = displacement_robustness_domain_params>::displacement_analysis_mode::EXHAUSTIVE; @@ -254,12 +254,12 @@ TEST_CASE("Determine the probability of fabricating an operational BDL, offset c SECTION("one displacement variation in x-direction") { displacement_robustness_domain_params> params{}; - params.displacement_variations = {1, 0}; - params.operational_params.simulation_parameters = sidb_simulation_parameters{2, -0.32}; - params.operational_params.bdl_params.maximum_distance = 2.0; - params.operational_params.bdl_params.minimum_distance = 0.2; - params.dimer_policy = displacement_robustness_domain_params< - cell>::dimer_displacement_policy::STAY_ON_ORIGINAL_DIMER; + params.displacement_variations = {1, 0}; + params.operational_params.simulation_parameters = sidb_simulation_parameters{2, -0.32}; + params.operational_params.input_bdl_iterator_params.bdl_pairs_params.maximum_distance = 2.0; + params.operational_params.input_bdl_iterator_params.bdl_pairs_params.minimum_distance = 0.2; + params.dimer_policy = displacement_robustness_domain_params< + cell>::dimer_displacement_policy::STAY_ON_ORIGINAL_DIMER; params.analysis_mode = displacement_robustness_domain_params>::displacement_analysis_mode::EXHAUSTIVE; @@ -271,10 +271,10 @@ TEST_CASE("Determine the probability of fabricating an operational BDL, offset c SECTION("one displacement variation in x-direction, random sampling") { displacement_robustness_domain_params> params{}; - params.displacement_variations = {1, 0}; - params.operational_params.simulation_parameters = sidb_simulation_parameters{2, -0.32}; - params.operational_params.bdl_params.maximum_distance = 2.0; - params.operational_params.bdl_params.minimum_distance = 0.2; + params.displacement_variations = {1, 0}; + params.operational_params.simulation_parameters = sidb_simulation_parameters{2, -0.32}; + params.operational_params.input_bdl_iterator_params.bdl_pairs_params.maximum_distance = 2.0; + params.operational_params.input_bdl_iterator_params.bdl_pairs_params.minimum_distance = 0.2; const auto result = determine_probability_of_fabricating_operational_gate( lyt_offset, std::vector{create_id_tt()}, params, 0.0); @@ -284,10 +284,10 @@ TEST_CASE("Determine the probability of fabricating an operational BDL, offset c SECTION("fabrication error rate p = 0.0") { displacement_robustness_domain_params> params{}; - params.displacement_variations = {0, 1}; - params.operational_params.simulation_parameters = sidb_simulation_parameters{2, -0.32}; - params.operational_params.bdl_params.maximum_distance = 2.0; - params.operational_params.bdl_params.minimum_distance = 0.2; + params.displacement_variations = {0, 1}; + params.operational_params.simulation_parameters = sidb_simulation_parameters{2, -0.32}; + params.operational_params.input_bdl_iterator_params.bdl_pairs_params.maximum_distance = 2.0; + params.operational_params.input_bdl_iterator_params.bdl_pairs_params.minimum_distance = 0.2; const auto result = determine_probability_of_fabricating_operational_gate( lyt_offset, std::vector{create_id_tt()}, params, 0.0); diff --git a/test/algorithms/simulation/sidb/is_operational.cpp b/test/algorithms/simulation/sidb/is_operational.cpp index ff49e9640..46bd24a2e 100644 --- a/test/algorithms/simulation/sidb/is_operational.cpp +++ b/test/algorithms/simulation/sidb/is_operational.cpp @@ -19,6 +19,20 @@ using namespace fiction; +TEST_CASE("SiQAD OR gate", "[is-operational]") +{ + const auto layout_or_gate = blueprints::siqad_or_gate(); + + const sidb_100_cell_clk_lyt_siqad lat{layout_or_gate}; + + CHECK(is_operational(lat, std::vector{create_or_tt()}, + is_operational_params{sidb_simulation_parameters{2, -0.30}}) + .first == operational_status::OPERATIONAL); + CHECK( + is_operational(lat, std::vector{create_or_tt()}, is_operational_params{sidb_simulation_parameters{2, -0.1}}) + .first == operational_status::NON_OPERATIONAL); +} + TEST_CASE("SiQAD's AND gate with input BDL pairs of different size", "[is-operational]") { using layout = sidb_cell_clk_lyt_siqad; @@ -286,3 +300,39 @@ TEST_CASE("is operational check for Bestagon CX gate", "[is-operational], [quali is_operational_params{sidb_simulation_parameters{2, -0.30}, sidb_simulation_engine::QUICKEXACT}) .first == operational_status::NON_OPERATIONAL); } + +TEST_CASE("is operational check for Bestagon double wire", "[is-operational], [quality]") +{ + const auto lyt = blueprints::bestagon_double_wire(); + + CHECK(lyt.num_cells() == 30); + + const sidb_100_cell_clk_lyt_siqad lat{lyt}; + + CHECK( + is_operational(lat, create_double_wire_tt(), + is_operational_params{sidb_simulation_parameters{2, -0.32}, sidb_simulation_engine::QUICKEXACT}) + .first == operational_status::OPERATIONAL); + CHECK( + is_operational(lat, create_double_wire_tt(), + is_operational_params{sidb_simulation_parameters{2, -0.30}, sidb_simulation_engine::QUICKEXACT}) + .first == operational_status::NON_OPERATIONAL); +} + +TEST_CASE("is operational check for Bestagon half adder", "[is-operational], [quality]") +{ + const auto lyt = blueprints::bestagon_ha(); + + CHECK(lyt.num_cells() == 26); + + const sidb_100_cell_clk_lyt_siqad lat{lyt}; + + CHECK( + is_operational(lat, create_half_adder_tt(), + is_operational_params{sidb_simulation_parameters{2, -0.32}, sidb_simulation_engine::QUICKEXACT}) + .first == operational_status::OPERATIONAL); + CHECK( + is_operational(lat, create_half_adder_tt(), + is_operational_params{sidb_simulation_parameters{2, -0.25}, sidb_simulation_engine::QUICKEXACT}) + .first == operational_status::NON_OPERATIONAL); +} diff --git a/test/algorithms/simulation/sidb/quickexact.cpp b/test/algorithms/simulation/sidb/quickexact.cpp index 4400bd243..c7c9736a3 100644 --- a/test/algorithms/simulation/sidb/quickexact.cpp +++ b/test/algorithms/simulation/sidb/quickexact.cpp @@ -13,7 +13,6 @@ #include #include #include -#include #include #include #include @@ -21,6 +20,7 @@ #include #include #include +#include #include #include @@ -1373,7 +1373,7 @@ TEMPLATE_TEST_CASE("QuickExact simulation of a Y-shaped SiDB OR gate with input lyt.assign_cell_type({10, 8, 1}, TestType::cell_type::NORMAL); lyt.assign_cell_type({16, 1, 0}, TestType::cell_type::NORMAL); - quickexact_params> params{ + const quickexact_params> params{ sidb_simulation_parameters{2, -0.28}, quickexact_params>::automatic_base_number_detection::OFF}; diff --git a/test/utils/blueprints/layout_blueprints.hpp b/test/utils/blueprints/layout_blueprints.hpp index ed8f90633..d1bc9ba98 100644 --- a/test/utils/blueprints/layout_blueprints.hpp +++ b/test/utils/blueprints/layout_blueprints.hpp @@ -761,6 +761,7 @@ Lyt siqad_and_gate() noexcept { static_assert(fiction::is_cell_level_layout_v, "Lyt is not a cell-level layout"); static_assert(fiction::has_sidb_technology_v, "Lyt is not an SiDB layout"); + static_assert(fiction::has_siqad_coord_v, "Lyt is not based on SiQAD coordinates"); Lyt lyt{}; @@ -783,6 +784,40 @@ Lyt siqad_and_gate() noexcept return lyt; }; +/** + * This layout represents the OR Gate, as proposed in the paper + * titled \"SiQAD: A Design and Simulation Tool for Atomic Silicon Quantum Dot Circuits\" by Samuel Sze Hang Ng, Jacob + * Retallick, Hsi Nien Chiu, Robert Lupoiu, Lucian Livadaru, Taleana Huff, Mohammad Rashidi, Wyatt Vine, Thomas Dienel, + * Robert A. Wolkow, and Konrad Walus in IEEE TRANSACTIONS ON NANOTECHNOLOGY, Volume 19, 2020. + */ +template +Lyt siqad_or_gate() noexcept +{ + static_assert(fiction::is_cell_level_layout_v, "Lyt is not a cell-level layout"); + static_assert(fiction::has_sidb_technology_v, "Lyt is not an SiDB layout"); + static_assert(fiction::has_siqad_coord_v, "Lyt is not based on SiQAD coordinates"); + + Lyt lyt{}; + + lyt.assign_cell_type({0, 0, 0}, Lyt::cell_type::INPUT); + lyt.assign_cell_type({2, 1, 0}, Lyt::cell_type::INPUT); + + lyt.assign_cell_type({16, 0, 0}, Lyt::cell_type::INPUT); + lyt.assign_cell_type({14, 1, 0}, Lyt::cell_type::INPUT); + + lyt.assign_cell_type({4, 2, 0}, Lyt::cell_type::NORMAL); + lyt.assign_cell_type({12, 2, 0}, Lyt::cell_type::NORMAL); + + lyt.assign_cell_type({6, 3, 0}, Lyt::cell_type::NORMAL); + lyt.assign_cell_type({10, 3, 0}, Lyt::cell_type::NORMAL); + + lyt.assign_cell_type({8, 5, 0}, Lyt::cell_type::OUTPUT); + lyt.assign_cell_type({8, 6, 1}, Lyt::cell_type::OUTPUT); + + lyt.assign_cell_type({8, 8, 1}, Lyt::cell_type::NORMAL); + + return lyt; +}; /** * This layout represents the AND Gate, as proposed in the paper * titled \"Hexagons are the Bestagons: Design Automation for Silicon Dangling Bond Logic\" by @@ -795,7 +830,7 @@ Lyt bestagon_and_gate() noexcept { static_assert(fiction::is_cell_level_layout_v, "Lyt is not a cell-level layout"); static_assert(fiction::has_sidb_technology_v, "Lyt is not an SiDB layout"); - static_assert(fiction::has_siqad_coord_v, "Lyt is not an SiDB layout"); + static_assert(fiction::has_siqad_coord_v, "Lyt is not based on SiQAD coordinates"); Lyt lyt{}; @@ -843,7 +878,7 @@ Lyt and_gate_111() noexcept static_assert(fiction::is_cell_level_layout_v, "Lyt is not a cell-level layout"); static_assert(fiction::has_sidb_technology_v, "Lyt is not an SiDB layout"); static_assert(fiction::is_sidb_lattice_111_v, "Lyt should have 111 as lattice orientation"); - static_assert(fiction::has_siqad_coord_v, "Lyt is not an SiDB layout"); + static_assert(fiction::has_siqad_coord_v, "Lyt is not based on SiQAD coordinates"); Lyt lyt{}; @@ -881,6 +916,133 @@ Lyt and_gate_111() noexcept return lyt; }; +/** + * This layout represents the double wire, as proposed in the paper titled \"Hexagons are the + * Bestagons: Design Automation for Silicon Dangling Bond Logic\" authored by Marcel Walter, Samuel Sze Hang Ng, Konrad + * Walus, and Robert Wille. + * + * (https://dl.acm.org/doi/10.1145/3489517.3530525) + */ +template +Lyt bestagon_double_wire() noexcept +{ + static_assert(fiction::is_cell_level_layout_v, "Lyt is not a cell-level layout"); + static_assert(fiction::has_sidb_technology_v, "Lyt is not an SiDB layout"); + static_assert(fiction::has_siqad_coord_v, "Lyt is not based on SiQAD coordinates"); + + Lyt lyt{}; + + // input wires + lyt.assign_cell_type({0, 0, 0}, Lyt::cell_type::INPUT); + lyt.assign_cell_type({38, 0, 0}, Lyt::cell_type::INPUT); + + lyt.assign_cell_type({36, 1, 0}, Lyt::cell_type::INPUT); + lyt.assign_cell_type({2, 1, 0}, Lyt::cell_type::INPUT); + + lyt.assign_cell_type({6, 2, 0}, Lyt::cell_type::NORMAL); + lyt.assign_cell_type({32, 2, 0}, Lyt::cell_type::NORMAL); + + lyt.assign_cell_type({8, 3, 0}, Lyt::cell_type::NORMAL); + lyt.assign_cell_type({30, 3, 0}, Lyt::cell_type::NORMAL); + + lyt.assign_cell_type({14, 5, 0}, Lyt::cell_type::NORMAL); + lyt.assign_cell_type({24, 5, 0}, Lyt::cell_type::NORMAL); + + lyt.assign_cell_type({12, 4, 0}, Lyt::cell_type::NORMAL); + lyt.assign_cell_type({26, 4, 0}, Lyt::cell_type::NORMAL); + + // canvas SiDBs + // left SiDBs + lyt.assign_cell_type({14, 7, 1}, Lyt::cell_type::NORMAL); + lyt.assign_cell_type({10, 9, 0}, Lyt::cell_type::NORMAL); + lyt.assign_cell_type({11, 11, 1}, Lyt::cell_type::NORMAL); + lyt.assign_cell_type({14, 12, 1}, Lyt::cell_type::NORMAL); + + // right SiDBs + lyt.assign_cell_type({24, 7, 1}, Lyt::cell_type::NORMAL); + lyt.assign_cell_type({28, 9, 0}, Lyt::cell_type::NORMAL); + lyt.assign_cell_type({27, 11, 1}, Lyt::cell_type::NORMAL); + lyt.assign_cell_type({24, 12, 1}, Lyt::cell_type::NORMAL); + + // output wires + lyt.assign_cell_type({14, 15, 0}, Lyt::cell_type::NORMAL); + lyt.assign_cell_type({24, 15, 0}, Lyt::cell_type::NORMAL); + + lyt.assign_cell_type({12, 16, 0}, Lyt::cell_type::NORMAL); + lyt.assign_cell_type({26, 16, 0}, Lyt::cell_type::NORMAL); + + lyt.assign_cell_type({8, 17, 0}, Lyt::cell_type::OUTPUT); + lyt.assign_cell_type({30, 17, 0}, Lyt::cell_type::OUTPUT); + + lyt.assign_cell_type({6, 18, 0}, Lyt::cell_type::OUTPUT); + lyt.assign_cell_type({32, 18, 0}, Lyt::cell_type::OUTPUT); + + lyt.assign_cell_type({2, 19, 0}, Lyt::cell_type::NORMAL); + lyt.assign_cell_type({36, 19, 0}, Lyt::cell_type::NORMAL); + + return lyt; +}; + +/** + * This layout represents the half adder gate, as proposed in the paper titled \"Hexagons are the + * Bestagons: Design Automation for Silicon Dangling Bond Logic\" authored by Marcel Walter, Samuel Sze Hang Ng, Konrad + * Walus, and Robert Wille. + * + * (https://dl.acm.org/doi/10.1145/3489517.3530525) + */ +template +Lyt bestagon_ha() noexcept +{ + static_assert(fiction::is_cell_level_layout_v, "Lyt is not a cell-level layout"); + static_assert(fiction::has_sidb_technology_v, "Lyt is not an SiDB layout"); + static_assert(fiction::has_siqad_coord_v, "Lyt is not based on SiQAD coordinates"); + + Lyt lyt{}; + + // input wires + lyt.assign_cell_type({0, 0, 0}, Lyt::cell_type::INPUT); + lyt.assign_cell_type({38, 0, 0}, Lyt::cell_type::INPUT); + + lyt.assign_cell_type({36, 1, 0}, Lyt::cell_type::INPUT); + lyt.assign_cell_type({2, 1, 0}, Lyt::cell_type::INPUT); + + lyt.assign_cell_type({6, 2, 0}, Lyt::cell_type::NORMAL); + lyt.assign_cell_type({32, 2, 0}, Lyt::cell_type::NORMAL); + + lyt.assign_cell_type({8, 3, 0}, Lyt::cell_type::NORMAL); + lyt.assign_cell_type({30, 3, 0}, Lyt::cell_type::NORMAL); + + lyt.assign_cell_type({14, 5, 0}, Lyt::cell_type::NORMAL); + lyt.assign_cell_type({24, 5, 0}, Lyt::cell_type::NORMAL); + + lyt.assign_cell_type({12, 4, 0}, Lyt::cell_type::NORMAL); + lyt.assign_cell_type({26, 4, 0}, Lyt::cell_type::NORMAL); + + // canvas SiDBs + lyt.assign_cell_type({17, 8, 0}, Lyt::cell_type::NORMAL); + lyt.assign_cell_type({16, 9, 1}, Lyt::cell_type::NORMAL); + lyt.assign_cell_type({17, 12, 0}, Lyt::cell_type::NORMAL); + lyt.assign_cell_type({20, 13, 1}, Lyt::cell_type::NORMAL); + + // output wires + lyt.assign_cell_type({14, 15, 0}, Lyt::cell_type::NORMAL); + lyt.assign_cell_type({24, 15, 0}, Lyt::cell_type::NORMAL); + + lyt.assign_cell_type({12, 16, 0}, Lyt::cell_type::NORMAL); + lyt.assign_cell_type({26, 16, 0}, Lyt::cell_type::NORMAL); + + lyt.assign_cell_type({8, 17, 0}, Lyt::cell_type::OUTPUT); + lyt.assign_cell_type({30, 17, 0}, Lyt::cell_type::OUTPUT); + + lyt.assign_cell_type({6, 18, 0}, Lyt::cell_type::OUTPUT); + lyt.assign_cell_type({32, 18, 0}, Lyt::cell_type::OUTPUT); + + lyt.assign_cell_type({2, 19, 0}, Lyt::cell_type::NORMAL); + lyt.assign_cell_type({36, 19, 0}, Lyt::cell_type::NORMAL); + + return lyt; +}; + } // namespace blueprints #endif // FICTION_LAYOUT_BLUEPRINTS_HPP