Code Monkey home page Code Monkey logo

fiction's People

Contributors

burgholzer avatar dependabot[bot] avatar drewniok avatar hibenj avatar lsschmid avatar marcelwa avatar mkay00 avatar pre-commit-ci[bot] avatar simon1hofmann avatar wlambooy avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

fiction's Issues

Security warnings and notes

CodeQL found some security warnings and had some notes. Nothing critical, fortunately. Would be cool to address them anyway for good measure.

๐Ÿ› `QuickExact` returns duplicate charge configurations

fiction version

fiction main -- latest to date (62a132f)

OS

Ubuntu 22.04.2 LTS | Linux 5.15.133.1-microsoft-standard-WSL2 x86_64 GNU/Linux

Python version

3.11.2

C++ compiler

Ubuntu clang version 14.0.0-1ubuntu1.1

Additional environment information

No response

Description

As the title states, I found as 20 DB layout (unfortunately not a smaller one thus far) for which QuickExact returns 4 physically valid charge distributions, yet the test below shows evidence that there are actually 2 unique physically valid charge distributions.

Expected behavior

An SiDB simulator should not return duplicate results, this could indicate some hidden inefficiency too.

How to Reproduce

#include <fiction/algorithms/simulation/sidb/quickexact.hpp>
#include <fiction/algorithms/simulation/sidb/sidb_simulation_parameters.hpp>
#include <fiction/algorithms/simulation/sidb/sidb_simulation_result.hpp>
#include <fiction/technology/charge_distribution_surface.hpp>
#include <fiction/technology/sidb_charge_state.hpp>
#include <fiction/types.hpp>

#include <cstdint>

