def write_tdb(dbf, fd, groupby='subsystem', if_incompatible='warn'): """ Write a TDB file from a pycalphad Database object. The goal is to produce TDBs that conform to the most restrictive subset of database specifications. Some of these can be adjusted for automatically, such as the Thermo-Calc line length limit of 78. Others require changing the database in non-trivial ways, such as the maximum length of function names (8). The default is to warn the user when attempting to write an incompatible database and the user must choose whether to warn and write the file anyway or to fix the incompatibility. Currently the supported compatibility fixes are: - Line length <= 78 characters (Thermo-Calc) - Function names <= 8 characters (Thermo-Calc) The current unsupported fixes include: - Keyword length <= 2000 characters (Thermo-Calc) - Element names <= 2 characters (Thermo-Calc) - Phase names <= 24 characters (Thermo-Calc) Other TDB compatibility issues required by Thermo-Calc or other software should be reported to the issue tracker. Parameters ---------- dbf : Database A pycalphad Database. fd : file-like File descriptor. groupby : ['subsystem', 'phase'], optional Desired grouping of parameters in the file. if_incompatible : string, optional ['raise', 'warn', 'fix'] Strategy if the database does not conform to the most restrictive database specification. The 'warn' option (default) will write out the incompatible database with a warning. The 'raise' option will raise a DatabaseExportError. The 'ignore' option will write out the incompatible database silently. The 'fix' option will rectify the incompatibilities e.g. through name mangling. """ # Before writing anything, check that the TDB is valid and take the appropriate action if not if if_incompatible not in ['warn', 'raise', 'ignore', 'fix']: raise ValueError( 'Incorrect options passed to \'if_invalid\'. Valid args are \'raise\', \'warn\', or \'fix\'.' ) # Handle function names > 8 characters long_function_names = {k for k in dbf.symbols.keys() if len(k) > 8} if len(long_function_names) > 0: if if_incompatible == 'raise': raise DatabaseExportError( 'The following function names are beyond the 8 character TDB limit: {}. Use the keyword argument \'if_incompatible\' to control this behavior.' .format(long_function_names)) elif if_incompatible == 'fix': # if we are going to make changes, make the changes to a copy and leave the original object untouched dbf = deepcopy( dbf) # TODO: if we do multiple fixes, we should only copy once symbol_name_map = {} for name in long_function_names: hashed_name = 'F' + str( hashlib.md5(name.encode('UTF-8')).hexdigest()).upper( )[:7] # this is implictly upper(), but it is explicit here symbol_name_map[name] = hashed_name _apply_new_symbol_names(dbf, symbol_name_map) elif if_incompatible == 'warn': warnings.warn( 'Ignoring that the following function names are beyond the 8 character TDB limit: {}. Use the keyword argument \'if_incompatible\' to control this behavior.' .format(long_function_names)) # Begin constructing the written database writetime = datetime.datetime.now() maxlen = 78 output = "" # Comment header block # Import here to prevent circular imports from pycalphad import __version__ output += ("$" * maxlen) + "\n" output += "$ Date: {}\n".format(writetime.strftime("%Y-%m-%d %H:%M")) output += "$ Components: {}\n".format(', '.join(sorted(dbf.elements))) output += "$ Phases: {}\n".format(', '.join(sorted(dbf.phases.keys()))) output += "$ Generated by {} (pycalphad {})\n".format( getpass.getuser(), __version__) output += ("$" * maxlen) + "\n\n" for element in sorted(dbf.elements): output += "ELEMENT {0} BLANK 0 0 0 !\n".format(element.upper()) if len(dbf.elements) > 0: output += "\n" for species in sorted(dbf.species): output += "SPECIES {0} !\n".format(species.upper()) if len(dbf.species) > 0: output += "\n" # Write FUNCTION block for name, expr in sorted(dbf.symbols.items()): if not isinstance(expr, Piecewise): # Non-piecewise exprs need to be wrapped to print # Otherwise TC's TDB parser will complain expr = Piecewise((expr, And(v.T >= 1, v.T < 10000))) expr = TCPrinter().doprint(expr).upper() if ';' not in expr: expr += '; N' output += "FUNCTION {0} {1} !\n".format(name.upper(), expr) output += "\n" # Boilerplate code output += "TYPE_DEFINITION % SEQ * !\n" output += "DEFINE_SYSTEM_DEFAULT ELEMENT 2 !\n" default_elements = [ i.upper() for i in sorted(dbf.elements) if i.upper() == 'VA' or i.upper() == '/-' ] if len(default_elements) > 0: output += 'DEFAULT_COMMAND DEFINE_SYSTEM_ELEMENT {} !\n'.format( ' '.join(default_elements)) output += "\n" typedef_chars = list("^&*()'ABCDEFGHIJKLMNOPQSRTUVWXYZ")[::-1] # Write necessary TYPE_DEF based on model hints typedefs = defaultdict(lambda: ["%"]) for name, phase_obj in sorted(dbf.phases.items()): model_hints = phase_obj.model_hints.copy() if ('ordered_phase' in model_hints.keys()) and (model_hints['ordered_phase'] == name): new_char = typedef_chars.pop() typedefs[name].append(new_char) typedefs[model_hints['disordered_phase']].append(new_char) output += 'TYPE_DEFINITION {} GES AMEND_PHASE_DESCRIPTION {} DISORDERED_PART {} !\n'\ .format(new_char, model_hints['ordered_phase'].upper(), model_hints['disordered_phase'].upper()) del model_hints['ordered_phase'] del model_hints['disordered_phase'] if ('disordered_phase' in model_hints.keys()) and (model_hints['disordered_phase'] == name): # We handle adding the correct typedef when we write the ordered phase del model_hints['ordered_phase'] del model_hints['disordered_phase'] if 'ihj_magnetic_afm_factor' in model_hints.keys(): new_char = typedef_chars.pop() typedefs[name].append(new_char) output += 'TYPE_DEFINITION {} GES AMEND_PHASE_DESCRIPTION {} MAGNETIC {} {} !\n'\ .format(new_char, name.upper(), model_hints['ihj_magnetic_afm_factor'], model_hints['ihj_magnetic_structure_factor']) del model_hints['ihj_magnetic_afm_factor'] del model_hints['ihj_magnetic_structure_factor'] if len(model_hints) > 0: # Some model hints were not properly consumed raise ValueError( 'Not all model hints are supported: {}'.format(model_hints)) # Perform a second loop now that all typedefs / model hints are consistent for name, phase_obj in sorted(dbf.phases.items()): output += "PHASE {0} {1} {2} {3} !\n".format( name.upper(), ''.join(typedefs[name]), len(phase_obj.sublattices), ' '.join([str(i) for i in phase_obj.sublattices])) constituents = ':'.join( [','.join(sorted(subl)) for subl in phase_obj.constituents]) output += "CONSTITUENT {0} :{1}: !\n".format(name.upper(), constituents) output += "\n" # PARAMETERs by subsystem param_sorted = defaultdict(lambda: list()) paramtuple = namedtuple('ParamTuple', [ 'phase_name', 'parameter_type', 'complexity', 'constituent_array', 'parameter_order', 'diffusing_species', 'parameter', 'reference' ]) for param in dbf._parameters.all(): if groupby == 'subsystem': components = set() for subl in param['constituent_array']: components |= set(subl) if param['diffusing_species'] is not None: components |= {param['diffusing_species']} # Wildcard operator is not a component components -= {'*'} # Remove vacancy if it's not the only component (pure vacancy endmember) if len(components) > 1: components -= {'VA'} components = tuple(sorted([c.upper() for c in components])) grouping = components elif groupby == 'phase': grouping = param['phase_name'].upper() else: raise ValueError( 'Unknown groupby attribute \'{}\''.format(groupby)) # We use the complexity parameter to help with sorting the parameters logically param_sorted[grouping].append( paramtuple(param['phase_name'], param['parameter_type'], sum([len(i) for i in param['constituent_array']]), param['constituent_array'], param['parameter_order'], param['diffusing_species'], param['parameter'], param['reference'])) def write_parameter(param_to_write): constituents = ':'.join([ ','.join(sorted([i.upper() for i in subl])) for subl in param_to_write.constituent_array ]) # TODO: Handle references paramx = param_to_write.parameter if not isinstance(paramx, Piecewise): # Non-piecewise parameters need to be wrapped to print correctly # Otherwise TC's TDB parser will fail paramx = Piecewise((paramx, And(v.T >= 1, v.T < 10000))) exprx = TCPrinter().doprint(paramx).upper() if ';' not in exprx: exprx += '; N' if param_to_write.diffusing_species is not None: ds = "&" + param_to_write.diffusing_species else: ds = "" return "PARAMETER {}({}{},{};{}) {} !\n".format( param_to_write.parameter_type.upper(), param_to_write.phase_name.upper(), ds, constituents, param_to_write.parameter_order, exprx) if groupby == 'subsystem': for num_elements in range(1, 5): subsystems = list( itertools.combinations( sorted([i.upper() for i in dbf.elements]), num_elements)) for subsystem in subsystems: parameters = sorted(param_sorted[subsystem]) if len(parameters) > 0: output += "\n\n" output += "$" * maxlen + "\n" output += "$ {}".format('-'.join(sorted(subsystem)).center( maxlen, " ")[2:-1]) + "$\n" output += "$" * maxlen + "\n" output += "\n" for parameter in parameters: output += write_parameter(parameter) # Don't generate combinatorics for multi-component subsystems or we'll run out of memory if len(dbf.elements) > 4: subsystems = [k for k in param_sorted.keys() if len(k) > 4] for subsystem in subsystems: parameters = sorted(param_sorted[subsystem]) for parameter in parameters: output += write_parameter(parameter) elif groupby == 'phase': for phase_name in sorted(dbf.phases.keys()): parameters = sorted(param_sorted[phase_name]) if len(parameters) > 0: output += "\n\n" output += "$" * maxlen + "\n" output += "$ {}".format(phase_name.upper().center( maxlen, " ")[2:-1]) + "$\n" output += "$" * maxlen + "\n" output += "\n" for parameter in parameters: output += write_parameter(parameter) else: raise ValueError('Unknown groupby attribute {}'.format(groupby)) # Reflow text to respect character limit per line fd.write(reflow_text(output, linewidth=maxlen))
def test_piecewise_solve(): abs2 = Piecewise((-x, x <= 0), (x, x > 0)) f = abs2.subs(x, x - 2) assert solve(f, x) == [2] assert solve(f - 1, x) == [1, 3] f = Piecewise(((x - 2)**2, x >= 0), (1, True)) assert solve(f, x) == [2] g = Piecewise(((x - 5)**5, x >= 4), (f, True)) assert solve(g, x) == [2, 5] g = Piecewise(((x - 5)**5, x >= 4), (f, x < 4)) assert solve(g, x) == [2, 5] g = Piecewise(((x - 5)**5, x >= 2), (f, x < 2)) assert solve(g, x) == [5] g = Piecewise(((x - 5)**5, x >= 2), (f, True)) assert solve(g, x) == [5] g = Piecewise(((x - 5)**5, x >= 2), (f, True), (10, False)) assert solve(g, x) == [5] g = Piecewise(((x - 5)**5, x >= 2), (-x + 2, x - 2 <= 0), (x - 2, x - 2 > 0)) assert solve(g, x) == [5] # if no symbol is given the piecewise detection must still work assert solve(Piecewise((x - 2, x > 2), (2 - x, True)) - 3) == [-1, 5] f = Piecewise(((x - 2)**2, x >= 0), (0, True)) raises(NotImplementedError, lambda: solve(f, x)) def nona(ans): return list(filter(lambda x: x is not S.NaN, ans)) p = Piecewise((x**2 - 4, x < y), (x - 2, True)) ans = solve(p, x) assert nona([i.subs(y, -2) for i in ans]) == [2] assert nona([i.subs(y, 2) for i in ans]) == [-2, 2] assert nona([i.subs(y, 3) for i in ans]) == [-2, 2] assert ans == [ Piecewise((-2, y > -2), (S.NaN, True)), Piecewise((2, y <= 2), (S.NaN, True)), Piecewise((2, y > 2), (S.NaN, True))] # issue 6060 absxm3 = Piecewise( (x - 3, S(0) <= x - 3), (3 - x, S(0) > x - 3) ) assert solve(absxm3 - y, x) == [ Piecewise((-y + 3, -y < 0), (S.NaN, True)), Piecewise((y + 3, y >= 0), (S.NaN, True))] p = Symbol('p', positive=True) assert solve(absxm3 - p, x) == [-p + 3, p + 3] # issue 6989 f = Function('f') assert solve(Eq(-f(x), Piecewise((1, x > 0), (0, True))), f(x)) == \ [Piecewise((-1, x > 0), (0, True))] # issue 8587 f = Piecewise((2*x**2, And(S(0) < x, x < 1)), (2, True)) assert solve(f - 1) == [1/sqrt(2)]
def test_issue_10122(): assert solve(abs(x) + abs(x - 1) - 1 > 0, x ) == Or(And(-oo < x, x < 0), And(S.One < x, x < oo))
def test_Intersection_as_relational(): x = Symbol('x') assert (Intersection(Interval(0, 1), FiniteSet(2), evaluate=False).as_relational(x) == And( And(Le(0, x), Le(x, 1)), Eq(x, 2)))
def test_piecewise1(): # Test canonicalization assert Piecewise((x, x < 1), (0, True)) == Piecewise((x, x < 1), (0, True)) assert Piecewise((x, x < 1), (0, True), (1, True)) == \ Piecewise((x, x < 1), (0, True)) assert Piecewise((x, x < 1), (0, False), (-1, 1 > 2)) == \ Piecewise((x, x < 1)) assert Piecewise((x, x < 1), (0, x < 1), (0, True)) == \ Piecewise((x, x < 1), (0, True)) assert Piecewise((x, x < 1), (0, x < 2), (0, True)) == \ Piecewise((x, x < 1), (0, True)) assert Piecewise((x, x < 1), (x, x < 2), (0, True)) == \ Piecewise((x, Or(x < 1, x < 2)), (0, True)) assert Piecewise((x, x < 1), (x, x < 2), (x, True)) == x assert Piecewise((x, True)) == x # Explicitly constructed empty Piecewise not accepted raises(TypeError, lambda: Piecewise()) # False condition is never retained assert Piecewise((2*x, x < 0), (x, False)) == \ Piecewise((2*x, x < 0), (x, False), evaluate=False) == \ Piecewise((2*x, x < 0)) assert Piecewise((x, False)) == Undefined raises(TypeError, lambda: Piecewise(x)) assert Piecewise((x, 1)) == x # 1 and 0 are accepted as True/False raises(TypeError, lambda: Piecewise((x, 2))) raises(TypeError, lambda: Piecewise((x, x**2))) raises(TypeError, lambda: Piecewise(([1], True))) assert Piecewise(((1, 2), True)) == Tuple(1, 2) cond = (Piecewise((1, x < 0), (2, True)) < y) assert Piecewise((1, cond) ) == Piecewise((1, ITE(x < 0, y > 1, y > 2))) assert Piecewise((1, x > 0), (2, And(x <= 0, x > -1)) ) == Piecewise((1, x > 0), (2, x > -1)) # Test subs p = Piecewise((-1, x < -1), (x**2, x < 0), (log(x), x >= 0)) p_x2 = Piecewise((-1, x**2 < -1), (x**4, x**2 < 0), (log(x**2), x**2 >= 0)) assert p.subs(x, x**2) == p_x2 assert p.subs(x, -5) == -1 assert p.subs(x, -1) == 1 assert p.subs(x, 1) == log(1) # More subs tests p2 = Piecewise((1, x < pi), (-1, x < 2*pi), (0, x > 2*pi)) p3 = Piecewise((1, Eq(x, 0)), (1/x, True)) p4 = Piecewise((1, Eq(x, 0)), (2, 1/x>2)) assert p2.subs(x, 2) == 1 assert p2.subs(x, 4) == -1 assert p2.subs(x, 10) == 0 assert p3.subs(x, 0.0) == 1 assert p4.subs(x, 0.0) == 1 f, g, h = symbols('f,g,h', cls=Function) pf = Piecewise((f(x), x < -1), (f(x) + h(x) + 2, x <= 1)) pg = Piecewise((g(x), x < -1), (g(x) + h(x) + 2, x <= 1)) assert pg.subs(g, f) == pf assert Piecewise((1, Eq(x, 0)), (0, True)).subs(x, 0) == 1 assert Piecewise((1, Eq(x, 0)), (0, True)).subs(x, 1) == 0 assert Piecewise((1, Eq(x, y)), (0, True)).subs(x, y) == 1 assert Piecewise((1, Eq(x, z)), (0, True)).subs(x, z) == 1 assert Piecewise((1, Eq(exp(x), cos(z))), (0, True)).subs(x, z) == \ Piecewise((1, Eq(exp(z), cos(z))), (0, True)) p5 = Piecewise( (0, Eq(cos(x) + y, 0)), (1, True)) assert p5.subs(y, 0) == Piecewise( (0, Eq(cos(x), 0)), (1, True)) assert Piecewise((-1, y < 1), (0, x < 0), (1, Eq(x, 0)), (2, True) ).subs(x, 1) == Piecewise((-1, y < 1), (2, True)) assert Piecewise((1, Eq(x**2, -1)), (2, x < 0)).subs(x, I) == 1 p6 = Piecewise((x, x > 0)) n = symbols('n', negative=True) assert p6.subs(x, n) == Undefined # Test evalf assert p.evalf() == p assert p.evalf(subs={x: -2}) == -1 assert p.evalf(subs={x: -1}) == 1 assert p.evalf(subs={x: 1}) == log(1) assert p6.evalf(subs={x: -5}) == Undefined # Test doit f_int = Piecewise((Integral(x, (x, 0, 1)), x < 1)) assert f_int.doit() == Piecewise( (S(1)/2, x < 1) ) # Test differentiation f = x fp = x*p dp = Piecewise((0, x < -1), (2*x, x < 0), (1/x, x >= 0)) fp_dx = x*dp + p assert diff(p, x) == dp assert diff(f*p, x) == fp_dx # Test simple arithmetic assert x*p == fp assert x*p + p == p + x*p assert p + f == f + p assert p + dp == dp + p assert p - dp == -(dp - p) # Test power dp2 = Piecewise((0, x < -1), (4*x**2, x < 0), (1/x**2, x >= 0)) assert dp**2 == dp2 # Test _eval_interval f1 = x*y + 2 f2 = x*y**2 + 3 peval = Piecewise((f1, x < 0), (f2, x > 0)) peval_interval = f1.subs( x, 0) - f1.subs(x, -1) + f2.subs(x, 1) - f2.subs(x, 0) assert peval._eval_interval(x, 0, 0) == 0 assert peval._eval_interval(x, -1, 1) == peval_interval peval2 = Piecewise((f1, x < 0), (f2, True)) assert peval2._eval_interval(x, 0, 0) == 0 assert peval2._eval_interval(x, 1, -1) == -peval_interval assert peval2._eval_interval(x, -1, -2) == f1.subs(x, -2) - f1.subs(x, -1) assert peval2._eval_interval(x, -1, 1) == peval_interval assert peval2._eval_interval(x, None, 0) == peval2.subs(x, 0) assert peval2._eval_interval(x, -1, None) == -peval2.subs(x, -1) # Test integration assert p.integrate() == Piecewise( (-x, x < -1), (x**3/3 + S(4)/3, x < 0), (x*log(x) - x + S(4)/3, True)) p = Piecewise((x, x < 1), (x**2, -1 <= x), (x, 3 < x)) assert integrate(p, (x, -2, 2)) == S(5)/6 assert integrate(p, (x, 2, -2)) == -S(5)/6 p = Piecewise((0, x < 0), (1, x < 1), (0, x < 2), (1, x < 3), (0, True)) assert integrate(p, (x, -oo, oo)) == 2 p = Piecewise((x, x < -10), (x**2, x <= -1), (x, 1 < x)) assert integrate(p, (x, -2, 2)) == Undefined # Test commutativity assert isinstance(p, Piecewise) and p.is_commutative is True
def as_boolean(self): return And(self.fulldomain.as_boolean(), self.condition)
def test_issue_10248(): assert list(Intersection(S.Reals, FiniteSet(x))) == [And(x < oo, x > -oo)]
def BayesTest(A, B): assert P(A, B) == P(And(A, B)) / P(B) assert P(A, B) == P(B, A) * P(A) / P(B)
def test_meijerint(): from sympy import symbols, expand, arg s, t, mu = symbols('s t mu', real=True) assert integrate(meijerg([], [], [0], [], s*t) *meijerg([], [], [mu/2], [-mu/2], t**2/4), (t, 0, oo)).is_Piecewise s = symbols('s', positive=True) assert integrate(x**s*meijerg([[], []], [[0], []], x), (x, 0, oo)) == \ gamma(s + 1) assert integrate(x**s*meijerg([[], []], [[0], []], x), (x, 0, oo), meijerg=True) == gamma(s + 1) assert isinstance(integrate(x**s*meijerg([[], []], [[0], []], x), (x, 0, oo), meijerg=False), Integral) assert meijerint_indefinite(exp(x), x) == exp(x) # TODO what simplifications should be done automatically? # This tests "extra case" for antecedents_1. a, b = symbols('a b', positive=True) assert simplify(meijerint_definite(x**a, x, 0, b)[0]) == \ b**(a + 1)/(a + 1) # This tests various conditions and expansions: meijerint_definite((x + 1)**3*exp(-x), x, 0, oo) == (16, True) # Again, how about simplifications? sigma, mu = symbols('sigma mu', positive=True) i, c = meijerint_definite(exp(-((x - mu)/(2*sigma))**2), x, 0, oo) assert simplify(i) == sqrt(pi)*sigma*(2 - erfc(mu/(2*sigma))) assert c == True i, _ = meijerint_definite(exp(-mu*x)*exp(sigma*x), x, 0, oo) # TODO it would be nice to test the condition assert simplify(i) == 1/(mu - sigma) # Test substitutions to change limits assert meijerint_definite(exp(x), x, -oo, 2) == (exp(2), True) # Note: causes a NaN in _check_antecedents assert expand(meijerint_definite(exp(x), x, 0, I)[0]) == exp(I) - 1 assert expand(meijerint_definite(exp(-x), x, 0, x)[0]) == \ 1 - exp(-exp(I*arg(x))*abs(x)) # Test -oo to oo assert meijerint_definite(exp(-x**2), x, -oo, oo) == (sqrt(pi), True) assert meijerint_definite(exp(-abs(x)), x, -oo, oo) == (2, True) assert meijerint_definite(exp(-(2*x - 3)**2), x, -oo, oo) == \ (sqrt(pi)/2, True) assert meijerint_definite(exp(-abs(2*x - 3)), x, -oo, oo) == (1, True) assert meijerint_definite(exp(-((x - mu)/sigma)**2/2)/sqrt(2*pi*sigma**2), x, -oo, oo) == (1, True) assert meijerint_definite(sinc(x)**2, x, -oo, oo) == (pi, True) # Test one of the extra conditions for 2 g-functinos assert meijerint_definite(exp(-x)*sin(x), x, 0, oo) == (S.Half, True) # Test a bug def res(n): return (1/(1 + x**2)).diff(x, n).subs(x, 1)*(-1)**n for n in range(6): assert integrate(exp(-x)*sin(x)*x**n, (x, 0, oo), meijerg=True) == \ res(n) # This used to test trigexpand... now it is done by linear substitution assert simplify(integrate(exp(-x)*sin(x + a), (x, 0, oo), meijerg=True) ) == sqrt(2)*sin(a + pi/4)/2 # Test the condition 14 from prudnikov. # (This is besselj*besselj in disguise, to stop the product from being # recognised in the tables.) a, b, s = symbols('a b s') from sympy import And, re assert meijerint_definite(meijerg([], [], [a/2], [-a/2], x/4) *meijerg([], [], [b/2], [-b/2], x/4)*x**(s - 1), x, 0, oo) == \ (4*2**(2*s - 2)*gamma(-2*s + 1)*gamma(a/2 + b/2 + s) /(gamma(-a/2 + b/2 - s + 1)*gamma(a/2 - b/2 - s + 1) *gamma(a/2 + b/2 - s + 1)), And(0 < -2*re(4*s) + 8, 0 < re(a/2 + b/2 + s), re(2*s) < 1)) # test a bug assert integrate(sin(x**a)*sin(x**b), (x, 0, oo), meijerg=True) == \ Integral(sin(x**a)*sin(x**b), (x, 0, oo)) # test better hyperexpand assert integrate(exp(-x**2)*log(x), (x, 0, oo), meijerg=True) == \ (sqrt(pi)*polygamma(0, S.Half)/4).expand() # Test hyperexpand bug. from sympy import lowergamma n = symbols('n', integer=True) assert simplify(integrate(exp(-x)*x**n, x, meijerg=True)) == \ lowergamma(n + 1, x) # Test a bug with argument 1/x alpha = symbols('alpha', positive=True) assert meijerint_definite((2 - x)**alpha*sin(alpha/x), x, 0, 2) == \ (sqrt(pi)*alpha*gamma(alpha + 1)*meijerg(((), (alpha/2 + S.Half, alpha/2 + 1)), ((0, 0, S.Half), (Rational(-1, 2),)), alpha**2/16)/4, True) # test a bug related to 3016 a, s = symbols('a s', positive=True) assert simplify(integrate(x**s*exp(-a*x**2), (x, -oo, oo))) == \ a**(-s/2 - S.Half)*((-1)**s + 1)*gamma(s/2 + S.Half)/2
def test_DiscreteMarkovChain(): # pass only the name X = DiscreteMarkovChain("X") assert X.state_space == S.Reals assert X.index_set == S.Naturals0 assert X.transition_probabilities == None t = symbols('t', positive=True, integer=True) assert isinstance(X[t], RandomIndexedSymbol) assert E(X[0]) == Expectation(X[0]) raises(TypeError, lambda: DiscreteMarkovChain(1)) raises(NotImplementedError, lambda: X(t)) # pass name and state_space Y = DiscreteMarkovChain("Y", [1, 2, 3]) assert Y.transition_probabilities == None assert Y.state_space == FiniteSet(1, 2, 3) assert P(Eq(Y[2], 1), Eq(Y[0], 2)) == Probability(Eq(Y[2], 1), Eq(Y[0], 2)) assert E(X[0]) == Expectation(X[0]) raises(TypeError, lambda: DiscreteMarkovChain("Y", dict((1, 1)))) # pass name, state_space and transition_probabilities T = Matrix([[0.5, 0.2, 0.3], [0.2, 0.5, 0.3], [0.2, 0.3, 0.5]]) TS = MatrixSymbol('T', 3, 3) Y = DiscreteMarkovChain("Y", [0, 1, 2], T) YS = DiscreteMarkovChain("Y", [0, 1, 2], TS) assert YS._transient2transient() == None assert YS._transient2absorbing() == None assert Y.joint_distribution(1, Y[2], 3) == JointDistribution(Y[1], Y[2], Y[3]) raises(ValueError, lambda: Y.joint_distribution(Y[1].symbol, Y[2].symbol)) assert P(Eq(Y[3], 2), Eq(Y[1], 1)).round(2) == Float(0.36, 2) assert str(P(Eq(YS[3], 2), Eq(YS[1], 1))) == \ "T[0, 2]*T[1, 0] + T[1, 1]*T[1, 2] + T[1, 2]*T[2, 2]" assert P(Eq(YS[1], 1), Eq(YS[2], 2)) == Probability(Eq(YS[1], 1)) assert P(Eq(YS[3], 3), Eq(YS[1], 1)) is S.Zero TO = Matrix([[0.25, 0.75, 0], [0, 0.25, 0.75], [0.75, 0, 0.25]]) assert P(Eq(Y[3], 2), Eq(Y[1], 1) & TransitionMatrixOf(Y, TO)).round(3) == Float( 0.375, 3) assert E(Y[3], evaluate=False) == Expectation(Y[3]) assert E(Y[3], Eq(Y[2], 1)).round(2) == Float(1.1, 3) TSO = MatrixSymbol('T', 4, 4) raises( ValueError, lambda: str(P(Eq(YS[3], 2), Eq(YS[1], 1) & TransitionMatrixOf(YS, TSO)))) raises(TypeError, lambda: DiscreteMarkovChain("Z", [0, 1, 2], symbols('M'))) raises( ValueError, lambda: DiscreteMarkovChain("Z", [0, 1, 2], MatrixSymbol('T', 3, 4))) raises(ValueError, lambda: E(Y[3], Eq(Y[2], 6))) raises(ValueError, lambda: E(Y[2], Eq(Y[3], 1))) # extended tests for probability queries TO1 = Matrix([[Rational(1, 4), Rational(3, 4), 0], [Rational(1, 3), Rational(1, 3), Rational(1, 3)], [0, Rational(1, 4), Rational(3, 4)]]) assert P( And(Eq(Y[2], 1), Eq(Y[1], 1), Eq(Y[0], 0)), Eq(Probability(Eq(Y[0], 0)), Rational(1, 4)) & TransitionMatrixOf(Y, TO1)) == Rational(1, 16) assert P(And(Eq(Y[2], 1), Eq(Y[1], 1), Eq(Y[0], 0)), TransitionMatrixOf(Y, TO1)) == \ Probability(Eq(Y[0], 0))/4 assert P( Lt(X[1], 2) & Gt(X[1], 0), Eq(X[0], 2) & StochasticStateSpaceOf(X, [0, 1, 2]) & TransitionMatrixOf(X, TO1)) == Rational(1, 4) assert P( Ne(X[1], 2) & Ne(X[1], 1), Eq(X[0], 2) & StochasticStateSpaceOf(X, [0, 1, 2]) & TransitionMatrixOf(X, TO1)) is S.Zero assert P(And(Eq(Y[2], 1), Eq(Y[1], 1), Eq(Y[0], 0)), Eq(Y[1], 1)) == 0.1 * Probability(Eq(Y[0], 0)) # testing properties of Markov chain TO2 = Matrix([[S.One, 0, 0], [Rational(1, 3), Rational(1, 3), Rational(1, 3)], [0, Rational(1, 4), Rational(3, 4)]]) TO3 = Matrix([[Rational(1, 4), Rational(3, 4), 0], [Rational(1, 3), Rational(1, 3), Rational(1, 3)], [0, Rational(1, 4), Rational(3, 4)]]) Y2 = DiscreteMarkovChain('Y', trans_probs=TO2) Y3 = DiscreteMarkovChain('Y', trans_probs=TO3) assert Y3._transient2absorbing() == None raises(ValueError, lambda: Y3.fundamental_matrix()) assert Y2.is_absorbing_chain() == True assert Y3.is_absorbing_chain() == False TO4 = Matrix([[Rational(1, 5), Rational(2, 5), Rational(2, 5)], [Rational(1, 10), S.Half, Rational(2, 5)], [Rational(3, 5), Rational(3, 10), Rational(1, 10)]]) Y4 = DiscreteMarkovChain('Y', trans_probs=TO4) w = ImmutableMatrix([[Rational(11, 39), Rational(16, 39), Rational(4, 13)]]) assert Y4.limiting_distribution == w assert Y4.is_regular() == True TS1 = MatrixSymbol('T', 3, 3) Y5 = DiscreteMarkovChain('Y', trans_probs=TS1) assert Y5.limiting_distribution(w, TO4).doit() == True TO6 = Matrix([[S.One, 0, 0, 0, 0], [S.Half, 0, S.Half, 0, 0], [0, S.Half, 0, S.Half, 0], [0, 0, S.Half, 0, S.Half], [0, 0, 0, 0, 1]]) Y6 = DiscreteMarkovChain('Y', trans_probs=TO6) assert Y6._transient2absorbing() == ImmutableMatrix([[S.Half, 0], [0, 0], [0, S.Half]]) assert Y6._transient2transient() == ImmutableMatrix([[0, S.Half, 0], [S.Half, 0, S.Half], [0, S.Half, 0]]) assert Y6.fundamental_matrix() == ImmutableMatrix( [[Rational(3, 2), S.One, S.Half], [S.One, S(2), S.One], [S.Half, S.One, Rational(3, 2)]]) assert Y6.absorbing_probabilites() == ImmutableMatrix( [[Rational(3, 4), Rational(1, 4)], [S.Half, S.Half], [Rational(1, 4), Rational(3, 4)]]) # testing miscellaneous queries T = Matrix([[S.Half, Rational(1, 4), Rational(1, 4)], [Rational(1, 3), 0, Rational(2, 3)], [S.Half, S.Half, 0]]) X = DiscreteMarkovChain('X', [0, 1, 2], T) assert P( Eq(X[1], 2) & Eq(X[2], 1) & Eq(X[3], 0), Eq(P(Eq(X[1], 0)), Rational(1, 4)) & Eq(P(Eq(X[1], 1)), Rational(1, 4))) == Rational(1, 12) assert P(Eq(X[2], 1) | Eq(X[2], 2), Eq(X[1], 1)) == Rational(2, 3) assert P(Eq(X[2], 1) & Eq(X[2], 2), Eq(X[1], 1)) is S.Zero assert P(Ne(X[2], 2), Eq(X[1], 1)) == Rational(1, 3) assert E(X[1]**2, Eq(X[0], 1)) == Rational(8, 3) assert variance(X[1], Eq(X[0], 1)) == Rational(8, 9) raises(ValueError, lambda: E(X[1], Eq(X[2], 1)))
def test_solve_univariate_inequality(): assert isolve(x**2 >= 4, x, relational=False) == Union(Interval(-oo, -2), Interval(2, oo)) assert isolve(x**2 >= 4, x) == Or(And(Le(2, x), Lt(x, oo)), And(Le(x, -2), Lt(-oo, x))) assert isolve((x - 1)*(x - 2)*(x - 3) >= 0, x, relational=False) == \ Union(Interval(1, 2), Interval(3, oo)) assert isolve((x - 1)*(x - 2)*(x - 3) >= 0, x) == \ Or(And(Le(1, x), Le(x, 2)), And(Le(3, x), Lt(x, oo))) assert isolve((x - 1)*(x - 2)*(x - 4) < 0, x, domain = FiniteSet(0, 3)) == \ Or(Eq(x, 0), Eq(x, 3)) # issue 2785: assert isolve(x**3 - 2*x - 1 > 0, x, relational=False) == \ Union(Interval(-1, -sqrt(5)/2 + S(1)/2, True, True), Interval(S(1)/2 + sqrt(5)/2, oo, True, True)) # issue 2794: assert isolve(x**3 - x**2 + x - 1 > 0, x, relational=False) == \ Interval(1, oo, True) #issue 13105 assert isolve((x + I) * (x + 2 * I) < 0, x) == Eq(x, 0) assert isolve(((x - 1) * (x - 2) + I) * ((x - 1) * (x - 2) + 2 * I) < 0, x) == Or(Eq(x, 1), Eq(x, 2)) assert isolve( (((x - 1) * (x - 2) + I) * ((x - 1) * (x - 2) + 2 * I)) / (x - 2) > 0, x) == Eq(x, 1) raises(ValueError, lambda: isolve((x**2 - 3 * x * I + 2) / x < 0, x)) # numerical testing in valid() is needed assert isolve(x**7 - x - 2 > 0, x) == \ And(rootof(x**7 - x - 2, 0) < x, x < oo) # handle numerator and denominator; although these would be handled as # rational inequalities, these test confirm that the right thing is done # when the domain is EX (e.g. when 2 is replaced with sqrt(2)) assert isolve(1 / (x - 2) > 0, x) == And(S(2) < x, x < oo) den = ((x - 1) * (x - 2)).expand() assert isolve((x - 1)/den <= 0, x) == \ Or(And(-oo < x, x < 1), And(S(1) < x, x < 2)) n = Dummy('n') raises(NotImplementedError, lambda: isolve(Abs(x) <= n, x, relational=False)) c1 = Dummy("c1", positive=True) raises(NotImplementedError, lambda: isolve(n / c1 < 0, c1)) n = Dummy('n', negative=True) assert isolve(n / c1 > -2, c1) == (-n / 2 < c1) assert isolve(n / c1 < 0, c1) == True assert isolve(n / c1 > 0, c1) == False zero = cos(1)**2 + sin(1)**2 - 1 raises(NotImplementedError, lambda: isolve(x**2 < zero, x)) raises(NotImplementedError, lambda: isolve(x**2 < zero * I, x)) raises(NotImplementedError, lambda: isolve(1 / (x - y) < 2, x)) raises(NotImplementedError, lambda: isolve(1 / (x - y) < 0, x)) raises(TypeError, lambda: isolve(x - I < 0, x)) zero = x**2 + x - x * (x + 1) assert isolve(zero < 0, x, relational=False) is S.EmptySet assert isolve(zero <= 0, x, relational=False) is S.Reals # make sure iter_solutions gets a default value raises(NotImplementedError, lambda: isolve(Eq(cos(x)**2 + sin(x)**2, 1), x))
def as_boolean(self): return Or( *[And(*[Eq(sym, val) for sym, val in item]) for item in self])
def test_manualintegrate_inversetrig(): # atan assert manualintegrate(exp(x) / (1 + exp(2 * x)), x) == atan(exp(x)) assert manualintegrate(1 / (4 + 9 * x**2), x) == atan(3 * x / 2) / 6 assert manualintegrate(1 / (16 + 16 * x**2), x) == atan(x) / 16 assert manualintegrate(1 / (4 + x**2), x) == atan(x / 2) / 2 assert manualintegrate(1 / (1 + 4 * x**2), x) == atan(2 * x) / 2 assert manualintegrate(1/(a + b*x**2), x) == \ Piecewise((atan(x/sqrt(a/b))/(b*sqrt(a/b)), a/b > 0), \ (-acoth(x/sqrt(-a/b))/(b*sqrt(-a/b)), And(a/b < 0, x**2 > -a/b)), \ (-atanh(x/sqrt(-a/b))/(b*sqrt(-a/b)), And(a/b < 0, x**2 < -a/b))) assert manualintegrate(1/(4 + b*x**2), x) == \ Piecewise((atan(x/(2*sqrt(1/b)))/(2*b*sqrt(1/b)), 4/b > 0), \ (-acoth(x/(2*sqrt(-1/b)))/(2*b*sqrt(-1/b)), And(4/b < 0, x**2 > -4/b)), \ (-atanh(x/(2*sqrt(-1/b)))/(2*b*sqrt(-1/b)), And(4/b < 0, x**2 < -4/b))) assert manualintegrate(1/(a + 4*x**2), x) == \ Piecewise((atan(2*x/sqrt(a))/(2*sqrt(a)), a/4 > 0), \ (-acoth(2*x/sqrt(-a))/(2*sqrt(-a)), And(a/4 < 0, x**2 > -a/4)), \ (-atanh(2*x/sqrt(-a))/(2*sqrt(-a)), And(a/4 < 0, x**2 < -a/4))) assert manualintegrate(1 / (4 + 4 * x**2), x) == atan(x) / 4 # asin assert manualintegrate(1 / sqrt(1 - x**2), x) == asin(x) assert manualintegrate(1 / sqrt(4 - 4 * x**2), x) == asin(x) / 2 assert manualintegrate(3 / sqrt(1 - 9 * x**2), x) == asin(3 * x) assert manualintegrate(1 / sqrt(4 - 9 * x**2), x) == asin(3 * x / 2) / 3 # asinh assert manualintegrate(1/sqrt(x**2 + 1), x) == \ asinh(x) assert manualintegrate(1/sqrt(x**2 + 4), x) == \ asinh(x/2) assert manualintegrate(1/sqrt(4*x**2 + 4), x) == \ asinh(x)/2 assert manualintegrate(1/sqrt(4*x**2 + 1), x) == \ asinh(2*x)/2 assert manualintegrate(1/sqrt(a*x**2 + 1), x) == \ Piecewise((sqrt(-1/a)*asin(x*sqrt(-a)), a < 0), (sqrt(1/a)*asinh(sqrt(a)*x), a > 0)) assert manualintegrate(1/sqrt(a + x**2), x) == \ Piecewise((asinh(x*sqrt(1/a)), a > 0), (acosh(x*sqrt(-1/a)), a < 0)) # acosh assert manualintegrate(1/sqrt(x**2 - 1), x) == \ acosh(x) assert manualintegrate(1/sqrt(x**2 - 4), x) == \ acosh(x/2) assert manualintegrate(1/sqrt(4*x**2 - 4), x) == \ acosh(x)/2 assert manualintegrate(1/sqrt(9*x**2 - 1), x) == \ acosh(3*x)/3 assert manualintegrate(1/sqrt(a*x**2 - 4), x) == \ Piecewise((sqrt(1/a)*acosh(sqrt(a)*x/2), a > 0)) assert manualintegrate(1/sqrt(-a + 4*x**2), x) == \ Piecewise((asinh(2*x*sqrt(-1/a))/2, -a > 0), (acosh(2*x*sqrt(1/a))/2, -a < 0)) # piecewise assert manualintegrate(1/sqrt(a-b*x**2), x) == \ Piecewise((sqrt(a/b)*asin(x*sqrt(b/a))/sqrt(a), And(-b < 0, a > 0)), (sqrt(-a/b)*asinh(x*sqrt(-b/a))/sqrt(a), And(-b > 0, a > 0)), (sqrt(a/b)*acosh(x*sqrt(b/a))/sqrt(-a), And(-b > 0, a < 0))) assert manualintegrate(1/sqrt(a + b*x**2), x) == \ Piecewise((sqrt(-a/b)*asin(x*sqrt(-b/a))/sqrt(a), And(a > 0, b < 0)), (sqrt(a/b)*asinh(x*sqrt(b/a))/sqrt(a), And(a > 0, b > 0)), (sqrt(-a/b)*acosh(x*sqrt(-b/a))/sqrt(-a), And(a < 0, b > 0)))
def define_ha(): '''make the hybrid automaton and return it''' # Variable ordering: [x, y, xvel, yvel] sym_x, sym_y, sym_xvel, sym_yvel = symbols('x y xvel yvel ') ha = HybridAutomaton() mode_0_0 = ha.new_mode('mode_0_0') mode_0_0.inv = lambda state: state[0] <= 1 and state[1] <= 1 mode_0_0.inv_sympy = And(sym_x <= 1, sym_y <= 1) mode_0_0.der = lambda _, state: [ state[2], state[3], -1.2 * (state[2] - 1) + 0.1 * (state[3] - 0.00000000000000006123233995736766), 0.1 * (state[2] - 1) + -1.2 * (state[3] - 0.00000000000000006123233995736766) ] mode_0_0.der_interval_list = [[0, 0], [0, 0], [-0.1, 0.1], [-0.1, 0.1]] mode_1_0 = ha.new_mode('mode_1_0') mode_1_0.inv = lambda state: state[0] >= 1 and state[0] <= 2 and state[ 1] <= 1 mode_1_0.inv_sympy = And(And(sym_x >= 1, sym_x <= 2), sym_y <= 1) mode_1_0.der = lambda _, state: [ state[2], state[3], -1.2 * (state[2] - 1) + 0.1 * (state[3] - 0.00000000000000006123233995736766), 0.1 * (state[2] - 1) + -1.2 * (state[3] - 0.00000000000000006123233995736766) ] mode_1_0.der_interval_list = [[0, 0], [0, 0], [-0.1, 0.1], [-0.1, 0.1]] mode_2_0 = ha.new_mode('mode_2_0') mode_2_0.inv = lambda state: state[0] >= 2 and state[1] <= 1 mode_2_0.inv_sympy = And(sym_x >= 2, sym_y <= 1) mode_2_0.der = lambda _, state: [0, 0, 0, 0] mode_2_0.der_interval_list = [[0, 0], [0, 0], [0, 0], [0, 0]] mode_0_1 = ha.new_mode('mode_0_1') mode_0_1.inv = lambda state: state[0] <= 1 and state[1] >= 1 and state[ 1] <= 2 mode_0_1.inv_sympy = And(And(sym_x <= 1, sym_y >= 1), sym_y <= 2) mode_0_1.der = lambda _, state: [ state[2], state[3], -1.2 * (state[2] - 0.00000000000000012246467991473532) + 0.1 * (state[3] - -1), 0.1 * (state[2] - 0.00000000000000012246467991473532) + -1.2 * (state[3] - -1) ] mode_0_1.der_interval_list = [[0, 0], [0, 0], [-0.1, 0.1], [-0.1, 0.1]] mode_1_1 = ha.new_mode('mode_1_1') mode_1_1.inv = lambda state: state[0] >= 1 and state[0] <= 2 and state[ 1] >= 1 and state[1] <= 2 mode_1_1.inv_sympy = And(And(And(sym_x >= 1, sym_x <= 2), sym_y >= 1), sym_y <= 2) mode_1_1.der = lambda _, state: [ state[2], state[3], -1.2 * (state[2] - 0.7071067811865476) + 0.1 * (state[3] - -0.7071067811865475), 0.1 * (state[2] - 0.7071067811865476) + -1.2 * (state[3] - -0.7071067811865475) ] mode_1_1.der_interval_list = [[0, 0], [0, 0], [-0.1, 0.1], [-0.1, 0.1]] mode_2_1 = ha.new_mode('mode_2_1') mode_2_1.inv = lambda state: state[0] >= 2 and state[1] >= 1 and state[ 1] <= 2 mode_2_1.inv_sympy = And(And(sym_x >= 2, sym_y >= 1), sym_y <= 2) mode_2_1.der = lambda _, state: [ state[2], state[3], -1.2 * (state[2] - 0.00000000000000012246467991473532) + 0.1 * (state[3] - -1), 0.1 * (state[2] - 0.00000000000000012246467991473532) + -1.2 * (state[3] - -1) ] mode_2_1.der_interval_list = [[0, 0], [0, 0], [-0.1, 0.1], [-0.1, 0.1]] mode_0_2 = ha.new_mode('mode_0_2') mode_0_2.inv = lambda state: state[0] <= 1 and state[1] >= 2 mode_0_2.inv_sympy = And(sym_x <= 1, sym_y >= 2) mode_0_2.der = lambda _, state: [0, 0, 0, 0] mode_0_2.der_interval_list = [[0, 0], [0, 0], [0, 0], [0, 0]] mode_1_2 = ha.new_mode('mode_1_2') mode_1_2.inv = lambda state: state[0] >= 1 and state[0] <= 2 and state[ 1] >= 2 mode_1_2.inv_sympy = And(And(sym_x >= 1, sym_x <= 2), sym_y >= 2) mode_1_2.der = lambda _, state: [ state[2], state[3], -1.2 * (state[2] - 1) + 0.1 * (state[3] - 0.00000000000000006123233995736766), 0.1 * (state[2] - 1) + -1.2 * (state[3] - 0.00000000000000006123233995736766) ] mode_1_2.der_interval_list = [[0, 0], [0, 0], [-0.1, 0.1], [-0.1, 0.1]] mode_2_2 = ha.new_mode('mode_2_2') mode_2_2.inv = lambda state: state[0] >= 2 and state[1] >= 2 mode_2_2.inv_sympy = And(sym_x >= 2, sym_y >= 2) mode_2_2.der = lambda _, state: [ state[2], state[3], -1.2 * (state[2] - 0.00000000000000012246467991473532) + 0.1 * (state[3] - -1), 0.1 * (state[2] - 0.00000000000000012246467991473532) + -1.2 * (state[3] - -1) ] mode_2_2.der_interval_list = [[0, 0], [0, 0], [-0.1, 0.1], [-0.1, 0.1]] t = ha.new_transition(mode_0_0, mode_1_0) t.guard = lambda state: state[0] >= 1 t.reset = lambda state: [None, None, None, None] t.guard_sympy = sym_x >= 1 t = ha.new_transition(mode_0_0, mode_0_1) t.guard = lambda state: state[1] >= 1 t.reset = lambda state: [None, None, None, None] t.guard_sympy = sym_y >= 1 t = ha.new_transition(mode_1_0, mode_0_0) t.guard = lambda state: state[0] <= 1 t.reset = lambda state: [None, None, None, None] t.guard_sympy = sym_x <= 1 t = ha.new_transition(mode_1_0, mode_2_0) t.guard = lambda state: state[0] >= 2 t.reset = lambda state: [None, None, None, None] t.guard_sympy = sym_x >= 2 t = ha.new_transition(mode_1_0, mode_1_1) t.guard = lambda state: state[1] >= 1 t.reset = lambda state: [None, None, None, None] t.guard_sympy = sym_y >= 1 t = ha.new_transition(mode_2_0, mode_1_0) t.guard = lambda state: state[0] <= 2 t.reset = lambda state: [None, None, None, None] t.guard_sympy = sym_x <= 2 t = ha.new_transition(mode_2_0, mode_2_1) t.guard = lambda state: state[1] >= 1 t.reset = lambda state: [None, None, None, None] t.guard_sympy = sym_y >= 1 t = ha.new_transition(mode_0_1, mode_1_1) t.guard = lambda state: state[0] >= 1 t.reset = lambda state: [None, None, None, None] t.guard_sympy = sym_x >= 1 t = ha.new_transition(mode_0_1, mode_0_0) t.guard = lambda state: state[1] <= 1 t.reset = lambda state: [None, None, None, None] t.guard_sympy = sym_y <= 1 t = ha.new_transition(mode_0_1, mode_0_2) t.guard = lambda state: state[1] >= 2 t.reset = lambda state: [None, None, None, None] t.guard_sympy = sym_y >= 2 t = ha.new_transition(mode_1_1, mode_0_1) t.guard = lambda state: state[0] <= 1 t.reset = lambda state: [None, None, None, None] t.guard_sympy = sym_x <= 1 t = ha.new_transition(mode_1_1, mode_2_1) t.guard = lambda state: state[0] >= 2 t.reset = lambda state: [None, None, None, None] t.guard_sympy = sym_x >= 2 t = ha.new_transition(mode_1_1, mode_1_0) t.guard = lambda state: state[1] <= 1 t.reset = lambda state: [None, None, None, None] t.guard_sympy = sym_y <= 1 t = ha.new_transition(mode_1_1, mode_1_2) t.guard = lambda state: state[1] >= 2 t.reset = lambda state: [None, None, None, None] t.guard_sympy = sym_y >= 2 t = ha.new_transition(mode_2_1, mode_1_1) t.guard = lambda state: state[0] <= 2 t.reset = lambda state: [None, None, None, None] t.guard_sympy = sym_x <= 2 t = ha.new_transition(mode_2_1, mode_2_0) t.guard = lambda state: state[1] <= 1 t.reset = lambda state: [None, None, None, None] t.guard_sympy = sym_y <= 1 t = ha.new_transition(mode_2_1, mode_2_2) t.guard = lambda state: state[1] >= 2 t.reset = lambda state: [None, None, None, None] t.guard_sympy = sym_y >= 2 t = ha.new_transition(mode_0_2, mode_1_2) t.guard = lambda state: state[0] >= 1 t.reset = lambda state: [None, None, None, None] t.guard_sympy = sym_x >= 1 t = ha.new_transition(mode_0_2, mode_0_1) t.guard = lambda state: state[1] <= 2 t.reset = lambda state: [None, None, None, None] t.guard_sympy = sym_y <= 2 t = ha.new_transition(mode_1_2, mode_0_2) t.guard = lambda state: state[0] <= 1 t.reset = lambda state: [None, None, None, None] t.guard_sympy = sym_x <= 1 t = ha.new_transition(mode_1_2, mode_2_2) t.guard = lambda state: state[0] >= 2 t.reset = lambda state: [None, None, None, None] t.guard_sympy = sym_x >= 2 t = ha.new_transition(mode_1_2, mode_1_1) t.guard = lambda state: state[1] <= 2 t.reset = lambda state: [None, None, None, None] t.guard_sympy = sym_y <= 2 t = ha.new_transition(mode_2_2, mode_1_2) t.guard = lambda state: state[0] <= 2 t.reset = lambda state: [None, None, None, None] t.guard_sympy = sym_x <= 2 t = ha.new_transition(mode_2_2, mode_2_1) t.guard = lambda state: state[1] <= 2 t.reset = lambda state: [None, None, None, None] t.guard_sympy = sym_y <= 2 return ha
def test_issue_10047(): assert solve(sin(x) < 2) == And(-oo < x, x < oo)
def test_mellin_transform(): from sympy import Max, Min MT = mellin_transform bpos = symbols('b', positive=True) # 8.4.2 assert MT(x**nu*Heaviside(x - 1), x, s) == \ (-1/(nu + s), (-oo, -re(nu)), True) assert MT(x**nu*Heaviside(1 - x), x, s) == \ (1/(nu + s), (-re(nu), oo), True) assert MT((1 - x)**(beta - 1)*Heaviside(1 - x), x, s) == \ (gamma(beta)*gamma(s)/gamma(beta + s), (0, oo), re(-beta) < 0) assert MT((x - 1)**(beta - 1)*Heaviside(x - 1), x, s) == \ (gamma(beta)*gamma(1 - beta - s)/gamma(1 - s), (-oo, -re(beta) + 1), re(-beta) < 0) assert MT((1 + x)**(-rho), x, s) == \ (gamma(s)*gamma(rho - s)/gamma(rho), (0, re(rho)), True) # TODO also the conditions should be simplified assert MT(abs(1 - x)**(-rho), x, s) == (cos(pi * (rho / 2 - s)) * gamma(s) * gamma(rho - s) / (cos(pi * rho / 2) * gamma(rho)), (0, re(rho)), And(re(rho) - 1 < 0, re(rho) < 1)) mt = MT((1 - x)**(beta - 1) * Heaviside(1 - x) + a * (x - 1)**(beta - 1) * Heaviside(x - 1), x, s) assert mt[1], mt[2] == ((0, -re(beta) + 1), True) assert MT((x**a - b**a)/(x - b), x, s)[0] == \ pi*b**(a + s - 1)*sin(pi*a)/(sin(pi*s)*sin(pi*(a + s))) assert MT((x**a - bpos**a)/(x - bpos), x, s) == \ (pi*bpos**(a + s - 1)*sin(pi*a)/(sin(pi*s)*sin(pi*(a + s))), (Max(-re(a), 0), Min(1 - re(a), 1)), True) expr = (sqrt(x + b**2) + b)**a assert MT(expr.subs(b, bpos), x, s) == \ (-a*(2*bpos)**(a + 2*s)*gamma(s)*gamma(-a - 2*s)/gamma(-a - s + 1), (0, -re(a)/2), True) expr = (sqrt(x + b**2) + b)**a / sqrt(x + b**2) assert MT(expr.subs(b, bpos), x, s) == \ (2**(a + 2*s)*bpos**(a + 2*s - 1)*gamma(s) *gamma(1 - a - 2*s)/gamma(1 - a - s), (0, -re(a)/2 + S(1)/2), True) # 8.4.2 assert MT(exp(-x), x, s) == (gamma(s), (0, oo), True) assert MT(exp(-1 / x), x, s) == (gamma(-s), (-oo, 0), True) # 8.4.5 assert MT(log(x)**4 * Heaviside(1 - x), x, s) == (24 / s**5, (0, oo), True) assert MT(log(x)**3 * Heaviside(x - 1), x, s) == (6 / s**4, (-oo, 0), True) assert MT(log(x + 1), x, s) == (pi / (s * sin(pi * s)), (-1, 0), True) assert MT(log(1 / x + 1), x, s) == (pi / (s * sin(pi * s)), (0, 1), True) assert MT(log(abs(1 - x)), x, s) == (pi / (s * tan(pi * s)), (-1, 0), True) assert MT(log(abs(1 - 1 / x)), x, s) == (pi / (s * tan(pi * s)), (0, 1), True) # TODO we cannot currently do these (needs summation of 3F2(-1)) # this also implies that they cannot be written as a single g-function # (although this is possible) mt = MT(log(x) / (x + 1), x, s) assert mt[1:] == ((0, 1), True) assert not hyperexpand(mt[0], allow_hyper=True).has(meijerg) mt = MT(log(x)**2 / (x + 1), x, s) assert mt[1:] == ((0, 1), True) assert not hyperexpand(mt[0], allow_hyper=True).has(meijerg) mt = MT(log(x) / (x + 1)**2, x, s) assert mt[1:] == ((0, 2), True) assert not hyperexpand(mt[0], allow_hyper=True).has(meijerg) # 8.4.14 assert MT(erf(sqrt(x)), x, s) == \ (-gamma(s + S(1)/2)/(sqrt(pi)*s), (-S(1)/2, 0), True)
def test_issue_10268(): assert solve(log(x) < 1000) == And(S(0) < x, x < exp(1000))
def test_reduce_poly_inequalities_complex_relational(): assert reduce_rational_inequalities([[Eq(x**2, 0)]], x, relational=True) == Eq(x, 0) assert reduce_rational_inequalities([[Le(x**2, 0)]], x, relational=True) == Eq(x, 0) assert reduce_rational_inequalities([[Lt(x**2, 0)]], x, relational=True) == False assert reduce_rational_inequalities([[Ge(x**2, 0)]], x, relational=True) == And( Lt(-oo, x), Lt(x, oo)) assert reduce_rational_inequalities( [[Gt(x**2, 0)]], x, relational=True) == \ And(Or(And(Lt(-oo, x), Lt(x, 0)), And(Lt(0, x), Lt(x, oo)))) assert reduce_rational_inequalities( [[Ne(x**2, 0)]], x, relational=True) == \ And(Or(And(Lt(-oo, x), Lt(x, 0)), And(Lt(0, x), Lt(x, oo)))) for one in (S(1), S(1.0)): inf = one * oo assert reduce_rational_inequalities( [[Eq(x**2, one)]], x, relational=True) == \ Or(Eq(x, -one), Eq(x, one)) assert reduce_rational_inequalities( [[Le(x**2, one)]], x, relational=True) == \ And(And(Le(-one, x), Le(x, one))) assert reduce_rational_inequalities( [[Lt(x**2, one)]], x, relational=True) == \ And(And(Lt(-one, x), Lt(x, one))) assert reduce_rational_inequalities( [[Ge(x**2, one)]], x, relational=True) == \ And(Or(And(Le(one, x), Lt(x, inf)), And(Le(x, -one), Lt(-inf, x)))) assert reduce_rational_inequalities( [[Gt(x**2, one)]], x, relational=True) == \ And(Or(And(Lt(-inf, x), Lt(x, -one)), And(Lt(one, x), Lt(x, inf)))) assert reduce_rational_inequalities( [[Ne(x**2, one)]], x, relational=True) == \ Or(And(Lt(-inf, x), Lt(x, -one)), And(Lt(-one, x), Lt(x, one)), And(Lt(one, x), Lt(x, inf)))
def as_boolean(self): return And(*[domain.as_boolean() for domain in self.domains])
def test_reduce_inequalities_multivariate(): assert reduce_inequalities([Ge(x**2, 1), Ge(y**2, 1)]) == And( Or(And(Le(1, x), Lt(x, oo)), And(Le(x, -1), Lt(-oo, x))), Or(And(Le(1, y), Lt(y, oo)), And(Le(y, -1), Lt(-oo, y))))
def test_Union_as_relational(): x = Symbol('x') assert (Interval(0, 1) + FiniteSet(2)).as_relational(x) == \ Or(And(Le(0, x), Le(x, 1)), Eq(x, 2)) assert (Interval(0, 1, True, True) + FiniteSet(1)).as_relational(x) == \ And(Lt(0, x), Le(x, 1))
def test_issue_6343(): eq = -3 * x**2 / 2 - 45 * x / 4 + S(33) / 2 > 0 assert reduce_inequalities(eq) == \ And(x < -S(15)/4 + sqrt(401)/4, -sqrt(401)/4 - S(15)/4 < x)
def test_Range_symbolic(): # symbolic Range sr = Range(x, y, t) i = Symbol('i', integer=True) ip = Symbol('i', integer=True, positive=True) ir = Range(i, i + 20, 2) inf = symbols('inf', infinite=True) # args assert sr.args == (x, y, t) assert ir.args == (i, i + 20, 2) # reversed raises(ValueError, lambda: sr.reversed) assert ir.reversed == Range(i + 18, i - 2, -2) # contains assert inf not in sr assert inf not in ir assert .1 not in sr assert .1 not in ir assert i + 1 not in ir assert i + 2 in ir raises(TypeError, lambda: 1 in sr) # XXX is this what contains is supposed to do? # iter raises(ValueError, lambda: next(iter(sr))) assert next(iter(ir)) == i assert sr.intersect(S.Integers) == sr assert sr.intersect(FiniteSet(x)) == Intersection({x}, sr) raises(ValueError, lambda: sr[:2]) raises(ValueError, lambda: sr[0]) raises(ValueError, lambda: sr.as_relational(x)) # len assert len(ir) == ir.size == 10 raises(ValueError, lambda: len(sr)) raises(ValueError, lambda: sr.size) # bool assert bool(ir) == bool(sr) == True # getitem raises(ValueError, lambda: sr[0]) raises(ValueError, lambda: sr[-1]) raises(ValueError, lambda: sr[:2]) assert ir[:2] == Range(i, i + 4, 2) assert ir[0] == i assert ir[-2] == i + 16 assert ir[-1] == i + 18 raises(ValueError, lambda: Range(i)[-1]) assert Range(ip)[-1] == ip - 1 assert ir.inf == i assert ir.sup == i + 18 assert Range(ip).inf == 0 assert Range(ip).sup == ip - 1 raises(ValueError, lambda: Range(i).inf) # as_relational raises(ValueError, lambda: sr.as_relational(x)) assert ir.as_relational(x) == (x >= i) & Eq(x, floor(x)) & (x <= i + 18) assert Range(i, i + 1).as_relational(x) == Eq(x, i) # contains() for symbolic values (issue #18146) e = Symbol('e', integer=True, even=True) o = Symbol('o', integer=True, odd=True) assert Range(5).contains(i) == And(i >= 0, i <= 4) assert Range(1).contains(i) == Eq(i, 0) assert Range(-oo, 5, 1).contains(i) == (i <= 4) assert Range(-oo, oo).contains(i) == True assert Range(0, 8, 2).contains(i) == Contains(i, Range(0, 8, 2)) assert Range(0, 8, 2).contains(e) == And(e >= 0, e <= 6) assert Range(0, 8, 2).contains(2 * i) == And(2 * i >= 0, 2 * i <= 6) assert Range(0, 8, 2).contains(o) == False assert Range(1, 9, 2).contains(e) == False assert Range(1, 9, 2).contains(o) == And(o >= 1, o <= 7) assert Range(8, 0, -2).contains(o) == False assert Range(9, 1, -2).contains(o) == And(o >= 3, o <= 9) assert Range(-oo, 8, 2).contains(i) == Contains(i, Range(-oo, 8, 2))
def test_slow_general_univariate(): r = rootof(x**5 - x**2 + 1, 0) assert solve(sqrt(x) + 1/root(x, 3) > 1) == \ Or(And(S(0) < x, x < r**6), And(r**6 < x, x < oo))
def test_piecewise_integrate4_symbolic_conditions(): a = Symbol('a', real=True, finite=True) b = Symbol('b', real=True, finite=True) x = Symbol('x', real=True, finite=True) y = Symbol('y', real=True, finite=True) p0 = Piecewise((0, Or(x < a, x > b)), (1, True)) p1 = Piecewise((0, x < a), (0, x > b), (1, True)) p2 = Piecewise((0, x > b), (0, x < a), (1, True)) p3 = Piecewise((0, x < a), (1, x < b), (0, True)) p4 = Piecewise((0, x > b), (1, x > a), (0, True)) p5 = Piecewise((1, And(a < x, x < b)), (0, True)) # check values of a=1, b=3 (and reversed) with values # of y of 0, 1, 2, 3, 4 lim = Tuple(x, -oo, y) for p in (p0, p1, p2, p3, p4, p5): ans = p.integrate(lim) for i in range(5): reps = {a:1, b:3, y:i} assert ans.subs(reps) == p.subs(reps).integrate(lim.subs(reps)) reps = {a: 3, b:1, y:i} assert ans.subs(reps) == p.subs(reps).integrate(lim.subs(reps)) lim = Tuple(x, y, oo) for p in (p0, p1, p2, p3, p4, p5): ans = p.integrate(lim) for i in range(5): reps = {a:1, b:3, y:i} assert ans.subs(reps) == p.subs(reps).integrate(lim.subs(reps)) reps = {a:3, b:1, y:i} assert ans.subs(reps) == p.subs(reps).integrate(lim.subs(reps)) ans = Piecewise( (0, x <= Min(a, b)), (x - Min(a, b), x <= b), (b - Min(a, b), True)) for i in (p0, p1, p2, p4): assert i.integrate(x) == ans assert p3.integrate(x) == Piecewise( (0, x < a), (-a + x, x <= Max(a, b)), (-a + Max(a, b), True)) assert p5.integrate(x) == Piecewise( (0, x <= a), (-a + x, x <= Max(a, b)), (-a + Max(a, b), True)) p1 = Piecewise((0, x < a), (0.5, x > b), (1, True)) p2 = Piecewise((0.5, x > b), (0, x < a), (1, True)) p3 = Piecewise((0, x < a), (1, x < b), (0.5, True)) p4 = Piecewise((0.5, x > b), (1, x > a), (0, True)) p5 = Piecewise((1, And(a < x, x < b)), (0.5, x > b), (0, True)) # check values of a=1, b=3 (and reversed) with values # of y of 0, 1, 2, 3, 4 lim = Tuple(x, -oo, y) for p in (p1, p2, p3, p4, p5): ans = p.integrate(lim) for i in range(5): reps = {a:1, b:3, y:i} assert ans.subs(reps) == p.subs(reps).integrate(lim.subs(reps)) reps = {a: 3, b:1, y:i} assert ans.subs(reps) == p.subs(reps).integrate(lim.subs(reps))
def test_issue_8545(): eq = 1 - x - abs(1 - x) ans = And(Lt(1, x), Lt(x, oo)) assert reduce_abs_inequality(eq, '<', x) == ans eq = 1 - x - sqrt((1 - x)**2) assert reduce_inequalities(eq < 0) == ans
def test_issue_11045(): assert integrate(1/(x*sqrt(x**2 - 1)), (x, 1, 2)) == pi/3 # handle And with Or arguments assert Piecewise((1, And(Or(x < 1, x > 3), x < 2)), (0, True) ).integrate((x, 0, 3)) == 1 # hidden false assert Piecewise((1, x > 1), (2, x > x + 1), (3, True) ).integrate((x, 0, 3)) == 5 # targetcond is Eq assert Piecewise((1, x > 1), (2, Eq(1, x)), (3, True) ).integrate((x, 0, 4)) == 6 # And has Relational needing to be solved assert Piecewise((1, And(2*x > x + 1, x < 2)), (0, True) ).integrate((x, 0, 3)) == 1 # Or has Relational needing to be solved assert Piecewise((1, Or(2*x > x + 2, x < 1)), (0, True) ).integrate((x, 0, 3)) == 2 # ignore hidden false (handled in canonicalization) assert Piecewise((1, x > 1), (2, x > x + 1), (3, True) ).integrate((x, 0, 3)) == 5 # watch for hidden True Piecewise assert Piecewise((2, Eq(1 - x, x*(1/x - 1))), (0, True) ).integrate((x, 0, 3)) == 6 # overlapping conditions of targetcond are recognized and ignored; # the condition x > 3 will be pre-empted by the first condition assert Piecewise((1, Or(x < 1, x > 2)), (2, x > 3), (3, True) ).integrate((x, 0, 4)) == 6 # convert Ne to Or assert Piecewise((1, Ne(x, 0)), (2, True) ).integrate((x, -1, 1)) == 2 # no default but well defined assert Piecewise((x, (x > 1) & (x < 3)), (1, (x < 4)) ).integrate((x, 1, 4)) == 5 p = Piecewise((x, (x > 1) & (x < 3)), (1, (x < 4))) nan = Undefined i = p.integrate((x, 1, y)) assert i == Piecewise( (y - 1, y < 1), (Min(3, y)**2/2 - Min(3, y) + Min(4, y) - S(1)/2, y <= Min(4, y)), (nan, True)) assert p.integrate((x, 1, -1)) == i.subs(y, -1) assert p.integrate((x, 1, 4)) == 5 assert p.integrate((x, 1, 5)) == nan # handle Not p = Piecewise((1, x > 1), (2, Not(And(x > 1, x< 3))), (3, True)) assert p.integrate((x, 0, 3)) == 4 # handle updating of int_expr when there is overlap p = Piecewise( (1, And(5 > x, x > 1)), (2, Or(x < 3, x > 7)), (4, x < 8)) assert p.integrate((x, 0, 10)) == 20 # And with Eq arg handling assert Piecewise((1, x < 1), (2, And(Eq(x, 3), x > 1)) ).integrate((x, 0, 3)) == S.NaN assert Piecewise((1, x < 1), (2, And(Eq(x, 3), x > 1)), (3, True) ).integrate((x, 0, 3)) == 7 assert Piecewise((1, x < 0), (2, And(Eq(x, 3), x < 1)), (3, True) ).integrate((x, -1, 1)) == 4 # middle condition doesn't matter: it's a zero width interval assert Piecewise((1, x < 1), (2, Eq(x, 3) & (y < x)), (3, True) ).integrate((x, 0, 3)) == 7
def test_issue_8974(): assert isolve(-oo < x, x) == And(-oo < x, x < oo) assert isolve(oo > x, x) == And(-oo < x, x < oo)
def test_reduce_inequalities_general(): assert reduce_inequalities(Ge(sqrt(2)*x, 1)) == And(sqrt(2)/2 <= x, x < oo) assert reduce_inequalities(PurePoly(x + 1, x) > 0) == And(S(-1) < x, x < oo)
def test_DiscreteMarkovChain(): # pass only the name X = DiscreteMarkovChain("X") assert isinstance(X.state_space, Range) assert X.index_set == S.Naturals0 assert isinstance(X.transition_probabilities, MatrixSymbol) t = symbols('t', positive=True, integer=True) assert isinstance(X[t], RandomIndexedSymbol) assert E(X[0]) == Expectation(X[0]) raises(TypeError, lambda: DiscreteMarkovChain(1)) raises(NotImplementedError, lambda: X(t)) nz = Symbol('n', integer=True) TZ = MatrixSymbol('M', nz, nz) SZ = Range(nz) YZ = DiscreteMarkovChain('Y', SZ, TZ) assert P(Eq(YZ[2], 1), Eq(YZ[1], 0)) == TZ[0, 1] raises(ValueError, lambda: sample_stochastic_process(t)) raises(ValueError, lambda: next(sample_stochastic_process(X))) # pass name and state_space # any hashable object should be a valid state # states should be valid as a tuple/set/list/Tuple/Range sym, rainy, cloudy, sunny = symbols('a Rainy Cloudy Sunny', real=True) state_spaces = [(1, 2, 3), [Str('Hello'), sym, DiscreteMarkovChain], Tuple(1, exp(sym), Str('World'), sympify=False), Range(-1, 5, 2), [rainy, cloudy, sunny]] chains = [DiscreteMarkovChain("Y", state_space) for state_space in state_spaces] for i, Y in enumerate(chains): assert isinstance(Y.transition_probabilities, MatrixSymbol) assert Y.state_space == state_spaces[i] or Y.state_space == FiniteSet(*state_spaces[i]) assert Y.number_of_states == 3 with ignore_warnings(UserWarning): # TODO: Restore tests once warnings are removed assert P(Eq(Y[2], 1), Eq(Y[0], 2), evaluate=False) == Probability(Eq(Y[2], 1), Eq(Y[0], 2)) assert E(Y[0]) == Expectation(Y[0]) raises(ValueError, lambda: next(sample_stochastic_process(Y))) raises(TypeError, lambda: DiscreteMarkovChain("Y", dict((1, 1)))) Y = DiscreteMarkovChain("Y", Range(1, t, 2)) assert Y.number_of_states == ceiling((t-1)/2) # pass name and transition_probabilities chains = [DiscreteMarkovChain("Y", trans_probs=Matrix([[]])), DiscreteMarkovChain("Y", trans_probs=Matrix([[0, 1], [1, 0]])), DiscreteMarkovChain("Y", trans_probs=Matrix([[pi, 1-pi], [sym, 1-sym]]))] for Z in chains: assert Z.number_of_states == Z.transition_probabilities.shape[0] assert isinstance(Z.transition_probabilities, ImmutableDenseMatrix) # pass name, state_space and transition_probabilities T = Matrix([[0.5, 0.2, 0.3],[0.2, 0.5, 0.3],[0.2, 0.3, 0.5]]) TS = MatrixSymbol('T', 3, 3) Y = DiscreteMarkovChain("Y", [0, 1, 2], T) YS = DiscreteMarkovChain("Y", ['One', 'Two', 3], TS) assert YS._transient2transient() == None assert YS._transient2absorbing() == None assert Y.joint_distribution(1, Y[2], 3) == JointDistribution(Y[1], Y[2], Y[3]) raises(ValueError, lambda: Y.joint_distribution(Y[1].symbol, Y[2].symbol)) assert P(Eq(Y[3], 2), Eq(Y[1], 1)).round(2) == Float(0.36, 2) assert (P(Eq(YS[3], 2), Eq(YS[1], 1)) - (TS[0, 2]*TS[1, 0] + TS[1, 1]*TS[1, 2] + TS[1, 2]*TS[2, 2])).simplify() == 0 assert P(Eq(YS[1], 1), Eq(YS[2], 2)) == Probability(Eq(YS[1], 1)) assert P(Eq(YS[3], 3), Eq(YS[1], 1)) == TS[0, 2]*TS[1, 0] + TS[1, 1]*TS[1, 2] + TS[1, 2]*TS[2, 2] TO = Matrix([[0.25, 0.75, 0],[0, 0.25, 0.75],[0.75, 0, 0.25]]) assert P(Eq(Y[3], 2), Eq(Y[1], 1) & TransitionMatrixOf(Y, TO)).round(3) == Float(0.375, 3) with ignore_warnings(UserWarning): ### TODO: Restore tests once warnings are removed assert E(Y[3], evaluate=False) == Expectation(Y[3]) assert E(Y[3], Eq(Y[2], 1)).round(2) == Float(1.1, 3) TSO = MatrixSymbol('T', 4, 4) raises(ValueError, lambda: str(P(Eq(YS[3], 2), Eq(YS[1], 1) & TransitionMatrixOf(YS, TSO)))) raises(TypeError, lambda: DiscreteMarkovChain("Z", [0, 1, 2], symbols('M'))) raises(ValueError, lambda: DiscreteMarkovChain("Z", [0, 1, 2], MatrixSymbol('T', 3, 4))) raises(ValueError, lambda: E(Y[3], Eq(Y[2], 6))) raises(ValueError, lambda: E(Y[2], Eq(Y[3], 1))) # extended tests for probability queries TO1 = Matrix([[Rational(1, 4), Rational(3, 4), 0],[Rational(1, 3), Rational(1, 3), Rational(1, 3)],[0, Rational(1, 4), Rational(3, 4)]]) assert P(And(Eq(Y[2], 1), Eq(Y[1], 1), Eq(Y[0], 0)), Eq(Probability(Eq(Y[0], 0)), Rational(1, 4)) & TransitionMatrixOf(Y, TO1)) == Rational(1, 16) assert P(And(Eq(Y[2], 1), Eq(Y[1], 1), Eq(Y[0], 0)), TransitionMatrixOf(Y, TO1)) == \ Probability(Eq(Y[0], 0))/4 assert P(Lt(X[1], 2) & Gt(X[1], 0), Eq(X[0], 2) & StochasticStateSpaceOf(X, [0, 1, 2]) & TransitionMatrixOf(X, TO1)) == Rational(1, 4) assert P(Lt(X[1], 2) & Gt(X[1], 0), Eq(X[0], 2) & StochasticStateSpaceOf(X, [None, 'None', 1]) & TransitionMatrixOf(X, TO1)) == Rational(1, 4) assert P(Ne(X[1], 2) & Ne(X[1], 1), Eq(X[0], 2) & StochasticStateSpaceOf(X, [0, 1, 2]) & TransitionMatrixOf(X, TO1)) is S.Zero assert P(Ne(X[1], 2) & Ne(X[1], 1), Eq(X[0], 2) & StochasticStateSpaceOf(X, [None, 'None', 1]) & TransitionMatrixOf(X, TO1)) is S.Zero assert P(And(Eq(Y[2], 1), Eq(Y[1], 1), Eq(Y[0], 0)), Eq(Y[1], 1)) == 0.1*Probability(Eq(Y[0], 0)) # testing properties of Markov chain TO2 = Matrix([[S.One, 0, 0],[Rational(1, 3), Rational(1, 3), Rational(1, 3)],[0, Rational(1, 4), Rational(3, 4)]]) TO3 = Matrix([[Rational(1, 4), Rational(3, 4), 0],[Rational(1, 3), Rational(1, 3), Rational(1, 3)],[0, Rational(1, 4), Rational(3, 4)]]) Y2 = DiscreteMarkovChain('Y', trans_probs=TO2) Y3 = DiscreteMarkovChain('Y', trans_probs=TO3) assert Y3._transient2absorbing() == None raises (ValueError, lambda: Y3.fundamental_matrix()) assert Y2.is_absorbing_chain() == True assert Y3.is_absorbing_chain() == False TO4 = Matrix([[Rational(1, 5), Rational(2, 5), Rational(2, 5)], [Rational(1, 10), S.Half, Rational(2, 5)], [Rational(3, 5), Rational(3, 10), Rational(1, 10)]]) Y4 = DiscreteMarkovChain('Y', trans_probs=TO4) w = ImmutableMatrix([[Rational(11, 39), Rational(16, 39), Rational(4, 13)]]) assert Y4.limiting_distribution == w assert Y4.is_regular() == True TS1 = MatrixSymbol('T', 3, 3) Y5 = DiscreteMarkovChain('Y', trans_probs=TS1) assert Y5.limiting_distribution(w, TO4).doit() == True assert Y5.stationary_distribution(condition_set=True).subs(TS1, TO4).contains(w).doit() == S.true TO6 = Matrix([[S.One, 0, 0, 0, 0],[S.Half, 0, S.Half, 0, 0],[0, S.Half, 0, S.Half, 0], [0, 0, S.Half, 0, S.Half], [0, 0, 0, 0, 1]]) Y6 = DiscreteMarkovChain('Y', trans_probs=TO6) assert Y6._transient2absorbing() == ImmutableMatrix([[S.Half, 0], [0, 0], [0, S.Half]]) assert Y6._transient2transient() == ImmutableMatrix([[0, S.Half, 0], [S.Half, 0, S.Half], [0, S.Half, 0]]) assert Y6.fundamental_matrix() == ImmutableMatrix([[Rational(3, 2), S.One, S.Half], [S.One, S(2), S.One], [S.Half, S.One, Rational(3, 2)]]) assert Y6.absorbing_probabilities() == ImmutableMatrix([[Rational(3, 4), Rational(1, 4)], [S.Half, S.Half], [Rational(1, 4), Rational(3, 4)]]) # test for zero-sized matrix functionality X = DiscreteMarkovChain('X', trans_probs=Matrix([[]])) assert X.number_of_states == 0 assert X.stationary_distribution() == Matrix([[]]) # test communication_class # see https://drive.google.com/drive/folders/1HbxLlwwn2b3U8Lj7eb_ASIUb5vYaNIjg?usp=sharing # tutorial 2.pdf TO7 = Matrix([[0, 5, 5, 0, 0], [0, 0, 0, 10, 0], [5, 0, 5, 0, 0], [0, 10, 0, 0, 0], [0, 3, 0, 3, 4]])/10 Y7 = DiscreteMarkovChain('Y', trans_probs=TO7) tuples = Y7.communication_classes() classes, recurrence, periods = list(zip(*tuples)) assert classes == ([1, 3], [0, 2], [4]) assert recurrence == (True, False, False) assert periods == (2, 1, 1) TO8 = Matrix([[0, 0, 0, 10, 0, 0], [5, 0, 5, 0, 0, 0], [0, 4, 0, 0, 0, 6], [10, 0, 0, 0, 0, 0], [0, 10, 0, 0, 0, 0], [0, 0, 0, 5, 5, 0]])/10 Y8 = DiscreteMarkovChain('Y', trans_probs=TO8) tuples = Y8.communication_classes() classes, recurrence, periods = list(zip(*tuples)) assert classes == ([0, 3], [1, 2, 5, 4]) assert recurrence == (True, False) assert periods == (2, 2) TO9 = Matrix([[2, 0, 0, 3, 0, 0, 3, 2, 0, 0], [0, 10, 0, 0, 0, 0, 0, 0, 0, 0], [0, 2, 2, 0, 0, 0, 0, 0, 3, 3], [0, 0, 0, 3, 0, 0, 6, 1, 0, 0], [0, 0, 0, 0, 5, 5, 0, 0, 0, 0], [0, 0, 0, 0, 0, 10, 0, 0, 0, 0], [4, 0, 0, 5, 0, 0, 1, 0, 0, 0], [2, 0, 0, 4, 0, 0, 2, 2, 0, 0], [3, 0, 1, 0, 0, 0, 0, 0, 4, 2], [0, 0, 4, 0, 0, 0, 0, 0, 3, 3]])/10 Y9 = DiscreteMarkovChain('Y', trans_probs=TO9) tuples = Y9.communication_classes() classes, recurrence, periods = list(zip(*tuples)) assert classes == ([0, 3, 6, 7], [1], [2, 8, 9], [5], [4]) assert recurrence == (True, True, False, True, False) assert periods == (1, 1, 1, 1, 1) # test custom state space Y10 = DiscreteMarkovChain('Y', [1, 2, 3], TO2) tuples = Y10.communication_classes() classes, recurrence, periods = list(zip(*tuples)) assert classes == ([1], [2, 3]) assert recurrence == (True, False) assert periods == (1, 1) # testing miscellaneous queries T = Matrix([[S.Half, Rational(1, 4), Rational(1, 4)], [Rational(1, 3), 0, Rational(2, 3)], [S.Half, S.Half, 0]]) X = DiscreteMarkovChain('X', [0, 1, 2], T) assert P(Eq(X[1], 2) & Eq(X[2], 1) & Eq(X[3], 0), Eq(P(Eq(X[1], 0)), Rational(1, 4)) & Eq(P(Eq(X[1], 1)), Rational(1, 4))) == Rational(1, 12) assert P(Eq(X[2], 1) | Eq(X[2], 2), Eq(X[1], 1)) == Rational(2, 3) assert P(Eq(X[2], 1) & Eq(X[2], 2), Eq(X[1], 1)) is S.Zero assert P(Ne(X[2], 2), Eq(X[1], 1)) == Rational(1, 3) assert E(X[1]**2, Eq(X[0], 1)) == Rational(8, 3) assert variance(X[1], Eq(X[0], 1)) == Rational(8, 9) raises(ValueError, lambda: E(X[1], Eq(X[2], 1))) raises(ValueError, lambda: DiscreteMarkovChain('X', [0, 1], T)) # testing miscellaneous queries with different state space X = DiscreteMarkovChain('X', ['A', 'B', 'C'], T) assert P(Eq(X[1], 2) & Eq(X[2], 1) & Eq(X[3], 0), Eq(P(Eq(X[1], 0)), Rational(1, 4)) & Eq(P(Eq(X[1], 1)), Rational(1, 4))) == Rational(1, 12) assert P(Eq(X[2], 1) | Eq(X[2], 2), Eq(X[1], 1)) == Rational(2, 3) assert P(Eq(X[2], 1) & Eq(X[2], 2), Eq(X[1], 1)) is S.Zero assert P(Ne(X[2], 2), Eq(X[1], 1)) == Rational(1, 3) a = X.state_space.args[0] c = X.state_space.args[2] assert (E(X[1] ** 2, Eq(X[0], 1)) - (a**2/3 + 2*c**2/3)).simplify() == 0 assert (variance(X[1], Eq(X[0], 1)) - (2*(-a/3 + c/3)**2/3 + (2*a/3 - 2*c/3)**2/3)).simplify() == 0 raises(ValueError, lambda: E(X[1], Eq(X[2], 1)))