Exemple #1
0
def test_subspace_mixed_values():
    """Test that parameter spaces with parameter dimensions that have mixed
    values raise the expected error message.
    """
    psp = ParamSpace(
        dict(
            all_str=ParamDim(default="foo", values=["foo", "bar", "baz"]),
            mixed=ParamDim(default="0", values=[0.0, "1", "2", 3, "4"]),
        )
    )
    assert psp.volume == 3 * 5

    # These should fail due to a mixed-type dimension is tried to be masked
    with pytest.raises(TypeError, match="Could not ascertain whether"):
        psp.activate_subspace(mixed=0.0)

    with pytest.raises(TypeError, match="Could not ascertain whether"):
        psp.activate_subspace(all_str="foo", mixed=[0.0, "1"])

    with pytest.raises(TypeError, match="Could not ascertain whether"):
        psp.activate_subspace(all_str="foo", mixed=["1", "2"])

    # ... but this should work, as the mixed-type dimension is not touched
    psp.activate_subspace(all_str="foo")
    assert psp.volume == 1 * 5
Exemple #2
0
def adv_psp():
    """Used to setup a more elaborate pspace object to be tested on. Includes
    name clashes, manually set names, order, ..."""
    d = dict(
        a=1,
        b=2,
        foo="bar",
        spam="eggs",
        mutable=[0, 0, 0],
        p1=ParamDim(default=0, values=[1, 2, 3], order=0),
        p2=ParamDim(default=0, values=[1, 2, 3], order=1),
        d=dict(
            a=1,
            b=2,
            p1=ParamDim(default=0, values=[1, 2, 3], order=-1),
            p2=ParamDim(default=0, values=[1, 2, 3], order=0),
            d=dict(
                a=1,
                b=2,
                p1=ParamDim(default=0, values=[1, 2, 3], name="ppp1"),
                p2=ParamDim(default=0, values=[1, 2, 3], name="ppp2"),
            ),
        ),
    )

    return ParamSpace(d)
Exemple #3
0
def test_shape(small_psp, basic_psp, adv_psp, seq_psp):
    """Asserts that the returned shape is correct"""
    assert small_psp.shape == (2, 3, 5)
    assert basic_psp.shape == (3, 3, 3, 3, 3, 3)
    assert adv_psp.shape == (3, 3, 3, 3, 3, 3)
    assert seq_psp.shape == (3, 3, 3, 3, 3, 3, 3)

    p = ParamSpace(
        dict(
            a=ParamDim(default=0, values=[1]),  # 1
            b=ParamDim(default=0, range=[0, 10, 2]),  # 5
            c=ParamDim(default=0, linspace=[1, 2, 20]),  # 20
            d=ParamDim(default=0, logspace=[1, 2, 12, 1]),  # 12
        )
    )
    assert p.shape == (1, 5, 20, 12)

    # Also test the number of dimensions
    assert basic_psp.num_dims == 6
    assert adv_psp.num_dims == 6
    assert p.num_dims == 4

    # And the state shape, which is +1 larger in each entry
    assert small_psp.states_shape == (3, 4, 6)
    assert basic_psp.states_shape == (4, 4, 4, 4, 4, 4)
    assert adv_psp.states_shape == (4, 4, 4, 4, 4, 4)

    # And that the maximum state number is correct
    assert small_psp.max_state_no == 71
    assert basic_psp.max_state_no == 4095
    assert adv_psp.max_state_no == 4095
Exemple #4
0
def basic_psp():
    """Used to setup a basic pspace object to be tested on."""
    d = dict(
        a=1,
        b=2,
        foo="bar",
        spam="eggs",
        mutable=[0, 0, 0],
        p1=ParamDim(default=0, values=[1, 2, 3]),
        p2=ParamDim(default=0, values=[1, 2, 3]),
        d=dict(
            aa=1,
            bb=2,
            pp1=ParamDim(default=0, values=[1, 2, 3]),
            pp2=ParamDim(default=0, values=[1, 2, 3]),
            dd=dict(
                aaa=1,
                bbb=2,
                ppp1=ParamDim(default=0, values=[1, 2, 3]),
                ppp2=ParamDim(default=0, values=[1, 2, 3]),
            ),
        ),
    )

    return ParamSpace(d)
Exemple #5
0
def str_valued_psp():
    """A small parameter space that has string values for parameter values"""
    return ParamSpace(
        dict(
            p0=ParamDim(default="foo", values=["foo", "bar", "baz"]),
            p1=ParamDim(default="0", values=["0", "1", "2", "3", "4"]),
            lin=ParamDim(default=0.0, linspace=[0.0, 1.0, 6]),
        )
    )
