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)
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_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()