Beispiel #1
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
Beispiel #2
0
def test_iteration(various_pdims):
    """Tests whether the iteration over the span's state works."""
    pd = ParamDim(default=0, values=[1, 2, 3])

    # Should start in default state
    assert pd.state == 0

    # First iteration
    assert pd.__next__() == 1
    assert pd.__next__() == 2
    assert pd.__next__() == 3
    with pytest.raises(StopIteration):
        pd.__next__()

    # Should be able to iterate again
    assert pd.__next__() == 1
    assert pd.__next__() == 2
    assert pd.__next__() == 3
    with pytest.raises(StopIteration):
        pd.__next__()

    # State should be reset to 0 now
    assert pd.state == 0

    # And as a loop
    for _ in pd:
        continue
Beispiel #3
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
Beispiel #4
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]),
        )
    )
Beispiel #5
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]),
        )
    )
Beispiel #6
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]),
        )
    )
Beispiel #7
0
 def check_names(*name_check_pdim):
     """Create the necessary input data for the create_names function, then
     perform it and assert equality to the expected values ...
     """
     kv_pairs = [
         (path, ParamDim(default=0, values=[1, 2], name=pd_name))
         if pdim is not None
         else (path, ParamDim(default=0, values=[1, 2]))
         for path, _, pd_name in name_check_pdim
     ]
     expected_names = [name_out for _, name_out, _ in name_check_pdim]
     actual_names = [k for k, _ in create_names(kv_pairs)]
     assert expected_names == actual_names
Beispiel #8
0
def test_np_methods_return_floats():
    """Assert that when using linspace or logspace, the values are floats and
    _not_ numpy scalar types.
    """
    pds = [
        ParamDim(default=0, linspace=[0, 10, 11]),
        ParamDim(default=0, logspace=[0, 10, 11]),
    ]

    for pd in pds:
        types = [type(v) for v in pd.values]
        print("Types: " + str(types))
        assert all([t is float for t in types])
Beispiel #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)
Beispiel #10
0
def various_pdims():
    """Used to setup various pspan objects to be tested on."""
    pds = {}

    pds["one"] = ParamDim(default=0, values=[1, 2, 3])
    pds["two"] = ParamDim(default=0, values=[1.0, 2, "three", np.inf])
    pds["range"] = ParamDim(default=0, range=[1, 4, 1])
    pds["linspace"] = ParamDim(default=0, linspace=[1, 3, 3, True])
    pds["logspace"] = ParamDim(default=0, logspace=[-1, 1, 11])
    pds["typed"] = ParamDim(default=0, range=[3], as_type="float")
    pds["a_list"] = ParamDim(default=0, values=[[1, 2], [3, 4]])
    pds["as_tuple"] = ParamDim(default=0,
                               values=[1, [2], [3, 4, [5]]],
                               as_type="tuple")
    pds["named"] = ParamDim(default=0, values=[1, 2, 3], name="named_span")
    pds["with_order"] = ParamDim(default=0, values=[1, 2, 3], order=42)

    return pds
Beispiel #11
0
def test_values(various_pdims):
    """Assert the correct values are chosen"""
    vpd = various_pdims

    assert vpd["range"].values == tuple(range(1, 4, 1))
    assert all(vpd["linspace"].values == np.linspace(1, 3, 3, True))
    assert all(vpd["logspace"].values == np.logspace(-1, 1, 11))

    # Test the as_type argument
    assert isinstance(vpd["a_list"].values[0], list)
    assert isinstance(vpd["typed"].values[0], float)
    assert vpd["as_tuple"].values == (1, (2, ), (3, 4, (5, )))

    with pytest.raises(KeyError, match="some_type"):
        ParamDim(default=0, range=[10], as_type="some_type")

    # Assert that values are unique
    with pytest.raises(ValueError, match="need to be unique, but there were"):
        ParamDim(default=0, values=[1, 1, 2])