Exemple #6
0
def float_valued_psp():
    """A small parameter space that has float values for parameter values"""
    return ParamSpace(
        dict(
            lin1=ParamDim(default=0.0, linspace=[-1.0, 1.0, 11]),
            lin2=ParamDim(default=0.0, linspace=[-2.0, 2.0, 11]),
            log1=ParamDim(default=0.0, logspace=[-10.0, 10.0, 6]),
        )
    )
Exemple #7
0
def small_psp():
    """Used to setup a small pspace object to be tested on."""
    return ParamSpace(
        dict(
            p0=ParamDim(default=0, values=[1, 2]),
            p1=ParamDim(default=0, values=[1, 2, 3]),
            p2=ParamDim(default=0, values=[1, 2, 3, 4, 5]),
        )
    )
Exemple #8
0
def test_volume(small_psp, basic_psp, adv_psp, seq_psp):
    """Asserts that the volume calculation is correct"""
    assert small_psp.volume == 2 * 3 * 5
    assert basic_psp.volume == 3 ** 6
    assert adv_psp.volume == 3 ** 6
    assert seq_psp.volume == 3 ** 7

    p = ParamSpace(
        dict(
            a=ParamDim(default=0, values=[1]),  # 1
            b=ParamDim(default=0, range=[0, 10, 2]),  # 5
            c=ParamDim(default=0, linspace=[1, 2, 20]),  # 20
            d=ParamDim(default=0, logspace=[1, 2, 12, 1]),  # 12
        )
    )
    assert p.volume == 1 * 5 * 20 * 12

    # And of a paramspace without dimensions
    empty_psp = ParamSpace(dict(a=1))
    assert empty_psp.volume == 0 == empty_psp.full_volume
Exemple #9
0
def psp_with_coupled():
    """Used to setup a pspace object with coupled param dims"""
    d = dict(
        a=ParamDim(default=0, values=[1, 2, 3], order=0),
        c1=CoupledParamDim(target_name=("a",)),
        d=dict(
            aa=ParamDim(default=0, values=[1, 2, 3], order=-1),
            cc1=CoupledParamDim(target_name=("d", "aa")),
            cc2=CoupledParamDim(target_name=("a",)),
            cc3=CoupledParamDim(target_name="aa"),
        ),
        foo="bar",
        spam="eggs",
        mutable=[0, 0, 0],
    )

    return ParamSpace(d)
Exemple #10
0
def test_coupled(psp_with_coupled):
    """Test parameter spaces with CoupledParamDims in them"""
    psp = psp_with_coupled
    print("ParamSpace with CoupledParamDim:\n", psp)

    def assert_coupling(src: tuple, target: tuple):
        """Asserts that the CoupledParamDim at keyseq src is coupled to the target ParamDim at keyseq target."""
        assert (
            psp.coupled_dims_by_loc[src].target_pdim == psp.dims_by_loc[target]
        )

    # Assert correct coupling
    assert_coupling(("c1",), ("a",))
    assert_coupling(("d", "cc1"), ("d", "aa"))
    assert_coupling(("d", "cc2"), ("a",))
    assert_coupling(("d", "cc3"), ("d", "aa"))

    # Check default is correct
    default = psp.default

    assert default["c1"] == default["a"]
    assert default["d"]["cc1"] == default["d"]["aa"]
    assert default["d"]["cc2"] == default["a"]
    assert default["d"]["cc3"] == default["d"]["aa"]

    # Iterate over the paramspace and check correctness
    for pt in psp:
        print("Point: ", pt)

        assert pt["c1"] == pt["a"]
        assert pt["d"]["cc1"] == pt["d"]["aa"]
        assert pt["d"]["cc2"] == pt["a"]
        assert pt["d"]["cc3"] == pt["d"]["aa"]

    # Invalid coupling targets should raise an error
    with pytest.raises(ValueError, match="Could not resolve the coupling"):
        ParamSpace(
            dict(
                a=ParamDim(default=0, range=[10]),
                b=CoupledParamDim(target_name="foo"),
            )
        )
Exemple #11
0
def seq_psp():
    """A parameter space with dimensions within sequences"""
    d = dict(
        a=1,
        b=2,
        foo="bar",
        spam="eggs",
        mutable=[0, 0, 0],
        s=[
            ParamDim(default=0, values=[1, 2, 3]),
            [ParamDim(default=1, values=[1, 2, 3], order=1), 2, 3],
        ],
        d=dict(
            a=1,
            b=2,
            s=[
                ParamDim(default=0, values=[1, 2, 3], order=-1),
                ParamDim(default=1, values=[1, 2, 3], order=0, name="ds1"),
                2,
                3,
            ],
            d=dict(
                a=1,
                b=2,
                p=ParamDim(default=0, values=[1, 2, 3]),
                s=[
                    0,
                    ParamDim(default=1, values=[1, 2, 3]),
                    ParamDim(default=2, values=[1, 2, 3], name="dds2"),
                    3,
                ],
            ),
        ),
    )

    return ParamSpace(d)
