Beispiel #1
0
def test_docs():
    """Make sure that the documentation examples work"""
    # Generate random real numbers between 3 and 7
    sampler = RealInterval(start=3, stop=7)
    # This is equivalent to
    sampler = RealInterval([3, 7])
    # The default is [1, 5]
    sampler = RealInterval()

    # Generate random integers between 3 and 7 inclusive
    sampler = IntegerRange(start=3, stop=7)
    # This is equivalent to
    sampler = IntegerRange([3, 7])
    # The default is [1, 5]
    sampler = IntegerRange()

    # Select random numbers from (1, 3, 5, 7, 9)
    sampler = DiscreteSet((1, 3, 5, 7, 9))
    # Always select 3.5
    sampler = DiscreteSet(3.5)

    # Select random complex numbers from 0 to 1 + i
    sampler = ComplexRectangle(re=[0, 1], im=[0, 1])
    # The default is re=[1, 3], im=[1, 3]
    sampler = ComplexRectangle()

    # Select random complex numbers from inside the unit circle
    sampler = ComplexSector(modulus=[0, 1], argument=[-np.pi, np.pi])
    # The default is modulus=[1, 3], argument=[0, pi/2]
    sampler = ComplexSector()

    # Test dependent sampling
    sampler = DependentSampler(depends=["x", "y", "z"],
                               formula="sqrt(x^2+y^2+z^2)")

    # Select either sin or cos randomly
    functionsampler = SpecificFunctions([np.cos, np.sin])
    # Always select a single lambda function
    functionsampler = SpecificFunctions(lambda x: x * x)

    # Generate a random function
    functionsampler = RandomFunction(center=1, amplitude=2)
    # The default is center=0, amplitude=10
    functionsampler = RandomFunction()

    # Generate a random sinusoid
    functionsampler = RandomFunction(num_terms=1)

    # Generate a function that takes in two values and outputs a 3D vector
    functionsampler = RandomFunction(input_dim=2, output_dim=3)
Beispiel #2
0
def test_dependent_sampler():
    """Tests the DependentSampler class"""
    # Test basic usage and multiple samples
    result = gen_symbols_samples(
        ["a", "b"], 2, {
            'a': IntegerRange([1, 1]),
            'b': DependentSampler(depends=["a"], formula="a+1")
        })
    assert result == [{"a": 1, "b": 2.0}, {"a": 1, "b": 2.0}]

    result = gen_symbols_samples(
        ["a", "b", "c", "d"], 1, {
            'a': RealInterval([1, 1]),
            'd': DependentSampler(depends=["c"], formula="c+1"),
            'c': DependentSampler(depends=["b"], formula="b+1"),
            'b': DependentSampler(depends=["a"], formula="a+1")
        })[0]
    assert result["b"] == 2 and result["c"] == 3 and result["d"] == 4

    result = gen_symbols_samples(
        ["x", "y", "z", "r"], 1, {
            'x':
            RealInterval([-5, 5]),
            'y':
            RealInterval([-5, 5]),
            'z':
            RealInterval([-5, 5]),
            'r':
            DependentSampler(depends=["x", "y", "z"],
                             formula="sqrt(x^2+y^2+z^2)")
        })[0]
    assert result["x"]**2 + result["y"]**2 + result["z"]**2 == approx(
        result["r"]**2)

    with raises(ConfigError,
                match="Circularly dependent DependentSamplers detected: x, y"):
        gen_symbols_samples(
            ["x", "y"], 1, {
                'x': DependentSampler(depends=["y"], formula="1"),
                'y': DependentSampler(depends=["x"], formula="1")
            })

    with raises(ConfigError,
                match=r"Formula error in dependent sampling formula: 1\+\(2"):
        gen_symbols_samples(
            ["x"], 1, {'x': DependentSampler(depends=[], formula="1+(2")})

    with raises(Exception,
                match="DependentSampler must be invoked with compute_sample."):
        DependentSampler(depends=[], formula="1").gen_sample()