TEST_CASE("QuickExact duplicate charge configurations", "[quickexact]")
{
    using sidb_lyt = sidb_cell_clk_lyt_siqad;
    sidb_lyt lyt{};

    lyt.assign_cell_type({3, 0, 0}, sidb_lyt::cell_type::NORMAL);
    lyt.assign_cell_type({4, 0, 0}, sidb_lyt::cell_type::NORMAL);
    lyt.assign_cell_type({13, 0, 1}, sidb_lyt::cell_type::NORMAL);
    lyt.assign_cell_type({5, 1, 1}, sidb_lyt::cell_type::NORMAL);
    lyt.assign_cell_type({22, 3, 0}, sidb_lyt::cell_type::NORMAL);
    lyt.assign_cell_type({11, 5, 1}, sidb_lyt::cell_type::NORMAL);
    lyt.assign_cell_type({2, 6, 1}, sidb_lyt::cell_type::NORMAL);
    lyt.assign_cell_type({4, 6, 1}, sidb_lyt::cell_type::NORMAL);
    lyt.assign_cell_type({23, 7, 1}, sidb_lyt::cell_type::NORMAL);
    lyt.assign_cell_type({16, 8, 0}, sidb_lyt::cell_type::NORMAL);
    lyt.assign_cell_type({8, 8, 1}, sidb_lyt::cell_type::NORMAL);
    lyt.assign_cell_type({15, 9, 0}, sidb_lyt::cell_type::NORMAL);
    lyt.assign_cell_type({1, 10, 1}, sidb_lyt::cell_type::NORMAL);
    lyt.assign_cell_type({12, 10, 1}, sidb_lyt::cell_type::NORMAL);
    lyt.assign_cell_type({14, 10, 1}, sidb_lyt::cell_type::NORMAL);
    lyt.assign_cell_type({9, 11, 0}, sidb_lyt::cell_type::NORMAL);
    lyt.assign_cell_type({24, 11, 0}, sidb_lyt::cell_type::NORMAL);
    lyt.assign_cell_type({10, 11, 1}, sidb_lyt::cell_type::NORMAL);
    lyt.assign_cell_type({13, 12, 0}, sidb_lyt::cell_type::NORMAL);
    lyt.assign_cell_type({24, 12, 0}, sidb_lyt::cell_type::NORMAL);


    // not needed, but I'm giving all default parameters explicitly for the sake of the test
    const sidb_simulation_parameters params{3, -0.32, 5.6, 5.0, 3.84, 7.68, 2.25};

    const sidb_simulation_result<sidb_lyt>& qe_res = quickexact(lyt, quickexact_params<sidb_lyt>{params, quickexact_params<sidb_lyt>::automatic_base_number_detection::ON, {}, 0});

    // QuickExact returns 4 physically valid charge layout
    REQUIRE(qe_res.charge_distributions.size() == 4);

    // This loop asserts that the first two are equal
    for (uint64_t i = 0; i < 2; ++i)
    {
        CHECK(qe_res.charge_distributions[i].get_charge_state({3, 0, 0}) == sidb_charge_state::NEGATIVE);
        CHECK(qe_res.charge_distributions[i].get_charge_state({4, 0, 0}) == sidb_charge_state::POSITIVE);
        CHECK(qe_res.charge_distributions[i].get_charge_state({13, 0, 1}) == sidb_charge_state::NEGATIVE);
        CHECK(qe_res.charge_distributions[i].get_charge_state({5, 1, 1}) == sidb_charge_state::NEGATIVE);
        CHECK(qe_res.charge_distributions[i].get_charge_state({22, 3, 0}) == sidb_charge_state::NEGATIVE);
        CHECK(qe_res.charge_distributions[i].get_charge_state({11, 5, 1}) == sidb_charge_state::NEGATIVE);
        CHECK(qe_res.charge_distributions[i].get_charge_state({2, 6, 1}) == sidb_charge_state::NEGATIVE);
        CHECK(qe_res.charge_distributions[i].get_charge_state({4, 6, 1}) == sidb_charge_state::NEUTRAL);
        CHECK(qe_res.charge_distributions[i].get_charge_state({23, 7, 1}) == sidb_charge_state::NEGATIVE);
        CHECK(qe_res.charge_distributions[i].get_charge_state({16, 8, 0}) == sidb_charge_state::NEGATIVE);
        CHECK(qe_res.charge_distributions[i].get_charge_state({8, 8, 1}) == sidb_charge_state::NEGATIVE);
        CHECK(qe_res.charge_distributions[i].get_charge_state({15, 9, 0}) == sidb_charge_state::NEUTRAL);
        CHECK(qe_res.charge_distributions[i].get_charge_state({1, 10, 1}) == sidb_charge_state::NEGATIVE);
        CHECK(qe_res.charge_distributions[i].get_charge_state({12, 10, 1}) == sidb_charge_state::NEUTRAL);
        CHECK(qe_res.charge_distributions[i].get_charge_state({14, 10, 1}) == sidb_charge_state::NEUTRAL);
        CHECK(qe_res.charge_distributions[i].get_charge_state({9, 11, 0}) == sidb_charge_state::NEGATIVE);
        CHECK(qe_res.charge_distributions[i].get_charge_state({24, 11, 0}) == sidb_charge_state::NEUTRAL);
        CHECK(qe_res.charge_distributions[i].get_charge_state({10, 11, 1}) == sidb_charge_state::POSITIVE);
        CHECK(qe_res.charge_distributions[i].get_charge_state({13, 12, 0}) == sidb_charge_state::NEGATIVE);
        CHECK(qe_res.charge_distributions[i].get_charge_state({24, 12, 0}) == sidb_charge_state::NEGATIVE);
    }

    // This loop asserts that the last two are equal
    for (uint64_t i = 2; i < 4; ++i)
    {
        CHECK(qe_res.charge_distributions[i].get_charge_state({3, 0, 0}) == sidb_charge_state::NEGATIVE);
        CHECK(qe_res.charge_distributions[i].get_charge_state({4, 0, 0}) == sidb_charge_state::POSITIVE);
        CHECK(qe_res.charge_distributions[i].get_charge_state({13, 0, 1}) == sidb_charge_state::NEGATIVE);
        CHECK(qe_res.charge_distributions[i].get_charge_state({5, 1, 1}) == sidb_charge_state::NEGATIVE);
        CHECK(qe_res.charge_distributions[i].get_charge_state({22, 3, 0}) == sidb_charge_state::NEGATIVE);
        CHECK(qe_res.charge_distributions[i].get_charge_state({11, 5, 1}) == sidb_charge_state::NEGATIVE);
        CHECK(qe_res.charge_distributions[i].get_charge_state({2, 6, 1}) == sidb_charge_state::NEGATIVE);
        CHECK(qe_res.charge_distributions[i].get_charge_state({4, 6, 1}) == sidb_charge_state::NEUTRAL);
        CHECK(qe_res.charge_distributions[i].get_charge_state({23, 7, 1}) == sidb_charge_state::NEGATIVE);
        CHECK(qe_res.charge_distributions[i].get_charge_state({16, 8, 0}) == sidb_charge_state::NEGATIVE);
        CHECK(qe_res.charge_distributions[i].get_charge_state({8, 8, 1}) == sidb_charge_state::NEUTRAL);
        CHECK(qe_res.charge_distributions[i].get_charge_state({15, 9, 0}) == sidb_charge_state::NEUTRAL);
        CHECK(qe_res.charge_distributions[i].get_charge_state({1, 10, 1}) == sidb_charge_state::NEGATIVE);
        CHECK(qe_res.charge_distributions[i].get_charge_state({12, 10, 1}) == sidb_charge_state::NEUTRAL);
        CHECK(qe_res.charge_distributions[i].get_charge_state({14, 10, 1}) == sidb_charge_state::NEUTRAL);
        CHECK(qe_res.charge_distributions[i].get_charge_state({9, 11, 0}) == sidb_charge_state::NEGATIVE);
        CHECK(qe_res.charge_distributions[i].get_charge_state({24, 11, 0}) == sidb_charge_state::NEUTRAL);
        CHECK(qe_res.charge_distributions[i].get_charge_state({10, 11, 1}) == sidb_charge_state::NEUTRAL);
        CHECK(qe_res.charge_distributions[i].get_charge_state({13, 12, 0}) == sidb_charge_state::NEGATIVE);
        CHECK(qe_res.charge_distributions[i].get_charge_state({24, 12, 0}) == sidb_charge_state::NEGATIVE);
    }
}

