Example #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)
Example #2
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']
Example #3
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_int_range():
    """Tests the IntegerRange class"""
    start = random.randint(-20, 20)
    stop = random.randint(-20, 20)
    if start > stop:
        start, stop = stop, start
    if start == stop:
        stop += 1
    mylist = list(range(start, stop + 1))

    # Right way around
    ii = IntegerRange(start=start, stop=stop)
    for i in range(10):
        assert ii.gen_sample() in mylist

    # Wrong way around
    ii = IntegerRange(start=stop, stop=start)
    for i in range(10):
        assert ii.gen_sample() in mylist

    # With only one selection
    ii = IntegerRange(start=4, stop=4)
    assert ii.gen_sample() == 4

    # In a list
    ii = IntegerRange([start, stop])
    for i in range(10):
        assert ii.gen_sample() in mylist

    # No arguments
    ii = IntegerRange()
    for i in range(10):
        assert ii.gen_sample() in list(range(1, 6))
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()