def test_ng_config():
    """Test that the NumericalGrader config bars unwanted entries"""
    expect = "not a valid value for dictionary value @ data\['failable_evals'\]. Got 1"
    with raises(Error, match=expect):
        NumericalGrader(answers="1", failable_evals=1)

    expect = "not a valid value for dictionary value @ data\['samples'\]. Got 2"
    with raises(Error, match=expect):
        NumericalGrader(answers="1", samples=2)

    expect = "not a valid value for dictionary value @ data\['variables'\]. Got \['x'\]"
    with raises(Error, match=expect):
        NumericalGrader(answers="1", variables=["x"])

    expect = "not a valid value for dictionary value @ data\['sample_from'\]. " + \
             "Got {'x': RealInterval\({'start': 1, 'stop': 5}\)}"
    with raises(Error, match=expect):
        NumericalGrader(answers="1", sample_from={"x": RealInterval()})

    expect = "not a valid value for dictionary value @ data\['user_functions'\]\['f'\]. " + \
             "Got RandomFunction"
    with raises(Error, match=expect):
        NumericalGrader(answers="1", user_functions={"f": RandomFunction()})

    expect = "not a valid value for dictionary value @ data\['user_functions'\]\['f'\]. " + \
             "Got \[<ufunc 'sin'>, <ufunc 'cos'>\]"
    with raises(Error, match=expect):
        NumericalGrader(answers="1", user_functions={"f": [np.sin, np.cos]})
def test_ng_config():
    """Test that the NumericalGrader config bars unwanted entries"""
    expect = r"not a valid value for dictionary value @ data\[u?'failable_evals'\]. Got 1"
    with raises(Error, match=expect):
        NumericalGrader(answers="1", failable_evals=1)

    expect = r"not a valid value for dictionary value @ data\[u?'samples'\]. Got 2"
    with raises(Error, match=expect):
        NumericalGrader(answers="1", samples=2)

    expect = (r"length of value must be at most 0 for dictionary value "
              r"@ data\[u?'variables'\]. Got \[u?'x'\]")
    with raises(Error, match=expect):
        NumericalGrader(answers="1", variables=["x"])

    expect = (
        r"extra keys not allowed @ data\[u?'sample_from'\]\[u?'x'\]. Got "
        r"RealInterval\({u?'start': 1, u?'stop': 5}\)")
    with raises(Error, match=expect):
        NumericalGrader(answers="1", sample_from={"x": RealInterval()})

    expect = (
        r"not a valid value for dictionary value @ data\[u?'user_functions'\]\[u?'f'\]. "
        r"Got RandomFunction")
    with raises(Error, match=expect):
        NumericalGrader(answers="1", user_functions={"f": RandomFunction()})

    expect = (r"not a valid value for dictionary value @ data\[u?'user_functions'\]\[u?'f'\]. " + \
              r"Got \[<ufunc 'sin'>, <ufunc 'cos'>\]")
    with raises(Error, match=expect):
        NumericalGrader(answers="1", user_functions={"f": [np.sin, np.cos]})
Beispiel #5
0
def test_fg_sampling():
    """Test various sampling methods in FormulaGrader"""
    grader = FormulaGrader(
        answers="x^2+y^2+z^2",
        variables=['x', 'y', 'z', 'w'],
        sample_from={
            'x': 2,
            'y': (1, 3, 5),
            'z': [1, 5]
        }
    )
    assert grader(None, 'x^2+y^2+z^2')['ok']
    assert isinstance(grader.config["sample_from"]['x'], DiscreteSet)
    assert isinstance(grader.config["sample_from"]['y'], DiscreteSet)
    assert isinstance(grader.config["sample_from"]['z'], RealInterval)
    assert isinstance(grader.config["sample_from"]['w'], RealInterval)

    with raises(MultipleInvalid, match="extra keys not allowed @ data\['w'\]"):
        grader = FormulaGrader(variables=['x'], sample_from={'w': 2})

    grader = FormulaGrader(
        answers="z^2",
        variables=['z'],
        sample_from={'z': ComplexSector()}
    )
    assert grader(None, '(z-1)*(z+1)+1')['ok']

    grader = FormulaGrader(
        answers="z^2",
        variables=['z'],
        sample_from={'z': ComplexRectangle()}
    )
    assert grader(None, '(z-1)*(z+1)+1')['ok']

    grader = FormulaGrader(
        answers="z^2",
        variables=['z'],
        sample_from={'z': IntegerRange()}
    )
    assert grader(None, '(z-1)*(z+1)+1')['ok']

    grader = FormulaGrader(
        answers="z^2",
        variables=['z'],
        sample_from={'z': RealInterval()}
    )
    assert grader(None, '(z-1)*(z+1)+1')['ok']

    grader = FormulaGrader(
        answers="z^2",
        variables=['z'],
        sample_from={'z': DiscreteSet((1, 3, 5))}
    )
    assert grader(None, '(z-1)*(z+1)+1')['ok']
def test_identity_multiples():
    # Test shape, identity times constant, MathArray
    shapes = tuple(range(2, 5))
    samples = ([-1, 1], RealInterval(), ComplexRectangle())

    for shape in shapes:
        for sample in samples:
            matrices = IdentityMatrixMultiples(dimension=shape, sampler=sample)
            m = matrices.gen_sample()
            assert m.shape == (shape, shape)
            assert np.array_equal(m, m[0, 0] * np.eye(shape))
            assert isinstance(m, MathArray)