๐Ÿ› 21 Physically valid layouts (for the same layout) not detected by `QuickExact`

fiction version

fiction main -- latest to date (62a132f)

OS

Ubuntu 22.04.2 LTS | Linux 5.15.133.1-microsoft-standard-WSL2 x86_64 GNU/Linux

Python version

3.11.2

C++ compiler

Ubuntu clang version 14.0.0-1ubuntu1.1

Additional environment information

No response

Description

There's not much more to say than the title states. I found a 20 DB layout for which QuickExact gives 0 physically valid layouts, while the 21 charge configurations in the "how to reproduce" section are actually physically valid as judged by charge_distribution_surface standard functionality. I suspect the presence of positive charges here brings up an issue. I'm very much curious to hear what the problem here is when the issue is discovered.

To be sure there is no issue with (physical) parameters, I have specified them explicitly, although the issue is reproduced when all parameters (of charge_distribution_surface and quickexact) are defaulted.

You will have to take my word for that the charge configurations below are all unique (either that or check it yourself I suppose). Though even if they weren't and only one physically valid charge distribution is not detected by QuickExact, the issue claim here would still be valid.

Expected behavior

QuickExact should find all physically valid layouts, hence also these ones. Either that or these layouts should not be judged physically valid, but I suspect the former is more likely.

How to Reproduce

Insert the following Catch2 test into a test file of choice and run it. On my systems the test passes, meaning all of these 21 charge distributions are physically valid, and QuickExact finds precisely 0 physically valid charge distributions for the same layout.

#include <fiction/algorithms/simulation/sidb/quickexact.hpp>
#include <fiction/algorithms/simulation/sidb/sidb_simulation_parameters.hpp>
#include <fiction/technology/charge_distribution_surface.hpp>
#include <fiction/types.hpp>

