def test_solver_22(): # 2 < abs(X) < 5 event = (2 < abs(Y)) < 5 solution = Interval.open(2, 5) | Interval.open(-5, -2) assert event.solve() == solution # 2 <= abs(X) < 5 event = (2 <= abs(Y)) < 5 solution = Interval.Ropen(2, 5) | Interval.Lopen(-5, -2) assert event.solve() == solution # 2 < abs(X) <= 5 event = (2 < abs(Y)) <= 5 solution = Interval.Lopen(2, 5) | Interval.Ropen(-5, -2) assert event.solve() == solution # 2 <= abs(X) <= 5 event = (2 <= abs(Y)) <= 5 solution = Interval(2, 5) | Interval(-5, -2) assert event.solve() == solution # -2 < abs(X) < 5 event = (-2 < abs(Y)) < 5 solution = Interval.open(-5, 5) assert event.solve() == solution # # -2 <= abs(X) < 5 event = (-2 <= abs(Y)) < 5 solution = Interval.open(-5, 5) assert event.solve() == solution # -2 < abs(X) <= 5 event = (-2 < abs(Y)) <= 5 solution = Interval(-5, 5) assert event.solve() == solution # 2 <= abs(X) <= 5 event = (-2 <= abs(Y)) <= 5 solution = Interval(-5, 5) assert event.solve() == solution
def test_parse_5_open(): # (2*x+10 < 4) & (x + 10 > 3) expr = ((2*X + 10) < 4) & (X + 10 > 3) event = EventAnd([ EventInterval(Poly(Y, [10, 2]), Interval.open(-oo, 4)), EventInterval(Poly(Y, [10, 1]), Interval.open(3, oo)), ]) assert expr == event
def test_solver_13(): # 2*sqrt(|x|**2) - 3 > 10 solution = Union( Interval.open(-oo, -Rat(13, 2)), Interval.open(Rat(13, 2), oo)) event = (2*Sqrt(abs(Y)**2) - 3) > 10 answer = event.solve() assert answer == solution
def test_solver_14(): # x**2 > 10 solution = Union( Interval.open(-oo, -sympy.sqrt(10)), Interval.open(sympy.sqrt(10), oo)) event = Y**2 > 10 answer = event.solve() assert answer == solution
def test_solver_20(): # log(x**2 - 3) < 5 solution = Union( Interval.open(-sympy.sqrt(3 + sympy.exp(5)), -sympy.sqrt(3)), Interval.open(sympy.sqrt(3), sympy.sqrt(3 + sympy.exp(5)))) event = Log(Y**2 - 3) < 5 answer = event.solve() assert answer == solution
def test_solver_6(): # (x**2 - 2*x) > 10 solution = Union( Interval.open(-oo, 1 - sympy.sqrt(11)), Interval.open(1 + sympy.sqrt(11), oo)) event = (Y**2 - 2*Y) > 10 answer = event.solve() assert answer == solution
def test_parse_2_open(): # log(x) < 2 & (x < exp(2)) expr = (Log(X) > 2) & (X < sympy.exp(2)) event = EventAnd([ EventInterval(Log(Y), Interval.open(2, oo)), EventInterval(Y, Interval.open(-oo, sympy.exp(2))) ]) assert expr == event
def test_parse_6(): # (x**2 - 2*x) > 10 expr = (X**2 - 2*X) > 10 event = EventInterval(Poly(Y, [0, -2, 1]), Interval.open(10, oo)) assert expr == event # (exp(x)**2 - 2*exp(x)) > 10 expr = (Exp(X)**2 - 2*Exp(X)) > 10 event = EventInterval(Poly(Exp(X), [0, -2, 1]), Interval.open(10, oo)) assert expr == event
def test_solver_27_piecewise_many(): expr = (Y < 0)*(Y**2) + (0 <= Y)*Y**(Rat(1, 2)) event = expr << {3} assert sorted(event.solve()) == [-sympy.sqrt(3), 9] event = 0 < expr assert event.solve() == Union( Interval.open(-oo, 0), Interval.open(0, oo)) # TODO: Consider banning the restriction of a function # to a segment outside of its domain. expr = (Y < 0)*Y**(Rat(1, 2)) assert (expr < 1).solve() is EmptySet
def test_parse_26_piecewise_one_expr_compound_event(): assert (Y**2)*((Y < 0) | (0 < Y)) == Piecewise( [Poly(Y, [0, 0, 1])], [EventOr([ EventInterval(Y, Interval.open(-oo, 0)), EventInterval(Y, Interval.open(0, oo)), ])]) assert (Y**2)*(~((3 < Y) <= 4)) == Piecewise( [Poly(Y, [0, 0, 1])], [EventOr([ EventInterval(Y, Interval(-oo, 3)), EventInterval(Y, Interval.open(4, oo)), ])])
def test_sum_normal_nominal(): X = Id('X') children = [ X >> norm(loc=0, scale=1), X >> choice({ 'low': Fraction(3, 10), 'high': Fraction(7, 10) }), ] weights = [log(Fraction(4, 7)), log(Fraction(3, 7))] spe = SumSPE(children, weights) assert allclose(spe.logprob(X < 0), log(Fraction(4, 7)) + log(Fraction(1, 2))) assert allclose(spe.logprob(X << {'low'}), log(Fraction(3, 7)) + log(Fraction(3, 10))) # The semantics of ~(X<<{'low'}) are (X << String and X != 'low') assert allclose(spe.logprob(~(X << {'low'})), spe.logprob((X << {'high'}))) assert allclose( spe.logprob((X << FiniteNominal(b=True)) & ~(X << {'low'})), spe.logprob((X << FiniteNominal(b=True)) & (X << {'high'}))) assert isinf_neg(spe.logprob((X < 0) & (X << {'low'}))) assert allclose(spe.logprob((X < 0) | (X << {'low'})), logsumexp([spe.logprob(X < 0), spe.logprob(X << {'low'})])) assert isinf_neg(spe.logprob(X << {'a'})) assert allclose(spe.logprob(~(X << {'a'})), spe.logprob(X << {'low', 'high'})) assert allclose(spe.logprob(X**2 < 9), log(Fraction(4, 7)) + spe.children[0].logprob(X**2 < 9)) spe_condition = spe.condition(X**2 < 9) assert isinstance(spe_condition, ContinuousLeaf) assert spe_condition.support == Interval.open(-3, 3) spe_condition = spe.condition((X**2 < 9) | X << {'low'}) assert isinstance(spe_condition, SumSPE) assert spe_condition.children[0].support == Interval.open(-3, 3) assert spe_condition.children[1].support == FiniteNominal('low', 'high') assert isinf_neg(spe_condition.children[1].logprob(X << {'high'})) assert spe_condition == spe.condition((X**2 < 9) | ~(X << {'high'})) assert allclose(spe.logprob((X < oo) | ~(X << {'1'})), 0)
def test_solver_23_reciprocal_lte(): for c in [1, 3]: # Positive # 1 / X < 10 solution = Interval.Ropen(-oo, 0) | Interval.Lopen(Rat(c, 10), oo) event = (c / Y) < 10 assert event.solve() == solution # 1 / X <= 10 solution = Interval.Ropen(-oo, 0) | Interval(Rat(c, 10), oo) event = (c / Y) <= 10 assert event.solve() == solution # 1 / X <= sqrt(2) solution = Interval.Ropen(-oo, 0) | Interval(c / sympy.sqrt(2), oo) event = (c / Y) <= sympy.sqrt(2) assert event.solve() == solution # Negative. # 1 / X < -10 solution = Interval.open(-Rat(c, 10), 0) event = (c / Y) < -10 assert event.solve() == solution # 1 / X <= -10 solution = Interval.Ropen(-Rat(c, 10), 0) event = (c / Y) <= -10 assert event.solve() == solution # 1 / X <= -sqrt(2) solution = Interval.Ropen(-c / sympy.sqrt(2), 0) event = (c / Y) <= -sympy.sqrt(2) assert event.solve() == solution
def test_parse_12(): # 2*sqrt(|x|) - 3 > 10 expr = 2*Sqrt(Abs(X)) - 3 expr_prime = Poly(Sqrt(Abs(Y)), [-3, 2]) assert expr == expr_prime event = EventInterval(expr, Interval.open(10, oo)) assert (expr > 10) == event
def test_parse_15(): # ((x**4)**(1/7)) < 9 expr = ((X**4))**Rat(1, 7) expr_prime = Radical(Pow(Y, 4), 7) assert expr == expr_prime event = EventInterval(expr_prime, Interval.open(-oo, 9)) assert (expr < 9) == event
def test_solver_24_negative_power_integer(): # Case 1. event = Y**(-3) < 6 assert event.solve() == Union( Interval.open(-oo, 0), Interval.open(6**Rat(-1, 3), oo)) # Case 2. event = (-1 < Y**(-3)) < 6 assert event.solve() == Union( Interval.open(-oo, -1), Interval.open(6**Rat(-1, 3), oo)) # Case 3. event = 5 <= Y**(-3) assert event.solve() == Interval.Lopen(0, 5**Rat(-1, 3)) # Case 4. event = (5 <= Y**(-3)) < 6 assert event.solve() == Interval.Lopen(6**Rat(-1, 3), 5**Rat(-1, 3))
def test_parse_16(): # (x**(1/7))**4 < 9 for expr in [((X**Rat(1,7)))**4, (X**(1,7))**4]: expr_prime = Pow(Radical(Y, 7), 4) assert expr == expr_prime event = EventInterval(expr, Interval.open(-oo, 9)) assert (expr < 9) == event
def test_Interval_invert(): assert ~(Interval(0, 1)) == Union(Interval.Ropen(-inf, 0), Interval.Lopen(1, inf)) assert ~(Interval.open(0, 1)) == Union(Interval(-inf, 0), Interval(1, inf)) assert ~(Interval.Lopen(0, 1)) == Union(Interval(-inf, 0), Interval.Lopen(1, inf)) assert ~(Interval.Ropen(0, 1)) == Union(Interval.Ropen(-inf, 0), Interval(1, inf)) assert ~(Interval(-inf, inf)) is EmptySet assert ~(Interval(3, inf)) == Interval.Ropen(-inf, 3) assert ~(Interval.open(3, inf)) == Interval(-inf, 3) assert ~(Interval.Lopen(3, inf)) == Interval(-inf, 3) assert ~(Interval.Ropen(3, inf)) == Interval.Ropen(-inf, 3) assert ~(Interval(-inf, 3)) == Interval.Lopen(3, inf) assert ~(Interval.open(-inf, 3)) == Interval(3, inf) assert ~(Interval.Lopen(-inf, 3)) == Interval.Lopen(3, inf) assert ~(Interval.Ropen(-inf, 3)) == Interval(3, inf) assert ~(Interval.open(-inf, inf)) is EmptySet
def test_Union_and(): x = (Interval(0, 1) | FR(1)) & (FN('a')) assert x is EmptySet x = (FN('x', b=True) | Interval(0, 1) | FR(1)) & (FN('a')) assert x == FN('a') x = (FN('x') | Interval(0, 1) | FR(1)) & (FN('a')) assert x is EmptySet x = (FN('x') | Interval.open(0, 1) | FR(7)) & ( (FN('x')) | FR(.5) | Interval(.75, 1.2)) assert x == Union(FR(.5), FN('x'), Interval.Ropen(.75, 1)) x = (FN('x') | Interval.open(0, 1) | FR(7)) & (FR(3)) assert x is EmptySet x = (Interval.Lopen(-5, inf)) & (Interval(0, inf) | FR(inf)) assert x == Interval(0, inf) x = (FR(1, 2) | Interval.Ropen(-inf, 0)) & Interval(0, inf) assert x == FR(1, 2) x = (FR(1, 12) | Interval(0, 5) | Interval(7, 10)) & Interval(4, 12) assert x == Union(Interval(4, 5), Interval(7, 10), FR(12))
def test_parse_27_piecewise_many(): assert (Y < 0)*(Y**2) + (0 <= Y)*Y**((1, 2)) == Piecewise( [ Poly(Y, [0, 0, 1]), Radical(Y, 2)], [ EventInterval(Y, Interval.open(-oo, 0)), EventInterval(Y, Interval(0, oo)) ])
def test_solver_23_reciprocal_range(): solution = Interval.Ropen(-1, -Rat(1, 3)) event = ((-3 < 1/Y) <= -1) assert event.solve() == solution solution = Interval.open(0, Rat(1, 3)) event = ((-3 < 1/(2*Y-1)) < -1) assert event.solve() == solution solution = Interval.open(-1 / sympy.sqrt(3), 1 / sympy.sqrt(3)) event = ((-3 < 1/(2*(abs(Y)**2)-1)) <= -1) assert event.solve() == solution solution = Union( Interval.open(-1 / sympy.sqrt(3), 0), Interval.open(0, 1 / sympy.sqrt(3))) event = ((-3 < 1/(2*(abs(Y)**2)-1)) < -1) assert event.solve() == solution
def test_solver_23_reciprocal_gte(): for c in [1, 3]: # Positive # 10 < 1 / X solution = Interval.open(0, Rat(c, 10)) event = 10 < (c / Y) assert event.solve() == solution # 10 <= 1 / X solution = Interval.Lopen(0, Rat(c, 10)) event = 10 <= (c / Y) assert event.solve() == solution # Negative # -10 < 1 / X solution = Interval.Lopen(0, oo) | Interval.open(-oo, -Rat(c, 10)) event = -10 < (c / Y) assert event.solve() == solution # -10 <= 1 / X solution = Interval.Lopen(0, oo) | Interval.Lopen(-oo, -Rat(c, 10)) event = -10 <= (c / Y) assert event.solve() == solution
def test_solver_finite_non_injective(): sqrt2 = sympy.sqrt(2) # Abs. solution = FiniteReal(-10, -3, 3, 10) event = abs(Y) << {10, 3} assert event.solve() == solution # Abs(Poly). solution = FiniteReal(-5, -Rat(3,2), Rat(3,2), 5) event = abs(2*Y) << {10, 3} assert event.solve() == solution # Poly order 2. solution = FiniteReal(-sqrt2, sqrt2) event = (Y**2) << {2} assert event.solve() == solution # Poly order 3. solution = FiniteReal(1, 3) event = Y**3 << {1, 27} assert event.solve() == solution # Poly Abs. solution = FiniteReal(-3, -1, 1, 3) event = (abs(Y))**3 << {1, 27} assert event.solve() == solution # Abs Not. solution = Union( Interval.open(-oo, -1), Interval.open(-1, 1), Interval.open(1, oo)) event = ~(abs(Y) << {1}) assert event.solve() == solution # Abs in EmptySet. solution = EmptySet event = (abs(Y))**3 << set() assert event.solve() == solution # Abs Not in EmptySet (yields all reals). solution = Interval(-oo, oo) event = ~(((abs(Y))**3) << set()) assert event.solve() == solution # Log in Reals (yields positive reals). solution = Interval.open(0, oo) event = ~((Log(Y))**3 << set()) assert event.solve() == solution
def test_parse_9_open(): # 2(log(x))**3 - log(x) -5 > 0 expr = 2*(Log(X))**3 - Log(X) - 5 expr_prime = Poly(Log(Y), [-5, -1, 0, 2]) assert expr == expr_prime event = EventInterval(expr, Interval.open(0, oo)) assert (expr > 0) == event # Cannot add polynomials with different subexpressions. with pytest.raises(ValueError): (2*Log(X))**3 - Log(X) - 5
def test_parse_19(): # 3*(x**(1/7))**4 - 3*(x**(1/7))**2 <= 9 # or || 3*(x**(1/7))**4 - 3*(x**(1/7))**2 > 11 Z = X**Rat(1, 7) expr = 3*Z**4 - 3*Z**2 event = (expr <= 9) | (expr > 11) event_prime = EventOr([ EventInterval(expr, Interval(-oo, 9)), EventInterval(expr, Interval.open(11, oo)), ]) assert event == event_prime event = ((expr <= 9) | (expr > 11)) & (~(expr < 10)) event_prime = EventAnd([ EventOr([ EventInterval(expr, Interval(-oo, 9)), EventInterval(expr, Interval.open(11, oo))]), EventInterval(expr, Interval(10, oo)) ]) assert event == event_prime
def test_FiniteReal_or(): assert FR(1) | FR(2) == FR(1, 2) assert FR(1, 2) | FR(2) == FR(1, 2) assert FR(1, 2) | FN('2') == Union(FR(1, 2), FN('2')) assert FR(1, 2) | Interval(0, 1) == Union(Interval(0, 1), FR(2)) assert FR(1, 2) | Interval.Ropen(0, 1) == Union(Interval(0, 1), FR(2)) assert FR(0, 1, 2) | Interval.open(0, 1) == Union(Interval(0, 1), FR(2)) assert FR(0, 2) | Interval.Lopen(0, 1) == Union(Interval(0, 1), FR(2)) assert FR(0, 2) | Interval.Lopen(2.5, 10) == Union(Interval.Lopen(2.5, 10), FR(0, 2)) assert FR(-1, 1) | Interval(-10, 10) == Interval(-10, 10) assert FR(-1, 11) | Interval(-10, 10) == Union(Interval(-10, 10), FR(11))
def test_solver_18(): # 3*(x**(1/7))**4 - 3*(x**(1/7))**2 <= 9 solution = Interval(0, (Rat(1, 2) + sympy.sqrt(13)/2)**(Rat(7, 2))) Z = Y**(Rat(1, 7)) expr = 3*Z**4 - 3*Z**2 event = (expr <= 9) answer = event.solve() assert answer == solution interval = (~event).solve() assert interval == Interval.open(solution.right, oo)
def test_event_inequality_parse(): assert (5 < (X < 10)) \ == ((5 < X) < 10) \ == EventInterval(X, Interval.open(5, 10)) assert (5 <= (X < 10)) \ == ((5 <= X) < 10) \ == EventInterval(X, Interval.Ropen(5, 10)) assert (5 < (X <= 10)) \ == ((5 < X) <= 10) \ == EventInterval(X, Interval.Lopen(5, 10)) assert (5 <= (X <= 10)) \ == ((5 <= X) <= 10) \ == EventInterval(X, Interval(5, 10)) # GOTCHA: This expression is syntactically equivalent to # (5 < X) and (X < 10) # Since and short circuits and 5 < X is not False, # return value of expression is X < 10 assert (5 < X < 10) == (X < 10) # Yields a finite set . assert ((5 < X) < 5) == EventFiniteReal(X, EmptySet) assert ((5 < X) <= 5) == EventFiniteReal(X, EmptySet) assert ((5 <= X) < 5) == EventFiniteReal(X, EmptySet) assert ((5 <= X) <= 5) == EventFiniteReal(X, FiniteReal(5)) # Negated single interval. assert ~(5 < X) == (X <= 5) assert ~(5 <= X) == (X < 5) assert ~(X < 5) == (5 <= X) assert ~(X <= 5) == (5 < X) # Negated union of two intervals. assert ~(5 < (X < 10)) \ == ~((5 < X) < 10) \ == (X <= 5) | (10 <= X) assert ~(5 <= (X < 10)) \ == ~((5 <= X) < 10) \ == (X < 5) | (10 <= X) assert ~(5 < (X <= 10)) \ == ~((5 < X) <= 10) \ == (X <= 5) | (10 < X) assert ~(5 <= (X <= 10)) \ == ~((5 <= X) <= 10) \ == (X < 5) | (10 < X) assert ~((10 < X) < 5) \ == ~(10 < (X < 5)) \ == EventInterval(X, Interval(-oo, oo)) # A complicated negated union. assert ((~(X < 5)) < 10) \ == ((5 <= X) < 10) \ == EventInterval(X, Interval.Ropen(5, 10))
def test_union_intervals_finite(): assert union_intervals_finite([ Interval.open(0,1), Interval(2,3), Interval.Lopen(1,2) ], FR(1)) \ == [Interval.Lopen(0, 3)] assert union_intervals_finite([ Interval.open(0,1), Interval.open(2, 3), Interval.open(1,2) ], FR(1, 3)) \ == [Interval.open(0, 2), Interval.Lopen(2, 3)] assert union_intervals_finite([ Interval.open(0,1), Interval.open(1, 3), Interval.open(11,15) ], FR(1, -11, -19, 3)) \ == [Interval.Lopen(0, 3), Interval.open(11,15), FR(-11, -19)]
def test_parse_18(): # 3*(x**(1/7))**4 - 3*(x**(1/7))**2 <= 9 Z = X**Rat(1, 7) expr = 3*Z**4 - 3*Z**2 expr_prime = Poly(Radical(Y, 7), [0, 0, -3, 0, 3]) assert expr == expr_prime event = EventInterval(expr_prime, Interval(-oo, 9)) assert (expr <= 9) == event event_not = EventInterval(expr_prime, Interval.open(9, oo)) assert ~(expr <= 9) == event_not expr = (3*Abs(Z))**4 - (3*Abs(Z))**2 expr_prime = Poly(Poly(Abs(Z), [0, 3]), [0, 0, -1, 0, 3])
def test_solver_9_open(): # 2(log(x))**3 - log(x) -5 > 0 solution = Interval.open( sympy.exp(1/(6*(sympy.sqrt(2019)/36 + Rat(5,4))**(Rat(1, 3))) + (sympy.sqrt(2019)/36 + Rat(5,4))**(Rat(1,3))), oo) # Our solver handles this case as follows # expr' = 2*Z**3 - Z - 5 > 0 [[subst. Z=log(X)]] # [Z_low, Z_high] = sympy_solver(expr') # Z_low < Z iff Z_low < log(X) iff exp(Z_low) < X # Z < Z_high iff log(X) < Z_high iff X < exp(Z_high) # sympy_solver(expr) = [exp(Z_low), exp(Z_high)] # For F invertible, can thus solve Poly(coeffs, F) > 0 using this method. event = 2*(Log(Y))**3 - Log(Y) - 5 > 0 answer = event.solve() assert answer == solution