diff --git a/bindings/pyfiction/include/pyfiction/algorithms/physical_design/design_sidb_gates.hpp b/bindings/pyfiction/include/pyfiction/algorithms/physical_design/design_sidb_gates.hpp index 56618ee37..c4fbf1598 100644 --- a/bindings/pyfiction/include/pyfiction/algorithms/physical_design/design_sidb_gates.hpp +++ b/bindings/pyfiction/include/pyfiction/algorithms/physical_design/design_sidb_gates.hpp @@ -50,18 +50,16 @@ inline void design_sidb_gates(pybind11::module& m) py::class_>(m, "design_sidb_gates_params", DOC(fiction_design_sidb_gates_params)) .def(py::init<>()) - .def_readwrite("simulation_parameters", - &fiction::design_sidb_gates_params::simulation_parameters, - DOC(fiction_design_sidb_gates_params)) + .def_readwrite("operational_params", + &fiction::design_sidb_gates_params::operational_params, + DOC(fiction_design_sidb_gates_params_operational_params)) .def_readwrite("design_mode", &fiction::design_sidb_gates_params::design_mode, DOC(fiction_design_sidb_gates_params_design_mode)) .def_readwrite("canvas", &fiction::design_sidb_gates_params::canvas, DOC(fiction_design_sidb_gates_params_canvas)) .def_readwrite("number_of_sidbs", &fiction::design_sidb_gates_params::number_of_sidbs, - DOC(fiction_design_sidb_gates_params_number_of_sidbs)) - .def_readwrite("sim_engine", &fiction::design_sidb_gates_params::sim_engine, - DOC(fiction_design_sidb_gates_params_sim_engine)); + DOC(fiction_design_sidb_gates_params_number_of_sidbs)); detail::design_sidb_gates(m); detail::design_sidb_gates(m); diff --git a/bindings/pyfiction/include/pyfiction/algorithms/simulation/sidb/random_sidb_layout_generator.hpp b/bindings/pyfiction/include/pyfiction/algorithms/simulation/sidb/random_sidb_layout_generator.hpp index b55bfe179..f64aee4d4 100644 --- a/bindings/pyfiction/include/pyfiction/algorithms/simulation/sidb/random_sidb_layout_generator.hpp +++ b/bindings/pyfiction/include/pyfiction/algorithms/simulation/sidb/random_sidb_layout_generator.hpp @@ -44,9 +44,15 @@ inline void random_sidb_layout_generator(pybind11::module& m) py::enum_::positive_charges>( m, "positive_charges", DOC(fiction_generate_random_sidb_layout_params_positive_charges)) - .value("ON", fiction::generate_random_sidb_layout_params::positive_charges::ALLOWED) - .value("OFF", - fiction::generate_random_sidb_layout_params::positive_charges::FORBIDDEN); + .value("ALLOWED", + fiction::generate_random_sidb_layout_params::positive_charges::ALLOWED, + DOC(fiction_generate_random_sidb_layout_params_positive_charges_ALLOWED)) + .value("FORBIDDEN", + fiction::generate_random_sidb_layout_params::positive_charges::FORBIDDEN, + DOC(fiction_generate_random_sidb_layout_params_positive_charges_FORBIDDEN)) + .value("MAY_OCCUR", + fiction::generate_random_sidb_layout_params::positive_charges::MAY_OCCUR, + DOC(fiction_generate_random_sidb_layout_params_positive_charges_MAY_OCCUR)); /** * Parameters. @@ -63,9 +69,6 @@ inline void random_sidb_layout_generator(pybind11::module& m) .def_readwrite("positive_sidbs", &fiction::generate_random_sidb_layout_params::positive_sidbs, DOC(fiction_generate_random_sidb_layout_params_positive_sidbs)) - .def_readwrite("minimal_spacing", - &fiction::generate_random_sidb_layout_params::minimal_spacing, - DOC(fiction_generate_random_sidb_layout_params_minimal_spacing)) .def_readwrite("maximal_attempts", &fiction::generate_random_sidb_layout_params::maximal_attempts, DOC(fiction_generate_random_sidb_layout_params_maximal_attempts)) @@ -77,8 +80,8 @@ inline void random_sidb_layout_generator(pybind11::module& m) &fiction::generate_random_sidb_layout_params< fiction::offset::ucoord_t>::maximal_attempts_for_multiple_layouts, DOC(fiction_generate_random_sidb_layout_params_maximal_attempts_for_multiple_layouts)); - // NOTE be careful with the order of the following calls! Python will resolve the first matching overload! + // NOTE be careful with the order of the following calls! Python will resolve the first matching overload! detail::random_layout_generator(m); detail::random_layout_generator(m); } diff --git a/bindings/pyfiction/include/pyfiction/pybind11_mkdoc_docstrings.hpp b/bindings/pyfiction/include/pyfiction/pybind11_mkdoc_docstrings.hpp index 31752dd78..beb224e23 100644 --- a/bindings/pyfiction/include/pyfiction/pybind11_mkdoc_docstrings.hpp +++ b/bindings/pyfiction/include/pyfiction/pybind11_mkdoc_docstrings.hpp @@ -295,6 +295,27 @@ Parameter ``params``: A cell-level layout that implements `lyt`'s gate types with building blocks defined in `GateLibrary`.)doc"; +static const char *__doc_fiction_are_cell_layouts_identical = +R"doc(This function checks whether the given layouts `first_lyt` and +`second_lyt` are identical by comparing various properties such as the +number of cells, the types of cells, defects (if applicable), and +charge states (if applicable). The comparison is done in a detailed +manner depending on the specific layout type. + +@Note The aspect ratios of the cell-level layouts are not compared. + +Template parameter ``Lyt``: + The layout type. Must be a cell-level layout. + +Parameter ``first_lyt``: + The first layout to compare. + +Parameter ``second_lyt``: + The second layout to compare. + +Returns: + `true` if the layouts are identical, `false` otherwise.)doc"; + static const char *__doc_fiction_area = R"doc(Computes the area of a given coordinate assuming its origin is (0, 0, 0). Calculates :math:`(|x| + 1) \cdot (|y| + 1)` by default. The @@ -3495,11 +3516,7 @@ static const char *__doc_fiction_design_sidb_gates_params_design_sidb_gates_mode static const char *__doc_fiction_design_sidb_gates_params_number_of_sidbs = R"doc(Number of SiDBs placed in the canvas to create a working gate.)doc"; -static const char *__doc_fiction_design_sidb_gates_params_sim_engine = -R"doc(The simulation engine to be used for the operational domain -computation.)doc"; - -static const char *__doc_fiction_design_sidb_gates_params_simulation_parameters = R"doc(All Parameters for physical SiDB simulations.)doc"; +static const char *__doc_fiction_design_sidb_gates_params_operational_params = R"doc(Parameters for the `is_operational` function.)doc"; static const char *__doc_fiction_design_sidb_gates_params_termination_cond = R"doc(The design process is terminated after a valid SiDB gate design is @@ -10870,10 +10887,6 @@ be difficult or 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.)doc"; -static const char *__doc_fiction_generate_random_sidb_layout_params_minimal_spacing = -R"doc(If positively charged SiDBs should be prevented, SiDBs are not placed -closer than this value (Euclidean distance of two cells).)doc"; - static const char *__doc_fiction_generate_random_sidb_layout_params_number_of_sidbs = R"doc(Number of SiDBs that are placed on the layout.)doc"; static const char *__doc_fiction_generate_random_sidb_layout_params_number_of_unique_generated_layouts = R"doc(The desired number of unique layouts to be generated.)doc"; @@ -10890,10 +10903,16 @@ static const char *__doc_fiction_generate_random_sidb_layout_params_positive_cha R"doc(Positive charges are not allowed to occur (i.e. SiDBs need to be seperated by a few lattice points).)doc"; +static const char *__doc_fiction_generate_random_sidb_layout_params_positive_charges_MAY_OCCUR = +R"doc(Positive charges can occur, which means that the +`can_positive_charges_occur` function returns `true`.)doc"; + static const char *__doc_fiction_generate_random_sidb_layout_params_positive_sidbs = R"doc(If positively charged SiDBs should be prevented, SiDBs are not placed closer than the minimal_spacing.)doc"; +static const char *__doc_fiction_generate_random_sidb_layout_params_sim_params = R"doc(Simulation parameters.)doc"; + static const char *__doc_fiction_geometric_temperature_schedule = R"doc(A logarithmically decreasing temperature schedule. The temperature is altered by multiplying it with `0.99`. diff --git a/bindings/pyfiction/test/algorithms/physical_design/test_design_sidb_gates.py b/bindings/pyfiction/test/algorithms/physical_design/test_design_sidb_gates.py index 299af40a2..9a0292bf8 100644 --- a/bindings/pyfiction/test/algorithms/physical_design/test_design_sidb_gates.py +++ b/bindings/pyfiction/test/algorithms/physical_design/test_design_sidb_gates.py @@ -26,14 +26,14 @@ def test_siqad_and_gate_skeleton_100(self): layout.assign_cell_type((10, 19), sidb_technology.cell_type.NORMAL) params = design_sidb_gates_params() - params.simulation_parameters.base = 2 - params.simulation_parameters.mu_minus = -0.28 + params.operational_params.simulation_parameters.base = 2 + params.operational_params.simulation_parameters.mu_minus = -0.28 params.design_mode = design_sidb_gates_mode.EXHAUSTIVE params.canvas = [(4, 8), (14, 11)] params.number_of_sidbs = 1 - params.sim_engine = sidb_simulation_engine.QUICKEXACT + params.operational_params.sim_engine = sidb_simulation_engine.QUICKEXACT - self.assertEqual(params.simulation_parameters.mu_minus, -0.28) + self.assertEqual(params.operational_params.simulation_parameters.mu_minus, -0.28) self.assertEqual(params.number_of_sidbs, 1) self.assertEqual(params.canvas[0], (4, 8, 0)) self.assertEqual(params.canvas[1], (14, 11)) @@ -72,14 +72,14 @@ def test_nor_gate_111(self): layout.assign_cell_type((23, 59), sidb_technology.cell_type.NORMAL) params = design_sidb_gates_params() - params.simulation_parameters.base = 2 - params.simulation_parameters.mu_minus = -0.32 + params.operational_params.simulation_parameters.base = 2 + params.operational_params.simulation_parameters.mu_minus = -0.32 params.design_mode = design_sidb_gates_mode.EXHAUSTIVE params.canvas = [(10, 22), (14, 34)] params.number_of_sidbs = 3 - params.sim_engine = sidb_simulation_engine.QUICKEXACT + params.operational_params.sim_engine = sidb_simulation_engine.QUICKEXACT - self.assertEqual(params.simulation_parameters.mu_minus, -0.32) + self.assertEqual(params.operational_params.simulation_parameters.mu_minus, -0.32) self.assertEqual(params.number_of_sidbs, 3) self.assertEqual(params.canvas[0], (10, 22, 0)) self.assertEqual(params.canvas[1], (14, 34)) diff --git a/bindings/pyfiction/test/algorithms/simulation/sidb/test_random_sidb_layout_generator.py b/bindings/pyfiction/test/algorithms/simulation/sidb/test_random_sidb_layout_generator.py index ff8c72d72..d9652c13c 100644 --- a/bindings/pyfiction/test/algorithms/simulation/sidb/test_random_sidb_layout_generator.py +++ b/bindings/pyfiction/test/algorithms/simulation/sidb/test_random_sidb_layout_generator.py @@ -5,7 +5,7 @@ class TestRandomSiDBLayoutGenerator(unittest.TestCase): - def test_area_with_one_coordinate_100_lattice(self): + def test_area_with_one_sidb_100_lattice(self): params = generate_random_sidb_layout_params() params.number_of_sidbs = 1 params.coordinate_pair = ((10,10), (10,10)) @@ -15,6 +15,14 @@ def test_area_with_one_coordinate_100_lattice(self): self.assertEqual(cell.x, 10) self.assertEqual(cell.y, 10) + def test_area_with_five_sidb_100_lattice(self): + params = generate_random_sidb_layout_params() + params.number_of_sidbs = 5 + print(params.number_of_sidbs) + params.coordinate_pair = ((0,0), (10,10)) + result_lyt = generate_random_sidb_layout(sidb_100_lattice(), params) + self.assertEqual(result_lyt.num_cells(), 5) + def test_area_with_one_coordinate_111_lattice(self): params = generate_random_sidb_layout_params() params.number_of_sidbs = 1 diff --git a/docs/changelog.rst b/docs/changelog.rst index efc11047d..fddd66a46 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -8,6 +8,14 @@ The format is based on `Keep a Changelog ` Unreleased``` ------------- +Added +##### +- Experiments: + - Script to conduct 3-state physical simulation of SiDB layouts. + +Unreleased``` +------------- + Added ##### - Experiments: diff --git a/experiments/physical_design_with_on_the_fly_gate_design/physical_design_with_on_the_fly_gate_design.cpp b/experiments/physical_design_with_on_the_fly_gate_design/physical_design_with_on_the_fly_gate_design.cpp index baea44fb1..d72e8b854 100644 --- a/experiments/physical_design_with_on_the_fly_gate_design/physical_design_with_on_the_fly_gate_design.cpp +++ b/experiments/physical_design_with_on_the_fly_gate_design/physical_design_with_on_the_fly_gate_design.cpp @@ -48,12 +48,12 @@ int main() // NOLINT using cell_lyt = fiction::sidb_cell_clk_lyt_cube; fiction::design_sidb_gates_params> design_gate_params{}; - design_gate_params.simulation_parameters = fiction::sidb_simulation_parameters{2, -0.32}; + design_gate_params.operational_params.simulation_parameters = fiction::sidb_simulation_parameters{2, -0.32}; // needs to be changed if a different skeleton is used. design_gate_params.canvas = {{24, 17}, {34, 28}}; - design_gate_params.number_of_sidbs = 3; - design_gate_params.sim_engine = fiction::sidb_simulation_engine::QUICKEXACT; + design_gate_params.number_of_sidbs = 3; + design_gate_params.operational_params.sim_engine = fiction::sidb_simulation_engine::QUICKEXACT; design_gate_params.termination_cond = fiction::design_sidb_gates_params>::termination_condition::AFTER_FIRST_SOLUTION; diff --git a/experiments/random_sidb_layout_generation/random_sidb_layout_generation.cpp b/experiments/random_sidb_layout_generation/random_sidb_layout_generation.cpp index 63f9fdd0b..02935feb4 100644 --- a/experiments/random_sidb_layout_generation/random_sidb_layout_generation.cpp +++ b/experiments/random_sidb_layout_generation/random_sidb_layout_generation.cpp @@ -4,6 +4,7 @@ #include #include +#include #include #include @@ -35,7 +36,7 @@ using namespace fiction; * --SE_x Sets the x coordinate of the south-east cell corner in SiQAD coordinates. * --SE_y Sets the y coordinate of the south-east cell corner in SiQAD coordinates. * --positive_charges Specifies whether positively charged SiDBs are allowed ("ALLOWED") or forbidden - * ("FORBIDDEN"). + * ("FORBIDDEN") for default physical parameters. * --lower Sets the number of SiDBs for the first bunch of layouts. * --upper Sets the number of SiDBs for the last bunch of layouts. * --num_layouts Sets the number of layouts to generate for each SiDB count. @@ -95,10 +96,23 @@ int main(int argc, const char* argv[]) // NOLINT const int32_t se_y = std::stoi(options["--SE_y"]); // specifies whether positively charged SiDBs are allowed ("ALLOWED") or forbidden ("FORBIDDEN") const std::string charges_str = options["--positive_charges"]; - // specifies whether positively charged SiDBs are allowed ("ALLOWED") or forbidden ("FORBIDDEN") - const generate_random_sidb_layout_params::positive_charges charges = - (charges_str == "ALLOWED") ? generate_random_sidb_layout_params::positive_charges::ALLOWED : - generate_random_sidb_layout_params::positive_charges::FORBIDDEN; + + // specifies whether positively charged SiDBs are allowed ("ALLOWED"), forbidden ("FORBIDDEN") or can occur + // ("MAY_OCCUR") + generate_random_sidb_layout_params::positive_charges charges{}; + if (charges_str == "ALLOWED") + { + charges = generate_random_sidb_layout_params::positive_charges::ALLOWED; + } + else if (charges_str == "MAY_OCCUR") + { + charges = generate_random_sidb_layout_params::positive_charges::MAY_OCCUR; + } + else + { + charges = generate_random_sidb_layout_params::positive_charges::FORBIDDEN; + } + // sets the number of SiDBs for the first bunch of layouts const uint64_t lower_limit = std::stoull(options["--lower"]); // sets the number of SiDBs for the last bunch of layouts @@ -165,8 +179,8 @@ int main(int argc, const char* argv[]) // NOLINT } const generate_random_sidb_layout_params params{ - {{nw_x, nw_y}, {se_x, se_y}}, number_of_placed_sidbs, charges, 2, - static_cast(10E6), number_of_layouts}; + {{nw_x, nw_y}, {se_x, se_y}}, number_of_placed_sidbs, charges, + sidb_simulation_parameters{3, -0.32}, static_cast(10E6), number_of_layouts}; const auto unique_lyts = generate_multiple_random_sidb_layouts(sidb_100_cell_clk_lyt{}, params); for (auto i = 0u; i < unique_lyts.size(); i++) { diff --git a/experiments/sidb_simulation/electrostatic_ground_state/runtime_analysis.cpp b/experiments/sidb_simulation/electrostatic_ground_state/runtime_analysis_bestagon_gates.cpp similarity index 89% rename from experiments/sidb_simulation/electrostatic_ground_state/runtime_analysis.cpp rename to experiments/sidb_simulation/electrostatic_ground_state/runtime_analysis_bestagon_gates.cpp index 20f8a23e0..ca0b8cef2 100644 --- a/experiments/sidb_simulation/electrostatic_ground_state/runtime_analysis.cpp +++ b/experiments/sidb_simulation/electrostatic_ground_state/runtime_analysis_bestagon_gates.cpp @@ -2,18 +2,19 @@ // Created by Jan Drewniok on 17.05.24. // -#include "fiction/algorithms/iter/bdl_input_iterator.hpp" -#include "fiction/algorithms/simulation/sidb/exhaustive_ground_state_simulation.hpp" -#include "fiction/algorithms/simulation/sidb/quickexact.hpp" -#include "fiction/algorithms/simulation/sidb/quicksim.hpp" -#include "fiction/algorithms/simulation/sidb/sidb_simulation_parameters.hpp" -#include "fiction/algorithms/simulation/sidb/time_to_solution.hpp" -#include "fiction/io/read_sqd_layout.hpp" -#include "fiction/layouts/coordinates.hpp" -#include "fiction/types.hpp" -#include "fiction/utils/truth_table_utils.hpp" #include "fiction_experiments.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + #include #include diff --git a/experiments/sidb_simulation/electrostatic_ground_state/runtime_analysis_layouts_with_possible_positive_sidbs.cpp b/experiments/sidb_simulation/electrostatic_ground_state/runtime_analysis_layouts_with_possible_positive_sidbs.cpp new file mode 100644 index 000000000..4f8d5a3dd --- /dev/null +++ b/experiments/sidb_simulation/electrostatic_ground_state/runtime_analysis_layouts_with_possible_positive_sidbs.cpp @@ -0,0 +1,91 @@ +// +// Created by Jan Drewniok on 02.09.24. +// + +#include "fiction_experiments.hpp" + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +using namespace fiction; + +// This script compares the simulation runtime of ExGS and QuickExact for randomly +// generated layouts that may contain positively charged SiDBs (`can_positive_charges_occur` returns `true`). The number +// of SiDBs in the layout varies from 5 to 20. + +int main() // NOLINT +{ + using Lyt = sidb_100_cell_clk_lyt; + + experiments::experiment simulation_exp{ + "Benchmark", + "Number SiDBs", + "#Instances", + "Exhaustive Runtime [s]", + "QuickExact Runtime [s]", + "Average #positive SiDBs of ground state"}; + + const sidb_simulation_parameters sim_params{3, -0.32}; + + const quickexact_params> qe_params{sim_params, + quickexact_params>::automatic_base_number_detection::OFF}; + + auto random_layouts_params = generate_random_sidb_layout_params>{ + {{0, 0}, {10, 10}}, + 0, + generate_random_sidb_layout_params>::positive_charges::MAY_OCCUR, + sim_params, + static_cast(10E6), + 10}; + + for (auto num_sidbs = 5u; num_sidbs < 20; num_sidbs++) + { + random_layouts_params.number_of_sidbs = num_sidbs; + + const auto random_layouts = generate_multiple_random_sidb_layouts(Lyt{}, random_layouts_params); + + double runtime_exhaustive = 0; + double runtime_quickexact = 0; + + std::vector number_of_positive_sidbs_of_gs_per_layout{}; + number_of_positive_sidbs_of_gs_per_layout.reserve(random_layouts_params.number_of_unique_generated_layouts); + + for (const auto& layout : random_layouts) + { + const auto exhaustive_results_layout = exhaustive_ground_state_simulation(layout, sim_params); + + const auto quickexact_results_layout = quickexact(layout, qe_params); + + const auto gs = determine_groundstate_from_simulation_results(exhaustive_results_layout); + + // determine the number of positive SiDBs in the ground state + number_of_positive_sidbs_of_gs_per_layout.push_back(gs.at(0).num_positive_sidbs()); + + runtime_exhaustive += mockturtle::to_seconds(exhaustive_results_layout.simulation_runtime); + runtime_quickexact += mockturtle::to_seconds(quickexact_results_layout.simulation_runtime); + } + + const auto average_pos_sibs_of_gs = + static_cast(std::accumulate(number_of_positive_sidbs_of_gs_per_layout.cbegin(), + number_of_positive_sidbs_of_gs_per_layout.cend(), 0u)) / + static_cast(number_of_positive_sidbs_of_gs_per_layout.size()); + + simulation_exp(random_layouts_params.number_of_sidbs, random_layouts.size(), runtime_exhaustive, + runtime_quickexact, average_pos_sibs_of_gs); + + simulation_exp.save(); + simulation_exp.table(); + } + + return EXIT_SUCCESS; +} diff --git a/experiments/sidb_simulation/temperature/critical_temperature_simulation_bestagon.cpp b/experiments/sidb_simulation/temperature/critical_temperature_simulation_bestagon.cpp index 641ada4bf..8c6f62835 100644 --- a/experiments/sidb_simulation/temperature/critical_temperature_simulation_bestagon.cpp +++ b/experiments/sidb_simulation/temperature/critical_temperature_simulation_bestagon.cpp @@ -5,7 +5,6 @@ #include "fiction_experiments.hpp" #include -#include #include #include #include diff --git a/include/fiction/algorithms/physical_design/design_sidb_gates.hpp b/include/fiction/algorithms/physical_design/design_sidb_gates.hpp index 820589baf..485343fe9 100644 --- a/include/fiction/algorithms/physical_design/design_sidb_gates.hpp +++ b/include/fiction/algorithms/physical_design/design_sidb_gates.hpp @@ -43,7 +43,6 @@ 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. */ @@ -73,9 +72,9 @@ struct design_sidb_gates_params RANDOM }; /** - * All Parameters for physical SiDB simulations. + * Parameters for the `is_operational` function. */ - sidb_simulation_parameters simulation_parameters{}; + is_operational_params operational_params{}; /** * Gate design mode. */ @@ -88,10 +87,6 @@ struct design_sidb_gates_params * Number of SiDBs placed in the canvas to create a working gate. */ std::size_t number_of_sidbs = 1; - /** - * The simulation engine to be used for the operational domain computation. - */ - sidb_simulation_engine sim_engine{sidb_simulation_engine::QUICKEXACT}; /** * The design process is terminated after a valid SiDB gate design is found. * @@ -132,8 +127,6 @@ class design_sidb_gates_impl */ [[nodiscard]] std::vector run_exhaustive_design() noexcept { - const is_operational_params params_is_operational{params.simulation_parameters, params.sim_engine}; - auto all_combinations = determine_all_combinations_of_distributing_k_entities_on_n_positions( params.number_of_sidbs, static_cast(all_sidbs_in_canvas.size())); std::unordered_set> sidbs_affected_by_defects = {}; @@ -152,9 +145,9 @@ class design_sidb_gates_impl std::shuffle(all_combinations.begin(), all_combinations.end(), std::default_random_engine(std::random_device{}())); - const auto add_combination_to_layout_and_check_operation = - [this, &mutex_to_protect_designed_gate_layouts, ¶ms_is_operational, &designed_gate_layouts, - &sidbs_affected_by_defects, &solution_found](const auto& combination) noexcept + const auto add_combination_to_layout_and_check_operation = [this, &mutex_to_protect_designed_gate_layouts, + &designed_gate_layouts, &sidbs_affected_by_defects, + &solution_found](const auto& combination) noexcept { for (const auto& comb : combination) { @@ -165,7 +158,7 @@ class design_sidb_gates_impl auto layout_with_added_cells = add_canvas_sidbs_to_skeleton_layout(comb); if (const auto [status, sim_calls] = - is_operational(layout_with_added_cells, truth_table, params_is_operational); + is_operational(layout_with_added_cells, truth_table, params.operational_params); status == operational_status::OPERATIONAL) { { @@ -227,8 +220,6 @@ class design_sidb_gates_impl { std::vector randomly_designed_gate_layouts = {}; - const is_operational_params params_is_operational{params.simulation_parameters, params.sim_engine}; - const generate_random_sidb_layout_params> parameter_random_layout{ params.canvas, params.number_of_sidbs, generate_random_sidb_layout_params>::positive_charges::FORBIDDEN}; @@ -244,7 +235,7 @@ class design_sidb_gates_impl { threads.emplace_back( [this, &gate_layout_is_found, &mutex_to_protect_designed_gate_layouts, ¶meter_random_layout, - ¶ms_is_operational, &randomly_designed_gate_layouts] + &randomly_designed_gate_layouts] { while (!gate_layout_is_found) { @@ -261,7 +252,7 @@ class design_sidb_gates_impl }); } if (const auto [status, sim_calls] = - is_operational(result_lyt, truth_table, params_is_operational); + is_operational(result_lyt, truth_table, params.operational_params); status == operational_status::OPERATIONAL) { const std::lock_guard lock{mutex_to_protect_designed_gate_layouts}; diff --git a/include/fiction/algorithms/simulation/sidb/critical_temperature.hpp b/include/fiction/algorithms/simulation/sidb/critical_temperature.hpp index 246d8de10..75b9b1d93 100644 --- a/include/fiction/algorithms/simulation/sidb/critical_temperature.hpp +++ b/include/fiction/algorithms/simulation/sidb/critical_temperature.hpp @@ -143,9 +143,8 @@ class critical_temperature_impl layout{lyt}, params{ps}, stats{st}, - bii(bdl_input_iterator{layout, params.input_bdl_iterator_params}), - critical_temperature{ps.max_temperature} - + critical_temperature{ps.max_temperature}, + bii(bdl_input_iterator{layout, params.input_bdl_iterator_params}) { stats.simulation_parameters = params.simulation_parameters; stats.algorithm_name = 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 3027dad12..2384a22cf 100644 --- a/include/fiction/algorithms/simulation/sidb/random_sidb_layout_generator.hpp +++ b/include/fiction/algorithms/simulation/sidb/random_sidb_layout_generator.hpp @@ -6,8 +6,11 @@ #define FICTION_RANDOM_SIDB_LAYOUT_GENERATOR_HPP #include "fiction/algorithms/path_finding/distance.hpp" +#include "fiction/algorithms/simulation/sidb/can_positive_charges_occur.hpp" +#include "fiction/algorithms/simulation/sidb/sidb_simulation_parameters.hpp" #include "fiction/technology/sidb_defects.hpp" #include "fiction/traits.hpp" +#include "fiction/utils/execution_utils.hpp" #include "fiction/utils/layout_utils.hpp" #include @@ -37,7 +40,11 @@ struct generate_random_sidb_layout_params /** * Positive charges are not allowed to occur (i.e. SiDBs need to be seperated by a few lattice points). */ - FORBIDDEN + FORBIDDEN, + /** + * Positive charges can occur, which means that the `can_positive_charges_occur` function returns `true`. + */ + MAY_OCCUR }; /** * Two coordinates that span the region where SiDBs may be placed (order is not important). The first coordinate is @@ -53,10 +60,9 @@ struct generate_random_sidb_layout_params */ positive_charges positive_sidbs = positive_charges::ALLOWED; /** - * If positively charged SiDBs should be prevented, SiDBs are not placed closer than this value (Euclidean distance - * of two cells). + * Simulation parameters. */ - double minimal_spacing = 2.0; + sidb_simulation_parameters sim_params{}; /** * Maximum number of steps to place the specified number of SiDBs. Example: If the area, where SiDBs can be placed, * is small and many SiDBs are to be placed, several tries are required to generate a layout with no positively @@ -108,24 +114,9 @@ Lyt generate_random_sidb_layout(const Lyt& // stops if either all SiDBs are placed or the maximum number of attempts was performed while (lyt.num_cells() < number_of_sidbs_of_final_layout && attempt_counter < params.maximal_attempts) { - // random coordinate within given area + // random coordinate within the area specified by two coordinates const auto random_coord = random_coordinate(params.coordinate_pair.first, params.coordinate_pair.second); - bool next_to_neutral_defect = false; - bool constraint_violation_positive_sidbs = false; - - if (params.positive_sidbs == generate_random_sidb_layout_params>::positive_charges::FORBIDDEN) - { - // checks if the new coordinate is not closer than 2 cells (Euclidean distance) to an already - // placed SiDB - lyt.foreach_cell( - [&lyt, &random_coord, &constraint_violation_positive_sidbs, ¶ms](const auto& c1) - { - if (euclidean_distance(lyt, c1, random_coord) < params.minimal_spacing) - { - constraint_violation_positive_sidbs = true; - } - }); - } + bool next_to_neutral_defect = false; if (sidbs_affected_by_defects.count(random_coord) > 0) { @@ -141,13 +132,26 @@ Lyt generate_random_sidb_layout(const Lyt& // if the constraints that no positive SiDBs occur and the cell is not yet occupied by a defect are satisfied, // the SiDB is added to the layout - if (!constraint_violation_positive_sidbs && !random_cell_is_identical_wih_defect && !next_to_neutral_defect) + if (!random_cell_is_identical_wih_defect && !next_to_neutral_defect) { lyt.assign_cell_type(random_coord, technology::cell_type::NORMAL); + + if (params.positive_sidbs == + generate_random_sidb_layout_params>::positive_charges::FORBIDDEN && + can_positive_charges_occur(lyt, params.sim_params)) + { + lyt.assign_cell_type(random_coord, technology::cell_type::EMPTY); + } } attempt_counter += 1; } + if (params.positive_sidbs == generate_random_sidb_layout_params>::positive_charges::MAY_OCCUR && + !can_positive_charges_occur(lyt, params.sim_params)) + { + return generate_random_sidb_layout(lyt_skeleton, params); + } + return lyt; } @@ -181,30 +185,9 @@ generate_multiple_random_sidb_layouts(const Lyt& const auto random_lyt = generate_random_sidb_layout(lyt_skeleton, params); // indicates if a found SiDB layout is identical to an already found one. - bool identical_layout = false; - for (const auto& old_lyt : unique_lyts) - { - // checks if two layouts have an SiDB at the same position - uint64_t identical_cell_counter = 0; - old_lyt.foreach_cell( - [&identical_cell_counter, random_lyt](const auto& cell_old) - { - random_lyt.foreach_cell( - [&identical_cell_counter, &cell_old](const auto& cell_new) - { - if (cell_new == cell_old) - { - identical_cell_counter += 1; - } - }); - }); - - // all cells are identical, so the new layout is a duplicate - if (identical_cell_counter == random_lyt.num_cells()) - { - identical_layout = true; - } - } + const auto identical_layout = + std::any_of(FICTION_EXECUTION_POLICY_PAR unique_lyts.cbegin(), unique_lyts.cend(), + [&](const auto& old_lyt) { return are_cell_layouts_identical(random_lyt, old_lyt); }); // if the randomly generated SiDB layout is not identical to a previously generated one, it is added to the // collection of all unique SiDB layouts (unique_lyts) diff --git a/include/fiction/technology/charge_distribution_surface.hpp b/include/fiction/technology/charge_distribution_surface.hpp index 7c39cc0dc..fe5f43ab1 100644 --- a/include/fiction/technology/charge_distribution_surface.hpp +++ b/include/fiction/technology/charge_distribution_surface.hpp @@ -126,7 +126,7 @@ enum class charge_index_mode /** * The charge state is assigned to the cell but the old charge index is kept. */ - KEEP_CHARGE_INDEX + KEEP_CHARGE_INDEX, }; /** @@ -1866,15 +1866,12 @@ class charge_distribution_surface : public Lyt std::sort(strg->sidb_order.begin(), strg->sidb_order.end()); this->foreach_cell([this, &cs](const auto&) { strg->cell_charge.push_back(cs); }); - assert((((this->num_cells() < 41) && (strg->simulation_parameters.base == 3)) || - ((strg->simulation_parameters.base == 2) && (this->num_cells() < 64))) && - "number of SiDBs is too large"); - + strg->max_charge_index = static_cast( + std::pow(static_cast(strg->simulation_parameters.base), this->num_cells()) - 1); this->charge_distribution_to_index(); + this->initialize_nm_distance_matrix(); this->initialize_potential_matrix(); - strg->max_charge_index = static_cast( - std::pow(static_cast(strg->simulation_parameters.base), this->num_cells()) - 1); this->update_local_potential(); this->recompute_system_energy(); this->validity_check(); diff --git a/include/fiction/technology/fcn_gate_library.hpp b/include/fiction/technology/fcn_gate_library.hpp index 2ea82e179..68a5c1b6b 100644 --- a/include/fiction/technology/fcn_gate_library.hpp +++ b/include/fiction/technology/fcn_gate_library.hpp @@ -17,6 +17,7 @@ #include #include #include +#include #include namespace fiction diff --git a/include/fiction/technology/sidb_on_the_fly_gate_library.hpp b/include/fiction/technology/sidb_on_the_fly_gate_library.hpp index a0240eead..6058a2770 100644 --- a/include/fiction/technology/sidb_on_the_fly_gate_library.hpp +++ b/include/fiction/technology/sidb_on_the_fly_gate_library.hpp @@ -431,10 +431,11 @@ class sidb_on_the_fly_gate_library : public fcn_gate_library(status == operational_status::OPERATIONAL); } /** @@ -494,7 +495,8 @@ class sidb_on_the_fly_gate_library : public fcn_gate_library, "CellLyt is not an SiDB layout"); static_assert(has_cube_coord_v, "CellLyt is not based on cube coordinates"); - const auto params = is_sidb_gate_design_impossible_params{parameters.design_gate_params.simulation_parameters}; + const auto params = is_sidb_gate_design_impossible_params{ + parameters.design_gate_params.operational_params.simulation_parameters}; if (spec == create_crossing_wire_tt() || spec == create_double_wire_tt()) { diff --git a/include/fiction/utils/layout_utils.hpp b/include/fiction/utils/layout_utils.hpp index cc5e79514..23d3ddae5 100644 --- a/include/fiction/utils/layout_utils.hpp +++ b/include/fiction/utils/layout_utils.hpp @@ -687,6 +687,110 @@ template } #pragma GCC diagnostic pop +/** + * This function checks whether the given layouts `first_lyt` and `second_lyt` are identical by comparing various + * properties such as the number of cells, the types of cells, defects (if applicable), and charge states (if + * applicable). The comparison is done in a detailed manner depending on the specific layout type. + * + * @Note The aspect ratios of the cell-level layouts are not compared. + * + * @tparam Lyt The layout type. Must be a cell-level layout. + * @param first_lyt The first layout to compare. + * @param second_lyt The second layout to compare. + * @return `true` if the layouts are identical, `false` otherwise. + */ +template +[[nodiscard]] inline bool are_cell_layouts_identical(const Lyt& first_lyt, const Lyt& second_lyt) noexcept +{ + static_assert(is_cell_level_layout_v, "Lyt is not a cell-level layout"); + + if (first_lyt.num_cells() != second_lyt.num_cells()) + { + return false; + } + + bool different_cells = false; + + first_lyt.foreach_cell( + [&first_lyt, &second_lyt, &different_cells](const auto& c) + { + if (first_lyt.get_cell_type(c) != second_lyt.get_cell_type(c)) + { + different_cells = true; + return false; // abort + } + return true; // keep looping + }); + + if (different_cells) + { + return false; + } + + if constexpr (is_sidb_defect_surface_v) + { + if (second_lyt.num_defects() != first_lyt.num_defects()) + { + return false; + } + + bool different_defects = false; + + first_lyt.foreach_sidb_defect( + [&first_lyt, &second_lyt, &different_defects](const auto& defect_old) + { + if (first_lyt.get_sidb_defect(defect_old.first) != second_lyt.get_sidb_defect(defect_old.first)) + { + different_defects = true; + return false; // abort + } + return true; // keep looping + }); + + if (different_defects) + { + return false; + } + } + + if constexpr (is_charge_distribution_surface_v) + { + if (second_lyt.num_neutral_sidbs() != first_lyt.num_neutral_sidbs()) + { + return false; + } + + if (second_lyt.num_negative_sidbs() != first_lyt.num_negative_sidbs()) + { + return false; + } + + if (second_lyt.num_positive_sidbs() != first_lyt.num_positive_sidbs()) + { + return false; + } + + bool different_charge_state = false; + first_lyt.foreach_cell( + [&different_charge_state, &first_lyt, &second_lyt](const auto& c) + { + if (first_lyt.get_charge_state(c) != second_lyt.get_charge_state(c)) + { + different_charge_state = true; + return false; // abort + } + return true; // keep looping + }); + + if (different_charge_state) + { + return false; + } + } + + return true; +} + } // namespace fiction #endif // FICTION_LAYOUT_UTILS_HPP diff --git a/test/algorithms/physical_design/design_sidb_gates.cpp b/test/algorithms/physical_design/design_sidb_gates.cpp index 537433438..f55c02827 100644 --- a/test/algorithms/physical_design/design_sidb_gates.cpp +++ b/test/algorithms/physical_design/design_sidb_gates.cpp @@ -5,14 +5,13 @@ #include #include +#include #include #include #include #include #include #include -#include -#include #include #include #include @@ -53,11 +52,10 @@ TEST_CASE("Use SiQAD XNOR skeleton and generate SiQAD XNOR gate, exhaustive", "[ CHECK(lyt.num_cells() == 13); design_sidb_gates_params> params{ - sidb_simulation_parameters{2, -0.32}, + is_operational_params{sidb_simulation_parameters{2, -0.32}}, design_sidb_gates_params>::design_sidb_gates_mode::EXHAUSTIVE, {{10, 4, 0}, {10, 4, 0}}, - 1, - sidb_simulation_engine::QUICKEXACT}; + 1}; SECTION("One cell in canvas") { @@ -70,12 +68,11 @@ TEST_CASE("Use SiQAD XNOR skeleton and generate SiQAD XNOR gate, exhaustive", "[ // using cube coordinates const auto lyt_in_cube_coord = convert_layout_to_fiction_coordinates(lyt); const design_sidb_gates_params> params_cube{ - sidb_simulation_parameters{2, -0.32}, + is_operational_params{sidb_simulation_parameters{2, -0.32}}, design_sidb_gates_params>::design_sidb_gates_mode::EXHAUSTIVE, {siqad::to_fiction_coord(siqad::coord_t{10, 4, 0}), siqad::to_fiction_coord(siqad::coord_t{10, 4, 0})}, - 1, - sidb_simulation_engine::QUICKEXACT}; + 1}; const auto found_gate_layouts_cube = design_sidb_gates(lyt_in_cube_coord, std::vector{create_xnor_tt()}, params_cube); @@ -88,12 +85,11 @@ TEST_CASE("Use SiQAD XNOR skeleton and generate SiQAD XNOR gate, exhaustive", "[ // using offset coordinates const auto lyt_in_offset_coord = convert_layout_to_fiction_coordinates(lyt); const design_sidb_gates_params> params_offset{ - sidb_simulation_parameters{2, -0.32}, + is_operational_params{sidb_simulation_parameters{2, -0.32}}, design_sidb_gates_params>::design_sidb_gates_mode::EXHAUSTIVE, {siqad::to_fiction_coord(siqad::coord_t{10, 4, 0}), siqad::to_fiction_coord(siqad::coord_t{10, 4, 0})}, - 1, - sidb_simulation_engine::QUICKEXACT}; + 1}; const auto found_gate_layouts_offset = design_sidb_gates(lyt_in_offset_coord, std::vector{create_xnor_tt()}, params_offset); @@ -106,11 +102,10 @@ TEST_CASE("Use SiQAD XNOR skeleton and generate SiQAD XNOR gate, exhaustive", "[ SECTION("Four cells in canvas, design all gates") { params = design_sidb_gates_params>{ - sidb_simulation_parameters{2, -0.32}, + is_operational_params{sidb_simulation_parameters{2, -0.32}}, design_sidb_gates_params>::design_sidb_gates_mode::EXHAUSTIVE, {{10, 4, 0}, {13, 4, 0}}, - 1, - sidb_simulation_engine::QUICKEXACT}; + 1}; const auto found_gate_layouts = design_sidb_gates(lyt, std::vector{create_xnor_tt()}, params); @@ -119,11 +114,10 @@ TEST_CASE("Use SiQAD XNOR skeleton and generate SiQAD XNOR gate, exhaustive", "[ SECTION("Four cells in canvas, design process is terminated after first solution is found") { params = design_sidb_gates_params>{ - sidb_simulation_parameters{2, -0.32}, + is_operational_params{sidb_simulation_parameters{2, -0.32}}, design_sidb_gates_params>::design_sidb_gates_mode::EXHAUSTIVE, {{10, 4, 0}, {10, 4, 0}}, 1, - sidb_simulation_engine::QUICKEXACT, design_sidb_gates_params>::termination_condition::AFTER_FIRST_SOLUTION}; const auto found_gate_layouts = design_sidb_gates(lyt, std::vector{create_xnor_tt()}, params); @@ -156,11 +150,10 @@ TEST_CASE("Use SiQAD's AND gate skeleton to generate all possible AND gates", "[ lyt.assign_cell_type({10, 9, 1}, sidb_technology::cell_type::NORMAL); design_sidb_gates_params> params{ - sidb_simulation_parameters{2, -0.28}, + is_operational_params{sidb_simulation_parameters{2, -0.28}, sidb_simulation_engine::EXGS}, design_sidb_gates_params>::design_sidb_gates_mode::EXHAUSTIVE, {{4, 4, 0}, {14, 5, 1}}, - 1, - sidb_simulation_engine::EXGS}; + 1}; SECTION("Exhaustive Generation") { @@ -214,11 +207,10 @@ TEST_CASE("Use FO2 Bestagon gate without SiDB at {17, 11, 0} and generate origin SECTION("generate original FO2") { const design_sidb_gates_params> params{ - sidb_simulation_parameters{2, -0.32}, + is_operational_params{sidb_simulation_parameters{2, -0.32}}, design_sidb_gates_params>::design_sidb_gates_mode::EXHAUSTIVE, {{17, 11, 0}, {17, 11, 0}}, - 1, - sidb_simulation_engine::QUICKEXACT}; + 1}; CHECK(lyt.get_cell_type({17, 11, 0}) == sidb_100_cell_clk_lyt_siqad::technology::EMPTY); @@ -234,11 +226,10 @@ TEST_CASE("Use FO2 Bestagon gate without SiDB at {17, 11, 0} and generate origin SECTION("replace the output perturbers by equivalent negatively charged defects") { const design_sidb_gates_params> params{ - sidb_simulation_parameters{2, -0.32}, + is_operational_params{sidb_simulation_parameters{2, -0.32}}, design_sidb_gates_params>::design_sidb_gates_mode::EXHAUSTIVE, {{17, 11, 0}, {17, 11, 0}}, - 1, - sidb_simulation_engine::QUICKEXACT}; + 1}; sidb_defect_surface defect_layout{lyt}; defect_layout.assign_cell_type({36, 19, 0}, sidb_100_cell_clk_lyt_siqad::cell_type::EMPTY); @@ -247,11 +238,12 @@ TEST_CASE("Use FO2 Bestagon gate without SiDB at {17, 11, 0} and generate origin CHECK(defect_layout.get_cell_type({2, 19, 0}) == sidb_100_cell_clk_lyt_siqad::cell_type::EMPTY); defect_layout.assign_sidb_defect({36, 19, 0}, - sidb_defect{sidb_defect_type::DB, -1, params.simulation_parameters.epsilon_r, - params.simulation_parameters.lambda_tf}); - defect_layout.assign_sidb_defect({2, 19, 0}, - sidb_defect{sidb_defect_type::DB, -1, params.simulation_parameters.epsilon_r, - params.simulation_parameters.lambda_tf}); + sidb_defect{sidb_defect_type::DB, -1, + params.operational_params.simulation_parameters.epsilon_r, + params.operational_params.simulation_parameters.lambda_tf}); + defect_layout.assign_sidb_defect( + {2, 19, 0}, sidb_defect{sidb_defect_type::DB, -1, params.operational_params.simulation_parameters.epsilon_r, + params.operational_params.simulation_parameters.lambda_tf}); const auto found_gate_layouts = design_sidb_gates(defect_layout, std::vector{create_fan_out_tt()}, params); @@ -293,11 +285,10 @@ TEST_CASE("Design AND Bestagon shaped gate", "[design-sidb-gates]") SECTION("Random Generation") { const design_sidb_gates_params> params{ - sidb_simulation_parameters{2, -0.32}, + is_operational_params{sidb_simulation_parameters{2, -0.32}}, design_sidb_gates_params>::design_sidb_gates_mode::RANDOM, {{14, 6, 0}, {24, 12, 0}}, - 3, - sidb_simulation_engine::QUICKEXACT}; + 3}; const auto found_gate_layouts = design_sidb_gates(lyt, std::vector{create_and_tt()}, params); REQUIRE(!found_gate_layouts.empty()); @@ -309,18 +300,19 @@ TEST_CASE("Design AND Bestagon shaped gate", "[design-sidb-gates]") sidb_defect_surface defect_layout{lyt}; const design_sidb_gates_params> params{ - sidb_simulation_parameters{2, -0.32}, + is_operational_params{sidb_simulation_parameters{2, -0.32}}, design_sidb_gates_params>::design_sidb_gates_mode::RANDOM, {{14, 6, 0}, {24, 12, 0}}, - 3, - sidb_simulation_engine::QUICKEXACT}; + 3}; defect_layout.assign_sidb_defect({15, 10, 0}, - sidb_defect{sidb_defect_type::DB, -1, params.simulation_parameters.epsilon_r, - params.simulation_parameters.lambda_tf}); + sidb_defect{sidb_defect_type::DB, -1, + params.operational_params.simulation_parameters.epsilon_r, + params.operational_params.simulation_parameters.lambda_tf}); defect_layout.assign_sidb_defect({20, 12, 0}, - sidb_defect{sidb_defect_type::DB, -1, params.simulation_parameters.epsilon_r, - params.simulation_parameters.lambda_tf}); + sidb_defect{sidb_defect_type::DB, -1, + params.operational_params.simulation_parameters.epsilon_r, + params.operational_params.simulation_parameters.lambda_tf}); defect_layout.assign_sidb_defect({23, 12, 0}, sidb_defect{sidb_defect_type::GUNK}); const auto found_gate_layouts = design_sidb_gates(defect_layout, std::vector{create_and_tt()}, params); @@ -370,11 +362,10 @@ TEST_CASE("Design AND Bestagon shaped gate on H-Si 111", "[design-sidb-gates]") SECTION("Random Generation") { const design_sidb_gates_params> params{ - sidb_simulation_parameters{2, -0.32}, + is_operational_params{sidb_simulation_parameters{2, -0.32}}, design_sidb_gates_params>::design_sidb_gates_mode::RANDOM, {{10, 11, 0}, {14, 15, 0}}, - 3, - sidb_simulation_engine::QUICKEXACT}; + 3}; const auto found_gate_layouts = design_sidb_gates(lyt, std::vector{create_nor_tt()}, params); REQUIRE(!found_gate_layouts.empty()); @@ -384,11 +375,10 @@ TEST_CASE("Design AND Bestagon shaped gate on H-Si 111", "[design-sidb-gates]") SECTION("Exhaustive Generation") { const design_sidb_gates_params> params{ - sidb_simulation_parameters{2, -0.32}, + is_operational_params{sidb_simulation_parameters{2, -0.32}}, design_sidb_gates_params>::design_sidb_gates_mode::EXHAUSTIVE, {{11, 11, 0}, {14, 16, 0}}, - 3, - sidb_simulation_engine::QUICKEXACT}; + 3}; const auto found_gate_layouts = design_sidb_gates(lyt, std::vector{create_nor_tt()}, params); REQUIRE(found_gate_layouts.size() == 52); diff --git a/test/algorithms/simulation/sidb/random_sidb_layout_generator.cpp b/test/algorithms/simulation/sidb/random_sidb_layout_generator.cpp index fa4aa2303..64f19d7c1 100644 --- a/test/algorithms/simulation/sidb/random_sidb_layout_generator.cpp +++ b/test/algorithms/simulation/sidb/random_sidb_layout_generator.cpp @@ -5,6 +5,7 @@ #include #include +#include #include #include #include @@ -12,6 +13,7 @@ #include #include #include +#include #include @@ -118,41 +120,30 @@ TEST_CASE("Random cube::coord_t layout generation", "[generate-random-sidb-layou SECTION("given corner coordinates and number of placed SiDBs, and allow positive charges") { const generate_random_sidb_layout_params params{ - {{0, 0, 0}, {90, 90, 0}}, - 100, + {{0, 0, 0}, {200, 200, 0}}, + 50, generate_random_sidb_layout_params::positive_charges::FORBIDDEN}; const auto result_lyt = generate_random_sidb_layout(sidb_cell_clk_lyt_cube{}, params); - CHECK(result_lyt.num_cells() == 100); + CHECK(result_lyt.num_cells() == 50); result_lyt.foreach_cell( [](const auto& cell) { - CHECK(cell.x < 91); - CHECK(cell.y < 91); - }); - // check if all cells are not closer than two cells (Euclidean distance). - result_lyt.foreach_cell( - [&result_lyt](const auto& cell_one) - { - result_lyt.foreach_cell( - [&cell_one, &result_lyt](const auto& cell_two) - { - if (cell_one != cell_two) - { - CHECK(euclidean_distance(result_lyt, cell_one, cell_two) >= 2); - } - }); + CHECK(cell.x <= 200); + CHECK(cell.y <= 200); }); + + CHECK(!can_positive_charges_occur(result_lyt, sidb_simulation_parameters{})); } SECTION("given previous layouts") { const generate_random_sidb_layout_params params{ - {{-5, -2}, {9, 9}}, - 10, + {{-5, -2}, {20, 20}}, + 6, generate_random_sidb_layout_params::positive_charges::FORBIDDEN, - 2, + sidb_simulation_parameters{}, static_cast(10E6), 3}; const auto result_lyts = generate_multiple_random_sidb_layouts(sidb_cell_clk_lyt_cube{}, params); @@ -163,9 +154,9 @@ TEST_CASE("Random cube::coord_t layout generation", "[generate-random-sidb-layou lyt.foreach_cell( [](const auto& cell) { - CHECK(cell.x < 10); + CHECK(cell.x <= 20); CHECK(cell.x > -6); - CHECK(cell.y < 10); + CHECK(cell.y <= 20); CHECK(cell.y > -3); }); } @@ -174,41 +165,30 @@ TEST_CASE("Random cube::coord_t layout generation", "[generate-random-sidb-layou SECTION("Check uniqueness of two layouts") { const generate_random_sidb_layout_params params{ - {{0, 0}, {9, 9}}, - 10, + {{0, 0}, {20, 20}}, + 8, generate_random_sidb_layout_params::positive_charges::FORBIDDEN, - 2, + sidb_simulation_parameters{}, static_cast(10E6), 2}; + const auto result_lyts = generate_multiple_random_sidb_layouts(sidb_cell_clk_lyt_cube{}, params); + REQUIRE(result_lyts.size() == 2); const auto& first_lyt = result_lyts.front(); const auto& second_lyt = result_lyts.back(); - uint64_t counter_different_cell = 0; - first_lyt.foreach_cell( - [&second_lyt, &counter_different_cell](const auto& cell_first) - { - second_lyt.foreach_cell( - [&cell_first, &counter_different_cell](const auto& cell_second) - { - if (cell_first != cell_second) - { - counter_different_cell += 1; - }; - }); - }); - CHECK(counter_different_cell != 0); + CHECK(!are_cell_layouts_identical(first_lyt, second_lyt)); } SECTION("Check all pairwise distances") { const generate_random_sidb_layout_params params{ - {{0, 0}, {30, 30}}, + {{0, 0}, {40, 40}}, 10, generate_random_sidb_layout_params::positive_charges::FORBIDDEN, - 2, + sidb_simulation_parameters{}, static_cast(10E6), 10}; const auto result_lyts = generate_multiple_random_sidb_layouts(sidb_cell_clk_lyt_cube{}, params); @@ -216,23 +196,7 @@ TEST_CASE("Random cube::coord_t layout generation", "[generate-random-sidb-layou for (const auto& lyt : result_lyts) { - bool all_cells_fulfill_distance = true; - lyt.foreach_cell( - [&lyt, ¶ms, &all_cells_fulfill_distance](const auto& cell_first) - { - lyt.foreach_cell( - [&lyt, &cell_first, ¶ms, &all_cells_fulfill_distance](const auto& cell_second) - { - if (cell_first != cell_second) - { - if (euclidean_distance(lyt, cell_first, cell_second) < params.minimal_spacing) - { - all_cells_fulfill_distance = false; - }; - } - }); - }); - CHECK(all_cells_fulfill_distance); + CHECK(!can_positive_charges_occur(lyt, sidb_simulation_parameters{})); } } } @@ -322,7 +286,7 @@ TEST_CASE("Random offset::ucoord_t layout generation", "[generate-random-sidb-la SECTION("given corner coordinates and number of placed SiDBs, and allow positive charges") { const generate_random_sidb_layout_params params{ - {{0, 0, 0}, {90, 90, 0}}, + {{0, 0, 0}, {200, 200, 0}}, 100, generate_random_sidb_layout_params::positive_charges::FORBIDDEN}; @@ -332,31 +296,20 @@ TEST_CASE("Random offset::ucoord_t layout generation", "[generate-random-sidb-la result_lyt.foreach_cell( [](const auto& cell) { - CHECK(cell.x < 91); - CHECK(cell.y < 91); - }); - // check if all cells are not closer than two cells (Euclidean distance). - result_lyt.foreach_cell( - [&result_lyt](const auto& cell_one) - { - result_lyt.foreach_cell( - [&cell_one, &result_lyt](const auto& cell_two) - { - if (cell_one != cell_two) - { - CHECK(euclidean_distance(result_lyt, cell_one, cell_two) >= 2); - } - }); + CHECK(cell.x <= 200); + CHECK(cell.y <= 200); }); + + CHECK(!can_positive_charges_occur(result_lyt, sidb_simulation_parameters{})); } SECTION("given previous layouts") { const generate_random_sidb_layout_params params{ - {{0, 0}, {9, 9, 2}}, + {{0, 0}, {40, 40}}, 10, generate_random_sidb_layout_params::positive_charges::FORBIDDEN, - 2, + sidb_simulation_parameters{}, static_cast(10E6), 3}; const auto result_lyts = generate_multiple_random_sidb_layouts(sidb_100_cell_clk_lyt{}, params); @@ -367,8 +320,8 @@ TEST_CASE("Random offset::ucoord_t layout generation", "[generate-random-sidb-la lyt.foreach_cell( [](const auto& cell) { - CHECK(cell.x < 10); - CHECK(cell.y < 10); + CHECK(cell.x <= 40); + CHECK(cell.y <= 40); }); } } @@ -376,10 +329,10 @@ TEST_CASE("Random offset::ucoord_t layout generation", "[generate-random-sidb-la SECTION("Check uniqueness of two layouts") { const generate_random_sidb_layout_params params{ - {{0, 0}, {9, 9}}, + {{0, 0}, {20, 20}}, 10, generate_random_sidb_layout_params::positive_charges::FORBIDDEN, - 2, + sidb_simulation_parameters{}, static_cast(10E6), 2}; const auto result_lyts = generate_multiple_random_sidb_layouts(sidb_100_cell_clk_lyt{}, params); @@ -388,20 +341,7 @@ TEST_CASE("Random offset::ucoord_t layout generation", "[generate-random-sidb-la const auto& first_lyt = result_lyts.front(); const auto& second_lyt = result_lyts.back(); - uint64_t counter_different_cell = 0; - first_lyt.foreach_cell( - [&second_lyt, &counter_different_cell](const auto& cell_first) - { - second_lyt.foreach_cell( - [&cell_first, &counter_different_cell](const auto& cell_second) - { - if (cell_first != cell_second) - { - counter_different_cell += 1; - }; - }); - }); - CHECK(counter_different_cell != 0); + CHECK(!are_cell_layouts_identical(first_lyt, second_lyt)); } SECTION("Check correct use of skeleton layout when generating only one random layout") @@ -419,16 +359,19 @@ TEST_CASE("Random offset::ucoord_t layout generation", "[generate-random-sidb-la SECTION("Check correct use of skeleton layout when generating multiple random layouts") { const generate_random_sidb_layout_params params{ - {{0, 0}, {9, 9}}, + {{0, 0}, {40, 40}}, 10, generate_random_sidb_layout_params::positive_charges::FORBIDDEN, - 2, + sidb_simulation_parameters{}, static_cast(10E6), 2}; + sidb_100_cell_clk_lyt skeleton_layout{}; + skeleton_layout.assign_cell_type({0, 0}, sidb_100_cell_clk_lyt::technology::NORMAL); skeleton_layout.assign_cell_type({3, 0}, sidb_100_cell_clk_lyt::technology::NORMAL); skeleton_layout.assign_cell_type({9, 1}, sidb_100_cell_clk_lyt::technology::NORMAL); + const auto result_lyts = generate_multiple_random_sidb_layouts(skeleton_layout, params); REQUIRE(result_lyts.size() == 2); @@ -553,10 +496,10 @@ TEST_CASE("Random siqad::coord_t layout generation", "[generate-random-sidb-layo SECTION("given previous layouts") { const generate_random_sidb_layout_params params{ - {{0, 0, 1}, {9, 9, 1}}, + {{0, 0, 1}, {20, 20, 1}}, 10, generate_random_sidb_layout_params::positive_charges::FORBIDDEN, - 2, + sidb_simulation_parameters{}, static_cast(10E6), 3}; const auto result_lyts = generate_multiple_random_sidb_layouts(sidb_cell_clk_lyt_siqad{}, params); @@ -567,9 +510,9 @@ TEST_CASE("Random siqad::coord_t layout generation", "[generate-random-sidb-layo lyt.foreach_cell( [](const auto& cell) { - CHECK(cell.x < 10); + CHECK(cell.x <= 20); CHECK(cell.x >= 0); - CHECK(cell.y < 10); + CHECK(cell.y <= 20); CHECK(cell.y >= 0); CHECK(cell.z <= 1); }); @@ -604,7 +547,7 @@ TEMPLATE_TEST_CASE("Random siqad::coord_t layout generation with defects", "[gen {{2, 1, 1}, {2, 1, 1}}, 1, generate_random_sidb_layout_params>::positive_charges::FORBIDDEN, - 2, + sidb_simulation_parameters{}, 5u}; auto defect_layout = TestType{}; @@ -624,7 +567,7 @@ TEMPLATE_TEST_CASE("Random siqad::coord_t layout generation with defects", "[gen {{2, 1, 1}, {2, 1, 1}}, 1, generate_random_sidb_layout_params>::positive_charges::FORBIDDEN, - 2, + sidb_simulation_parameters{}, 5u}; auto defect_layout = TestType{}; @@ -647,7 +590,7 @@ TEMPLATE_TEST_CASE("Random siqad::coord_t layout generation with defects", "[gen {{0, 0, 0}, {10, 2, 0}}, 10, generate_random_sidb_layout_params>::positive_charges::ALLOWED, - 2}; + sidb_simulation_parameters{}}; auto defect_layout = TestType{}; defect_layout.assign_sidb_defect({2, 2, 0}, sidb_defect{sidb_defect_type::DB, -1, 5.6, 5}); @@ -683,7 +626,7 @@ TEST_CASE("Random cube::coord_t layout generation with defects", "[generate-rand siqad::to_fiction_coord(siqad::coord_t{10, 2, 0})}, 10, generate_random_sidb_layout_params::positive_charges::ALLOWED, - 2}; + sidb_simulation_parameters{}}; lyt layout{}; diff --git a/test/utils/layout_utils.cpp b/test/utils/layout_utils.cpp index 5b607f60f..d266f3f69 100644 --- a/test/utils/layout_utils.cpp +++ b/test/utils/layout_utils.cpp @@ -853,3 +853,82 @@ TEST_CASE("Generate all cells in area spanned by two cells, using offset coordin CHECK(final_cell.z == 0); } } + +TEST_CASE("Test identity of two layouts", "[layout-utils]") +{ + sidb_cell_clk_lyt_siqad lyt_first{{5, 3}}; + + lyt_first.assign_cell_type({5, 3}, sidb_cell_clk_lyt::cell_type::NORMAL); + lyt_first.assign_cell_type({0, 0}, sidb_cell_clk_lyt::cell_type::INPUT); + lyt_first.assign_cell_type({1, 1}, sidb_cell_clk_lyt::cell_type::INPUT); + lyt_first.assign_cell_type({2, 2}, sidb_cell_clk_lyt::cell_type::OUTPUT); + + auto lyt_second{lyt_first.clone()}; + + SECTION("cell-level layout") + { + SECTION("identical layouts") + { + CHECK(are_cell_layouts_identical(lyt_first, lyt_second)); + } + SECTION("different cell type") + { + lyt_second.assign_cell_type({5, 3}, sidb_cell_clk_lyt::cell_type::INPUT); + CHECK(!are_cell_layouts_identical(lyt_first, lyt_second)); + } + SECTION("different number of cells") + { + lyt_second.assign_cell_type({5, 3}, sidb_cell_clk_lyt::cell_type::EMPTY); + CHECK(!are_cell_layouts_identical(lyt_first, lyt_second)); + } + } + + charge_distribution_surface cds_first{lyt_first}; + charge_distribution_surface cds_second{lyt_second}; + + SECTION("charge distribution surface") + { + SECTION("identical layouts") + { + CHECK(are_cell_layouts_identical(cds_first, cds_second)); + } + SECTION("different charge state") + { + cds_first.assign_charge_state({0, 0}, sidb_charge_state::POSITIVE); + cds_second.assign_charge_state({5, 3}, sidb_charge_state::POSITIVE); + CHECK(cds_first.num_negative_sidbs() == cds_second.num_negative_sidbs()); + CHECK(cds_first.num_positive_sidbs() == cds_second.num_positive_sidbs()); + CHECK(cds_first.num_neutral_sidbs() == cds_second.num_neutral_sidbs()); + CHECK(!are_cell_layouts_identical(cds_first, cds_second)); + } + } + + SECTION("SiDB defect surface on top of the charge distribution surface") + { + sidb_defect_surface defect_first{cds_first}; + defect_first.assign_sidb_defect({1, 1}, sidb_defect{sidb_defect_type::UNKNOWN}); + defect_first.assign_sidb_defect({1, 2}, sidb_defect{sidb_defect_type::SI_VACANCY}); + + sidb_defect_surface defect_second{cds_second}; + defect_second.assign_sidb_defect({1, 1}, sidb_defect{sidb_defect_type::UNKNOWN}); + defect_second.assign_sidb_defect({1, 2}, sidb_defect{sidb_defect_type::SI_VACANCY}); + + SECTION("identical layouts") + { + CHECK(are_cell_layouts_identical(defect_first, defect_second)); + } + SECTION("different layouts") + { + SECTION("different number of defects") + { + defect_second.assign_sidb_defect({1, 2}, sidb_defect{sidb_defect_type::NONE}); + CHECK(!are_cell_layouts_identical(defect_first, defect_second)); + } + SECTION("different defect type") + { + defect_second.assign_sidb_defect({1, 2}, sidb_defect{sidb_defect_type::DB}); + CHECK(!are_cell_layouts_identical(defect_first, defect_second)); + } + } + } +}