Exemple #12
0
def test_init(basic_psp, adv_psp, seq_psp):
    """Test whether initialisation behaves as expected"""
    # These should work
    ParamSpace(dict(a=1))
    ParamSpace(OrderedDict(a=1))

    # These should also work, albeit not that practical
    ParamSpace(list(range(10)))

    # These should create a warning (not mutable)
    with pytest.warns(UserWarning, match="Got unusual type <class 'tuple'>"):
        ParamSpace(tuple(range(10)))

    with pytest.warns(UserWarning, match="Got unusual type <class 'set'>"):
        ParamSpace(set(range(10)))

    # These should warn and fail (not iterable)
    with pytest.raises(TypeError, match="'int' object is not iterable"):
        with pytest.warns(UserWarning, match="Got unusual type"):
            ParamSpace(1)

    with pytest.raises(TypeError, match="'function' object is not iterable"):
        with pytest.warns(UserWarning, match="Got unusual type"):
            ParamSpace(lambda x: None)
Exemple #13
0
def test_basic_iteration(small_psp, seq_psp):
    """Tests whether the iteration goes through all points"""
    # Test on the __iter__ and __next__ level
    psp = small_psp
    it = psp.iterator()  # is a generator now
    assert it.__next__() == dict(p0=1, p1=1, p2=1)
    assert psp.state_vector == (1, 1, 1)
    assert psp.state_no == 31  # == 24 + 6 + 1

    assert it.__next__() == dict(p0=1, p1=1, p2=2)
    assert psp.state_vector == (1, 1, 2)
    assert psp.state_no == 31 + 1

    assert it.__next__() == dict(p0=1, p1=1, p2=3)
    assert psp.state_vector == (1, 1, 3)
    assert psp.state_no == 31 + 2

    assert it.__next__() == dict(p0=1, p1=1, p2=4)
    assert it.__next__() == dict(p0=1, p1=1, p2=5)
    assert it.__next__() == dict(p0=1, p1=2, p2=1)
    assert psp.state_vector == (1, 2, 1)
    assert psp.state_no == 31 + 6

    # ... and so on
    psp.reset()
    assert psp.state_vector == (0, 0, 0)
    assert psp.state_no == 0

    # Test some general properties relating to iteration and state
    # Test manually setting state vector
    psp.state_vector = (1, 1, 1)
    assert psp.current_point == dict(p0=1, p1=1, p2=1)

    with pytest.raises(ValueError, match="needs to be of same length as"):
        psp.state_vector = (0, 0)

    with pytest.raises(ValueError, match="Could not set the state of "):
        psp.state_vector = (-1, 42, 123.45)

    # A paramspace without volume should still be iterable
    empty_psp = ParamSpace(dict(foo="bar"))
    assert list(iter(empty_psp)) == [dict(foo="bar")]

    # Check the dry run
    psp.reset()
    snos = list(s for s in psp.iterator(with_info="state_no", omit_pt=True))
    assert snos[:4] == [31, 32, 33, 34]

    # Check that the counts match using a helper function . . . . . . . . . . .
    def check_counts(iters, counts):
        cntrs = {i: 0 for i, _ in enumerate(counts)}

        for it_no, (it, count) in enumerate(zip(iters, counts)):
            for _ in it:
                cntrs[it_no] += 1
            assert cntrs[it_no] == count

    # For the explicit call
    check_counts(
        (small_psp.iterator(), seq_psp.iterator()),
        (small_psp.volume, seq_psp.volume),
    )

    # For the call via __iter__ and __next__
    check_counts((small_psp, seq_psp), (small_psp.volume, seq_psp.volume))

    # Also test all information tuples and the dry run
    info = ("state_no", "state_vec", "state_no_str", "current_coords")
    check_counts(
        (
            small_psp.iterator(with_info=info),
            empty_psp.iterator(with_info=info),
        ),
        (small_psp.volume, 1),
    )
    check_counts(
        (small_psp.iterator(with_info="state_no"),), (small_psp.volume,)
    )

    # ... and whether invalid values lead to failure
    with pytest.raises(ValueError, match="No such information 'foo bar' avai"):
        info = ("state_no", "foo bar")
        check_counts(
            (small_psp.iterator(with_info=info),), (small_psp.volume,)
        )
Exemple #14
0
def psp_nested(basic_psp):
    """Creates two ParamSpaces nested within another ParamSpace"""
    return ParamSpace(
        dict(foo="bar", basic=basic_psp, deeper=dict(basic=basic_psp))
    )