TEST_CASE("21 Physically valid charge distributions for the same layout not detected by QuickExact", "[quickexact]")
{
    using sidb_lyt = sidb_cell_clk_lyt_siqad;
    sidb_lyt lyt{};

    lyt.assign_cell_type({22, 1, 0}, sidb_lyt::cell_type::NORMAL);
    lyt.assign_cell_type({24, 2, 1}, sidb_lyt::cell_type::NORMAL);
    lyt.assign_cell_type({23, 3, 1}, sidb_lyt::cell_type::NORMAL);
    lyt.assign_cell_type({13, 4, 0}, sidb_lyt::cell_type::NORMAL);
    lyt.assign_cell_type({10, 4, 1}, sidb_lyt::cell_type::NORMAL);
    lyt.assign_cell_type({1, 5, 1}, sidb_lyt::cell_type::NORMAL);
    lyt.assign_cell_type({0, 6, 0}, sidb_lyt::cell_type::NORMAL);
    lyt.assign_cell_type({1, 6, 0}, sidb_lyt::cell_type::NORMAL);
    lyt.assign_cell_type({24, 6, 0}, sidb_lyt::cell_type::NORMAL);
    lyt.assign_cell_type({4, 6, 1}, sidb_lyt::cell_type::NORMAL);
    lyt.assign_cell_type({3, 7, 1}, sidb_lyt::cell_type::NORMAL);
    lyt.assign_cell_type({0, 8, 1}, sidb_lyt::cell_type::NORMAL);
    lyt.assign_cell_type({1, 8, 1}, sidb_lyt::cell_type::NORMAL);
    lyt.assign_cell_type({9, 9, 0}, sidb_lyt::cell_type::NORMAL);
    lyt.assign_cell_type({24, 9, 0}, sidb_lyt::cell_type::NORMAL);
    lyt.assign_cell_type({22, 9, 1}, sidb_lyt::cell_type::NORMAL);
    lyt.assign_cell_type({13, 10, 0}, sidb_lyt::cell_type::NORMAL);
    lyt.assign_cell_type({14, 10, 0}, sidb_lyt::cell_type::NORMAL);
    lyt.assign_cell_type({1, 11, 1}, sidb_lyt::cell_type::NORMAL);
    lyt.assign_cell_type({17, 11, 1}, sidb_lyt::cell_type::NORMAL);

    // not needed, but I'm giving all default parameters explicitly for the sake of the test
    const sidb_simulation_parameters params{3, -0.32, 5.6, 5.0, 3.84, 7.68, 2.25};

    charge_distribution_surface charge_lyt{lyt};
    charge_lyt.assign_physical_parameters(params);

    charge_lyt.assign_charge_state({22, 1, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({24, 2, 1}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({23, 3, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({13, 4, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({10, 4, 1}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({1, 5, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({0, 6, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({1, 6, 0}, sidb_charge_state::POSITIVE);
    charge_lyt.assign_charge_state({24, 6, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({4, 6, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({3, 7, 1}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({0, 8, 1}, sidb_charge_state::POSITIVE);
    charge_lyt.assign_charge_state({1, 8, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({9, 9, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({24, 9, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({22, 9, 1}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({13, 10, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({14, 10, 0}, sidb_charge_state::POSITIVE);
    charge_lyt.assign_charge_state({1, 11, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({17, 11, 1}, sidb_charge_state::NEGATIVE);

    charge_lyt.update_after_charge_change();

    CHECK(charge_lyt.is_physically_valid());

    charge_lyt.assign_charge_state({22, 1, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({24, 2, 1}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({23, 3, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({13, 4, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({10, 4, 1}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({1, 5, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({0, 6, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({1, 6, 0}, sidb_charge_state::POSITIVE);
    charge_lyt.assign_charge_state({24, 6, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({4, 6, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({3, 7, 1}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({0, 8, 1}, sidb_charge_state::POSITIVE);
    charge_lyt.assign_charge_state({1, 8, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({9, 9, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({24, 9, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({22, 9, 1}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({13, 10, 0}, sidb_charge_state::POSITIVE);
    charge_lyt.assign_charge_state({14, 10, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({1, 11, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({17, 11, 1}, sidb_charge_state::NEGATIVE);

    charge_lyt.update_after_charge_change();

    CHECK(charge_lyt.is_physically_valid());

    charge_lyt.assign_charge_state({22, 1, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({24, 2, 1}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({23, 3, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({13, 4, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({10, 4, 1}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({1, 5, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({0, 6, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({1, 6, 0}, sidb_charge_state::POSITIVE);
    charge_lyt.assign_charge_state({24, 6, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({4, 6, 1}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({3, 7, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({0, 8, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({1, 8, 1}, sidb_charge_state::POSITIVE);
    charge_lyt.assign_charge_state({9, 9, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({24, 9, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({22, 9, 1}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({13, 10, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({14, 10, 0}, sidb_charge_state::POSITIVE);
    charge_lyt.assign_charge_state({1, 11, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({17, 11, 1}, sidb_charge_state::NEGATIVE);

    charge_lyt.update_after_charge_change();

    CHECK(charge_lyt.is_physically_valid());

    charge_lyt.assign_charge_state({22, 1, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({24, 2, 1}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({23, 3, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({13, 4, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({10, 4, 1}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({1, 5, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({0, 6, 0}, sidb_charge_state::POSITIVE);
    charge_lyt.assign_charge_state({1, 6, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({24, 6, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({4, 6, 1}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({3, 7, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({0, 8, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({1, 8, 1}, sidb_charge_state::POSITIVE);
    charge_lyt.assign_charge_state({9, 9, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({24, 9, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({22, 9, 1}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({13, 10, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({14, 10, 0}, sidb_charge_state::POSITIVE);
    charge_lyt.assign_charge_state({1, 11, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({17, 11, 1}, sidb_charge_state::NEGATIVE);

    charge_lyt.update_after_charge_change();

    CHECK(charge_lyt.is_physically_valid());

    charge_lyt.assign_charge_state({22, 1, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({24, 2, 1}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({23, 3, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({13, 4, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({10, 4, 1}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({1, 5, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({0, 6, 0}, sidb_charge_state::POSITIVE);
    charge_lyt.assign_charge_state({1, 6, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({24, 6, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({4, 6, 1}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({3, 7, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({0, 8, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({1, 8, 1}, sidb_charge_state::POSITIVE);
    charge_lyt.assign_charge_state({9, 9, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({24, 9, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({22, 9, 1}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({13, 10, 0}, sidb_charge_state::POSITIVE);
    charge_lyt.assign_charge_state({14, 10, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({1, 11, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({17, 11, 1}, sidb_charge_state::NEGATIVE);

    charge_lyt.update_after_charge_change();

    CHECK(charge_lyt.is_physically_valid());

    charge_lyt.assign_charge_state({22, 1, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({24, 2, 1}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({23, 3, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({13, 4, 0}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({10, 4, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({1, 5, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({0, 6, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({1, 6, 0}, sidb_charge_state::POSITIVE);
    charge_lyt.assign_charge_state({24, 6, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({4, 6, 1}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({3, 7, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({0, 8, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({1, 8, 1}, sidb_charge_state::POSITIVE);
    charge_lyt.assign_charge_state({9, 9, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({24, 9, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({22, 9, 1}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({13, 10, 0}, sidb_charge_state::POSITIVE);
    charge_lyt.assign_charge_state({14, 10, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({1, 11, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({17, 11, 1}, sidb_charge_state::NEGATIVE);

    charge_lyt.update_after_charge_change();

    CHECK(charge_lyt.is_physically_valid());

    charge_lyt.assign_charge_state({22, 1, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({24, 2, 1}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({23, 3, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({13, 4, 0}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({10, 4, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({1, 5, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({0, 6, 0}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({1, 6, 0}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({24, 6, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({4, 6, 1}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({3, 7, 1}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({0, 8, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({1, 8, 1}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({9, 9, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({24, 9, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({22, 9, 1}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({13, 10, 0}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({14, 10, 0}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({1, 11, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({17, 11, 1}, sidb_charge_state::NEGATIVE);

    charge_lyt.update_after_charge_change();

    CHECK(charge_lyt.is_physically_valid());

    charge_lyt.assign_charge_state({22, 1, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({24, 2, 1}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({23, 3, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({13, 4, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({10, 4, 1}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({1, 5, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({0, 6, 0}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({1, 6, 0}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({24, 6, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({4, 6, 1}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({3, 7, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({0, 8, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({1, 8, 1}, sidb_charge_state::POSITIVE);
    charge_lyt.assign_charge_state({9, 9, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({24, 9, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({22, 9, 1}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({13, 10, 0}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({14, 10, 0}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({1, 11, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({17, 11, 1}, sidb_charge_state::NEGATIVE);

    charge_lyt.update_after_charge_change();

    CHECK(charge_lyt.is_physically_valid());

    charge_lyt.assign_charge_state({22, 1, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({24, 2, 1}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({23, 3, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({13, 4, 0}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({10, 4, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({1, 5, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({0, 6, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({1, 6, 0}, sidb_charge_state::POSITIVE);
    charge_lyt.assign_charge_state({24, 6, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({4, 6, 1}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({3, 7, 1}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({0, 8, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({1, 8, 1}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({9, 9, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({24, 9, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({22, 9, 1}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({13, 10, 0}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({14, 10, 0}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({1, 11, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({17, 11, 1}, sidb_charge_state::NEGATIVE);

    charge_lyt.update_after_charge_change();

    CHECK(charge_lyt.is_physically_valid());

    charge_lyt.assign_charge_state({22, 1, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({24, 2, 1}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({23, 3, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({13, 4, 0}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({10, 4, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({1, 5, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({0, 6, 0}, sidb_charge_state::POSITIVE);
    charge_lyt.assign_charge_state({1, 6, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({24, 6, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({4, 6, 1}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({3, 7, 1}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({0, 8, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({1, 8, 1}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({9, 9, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({24, 9, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({22, 9, 1}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({13, 10, 0}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({14, 10, 0}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({1, 11, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({17, 11, 1}, sidb_charge_state::NEGATIVE);

    charge_lyt.update_after_charge_change();

    CHECK(charge_lyt.is_physically_valid());

    charge_lyt.assign_charge_state({22, 1, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({24, 2, 1}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({23, 3, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({13, 4, 0}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({10, 4, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({1, 5, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({0, 6, 0}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({1, 6, 0}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({24, 6, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({4, 6, 1}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({3, 7, 1}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({0, 8, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({1, 8, 1}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({9, 9, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({24, 9, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({22, 9, 1}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({13, 10, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({14, 10, 0}, sidb_charge_state::POSITIVE);
    charge_lyt.assign_charge_state({1, 11, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({17, 11, 1}, sidb_charge_state::NEGATIVE);

    charge_lyt.update_after_charge_change();

    CHECK(charge_lyt.is_physically_valid());

    charge_lyt.assign_charge_state({22, 1, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({24, 2, 1}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({23, 3, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({13, 4, 0}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({10, 4, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({1, 5, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({0, 6, 0}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({1, 6, 0}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({24, 6, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({4, 6, 1}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({3, 7, 1}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({0, 8, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({1, 8, 1}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({9, 9, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({24, 9, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({22, 9, 1}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({13, 10, 0}, sidb_charge_state::POSITIVE);
    charge_lyt.assign_charge_state({14, 10, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({1, 11, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({17, 11, 1}, sidb_charge_state::NEGATIVE);

    charge_lyt.update_after_charge_change();

    CHECK(charge_lyt.is_physically_valid());

    charge_lyt.assign_charge_state({22, 1, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({24, 2, 1}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({23, 3, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({13, 4, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({10, 4, 1}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({1, 5, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({0, 6, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({1, 6, 0}, sidb_charge_state::POSITIVE);
    charge_lyt.assign_charge_state({24, 6, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({4, 6, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({3, 7, 1}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({0, 8, 1}, sidb_charge_state::POSITIVE);
    charge_lyt.assign_charge_state({1, 8, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({9, 9, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({24, 9, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({22, 9, 1}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({13, 10, 0}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({14, 10, 0}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({1, 11, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({17, 11, 1}, sidb_charge_state::NEGATIVE);

    charge_lyt.update_after_charge_change();

    CHECK(charge_lyt.is_physically_valid());

    charge_lyt.assign_charge_state({22, 1, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({24, 2, 1}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({23, 3, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({13, 4, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({10, 4, 1}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({1, 5, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({0, 6, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({1, 6, 0}, sidb_charge_state::POSITIVE);
    charge_lyt.assign_charge_state({24, 6, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({4, 6, 1}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({3, 7, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({0, 8, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({1, 8, 1}, sidb_charge_state::POSITIVE);
    charge_lyt.assign_charge_state({9, 9, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({24, 9, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({22, 9, 1}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({13, 10, 0}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({14, 10, 0}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({1, 11, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({17, 11, 1}, sidb_charge_state::NEGATIVE);

    charge_lyt.update_after_charge_change();

    CHECK(charge_lyt.is_physically_valid());

    charge_lyt.assign_charge_state({22, 1, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({24, 2, 1}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({23, 3, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({13, 4, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({10, 4, 1}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({1, 5, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({0, 6, 0}, sidb_charge_state::POSITIVE);
    charge_lyt.assign_charge_state({1, 6, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({24, 6, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({4, 6, 1}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({3, 7, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({0, 8, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({1, 8, 1}, sidb_charge_state::POSITIVE);
    charge_lyt.assign_charge_state({9, 9, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({24, 9, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({22, 9, 1}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({13, 10, 0}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({14, 10, 0}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({1, 11, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({17, 11, 1}, sidb_charge_state::NEGATIVE);

    charge_lyt.update_after_charge_change();

    CHECK(charge_lyt.is_physically_valid());

    charge_lyt.assign_charge_state({22, 1, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({24, 2, 1}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({23, 3, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({13, 4, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({10, 4, 1}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({1, 5, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({0, 6, 0}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({1, 6, 0}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({24, 6, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({4, 6, 1}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({3, 7, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({0, 8, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({1, 8, 1}, sidb_charge_state::POSITIVE);
    charge_lyt.assign_charge_state({9, 9, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({24, 9, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({22, 9, 1}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({13, 10, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({14, 10, 0}, sidb_charge_state::POSITIVE);
    charge_lyt.assign_charge_state({1, 11, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({17, 11, 1}, sidb_charge_state::NEGATIVE);

    charge_lyt.update_after_charge_change();

    CHECK(charge_lyt.is_physically_valid());

    charge_lyt.assign_charge_state({22, 1, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({24, 2, 1}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({23, 3, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({13, 4, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({10, 4, 1}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({1, 5, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({0, 6, 0}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({1, 6, 0}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({24, 6, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({4, 6, 1}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({3, 7, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({0, 8, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({1, 8, 1}, sidb_charge_state::POSITIVE);
    charge_lyt.assign_charge_state({9, 9, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({24, 9, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({22, 9, 1}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({13, 10, 0}, sidb_charge_state::POSITIVE);
    charge_lyt.assign_charge_state({14, 10, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({1, 11, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({17, 11, 1}, sidb_charge_state::NEGATIVE);

    charge_lyt.update_after_charge_change();

    CHECK(charge_lyt.is_physically_valid());

    charge_lyt.assign_charge_state({22, 1, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({24, 2, 1}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({23, 3, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({13, 4, 0}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({10, 4, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({1, 5, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({0, 6, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({1, 6, 0}, sidb_charge_state::POSITIVE);
    charge_lyt.assign_charge_state({24, 6, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({4, 6, 1}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({3, 7, 1}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({0, 8, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({1, 8, 1}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({9, 9, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({24, 9, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({22, 9, 1}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({13, 10, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({14, 10, 0}, sidb_charge_state::POSITIVE);
    charge_lyt.assign_charge_state({1, 11, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({17, 11, 1}, sidb_charge_state::NEGATIVE);

    charge_lyt.update_after_charge_change();

    CHECK(charge_lyt.is_physically_valid());

    charge_lyt.assign_charge_state({22, 1, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({24, 2, 1}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({23, 3, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({13, 4, 0}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({10, 4, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({1, 5, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({0, 6, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({1, 6, 0}, sidb_charge_state::POSITIVE);
    charge_lyt.assign_charge_state({24, 6, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({4, 6, 1}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({3, 7, 1}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({0, 8, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({1, 8, 1}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({9, 9, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({24, 9, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({22, 9, 1}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({13, 10, 0}, sidb_charge_state::POSITIVE);
    charge_lyt.assign_charge_state({14, 10, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({1, 11, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({17, 11, 1}, sidb_charge_state::NEGATIVE);

    charge_lyt.update_after_charge_change();

    CHECK(charge_lyt.is_physically_valid());

    charge_lyt.assign_charge_state({22, 1, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({24, 2, 1}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({23, 3, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({13, 4, 0}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({10, 4, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({1, 5, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({0, 6, 0}, sidb_charge_state::POSITIVE);
    charge_lyt.assign_charge_state({1, 6, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({24, 6, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({4, 6, 1}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({3, 7, 1}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({0, 8, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({1, 8, 1}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({9, 9, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({24, 9, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({22, 9, 1}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({13, 10, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({14, 10, 0}, sidb_charge_state::POSITIVE);
    charge_lyt.assign_charge_state({1, 11, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({17, 11, 1}, sidb_charge_state::NEGATIVE);

    charge_lyt.update_after_charge_change();

    CHECK(charge_lyt.is_physically_valid());

    charge_lyt.assign_charge_state({22, 1, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({24, 2, 1}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({23, 3, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({13, 4, 0}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({10, 4, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({1, 5, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({0, 6, 0}, sidb_charge_state::POSITIVE);
    charge_lyt.assign_charge_state({1, 6, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({24, 6, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({4, 6, 1}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({3, 7, 1}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({0, 8, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({1, 8, 1}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({9, 9, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({24, 9, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({22, 9, 1}, sidb_charge_state::NEUTRAL);
    charge_lyt.assign_charge_state({13, 10, 0}, sidb_charge_state::POSITIVE);
    charge_lyt.assign_charge_state({14, 10, 0}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({1, 11, 1}, sidb_charge_state::NEGATIVE);
    charge_lyt.assign_charge_state({17, 11, 1}, sidb_charge_state::NEGATIVE);

    charge_lyt.update_after_charge_change();

    CHECK(charge_lyt.is_physically_valid());

    // QuickExact finds 0 physically valid charge distributions for this layout
    CHECK(quickexact(lyt,
                     quickexact_params<sidb_lyt>{params, quickexact_params<sidb_lyt>::automatic_base_number_detection::ON, {}, 0})
              .charge_distributions.size() == 0);
}

๐Ÿ› `is_ground_state` does not use `QuickSim`'s results

fiction version

latest

OS

doesn't matter

Python version

No response

C++ compiler

No response

Additional environment information

No response

Description

It's clear to see what the problem is here:

template <typename Lyt>
[[nodiscard]] bool is_ground_state(const sidb_simulation_result<Lyt>& quicksim_results,
                                   const sidb_simulation_result<Lyt>& exhaustive_results) noexcept
{
    static_assert(is_cell_level_layout_v<Lyt>, "Lyt is not a cell-level layout");
    static_assert(has_sidb_technology_v<Lyt>, "Lyt is not an SiDB layout");

    if (exhaustive_results.charge_distributions.empty())
    {
        return false;
    }

    const auto min_energy_exact  = minimum_energy(exhaustive_results.charge_distributions.cbegin(),
                                                  exhaustive_results.charge_distributions.cend());
    const auto min_energy_new_ap = minimum_energy(exhaustive_results.charge_distributions.cbegin(),
                                                  exhaustive_results.charge_distributions.cend());

    return round_to_n_decimal_places(std::abs(min_energy_exact - min_energy_new_ap), 6) == 0;
}

I got a warning for an unused parameter (quicksim_results), so I thought I would put a small fix in the ClusterComplete PR, but apparently TTS fails now, which is unrelated. So I took out the change there and made this issue instead, highlighting the problem.

Expected behavior

No response

How to Reproduce

Permission denied error when building v.0.3.0

When I try to build the project with the "make" command, I get the following error:

Scanning dependencies of target z3
[ 3%] Generating z3/lib/libz3.so
/bin/sh: 1: scripts/mk_make.py: Permission denied
CMakeFiles/z3.dir/build.make:60: recipe for target 'z3/lib/libz3.so' failed
make[2]: *** [z3/lib/libz3.so] Error 126
CMakeFiles/Makefile2:67: recipe for target 'CMakeFiles/z3.dir/all' failed
make[1]: *** [CMakeFiles/z3.dir/all] Error 2
Makefile:83: recipe for target 'all' failed
make: *** [all] Error 2

I tried it in WSL and in a docker container, both with Ubuntu 18.04. If I checkout an older version (v.0.2.1) the build works after a submodule update.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.