Beispiel #12
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
Beispiel #13
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)
Beispiel #14
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)
Beispiel #15
0
def test_cpd_iteration():
    """Tests iteration of CoupledParamDim"""
    # ParamDim to couple to for testing
    pd = ParamDim(default=0, values=[1, 2, 3])

    # Simplest case: cpd follows pd
    for pval, cpval in zip(pd, CoupledParamDim(target_pdim=pd)):
        assert pval == cpval

    # With custom cpd values
    for pval, cpval in zip(pd, CoupledParamDim(target_pdim=pd,
                                               values=[2, 3, 4])):
        assert pval + 1 == cpval
Beispiel #16
0
def test_coupled_mask():
    """Test the masking features' effects on CoupledParamDim"""
    pd = ParamDim(default=0, values=[1, 2, 3, 4], mask=(0, 1, 0, 1))

    # It should not be possible to mask a CPD
    with pytest.raises(TypeError, match="Received invalid keyword-argument"):
        CoupledParamDim(target_pdim=pd, mask=True)

    # Test that coupled iteration is masked accordingly
    vals = []
    for pval, cpval in zip(pd, CoupledParamDim(target_pdim=pd)):
        assert pval == cpval
        vals.append(pval)
    assert vals == [1, 3]
Beispiel #17
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"),
            )
        )
Beispiel #18
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)
Beispiel #19
0
def test_mask():
    """Test that masking works"""
    # Test initialization, property getter and setter, and type
    pd = ParamDim(default=0, values=[1, 2, 3, 4], mask=False)
    assert pd.mask is False
    # NOTE not trivial to test because the .mask getter _computes_ the value
    assert not any([isinstance(v, Masked) for v in pd.values])

    pd.mask = True
    assert pd.mask is True
    assert all([isinstance(v, Masked) for v in pd.values])

    # Check the string representation of masked values
    assert str(pd.values[0]).find("<1>") > -1
    assert str(pd).find("Masked object, value:") > -1

    # Now to a more complex mask
    pd.mask = (True, False, True, False)
    assert pd.mask == (True, False, True, False)

    # Test the properties that inform about the number of masked and unmasked
    # values
    assert len(pd) == 2
    assert pd.num_masked == 2

    # Setting one with a bad length should not work
    with pytest.raises(ValueError, match="container of same length as the"):
        pd.mask = (True, False)

    # Check that iteration starts at first unmasked state
    pd.enter_iteration()
    assert pd.state == 2
    assert pd.current_value == 2

    # Iterate one step, this should jump to index and value 3
    assert pd.__next__() == 4
    assert pd.state == 4

    # Setting the state manually to something masked should not work
    with pytest.raises(MaskedValueError, match="Value at index 1 is masked"):
        pd.state = 1

    # No further iteration should be possible for this one
    with pytest.raises(StopIteration):
        pd.iterate_state()
    assert pd.state == 0

    # Check iteration again
    assert list(pd) == [2, 4]

    # For fully masked, the default value should be returned. Eff. length: 1
    pd.mask = True
    assert len(pd) == 1
    assert pd.num_masked == pd.num_states - 1
    assert list(pd) == [0]

    # Try using a slice to set the mask
    pd.mask = slice(2)
    assert pd.mask == (True, True, False, False)

    pd.mask = slice(2, None)
    assert pd.mask == (False, False, True, True)

    pd.mask = slice(None, None, 2)
    assert pd.mask == (True, False, True, False)