def test_overriding_constant_with_dependent_sampling():
    symbols = ['a', 'b', 'c']
    samples = 1
    sample_from = {
        'a': RealInterval([10, 10]),
        'b': DependentSampler(depends=["a"], formula="a+1"),
        'c': DependentSampler(depends=["b"], formula="b+1")
    }
    funcs, suffs = {}, {}
    consts = {'unity': 1, 'b': 3.14}
    result = gen_symbols_samples(symbols, samples, sample_from, funcs, suffs, consts)[0]
    a, b, c = [result[sym] for sym in 'abc']

    assert a == 10
    assert b == 11
    assert c == 12
def test_dependent_sampler():
    """Tests the DependentSampler class"""
    # Test basic usage and multiple samples
    symbols = ["a", "b"]
    samples = 2
    sample_from = {
        'a': IntegerRange([1, 1]),
        'b': DependentSampler(depends=["a"], formula="a+1")
    }
    funcs, suffs, consts = {}, {}, {}
    result = gen_symbols_samples(symbols, samples, sample_from, funcs, suffs, consts)
    assert result == [{"a": 1, "b": 2.0}, {"a": 1, "b": 2.0}]

    symbols = ["a", "b", "c", "d"]
    samples = 1
    sample_from = {
        'a': RealInterval([1, 1]),
        'd': DependentSampler(depends=["c"], formula="c+1"),
        'c': DependentSampler(depends=["b"], formula="b+1"),
        'b': DependentSampler(depends=["a"], formula="a+1")
    }
    funcs, suffs, consts = {}, {}, {}
    result = gen_symbols_samples(symbols, samples, sample_from, funcs, suffs, consts)[0]
    assert result["b"] == 2 and result["c"] == 3 and result["d"] == 4

    symbols = ["x", "y", "z", "r"]
    samples = 1
    sample_from = {
        'x': RealInterval([-5, 5]),
        'y': RealInterval([-5, 5]),
        'z': RealInterval([-5, 5]),
        'r': DependentSampler(depends=["x", "y", "z"], formula="sqrt(x^2+y^2+z^2 + unity)")
    }
    funcs = {'sqrt': lambda x: x**0.5}
    consts = {'unity': 1}
    suffs = {}
    result = gen_symbols_samples(symbols, samples, sample_from, funcs, suffs, consts)[0]
    assert result["x"]**2 + result["y"]**2 + result["z"]**2 + 1 == approx(result["r"]**2)

    symbols = ["x", "y"]
    samples = 1
    sample_from = {
        'x': DependentSampler(depends=["y"], formula="y"),
        'y': DependentSampler(depends=["x"], formula="x")
    }
    funcs, suffs, consts = {}, {}, {}
    with raises(ConfigError, match="Circularly dependent DependentSamplers detected: x, y"):
        gen_symbols_samples(symbols, samples, sample_from, funcs, suffs, consts)

    with raises(ConfigError, match=r"Formula error in dependent sampling formula: 1\+\(2"):
        DependentSampler(formula="1+(2")

    symbols = ["x"]
    samples = 1
    sample_from = {'x': DependentSampler(formula="min(j, i)")}
    with raises(ConfigError, match=r"Formula error in dependent sampling formula: min\(j, i\)"):
        gen_symbols_samples(symbols, samples, sample_from, funcs, suffs, {'i': 1j, 'j': 1j})

    with raises(ConfigError, match=r"DependentSamplers depend on undefined quantities: i, j"):
        gen_symbols_samples(symbols, samples, sample_from, funcs, suffs, consts)

    with raises(Exception, match="DependentSampler must be invoked with compute_sample."):
        DependentSampler(depends=[], formula="1").gen_sample()
def test_real_interval():
    """Tests the RealInterval class"""
    start = random.random() * 20 - 10
    stop = random.random() * 20 - 10
    if start > stop:
        start, stop = stop, start

    # Right way around
    ri = RealInterval(start=start, stop=stop)
    for i in range(10):
        assert start <= ri.gen_sample() <= stop

    # Wrong way around
    ri = RealInterval(start=stop, stop=start)
    for i in range(10):
        assert start <= ri.gen_sample() <= stop

    # In a list
    ri = RealInterval([start, stop])
    for i in range(10):
        assert start <= ri.gen_sample() <= stop

    # No arguments
    ri = RealInterval()
    for i in range(10):
        assert 1 <= ri.gen_sample() <= 5

    # Rejects tuples
    with raises(Error, match=r"expected a dictionary. Got \(1, 3\)"):
        RealInterval((1, 3))