def test_gaussian_distribution():
    """Check that the Gaussian generator samples resemble the distribution."""
    n_samples = 10000
    mean = 2 * units("m")
    var = 1 * units("m")
    gen = opt.dist.Gaussian(mean, var)
    samples = [gen.draw() for i in range(n_samples)]
    check_samples_match(samples, avg=mean, var=var, rtol=0.05)
def test_uniform_distribution():
    """Check that the uniform generator samples resemble the distribution."""
    n_samples = 10000
    limit = 5 * units("m")
    gen = opt.dist.Uniform(-limit, limit)
    true_avg = 0 * units("m")
    true_var = limit * limit / 3
    samples = [gen.draw() for i in range(n_samples)]
    check_samples_match(samples,
                        min=-limit,
                        max=limit,
                        avg=true_avg,
                        var=true_var,
                        rtol=0.05,
                        atol=0.1)
def test_sensitivity_running():
    """Check that the results are as expected for a simple model."""
    doubler = Doubler()
    limit = 5 * units("dimensionless")
    sa = opt.SensitivityAnalyser(doubler)
    sa.add_variable(gen=opt.dist.Uniform(-limit, limit),
                    component=opt.sel.facility(),
                    collection="inputs",
                    item="x")
    sa.add_output("y", component=opt.sel.facility(), item="y")
    sa.parameters["numberOfSamples"] = 1000
    sa.run()
    output = sa.outputs["y"]
    # From properties of uniform distribution: Min and max should be twice that
    # of the input; mean should be the same (0), variance 4 times as much.
    # Note that checks are quite tolerant, as we are unlikely to get exact
    # matches without more samples.
    # Also note that assert_allclose does not do any unit conversion, but seems
    # to just consider the magnitude. This is not a problem here as the spec is
    # dimensioness, but it's worth keeping in mind if the tests change!
    assert_allclose(output["min"], -2 * limit, rtol=0.1)
    assert_allclose(output["max"], 2 * limit, rtol=0.1)
    # This test uses absolute tolerance because the target value is 0,
    # and relative tolerance is therefore meaningless
    # TODO better to switch target and actual values around?
    assert_allclose(output["avg"], 0, atol=0.5)
    input_var = limit * limit / 3  # var = (max-min)^2 / 12 = 4 * limit^2 / 12
    assert_allclose(output["var"], 4 * input_var, rtol=0.1)
def test_triangular_distribution():
    """Check that the triangular generator samples resemble the distribution."""
    n_samples = 10000
    min = 1 * units("m")
    max = 5 * units("m")
    gen = opt.dist.Triangular(min, max)
    true_avg = (min + max) / 2
    # Variance of triangular distribution with (min, max, mode) = (a, b, c) is:
    # (a^2 + b^2 + c^2 - a*b - a*c -b*c) / 18
    # which for symmetric distributions reduces to:
    true_var = (min - max)**2 / 24
    samples = [gen.draw() for i in range(n_samples)]
    check_samples_match(samples,
                        min=min,
                        max=max,
                        avg=true_avg,
                        var=true_var,
                        rtol=0.05)
def test_units():
    spec = {
        'dless': Q('dimensionless', ''),
        'count': Q('count', ''),
        'metre': Q('metre', ''),
        'm_per_s': Q('m / s', ''),
        'money': Q('GBP', '')
    }
    d = SpecifiedDict(spec, 'test')
    d['dless'] = units.Quantity(1)
    assert d['dless'].magnitude == 1
    assert d['dless'].units == units.dimensionless
    d['count'] = 2
    assert d['count'] == 2
    assert d['count'] == 2 * units.count
    assert d['count'].units == units.count
    d['count'] = units('4')
    assert d['count'] == 4
    d['metre'] = 3 * units.m
    assert d['metre'] == 3 * units.m
    d['metre'] = 3 * units.cm
    assert d['metre'].units == units.m
    assert d['metre'] == 0.03 * units.m
    d['metre'] = units('1 m')
    assert d['metre'] == 1 * units.m
    d['metre'] = units('2 * m')
    assert d['metre'] == 2 * units.m
    d['m_per_s'] = 4 * (units.m**2) / (units.m * units.s)
    assert d['m_per_s'] == 4 * units.m / units.s
    d['money'] = 5 * units.GBP
    assert d['money'] == 5 * units.GBP
    d['money'] = 5 * units.EUR
    assert d['money'] == 0.8 * 5 * units.GBP

    with raises(SpecificationViolatedError) as excinfo:
        d['metre'] = 2
    excinfo.match(
        r'Invalid value provided for test metre: '
        r'Number "2" provided but quantity with units meter required')
    with raises(SpecificationViolatedError) as excinfo:
        d['metre'] = 2 * units.s
    excinfo.match(r'Invalid value provided for test metre: '
                  r'Value "2 second" does not have units meter')
示例#6
0
def load_data(file_name, folder=None, sections={'inputs', 'outputs'}):
    """Helper function used by the ref_data fixture, that tests can also call directly."""
    if folder is None:
        # Default to the data folder adjacent to this file
        folder = data_dir()
    data_path = folder.join(file_name)
    with data_path.open() as f:
        data = yaml.safe_load(f)
    # Parse all entries as values with units, unless they're booleans!
    for section in sections:
        for key, value in data[section].items():
            if isinstance(value, bool):
                data[section][key] = value
            else:
                data[section][key] = units(str(value))
    return data
def test_minimise_variance():
    """Check that minimising the variance of an output works as expected."""
    target = 5 * units("dimensionless")
    # Set up the sensitivity analysis, which will not actually vary anything
    analyser = opt.SensitivityAnalyser(Fussy(target, 100))
    analyser.add_output("y", component=opt.sel.facility(), item="y")
    analyser.parameters["numberOfSamples"] = 10
    # Set up the optimiser to minimise the variance of the output
    optimiser = opt.Optimiser(analyser)
    optimiser.add_variable(gen=opt.gen.RangeGenerator(0 * target, 2 * target),
                           component=opt.sel.facility(),
                           item='p')
    optimiser.add_objective(component=opt.sel.self(),
                            item=("y", "var"),
                            minimise=True)
    optimiser.parameters["maxGenerations"] = 5
    # Run combined optimisation + SA, and check we get the expected result
    optimiser.run()
    best = optimiser.outputs["bestIndividuals"][0]
    assert best.get_variable('Fussy', 'p').value == target