Beispiel #20
0
def test_cpd_init():
    """Test whether initialisation of CoupledParamDim works"""
    # These should work
    CoupledParamDim(target_name=("foo", ))
    CoupledParamDim(target_name=("foo", ), default=0)
    CoupledParamDim(target_name=("foo", ), values=[1, 2, 3])
    CoupledParamDim(target_name=("foo", ), range=[3])
    CoupledParamDim(target_name=("foo", ), linspace=[0, 1, 3])
    CoupledParamDim(target_name=("foo", ), logspace=[0, 2, 3])
    CoupledParamDim(target_name="foo")

    # These should fail due to wrong arguments given
    with pytest.raises(TypeError, match="Expected either argument"):
        # Neither target_pdim nor target_name given
        CoupledParamDim()

    with pytest.raises(ValueError, match="The coupling target has not been"):
        # Not coupled yet
        CoupledParamDim(target_name=("foo", )).default

    with pytest.raises(TypeError, match="Got both `target_pdim` and"):
        # Got both target_pdim and target_name
        CoupledParamDim(
            target_pdim=ParamDim(default=0, values=[1, 2, 3]),
            target_name=["foo", "bar"],
        )

    with pytest.raises(TypeError, match="should be a tuple or list"):
        # Bad target_name type
        CoupledParamDim(target_name=dict(foo="bar"))

    # Set target
    pd = ParamDim(default=0, values=[1, 2, 3])
    cpd = CoupledParamDim(target_pdim=pd)
    assert len(pd) == len(cpd)
    assert pd.values == cpd.values
    assert pd.default == cpd.default
    assert cpd.target_name is None

    # Test if the name behaviour is correct
    with pytest.raises(ValueError, match="name cannot be changed after"):
        cpd.target_name = ("bar", )

    # Accessing coupling target without it having been set should raise errors
    cpd = CoupledParamDim(target_name=("foo", ))

    with pytest.raises(ValueError, match="name cannot be changed!"):
        cpd.target_name = ("foo", )

    with pytest.raises(ValueError, match="The coupling target has not been"):
        cpd.target_pdim

    with pytest.raises(TypeError, match="Target of CoupledParamDim needs to"):
        cpd.target_pdim = "foo"

    cpd.target_pdim = pd

    # Setting it again also works
    cpd.target_pdim = pd

    # Test lengths are matching
    with pytest.raises(ValueError, match="The lengths of the value sequences"):
        cpd = CoupledParamDim(target_pdim=pd, values=[1, 2, 3, 4])

    # Assure values cannot be changed
    cpd = CoupledParamDim(target_pdim=pd, values=[2, 3, 4])
    with pytest.raises(AttributeError, match="Values already set; cannot be"):
        cpd._set_values([1, 2, 3], assert_unique=False)

    # Test it has no state set
    cpd = CoupledParamDim(target_pdim=pd, values=[2, 3, 4])
    assert cpd.state == 0
    assert cpd.current_value == 0  # that of the coupled ParamDim!

    # Check that it can access the target's mask
    assert cpd.mask is cpd.target_pdim.mask
Beispiel #21
0
def test_init():
    """Test whether all initialisation methods work."""
    # These should all work
    ParamDim(default=0, values=[1, 2, 3])
    ParamDim(default=0, values=[1.0, 2, "three", np.inf])
    ParamDim(default=0, range=[1, 4, 1])
    ParamDim(default=0, linspace=[1, 3, 3, True])
    ParamDim(default=0, logspace=[-1, 1, 11])
    ParamDim(default=0, range=[3], as_type="float")
    ParamDim(default=0, values=[[1, 2], [3, 4]])
    ParamDim(default=0, values=[1, [2], [3, 4, [5]]], as_type="tuple")
    ParamDim(default=0, values=[1, 2, 3], name="named_span")
    ParamDim(default=0, values=[1, 2, 3], order=42)

    # No default given
    with pytest.raises(TypeError):
        ParamDim()

    # No values given
    with pytest.raises(TypeError, match="Missing one of the following"):
        ParamDim(default=0)

    with pytest.raises(ValueError, match="need be a container of length >= 1"):
        ParamDim(default=0, values=[])

    with pytest.raises(TypeError, match="Received invalid keyword argument"):
        ParamDim(default=0, foo="bar")

    # Multiple values or kwargs given
    with pytest.raises(TypeError, match="Received too many keyword arguments"):
        ParamDim(default=0, values=[1, 2, 3], linspace=[10, 20, 30])

    with pytest.raises(TypeError, match="Received too many keyword arguments"):
        ParamDim(default=0, range=[1, 2], linspace=[10, 20, 30])