예제 #1
0
def test_bool_monomial():
    x, y = symbols('x,y')
    assert bool_monomial(1, [x, y]) == y
    assert bool_monomial([1, 1], [x, y]) == And(x, y)
예제 #2
0
파일: ask.py 프로젝트: skolwind/sympy
    ("lower_triangular", "matrices.AskLowerTriangularHandler"),
    ("diagonal", "matrices.AskDiagonalHandler"),
]
for name, value in _handlers:
    register_handler(name, _val_template % value)

known_facts_keys = [
    getattr(Q, attr) for attr in Q.__dict__ if not attr.startswith('__')
]
known_facts = And(Implies(Q.real, Q.complex), Implies(Q.real, Q.hermitian),
                  Equivalent(Q.even, Q.integer & ~Q.odd),
                  Equivalent(Q.extended_real, Q.real | Q.infinity),
                  Equivalent(Q.odd, Q.integer & ~Q.even),
                  Equivalent(Q.prime, Q.integer & Q.positive & ~Q.composite),
                  Implies(Q.integer, Q.rational),
                  Implies(Q.imaginary, Q.complex & ~Q.real),
                  Implies(Q.imaginary, Q.antihermitian),
                  Implies(Q.antihermitian, ~Q.hermitian),
                  Equivalent(Q.negative, Q.nonzero & ~Q.positive),
                  Equivalent(Q.positive, Q.nonzero & ~Q.negative),
                  Equivalent(Q.rational, Q.real & ~Q.irrational),
                  Equivalent(Q.real, Q.rational | Q.irrational),
                  Implies(Q.nonzero, Q.real),
                  Equivalent(Q.nonzero, Q.positive | Q.negative),
                  Implies(Q.orthogonal, Q.positive_definite),
                  Implies(Q.positive_definite, Q.invertible),
                  Implies(Q.diagonal, Q.upper_triangular),
                  Implies(Q.diagonal, Q.lower_triangular))

from sympy.assumptions.ask_generated import known_facts_dict, known_facts_cnf
예제 #3
0
def piecewise_fold(expr):
    """
    Takes an expression containing a piecewise function and returns the
    expression in piecewise form. In addition, any ITE conditions are
    rewritten in negation normal form and simplified.

    Examples
    ========

    >>> from sympy import Piecewise, piecewise_fold, sympify as S
    >>> from sympy.abc import x
    >>> p = Piecewise((x, x < 1), (1, S(1) <= x))
    >>> piecewise_fold(x*p)
    Piecewise((x**2, x < 1), (x, True))

    See Also
    ========

    Piecewise
    """
    if not isinstance(expr, Basic) or not expr.has(Piecewise):
        return expr

    new_args = []
    if isinstance(expr, (ExprCondPair, Piecewise)):
        for e, c in expr.args:
            if not isinstance(e, Piecewise):
                e = piecewise_fold(e)
            # we don't keep Piecewise in condition because
            # it has to be checked to see that it's complete
            # and we convert it to ITE at that time
            assert not c.has(Piecewise)  # pragma: no cover
            if isinstance(c, ITE):
                c = c.to_nnf()
                c = simplify_logic(c, form='cnf')
            if isinstance(e, Piecewise):
                new_args.extend([(piecewise_fold(ei), And(ci, c))
                                 for ei, ci in e.args])
            else:
                new_args.append((e, c))
    else:
        from sympy.utilities.iterables import cartes, sift, common_prefix
        # Given
        #     P1 = Piecewise((e11, c1), (e12, c2), A)
        #     P2 = Piecewise((e21, c1), (e22, c2), B)
        #     ...
        # the folding of f(P1, P2) is trivially
        # Piecewise(
        #   (f(e11, e21), c1),
        #   (f(e12, e22), c2),
        #   (f(Piecewise(A), Piecewise(B)), True))
        # Certain objects end up rewriting themselves as thus, so
        # we do that grouping before the more generic folding.
        # The following applies this idea when f = Add or f = Mul
        # (and the expression is commutative).
        if expr.is_Add or expr.is_Mul and expr.is_commutative:
            p, args = sift(expr.args, lambda x: x.is_Piecewise, binary=True)
            pc = sift(p, lambda x: tuple([c for e, c in x.args]))
            for c in list(ordered(pc)):
                if len(pc[c]) > 1:
                    pargs = [list(i.args) for i in pc[c]]
                    # the first one is the same; there may be more
                    com = common_prefix(*[[i.cond for i in j] for j in pargs])
                    n = len(com)
                    collected = []
                    for i in range(n):
                        collected.append(
                            (expr.func(*[ai[i].expr for ai in pargs]), com[i]))
                    remains = []
                    for a in pargs:
                        if n == len(a):  # no more args
                            continue
                        if a[n].cond == True:  # no longer Piecewise
                            remains.append(a[n].expr)
                        else:  # restore the remaining Piecewise
                            remains.append(Piecewise(*a[n:], evaluate=False))
                    if remains:
                        collected.append((expr.func(*remains), True))
                    args.append(Piecewise(*collected, evaluate=False))
                    continue
                args.extend(pc[c])
        else:
            args = expr.args
        # fold
        folded = list(map(piecewise_fold, args))
        for ec in cartes(*[(i.args if isinstance(i, Piecewise) else [(i,
                                                                      true)])
                           for i in folded]):
            e, c = zip(*ec)
            new_args.append((expr.func(*e), And(*c)))

    return Piecewise(*new_args)
예제 #4
0
def test_multivariate_bool_as_set():
    x, y = symbols('x,y')

    assert And(x >= 0, y >= 0).as_set() == Interval(0, oo) * Interval(0, oo)
    assert Or(x >= 0, y >= 0).as_set() == S.Reals*S.Reals - \
        Interval(-oo, 0, True, True)*Interval(-oo, 0, True, True)
예제 #5
0
def test_issue_8975():
    assert Or(And(-oo < x, x <= -2), And(2 <= x, x < oo)).as_set() == \
        Interval(-oo, -2) + Interval(2, oo)
예제 #6
0
def test_simplification():
    """
    Test working of simplification methods.
    """
    set1 = [[0, 0, 1], [0, 1, 1], [1, 0, 0], [1, 1, 0]]
    set2 = [[0, 0, 0], [0, 1, 0], [1, 0, 1], [1, 1, 1]]
    assert SOPform([x, y, z], set1) == Or(And(Not(x), z), And(Not(z), x))
    assert Not(SOPform([x, y, z], set2)) == \
        Not(Or(And(Not(x), Not(z)), And(x, z)))
    assert POSform([x, y, z], set1 + set2) is true
    assert SOPform([x, y, z], set1 + set2) is true
    assert SOPform([Dummy(), Dummy(), Dummy()], set1 + set2) is true

    minterms = [[0, 0, 0, 1], [0, 0, 1, 1], [0, 1, 1, 1], [1, 0, 1, 1],
                [1, 1, 1, 1]]
    dontcares = [[0, 0, 0, 0], [0, 0, 1, 0], [0, 1, 0, 1]]
    assert (SOPform([w, x, y, z], minterms,
                    dontcares) == Or(And(Not(w), z), And(y, z)))
    assert POSform([w, x, y, z], minterms, dontcares) == And(Or(Not(w), y), z)

    minterms = [1, 3, 7, 11, 15]
    dontcares = [0, 2, 5]
    assert (SOPform([w, x, y, z], minterms,
                    dontcares) == Or(And(Not(w), z), And(y, z)))
    assert POSform([w, x, y, z], minterms, dontcares) == And(Or(Not(w), y), z)

    minterms = [1, [0, 0, 1, 1], 7, [1, 0, 1, 1], [1, 1, 1, 1]]
    dontcares = [0, [0, 0, 1, 0], 5]
    assert (SOPform([w, x, y, z], minterms,
                    dontcares) == Or(And(Not(w), z), And(y, z)))
    assert POSform([w, x, y, z], minterms, dontcares) == And(Or(Not(w), y), z)

    minterms = [1, {y: 1, z: 1}]
    dontcares = [0, [0, 0, 1, 0], 5]
    assert (SOPform([w, x, y, z], minterms,
                    dontcares) == Or(And(Not(w), z), And(y, z)))
    assert POSform([w, x, y, z], minterms, dontcares) == And(Or(Not(w), y), z)

    minterms = [{y: 1, z: 1}, 1]
    dontcares = [[0, 0, 0, 0]]

    minterms = [[0, 0, 0]]
    raises(ValueError, lambda: SOPform([w, x, y, z], minterms))
    raises(ValueError, lambda: POSform([w, x, y, z], minterms))

    raises(TypeError, lambda: POSform([w, x, y, z], ["abcdefg"]))

    # test simplification
    ans = And(A, Or(B, C))
    assert simplify_logic(A & (B | C)) == ans
    assert simplify_logic((A & B) | (A & C)) == ans
    assert simplify_logic(Implies(A, B)) == Or(Not(A), B)
    assert simplify_logic(Equivalent(A, B)) == \
        Or(And(A, B), And(Not(A), Not(B)))
    assert simplify_logic(And(Equality(A, 2), C)) == And(Equality(A, 2), C)
    assert simplify_logic(And(Equality(A, 2), A)) is S.false
    assert simplify_logic(And(Equality(A, 2), A)) == And(Equality(A, 2), A)
    assert simplify_logic(And(Equality(A, B), C)) == And(Equality(A, B), C)
    assert simplify_logic(Or(And(Equality(A, 3), B), And(Equality(A, 3), C))) \
        == And(Equality(A, 3), Or(B, C))
    b = (~x & ~y & ~z) | (~x & ~y & z)
    e = And(A, b)
    assert simplify_logic(e) == A & ~x & ~y
    raises(ValueError, lambda: simplify_logic(A & (B | C), form='blabla'))

    # Check that expressions with nine variables or more are not simplified
    # (without the force-flag)
    a, b, c, d, e, f, g, h, j = symbols('a b c d e f g h j')
    expr = a & b & c & d & e & f & g & h & j | \
        a & b & c & d & e & f & g & h & ~j
    # This expression can be simplified to get rid of the j variables
    assert simplify_logic(expr) == expr

    # check input
    ans = SOPform([x, y], [[1, 0]])
    assert SOPform([x, y], [[1, 0]]) == ans
    assert POSform([x, y], [[1, 0]]) == ans

    raises(ValueError, lambda: SOPform([x], [[1]], [[1]]))
    assert SOPform([x], [[1]], [[0]]) is true
    assert SOPform([x], [[0]], [[1]]) is true
    assert SOPform([x], [], []) is false

    raises(ValueError, lambda: POSform([x], [[1]], [[1]]))
    assert POSform([x], [[1]], [[0]]) is true
    assert POSform([x], [[0]], [[1]]) is true
    assert POSform([x], [], []) is false

    # check working of simplify
    assert simplify((A & B) | (A & C)) == And(A, Or(B, C))
    assert simplify(And(x, Not(x))) == False
    assert simplify(Or(x, Not(x))) == True
    assert simplify(And(Eq(x, 0), Eq(x, y))) == And(Eq(x, 0), Eq(y, 0))
    assert And(Eq(x - 1, 0), Eq(x, y)).simplify() == And(Eq(x, 1), Eq(y, 1))
    assert And(Ne(x - 1, 0), Ne(x, y)).simplify() == And(Ne(x, 1), Ne(x, y))
    assert And(Eq(x - 1, 0), Ne(x, y)).simplify() == And(Eq(x, 1), Ne(y, 1))
    assert And(Eq(x - 1, 0), Eq(x, z + y),
               Eq(y + x, 0)).simplify() == And(Eq(x, 1), Eq(y, -1), Eq(z, 2))
    assert And(Eq(x - 1, 0), Eq(x + 2, 3)).simplify() == Eq(x, 1)
    assert And(Ne(x - 1, 0), Ne(x + 2, 3)).simplify() == Ne(x, 1)
    assert And(Eq(x - 1, 0), Eq(x + 2, 2)).simplify() == False
    assert And(Ne(x - 1, 0), Ne(x + 2,
                                2)).simplify() == And(Ne(x, 1), Ne(x, 0))
예제 #7
0
def test_distribute():
    assert distribute_and_over_or(Or(And(A, B), C)) == And(Or(A, C), Or(B, C))
    assert distribute_or_over_and(And(A, Or(B, C))) == Or(And(A, B), And(A, C))
예제 #8
0
    def _eval_interval(self, sym, a, b):
        """Evaluates the function along the sym in a given interval ab"""
        # FIXME: Currently complex intervals are not supported.  A possible
        # replacement algorithm, discussed in issue 2128, can be found in the
        # following papers;
        #     http://portal.acm.org/citation.cfm?id=281649
        #     http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.70.4127&rep=rep1&type=pdf

        if a is None or b is None:
            # In this case, it is just simple substitution
            return piecewise_fold(
                super(Piecewise, self)._eval_interval(sym, a, b))

        mul = 1
        if (a == b) is True:
            return S.Zero
        elif (a > b) is True:
            a, b, mul = b, a, -1
        elif (a <= b) is not True:
            newargs = []
            for e, c in self.args:
                intervals = self._sort_expr_cond(
                    sym, S.NegativeInfinity, S.Infinity, c)
                values = []
                for lower, upper, expr in intervals:
                    if (a < lower) is True:
                        mid = lower
                        rep = b
                        val = e._eval_interval(sym, mid, b)
                        val += self._eval_interval(sym, a, mid)
                    elif (a > upper) is True:
                        mid = upper
                        rep = b
                        val = e._eval_interval(sym, mid, b)
                        val += self._eval_interval(sym, a, mid)
                    elif (a >= lower) is True and (a <= upper) is True:
                        rep = b
                        val = e._eval_interval(sym, a, b)
                    elif (b < lower) is True:
                        mid = lower
                        rep = a
                        val = e._eval_interval(sym, a, mid)
                        val += self._eval_interval(sym, mid, b)
                    elif (b > upper) is True:
                        mid = upper
                        rep = a
                        val = e._eval_interval(sym, a, mid)
                        val += self._eval_interval(sym, mid, b)
                    elif ((b >= lower) is True) and ((b <= upper) is True):
                        rep = a
                        val = e._eval_interval(sym, a, b)
                    else:
                        raise NotImplementedError(
                            """The evaluation of a Piecewise interval when both the lower
                            and the upper limit are symbolic is not yet implemented.""")
                    values.append(val)
                if len(set(values)) == 1:
                    try:
                        c = c.subs(sym, rep)
                    except AttributeError:
                        pass
                    e = values[0]
                    newargs.append((e, c))
                else:
                    for i in range(len(values)):
                        newargs.append((values[i], (c == True and i == len(values) - 1) or
                            And(rep >= intervals[i][0], rep <= intervals[i][1])))
            return self.func(*newargs)

        # Determine what intervals the expr,cond pairs affect.
        int_expr = self._sort_expr_cond(sym, a, b)

        # Finally run through the intervals and sum the evaluation.
        ret_fun = 0
        for int_a, int_b, expr in int_expr:
            if isinstance(expr, Piecewise):
                # If we still have a Piecewise by now, _sort_expr_cond would
                # already have determined that its conditions are independent
                # of the integration variable, thus we just use substitution.
                ret_fun += piecewise_fold(
                    super(Piecewise, expr)._eval_interval(sym, Max(a, int_a), Min(b, int_b)))
            else:
                ret_fun += expr._eval_interval(sym, Max(a, int_a), Min(b, int_b))
        return mul * ret_fun
예제 #9
0
known_facts = And(
    Implies(Q.real, Q.complex),
    Implies(Q.real, Q.hermitian),
    Equivalent(Q.even, Q.integer & ~Q.odd),
    Equivalent(Q.extended_real, Q.real | Q.infinity),
    Equivalent(Q.odd, Q.integer & ~Q.even),
    Equivalent(Q.prime, Q.integer & Q.positive & ~Q.composite),
    Implies(Q.integer, Q.rational),
    Implies(Q.rational, Q.algebraic),
    Implies(Q.algebraic, Q.complex),
    Implies(Q.imaginary, Q.complex & ~Q.real),
    Implies(Q.imaginary, Q.antihermitian),
    Implies(Q.antihermitian, ~Q.hermitian),
    Equivalent(Q.negative, Q.nonzero & ~Q.positive),
    Equivalent(Q.positive, Q.nonzero & ~Q.negative),
    Equivalent(Q.rational, Q.real & ~Q.irrational),
    Equivalent(Q.real, Q.rational | Q.irrational),
    Implies(Q.nonzero, Q.real),
    Equivalent(Q.nonzero, Q.positive | Q.negative),
    Implies(Q.orthogonal, Q.positive_definite),
    Implies(Q.orthogonal, Q.unitary),
    Implies(Q.unitary & Q.real, Q.orthogonal),
    Implies(Q.unitary, Q.normal),
    Implies(Q.unitary, Q.invertible),
    Implies(Q.normal, Q.square),
    Implies(Q.diagonal, Q.normal),
    Implies(Q.positive_definite, Q.invertible),
    Implies(Q.diagonal, Q.upper_triangular),
    Implies(Q.diagonal, Q.lower_triangular),
    Implies(Q.lower_triangular, Q.triangular),
    Implies(Q.upper_triangular, Q.triangular),
    Implies(Q.triangular, Q.upper_triangular | Q.lower_triangular),
    Implies(Q.upper_triangular & Q.lower_triangular, Q.diagonal),
    Implies(Q.diagonal, Q.symmetric),
    Implies(Q.unit_triangular, Q.triangular),
    Implies(Q.invertible, Q.fullrank),
    Implies(Q.invertible, Q.square),
    Implies(Q.symmetric, Q.square),
    Implies(Q.fullrank & Q.square, Q.invertible),
    Equivalent(Q.invertible, ~Q.singular),
)
예제 #10
0
def get_known_facts(x=None):
    """
    Facts between unary predicates.

    Parameters
    ==========

    x : Symbol, optional
        Placeholder symbol for unary facts. Default is ``Symbol('x')``.

    Returns
    =======

    fact : Known facts in conjugated normal form.

    """
    if x is None:
        x = Symbol('x')

    fact = And(
        # primitive predicates for extended real exclude each other.
        Exclusive(Q.negative_infinite(x), Q.negative(x), Q.zero(x),
                  Q.positive(x), Q.positive_infinite(x)),

        # build complex plane
        Exclusive(Q.real(x), Q.imaginary(x)),
        Implies(Q.real(x) | Q.imaginary(x), Q.complex(x)),

        # other subsets of complex
        Exclusive(Q.transcendental(x), Q.algebraic(x)),
        Equivalent(Q.real(x),
                   Q.rational(x) | Q.irrational(x)),
        Exclusive(Q.irrational(x), Q.rational(x)),
        Implies(Q.rational(x), Q.algebraic(x)),

        # integers
        Exclusive(Q.even(x), Q.odd(x)),
        Implies(Q.integer(x), Q.rational(x)),
        Implies(Q.zero(x), Q.even(x)),
        Exclusive(Q.composite(x), Q.prime(x)),
        Implies(Q.composite(x) | Q.prime(x),
                Q.integer(x) & Q.positive(x)),
        Implies(Q.even(x) & Q.positive(x) & ~Q.prime(x), Q.composite(x)),

        # hermitian and antihermitian
        Implies(Q.real(x), Q.hermitian(x)),
        Implies(Q.imaginary(x), Q.antihermitian(x)),
        Implies(Q.zero(x),
                Q.hermitian(x) | Q.antihermitian(x)),

        # define finity and infinity, and build extended real line
        Exclusive(Q.infinite(x), Q.finite(x)),
        Implies(Q.complex(x), Q.finite(x)),
        Implies(
            Q.negative_infinite(x) | Q.positive_infinite(x), Q.infinite(x)),

        # commutativity
        Implies(Q.finite(x) | Q.infinite(x), Q.commutative(x)),

        # matrices
        Implies(Q.orthogonal(x), Q.positive_definite(x)),
        Implies(Q.orthogonal(x), Q.unitary(x)),
        Implies(Q.unitary(x) & Q.real_elements(x), Q.orthogonal(x)),
        Implies(Q.unitary(x), Q.normal(x)),
        Implies(Q.unitary(x), Q.invertible(x)),
        Implies(Q.normal(x), Q.square(x)),
        Implies(Q.diagonal(x), Q.normal(x)),
        Implies(Q.positive_definite(x), Q.invertible(x)),
        Implies(Q.diagonal(x), Q.upper_triangular(x)),
        Implies(Q.diagonal(x), Q.lower_triangular(x)),
        Implies(Q.lower_triangular(x), Q.triangular(x)),
        Implies(Q.upper_triangular(x), Q.triangular(x)),
        Implies(Q.triangular(x),
                Q.upper_triangular(x) | Q.lower_triangular(x)),
        Implies(Q.upper_triangular(x) & Q.lower_triangular(x), Q.diagonal(x)),
        Implies(Q.diagonal(x), Q.symmetric(x)),
        Implies(Q.unit_triangular(x), Q.triangular(x)),
        Implies(Q.invertible(x), Q.fullrank(x)),
        Implies(Q.invertible(x), Q.square(x)),
        Implies(Q.symmetric(x), Q.square(x)),
        Implies(Q.fullrank(x) & Q.square(x), Q.invertible(x)),
        Equivalent(Q.invertible(x), ~Q.singular(x)),
        Implies(Q.integer_elements(x), Q.real_elements(x)),
        Implies(Q.real_elements(x), Q.complex_elements(x)),
    )
    return fact
예제 #11
0
    from sympy.logic.boolalg import And

    old_sum = Sum(f, (i, a, b))

    if b != S.Infinity:
        if a == S.NegativeInfinity:
            res = _eval_sum_hyper(f.subs(i, -i), i, -b)
            if res is not None:
                return Piecewise(res, (old_sum, True))
        else:
            res1 = _eval_sum_hyper(f, i, a)
            res2 = _eval_sum_hyper(f, i, b + 1)
            if res1 is None or res2 is None:
                return None
            (res1, cond1), (res2, cond2) = res1, res2
            cond = And(cond1, cond2)
            if cond is False:
                return None
        return Piecewise((res1 - res2, cond), (old_sum, True))

    if a == S.NegativeInfinity:
        res1 = _eval_sum_hyper(f.subs(i, -i), i, 1)
        res2 = _eval_sum_hyper(f, i, 0)
        if res1 is None or res2 is None:
            return None
        res1, cond1 = res1
        res2, cond2 = res2
        cond = And(cond1, cond2)
        if cond is False:
            return None
        return Piecewise((res1 + res2, cond), (old_sum, True))
예제 #12
0
def test_And():
    assert And() is true
    assert And(A) == A
    assert And(True) is true
    assert And(False) is false
    assert And(True, True) is true
    assert And(True, False) is false
    assert And(False, False) is false
    assert And(True, A) == A
    assert And(False, A) is false
    assert And(True, True, True) is true
    assert And(True, True, A) == A
    assert And(True, False, A) is false
    assert And(1, A) == A
    raises(TypeError, lambda: And(2, A))
    raises(TypeError, lambda: And(A < 2, A))
    assert And(A < 1, A >= 1) is false
    e = A > 1
    assert And(e, e.canonical) == e.canonical
    g, l, ge, le = A > B, B < A, A >= B, B <= A
    assert And(g, l, ge, le) == And(ge, g)
    assert {And(*i) for i in permutations((l, g, le, ge))} == {And(ge, g)}
    assert And(And(Eq(a, 0), Eq(b, 0)), And(Ne(a, 0), Eq(c, 0))) is false
예제 #13
0
def test_to_anf():
    x, y, z = symbols('x,y,z')
    assert to_anf(And(x, y)) == And(x, y)
    assert to_anf(Or(x, y)) == Xor(x, y, And(x, y))
    assert to_anf(Or(Implies(x, y), And(x, y), y)) == \
            Xor(x, True, x & y, remove_true=False)
    assert to_anf(Or(Nand(x, y), Nor(x, y), Xnor(x, y), Implies(x, y))) == True
    assert to_anf(Or(x, Not(y), Nor(x,z), And(x, y), Nand(y, z))) == \
            Xor(True, And(y, z), And(x, y, z), remove_true=False)
    assert to_anf(Xor(x, y)) == Xor(x, y)
    assert to_anf(Not(x)) == Xor(x, True, remove_true=False)
    assert to_anf(Nand(x, y)) == Xor(True, And(x, y), remove_true=False)
    assert to_anf(Nor(x, y)) == Xor(x, y, True, And(x, y), remove_true=False)
    assert to_anf(Implies(x, y)) == Xor(x, True, And(x, y), remove_true=False)
    assert to_anf(Equivalent(x, y)) == Xor(x, y, True, remove_true=False)
    assert to_anf(Nand(x | y, x >> y), deep=False) == \
            Xor(True, And(Or(x, y), Implies(x, y)), remove_true=False)
    assert to_anf(Nor(x ^ y, x & y), deep=False) == \
            Xor(True, Or(Xor(x, y), And(x, y)), remove_true=False)
예제 #14
0
def test_convert_to_varsSOP():
    assert _convert_to_varsSOP([0, 1, 0], [x, y, z]) == And(Not(x), y, Not(z))
    assert _convert_to_varsSOP([3, 1, 0], [x, y, z]) == And(y, Not(z))
예제 #15
0
def test_fcode_Xlogical():
    x, y, z = symbols("x y z")
    # binary Xor
    assert fcode(Xor(x, y, evaluate=False), source_format="free") == \
        "x .neqv. y"
    assert fcode(Xor(x, Not(y), evaluate=False), source_format="free") == \
        "x .neqv. .not. y"
    assert fcode(Xor(Not(x), y, evaluate=False), source_format="free") == \
        "y .neqv. .not. x"
    assert fcode(Xor(Not(x), Not(y), evaluate=False),
                 source_format="free") == ".not. x .neqv. .not. y"
    assert fcode(Not(Xor(x, y, evaluate=False), evaluate=False),
                 source_format="free") == ".not. (x .neqv. y)"
    # binary Equivalent
    assert fcode(Equivalent(x, y), source_format="free") == "x .eqv. y"
    assert fcode(Equivalent(x, Not(y)), source_format="free") == \
        "x .eqv. .not. y"
    assert fcode(Equivalent(Not(x), y), source_format="free") == \
        "y .eqv. .not. x"
    assert fcode(Equivalent(Not(x), Not(y)), source_format="free") == \
        ".not. x .eqv. .not. y"
    assert fcode(Not(Equivalent(x, y), evaluate=False),
                 source_format="free") == ".not. (x .eqv. y)"
    # mixed And/Equivalent
    assert fcode(Equivalent(And(y, z), x), source_format="free") == \
        "x .eqv. y .and. z"
    assert fcode(Equivalent(And(z, x), y), source_format="free") == \
        "y .eqv. x .and. z"
    assert fcode(Equivalent(And(x, y), z), source_format="free") == \
        "z .eqv. x .and. y"
    assert fcode(And(Equivalent(y, z), x), source_format="free") == \
        "x .and. (y .eqv. z)"
    assert fcode(And(Equivalent(z, x), y), source_format="free") == \
        "y .and. (x .eqv. z)"
    assert fcode(And(Equivalent(x, y), z), source_format="free") == \
        "z .and. (x .eqv. y)"
    # mixed Or/Equivalent
    assert fcode(Equivalent(Or(y, z), x), source_format="free") == \
        "x .eqv. y .or. z"
    assert fcode(Equivalent(Or(z, x), y), source_format="free") == \
        "y .eqv. x .or. z"
    assert fcode(Equivalent(Or(x, y), z), source_format="free") == \
        "z .eqv. x .or. y"
    assert fcode(Or(Equivalent(y, z), x), source_format="free") == \
        "x .or. (y .eqv. z)"
    assert fcode(Or(Equivalent(z, x), y), source_format="free") == \
        "y .or. (x .eqv. z)"
    assert fcode(Or(Equivalent(x, y), z), source_format="free") == \
        "z .or. (x .eqv. y)"
    # mixed Xor/Equivalent
    assert fcode(Equivalent(Xor(y, z, evaluate=False), x),
                 source_format="free") == "x .eqv. (y .neqv. z)"
    assert fcode(Equivalent(Xor(z, x, evaluate=False), y),
                 source_format="free") == "y .eqv. (x .neqv. z)"
    assert fcode(Equivalent(Xor(x, y, evaluate=False), z),
                 source_format="free") == "z .eqv. (x .neqv. y)"
    assert fcode(Xor(Equivalent(y, z), x, evaluate=False),
                 source_format="free") == "x .neqv. (y .eqv. z)"
    assert fcode(Xor(Equivalent(z, x), y, evaluate=False),
                 source_format="free") == "y .neqv. (x .eqv. z)"
    assert fcode(Xor(Equivalent(x, y), z, evaluate=False),
                 source_format="free") == "z .neqv. (x .eqv. y)"
    # mixed And/Xor
    assert fcode(Xor(And(y, z), x, evaluate=False), source_format="free") == \
        "x .neqv. y .and. z"
    assert fcode(Xor(And(z, x), y, evaluate=False), source_format="free") == \
        "y .neqv. x .and. z"
    assert fcode(Xor(And(x, y), z, evaluate=False), source_format="free") == \
        "z .neqv. x .and. y"
    assert fcode(And(Xor(y, z, evaluate=False), x), source_format="free") == \
        "x .and. (y .neqv. z)"
    assert fcode(And(Xor(z, x, evaluate=False), y), source_format="free") == \
        "y .and. (x .neqv. z)"
    assert fcode(And(Xor(x, y, evaluate=False), z), source_format="free") == \
        "z .and. (x .neqv. y)"
    # mixed Or/Xor
    assert fcode(Xor(Or(y, z), x, evaluate=False), source_format="free") == \
        "x .neqv. y .or. z"
    assert fcode(Xor(Or(z, x), y, evaluate=False), source_format="free") == \
        "y .neqv. x .or. z"
    assert fcode(Xor(Or(x, y), z, evaluate=False), source_format="free") == \
        "z .neqv. x .or. y"
    assert fcode(Or(Xor(y, z, evaluate=False), x), source_format="free") == \
        "x .or. (y .neqv. z)"
    assert fcode(Or(Xor(z, x, evaluate=False), y), source_format="free") == \
        "y .or. (x .neqv. z)"
    assert fcode(Or(Xor(x, y, evaluate=False), z), source_format="free") == \
        "z .or. (x .neqv. y)"
    # trinary Xor
    assert fcode(Xor(x, y, z, evaluate=False), source_format="free") == \
        "x .neqv. y .neqv. z"
    assert fcode(Xor(x, y, Not(z), evaluate=False), source_format="free") == \
        "x .neqv. y .neqv. .not. z"
    assert fcode(Xor(x, Not(y), z, evaluate=False), source_format="free") == \
        "x .neqv. z .neqv. .not. y"
    assert fcode(Xor(Not(x), y, z, evaluate=False), source_format="free") == \
        "y .neqv. z .neqv. .not. x"
예제 #16
0
known_facts_cnf = And(
    Or(Q.invertible, Q.singular), Or(Not(Q.rational), Q.algebraic),
    Or(Not(Q.imaginary), Q.antihermitian), Or(Not(Q.algebraic), Q.complex),
    Or(Not(Q.imaginary), Q.complex), Or(Not(Q.real), Q.complex),
    Or(Not(Q.real_elements), Q.complex_elements),
    Or(Not(Q.infinity), Q.extended_real), Or(Not(Q.real), Q.extended_real),
    Or(Not(Q.invertible), Q.fullrank), Or(Not(Q.real), Q.hermitian),
    Or(Not(Q.even), Q.integer), Or(Not(Q.odd), Q.integer),
    Or(Not(Q.prime), Q.integer), Or(Not(Q.positive_definite), Q.invertible),
    Or(Not(Q.unitary), Q.invertible), Or(Not(Q.diagonal), Q.lower_triangular),
    Or(Not(Q.negative), Q.nonzero), Or(Not(Q.positive), Q.nonzero),
    Or(Not(Q.diagonal), Q.normal), Or(Not(Q.unitary), Q.normal),
    Or(Not(Q.prime), Q.positive), Or(Not(Q.orthogonal), Q.positive_definite),
    Or(Not(Q.integer), Q.rational), Or(Not(Q.irrational), Q.real),
    Or(Not(Q.nonzero), Q.real), Or(Not(Q.rational), Q.real),
    Or(Not(Q.integer_elements), Q.real_elements),
    Or(Not(Q.invertible), Q.square), Or(Not(Q.normal), Q.square),
    Or(Not(Q.symmetric), Q.square), Or(Not(Q.diagonal), Q.symmetric),
    Or(Not(Q.lower_triangular), Q.triangular),
    Or(Not(Q.unit_triangular), Q.triangular),
    Or(Not(Q.upper_triangular), Q.triangular), Or(Not(Q.orthogonal),
                                                  Q.unitary),
    Or(Not(Q.diagonal), Q.upper_triangular),
    Or(Not(Q.antihermitian), Not(Q.hermitian)),
    Or(Not(Q.composite), Not(Q.prime)), Or(Not(Q.even), Not(Q.odd)),
    Or(Not(Q.imaginary), Not(Q.real)), Or(Not(Q.invertible), Not(Q.singular)),
    Or(Not(Q.irrational), Not(Q.rational)), Or(Not(Q.negative),
                                               Not(Q.positive)),
    Or(Not(Q.integer), Q.even, Q.odd),
    Or(Not(Q.extended_real), Q.infinity, Q.real),
    Or(Not(Q.real), Q.irrational, Q.rational),
    Or(Not(Q.triangular), Q.lower_triangular, Q.upper_triangular),
    Or(Not(Q.nonzero), Q.negative, Q.positive),
    Or(Not(Q.lower_triangular), Not(Q.upper_triangular), Q.diagonal),
    Or(Not(Q.fullrank), Not(Q.square), Q.invertible),
    Or(Not(Q.real), Not(Q.unitary), Q.orthogonal),
    Or(Not(Q.integer), Not(Q.positive), Q.composite, Q.prime))
예제 #17
0
파일: heurisch.py 프로젝트: sunny94/sympy
def heurisch_wrapper(f,
                     x,
                     rewrite=False,
                     hints=None,
                     mappings=None,
                     retries=3,
                     degree_offset=0,
                     unnecessary_permutations=None):
    """
    A wrapper around the heurisch integration algorithm.

    This method takes the result from heurisch and checks for poles in the
    denominator. For each of these poles, the integral is reevaluated, and
    the final integration result is given in terms of a Piecewise.

    Examples
    ========

    >>> from sympy.core import symbols
    >>> from sympy.functions import cos
    >>> from sympy.integrals.heurisch import heurisch, heurisch_wrapper
    >>> n, x = symbols('n x')
    >>> heurisch(cos(n*x), x)
    sin(n*x)/n
    >>> heurisch_wrapper(cos(n*x), x)
    Piecewise((x, n == 0), (sin(n*x)/n, True))

    See Also
    ========

    heurisch
    """
    f = sympify(f)
    if x not in f.free_symbols:
        return f * x

    res = heurisch(f, x, rewrite, hints, mappings, retries, degree_offset,
                   unnecessary_permutations)
    if not isinstance(res, Basic):
        return res
    # We consider each denominator in the expression, and try to find
    # cases where one or more symbolic denominator might be zero. The
    # conditions for these cases are stored in the list slns.
    slns = []
    for d in denoms(res):
        try:
            slns += solve(d, dict=True, exclude=(x, ))
        except NotImplementedError:
            pass
    if not slns:
        return res
    slns = list(uniq(slns))
    # Remove the solutions corresponding to poles in the original expression.
    slns0 = []
    for d in denoms(f):
        try:
            slns0 += solve(d, dict=True, exclude=(x, ))
        except NotImplementedError:
            pass
    slns = [s for s in slns if s not in slns0]
    if not slns:
        return res
    if len(slns) > 1:
        eqs = []
        for sub_dict in slns:
            eqs.extend([Eq(key, value) for key, value in sub_dict.items()])
        slns = solve(eqs, dict=True, exclude=(x, )) + slns
    # For each case listed in the list slns, we reevaluate the integral.
    pairs = []
    for sub_dict in slns:
        expr = heurisch(f.subs(sub_dict), x, rewrite, hints, mappings, retries,
                        degree_offset, unnecessary_permutations)
        cond = And(*[Eq(key, value) for key, value in sub_dict.items()])
        pairs.append((expr, cond))
    pairs.append((heurisch(f, x, rewrite, hints, mappings, retries,
                           degree_offset, unnecessary_permutations), True))
    return Piecewise(*pairs)
예제 #18
0
파일: sets.py 프로젝트: stefanv/sympy
 def as_relational(self, symbol):
     """Rewrite an Intersection in terms of equalities and logic operators"""
     return And(*[set.as_relational(symbol) for set in self.args])
예제 #19
0
def test_And():
    assert And() is true
    assert And(A) == A
    assert And(True) is true
    assert And(False) is false
    assert And(True, True) is true
    assert And(True, False) is false
    assert And(False, False) is false
    assert And(True, A) == A
    assert And(False, A) is false
    assert And(True, True, True) is true
    assert And(True, True, A) == A
    assert And(True, False, A) is false
    assert And(1, A) == A
    raises(TypeError, lambda: And(2, A))
    raises(TypeError, lambda: And(A < 2, A))
    assert And(A < 1, A >= 1) is false
    e = A > 1
    assert And(e, e.canonical) == e.canonical
    g, l, ge, le = A > B, B < A, A >= B, B <= A
    assert And(g, l, ge, le) == And(l, le)
예제 #20
0
파일: sets.py 프로젝트: stefanv/sympy
 def _contains(self, other):
     from sympy.logic.boolalg import And
     return And(*[set.contains(other) for set in self.args])
예제 #21
0
def test_true_false():
    assert true is S.true
    assert false is S.false
    assert true is not True
    assert false is not False
    assert true
    assert not false
    assert true == True
    assert false == False
    assert not (true == False)
    assert not (false == True)
    assert not (true == false)

    assert hash(true) == hash(True)
    assert hash(false) == hash(False)
    assert len({true, True}) == len({false, False}) == 1

    assert isinstance(true, BooleanAtom)
    assert isinstance(false, BooleanAtom)
    # We don't want to subclass from bool, because bool subclasses from
    # int. But operators like &, |, ^, <<, >>, and ~ act differently on 0 and
    # 1 then we want them to on true and false.  See the docstrings of the
    # various And, Or, etc. functions for examples.
    assert not isinstance(true, bool)
    assert not isinstance(false, bool)

    # Note: using 'is' comparison is important here. We want these to return
    # true and false, not True and False

    assert Not(true) is false
    assert Not(True) is false
    assert Not(false) is true
    assert Not(False) is true
    assert ~true is false
    assert ~false is true

    for T, F in cartes([True, true], [False, false]):
        assert And(T, F) is false
        assert And(F, T) is false
        assert And(F, F) is false
        assert And(T, T) is true
        assert And(T, x) == x
        assert And(F, x) is false
        if not (T is True and F is False):
            assert T & F is false
            assert F & T is false
        if F is not False:
            assert F & F is false
        if T is not True:
            assert T & T is true

        assert Or(T, F) is true
        assert Or(F, T) is true
        assert Or(F, F) is false
        assert Or(T, T) is true
        assert Or(T, x) is true
        assert Or(F, x) == x
        if not (T is True and F is False):
            assert T | F is true
            assert F | T is true
        if F is not False:
            assert F | F is false
        if T is not True:
            assert T | T is true

        assert Xor(T, F) is true
        assert Xor(F, T) is true
        assert Xor(F, F) is false
        assert Xor(T, T) is false
        assert Xor(T, x) == ~x
        assert Xor(F, x) == x
        if not (T is True and F is False):
            assert T ^ F is true
            assert F ^ T is true
        if F is not False:
            assert F ^ F is false
        if T is not True:
            assert T ^ T is false

        assert Nand(T, F) is true
        assert Nand(F, T) is true
        assert Nand(F, F) is true
        assert Nand(T, T) is false
        assert Nand(T, x) == ~x
        assert Nand(F, x) is true

        assert Nor(T, F) is false
        assert Nor(F, T) is false
        assert Nor(F, F) is true
        assert Nor(T, T) is false
        assert Nor(T, x) is false
        assert Nor(F, x) == ~x

        assert Implies(T, F) is false
        assert Implies(F, T) is true
        assert Implies(F, F) is true
        assert Implies(T, T) is true
        assert Implies(T, x) == x
        assert Implies(F, x) is true
        assert Implies(x, T) is true
        assert Implies(x, F) == ~x
        if not (T is True and F is False):
            assert T >> F is false
            assert F << T is false
            assert F >> T is true
            assert T << F is true
        if F is not False:
            assert F >> F is true
            assert F << F is true
        if T is not True:
            assert T >> T is true
            assert T << T is true

        assert Equivalent(T, F) is false
        assert Equivalent(F, T) is false
        assert Equivalent(F, F) is true
        assert Equivalent(T, T) is true
        assert Equivalent(T, x) == x
        assert Equivalent(F, x) == ~x
        assert Equivalent(x, T) == x
        assert Equivalent(x, F) == ~x

        assert ITE(T, T, T) is true
        assert ITE(T, T, F) is true
        assert ITE(T, F, T) is false
        assert ITE(T, F, F) is false
        assert ITE(F, T, T) is true
        assert ITE(F, T, F) is false
        assert ITE(F, F, T) is true
        assert ITE(F, F, F) is false

    assert all(i.simplify(1, 2) is i for i in (S.true, S.false))
예제 #22
0
 def as_relational(self, x):
     from sympy.functions.elementary.integers import floor
     return And(Eq(floor(x), x), -oo < x, x < oo)
예제 #23
0
def test_issue_8777():
    assert And(x > 2, x < oo).as_set() == Interval(2, oo, left_open=True)
    assert And(x >= 1, x < oo).as_set() == Interval(1, oo)
    assert (x < oo).as_set() == Interval(-oo, oo)
    assert (x > -oo).as_set() == Interval(-oo, oo)
예제 #24
0
 def _handle_irel(self, x, handler):
     """Return either None (if the conditions of self depend only on x) else
     a Piecewise expression whose expressions (handled by the handler that
     was passed) are paired with the governing x-independent relationals,
     e.g. Piecewise((A, a(x) & b(y)), (B, c(x) | c(y)) ->
     Piecewise(
         (handler(Piecewise((A, a(x) & True), (B, c(x) | True)), b(y) & c(y)),
         (handler(Piecewise((A, a(x) & True), (B, c(x) | False)), b(y)),
         (handler(Piecewise((A, a(x) & False), (B, c(x) | True)), c(y)),
         (handler(Piecewise((A, a(x) & False), (B, c(x) | False)), True))
     """
     # identify governing relationals
     rel = self.atoms(Relational)
     irel = list(
         ordered([
             r for r in rel
             if x not in r.free_symbols and r not in (S.true, S.false)
         ]))
     if irel:
         args = {}
         exprinorder = []
         for truth in product((1, 0), repeat=len(irel)):
             reps = dict(zip(irel, truth))
             # only store the true conditions since the false are implied
             # when they appear lower in the Piecewise args
             if 1 not in truth:
                 cond = None  # flag this one so it doesn't get combined
             else:
                 andargs = Tuple(*[i for i in reps if reps[i]])
                 free = list(andargs.free_symbols)
                 if len(free) == 1:
                     from sympy.solvers.inequalities import (
                         reduce_inequalities, _solve_inequality)
                     try:
                         t = reduce_inequalities(andargs, free[0])
                         # ValueError when there are potentially
                         # nonvanishing imaginary parts
                     except (ValueError, NotImplementedError):
                         # at least isolate free symbol on left
                         t = And(*[
                             _solve_inequality(a, free[0], linear=True)
                             for a in andargs
                         ])
                 else:
                     t = And(*andargs)
                 if t is S.false:
                     continue  # an impossible combination
                 cond = t
             expr = handler(self.xreplace(reps))
             if isinstance(expr, self.func) and len(expr.args) == 1:
                 expr, econd = expr.args[0]
                 cond = And(econd, True if cond is None else cond)
             # the ec pairs are being collected since all possibilities
             # are being enumerated, but don't put the last one in since
             # its expr might match a previous expression and it
             # must appear last in the args
             if cond is not None:
                 args.setdefault(expr, []).append(cond)
                 # but since we only store the true conditions we must maintain
                 # the order so that the expression with the most true values
                 # comes first
                 exprinorder.append(expr)
         # convert collected conditions as args of Or
         for k in args:
             args[k] = Or(*args[k])
         # take them in the order obtained
         args = [(e, args[e]) for e in uniq(exprinorder)]
         # add in the last arg
         args.append((expr, True))
         # if any condition reduced to True, it needs to go last
         # and there should only be one of them or else the exprs
         # should agree
         trues = [i for i in range(len(args)) if args[i][1] is S.true]
         if not trues:
             # make the last one True since all cases were enumerated
             e, c = args[-1]
             args[-1] = (e, S.true)
         else:
             assert len(set([e for e, c in [args[i] for i in trues]])) == 1
             args.append(args.pop(trues.pop()))
             while trues:
                 args.pop(trues.pop())
         return Piecewise(*args)
예제 #25
0
def test_BooleanFunction_diff():
    assert And(x, y).diff(x) == Piecewise((0, Eq(y, False)), (1, True))
예제 #26
0
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))
    raises(NotImplementedError, lambda: X.communication_classes())
    raises(NotImplementedError, lambda: X.canonical_form())
    raises(NotImplementedError, lambda: X.decompose())

    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("Y", (1, 2, 3))],
                    Tuple(S(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, ImmutableMatrix)

    # 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 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, [S(0), '0', 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, [S(0), '0', 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.fundamental_matrix() == ImmutableMatrix(
        [[176, 81, -132], [36, 141, -52], [-44, -39, 208]]) / 125
    assert Y2.is_absorbing_chain() == True
    assert Y3.is_absorbing_chain() == False
    assert Y2.canonical_form() == ([0, 1, 2], TO2)
    assert Y3.canonical_form() == ([0, 1, 2], TO3)
    assert Y2.decompose() == ([0, 1,
                               2], TO2[0:1, 0:1], TO2[1:3, 0:1], TO2[1:3, 1:3])
    assert Y3.decompose() == ([0, 1, 2], TO3, Matrix(0, 3,
                                                     []), Matrix(0, 0, []))
    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
    assert Y4.is_ergodic() == 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.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)]])
    TO7 = Matrix([[Rational(1, 2),
                   Rational(1, 4),
                   Rational(1, 4)], [Rational(1, 2), 0,
                                     Rational(1, 2)],
                  [Rational(1, 4),
                   Rational(1, 4),
                   Rational(1, 2)]])
    Y7 = DiscreteMarkovChain('Y', trans_probs=TO7)
    assert Y7.is_absorbing_chain() == False
    assert Y7.fundamental_matrix() == ImmutableMatrix(
        [[Rational(86, 75),
          Rational(1, 25),
          Rational(-14, 75)],
         [Rational(2, 25), Rational(21, 25),
          Rational(2, 25)],
         [Rational(-14, 75),
          Rational(1, 25),
          Rational(86, 75)]])

    # test for zero-sized matrix functionality
    X = DiscreteMarkovChain('X', trans_probs=Matrix([[]]))
    assert X.number_of_states == 0
    assert X.stationary_distribution() == Matrix([[]])
    assert X.communication_classes() == []
    assert X.canonical_form() == ([], Matrix([[]]))
    assert X.decompose() == ([], Matrix([[]]), Matrix([[]]), Matrix([[]]))
    assert X.is_regular() == False
    assert X.is_ergodic() == False

    # 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 canonical form
    # see https://www.dartmouth.edu/~chance/teaching_aids/books_articles/probability_book/Chapter11.pdf
    # example 11.13
    T = Matrix([[1, 0, 0, 0, 0], [S(1) / 2, 0, S(1) / 2, 0, 0],
                [0, S(1) / 2, 0, S(1) / 2, 0], [0, 0,
                                                S(1) / 2, 0,
                                                S(1) / 2], [0, 0, 0, 0,
                                                            S(1)]])
    DW = DiscreteMarkovChain('DW', [0, 1, 2, 3, 4], T)
    states, A, B, C = DW.decompose()
    assert states == [0, 4, 1, 2, 3]
    assert A == Matrix([[1, 0], [0, 1]])
    assert B == Matrix([[S(1) / 2, 0], [0, 0], [0, S(1) / 2]])
    assert C == Matrix([[0, S(1) / 2, 0], [S(1) / 2, 0, S(1) / 2],
                        [0, S(1) / 2, 0]])
    states, new_matrix = DW.canonical_form()
    assert states == [0, 4, 1, 2, 3]
    assert new_matrix == Matrix([[1, 0, 0, 0, 0], [0, 1, 0, 0, 0],
                                 [S(1) / 2, 0, 0, S(1) / 2, 0],
                                 [0, 0, S(1) / 2, 0,
                                  S(1) / 2], [0, S(1) / 2, 0,
                                              S(1) / 2, 0]])

    # test regular and ergodic
    # https://www.dartmouth.edu/~chance/teaching_aids/books_articles/probability_book/Chapter11.pdf
    T = Matrix([[0, 4, 0, 0, 0], [1, 0, 3, 0, 0], [0, 2, 0, 2, 0],
                [0, 0, 3, 0, 1], [0, 0, 0, 4, 0]]) / 4
    X = DiscreteMarkovChain('X', trans_probs=T)
    assert not X.is_regular()
    assert X.is_ergodic()
    T = Matrix([[0, 1], [1, 0]])
    X = DiscreteMarkovChain('X', trans_probs=T)
    assert not X.is_regular()
    assert X.is_ergodic()
    # http://www.math.wisc.edu/~valko/courses/331/MC2.pdf
    T = Matrix([[2, 1, 1], [2, 0, 2], [1, 1, 2]]) / 4
    X = DiscreteMarkovChain('X', trans_probs=T)
    assert X.is_regular()
    assert X.is_ergodic()
    # https://docs.ufpr.br/~lucambio/CE222/1S2014/Kemeny-Snell1976.pdf
    T = Matrix([[1, 1], [1, 1]]) / 2
    X = DiscreteMarkovChain('X', trans_probs=T)
    assert X.is_regular()
    assert X.is_ergodic()

    # test is_absorbing_chain
    T = Matrix([[0, 1, 0], [1, 0, 0], [0, 0, 1]])
    X = DiscreteMarkovChain('X', trans_probs=T)
    assert not X.is_absorbing_chain()
    # https://en.wikipedia.org/wiki/Absorbing_Markov_chain
    T = Matrix([[1, 1, 0, 0], [0, 1, 1, 0], [1, 0, 0, 1], [0, 0, 0, 2]]) / 2
    X = DiscreteMarkovChain('X', trans_probs=T)
    assert X.is_absorbing_chain()
    T = Matrix([[2, 0, 0, 0, 0], [1, 0, 1, 0, 0], [0, 1, 0, 1, 0],
                [0, 0, 1, 0, 1], [0, 0, 0, 0, 2]]) / 2
    X = DiscreteMarkovChain('X', trans_probs=T)
    assert X.is_absorbing_chain()

    # 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)
    assert Y10.canonical_form() == ([1, 2, 3], TO2)
    assert Y10.decompose() == ([1, 2, 3], TO2[0:1, 0:1], TO2[1:3,
                                                             0:1], TO2[1:3,
                                                                       1:3])

    # 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)))

    #testing queries with multiple RandomIndexedSymbols
    T = Matrix([[Rational(5, 10),
                 Rational(3, 10),
                 Rational(2, 10)],
                [Rational(2, 10),
                 Rational(7, 10),
                 Rational(1, 10)],
                [Rational(3, 10),
                 Rational(3, 10),
                 Rational(4, 10)]])
    Y = DiscreteMarkovChain("Y", [0, 1, 2], T)
    assert P(Eq(Y[7], Y[5]), Eq(Y[2], 0)).round(5) == Float(0.44428, 5)
    assert P(Gt(Y[3], Y[1]), Eq(Y[0], 0)).round(2) == Float(0.36, 2)
    assert P(Le(Y[5], Y[10]), Eq(Y[4], 2)).round(6) == Float(0.583120, 6)
    assert Float(P(Eq(Y[10], Y[5]), Eq(Y[4], 1)),
                 14) == Float(1 - P(Ne(Y[10], Y[5]), Eq(Y[4], 1)), 14)
    assert Float(P(Gt(Y[8], Y[9]), Eq(Y[3], 2)),
                 14) == Float(1 - P(Le(Y[8], Y[9]), Eq(Y[3], 2)), 14)
    assert Float(P(Lt(Y[1], Y[4]), Eq(Y[0], 0)),
                 14) == Float(1 - P(Ge(Y[1], Y[4]), Eq(Y[0], 0)), 14)
    assert P(Eq(Y[5], Y[10]), Eq(Y[2], 1)) == P(Eq(Y[10], Y[5]), Eq(Y[2], 1))
    assert P(Gt(Y[1], Y[2]), Eq(Y[0], 1)) == P(Lt(Y[2], Y[1]), Eq(Y[0], 1))
    assert P(Ge(Y[7], Y[6]), Eq(Y[4], 1)) == P(Le(Y[6], Y[7]), Eq(Y[4], 1))

    #test symbolic queries
    a, b, c, d = symbols('a b c d')
    T = Matrix([[Rational(1, 10),
                 Rational(4, 10),
                 Rational(5, 10)],
                [Rational(3, 10),
                 Rational(4, 10),
                 Rational(3, 10)],
                [Rational(7, 10),
                 Rational(2, 10),
                 Rational(1, 10)]])
    Y = DiscreteMarkovChain("Y", [0, 1, 2], T)
    query = P(Eq(Y[a], b), Eq(Y[c], d))
    assert query.subs({
        a: 10,
        b: 2,
        c: 5,
        d: 1
    }).evalf().round(4) == P(Eq(Y[10], 2), Eq(Y[5], 1)).round(4)
    assert query.subs({
        a: 15,
        b: 0,
        c: 10,
        d: 1
    }).evalf().round(4) == P(Eq(Y[15], 0), Eq(Y[10], 1)).round(4)
    query_gt = P(Gt(Y[a], b), Eq(Y[c], d))
    query_le = P(Le(Y[a], b), Eq(Y[c], d))
    assert query_gt.subs({
        a: 5,
        b: 2,
        c: 1,
        d: 0
    }).evalf() + query_le.subs({
        a: 5,
        b: 2,
        c: 1,
        d: 0
    }).evalf() == 1
    query_ge = P(Ge(Y[a], b), Eq(Y[c], d))
    query_lt = P(Lt(Y[a], b), Eq(Y[c], d))
    assert query_ge.subs({
        a: 4,
        b: 1,
        c: 0,
        d: 2
    }).evalf() + query_lt.subs({
        a: 4,
        b: 1,
        c: 0,
        d: 2
    }).evalf() == 1

    #test issue 20078
    assert (2 * Y[1] + 3 * Y[1]).simplify() == 5 * Y[1]
    assert (2 * Y[1] - 3 * Y[1]).simplify() == -Y[1]
    assert (2 * (0.25 * Y[1])).simplify() == 0.5 * Y[1]
    assert ((2 * Y[1]) * (0.25 * Y[1])).simplify() == 0.5 * Y[1]**2
    assert (Y[1]**2 + Y[1]**3).simplify() == (Y[1] + 1) * Y[1]**2
예제 #27
0
파일: ask.py 프로젝트: skolwind/sympy
def ask(proposition, assumptions=True, context=global_assumptions):
    """
    Method for inferring properties about objects.

    **Syntax**

        * ask(proposition)

        * ask(proposition, assumptions)

            where ``proposition`` is any boolean expression

    Examples
    ========

    >>> from sympy import ask, Q, pi
    >>> from sympy.abc import x, y
    >>> ask(Q.rational(pi))
    False
    >>> ask(Q.even(x*y), Q.even(x) & Q.integer(y))
    True
    >>> ask(Q.prime(x*y), Q.integer(x) &  Q.integer(y))
    False

    **Remarks**
        Relations in assumptions are not implemented (yet), so the following
        will not give a meaningful result.

        >>> ask(Q.positive(x), Q.is_true(x > 0)) # doctest: +SKIP

        It is however a work in progress.

    """
    assumptions = And(assumptions, And(*context))
    if isinstance(proposition, AppliedPredicate):
        key, expr = proposition.func, sympify(proposition.arg)
    else:
        key, expr = Q.is_true, sympify(proposition)

    # direct resolution method, no logic
    res = key(expr)._eval_ask(assumptions)
    if res is not None:
        return res

    if assumptions is True:
        return

    local_facts = _extract_facts(assumptions, expr)
    if local_facts is None or local_facts is True:
        return

    # See if there's a straight-forward conclusion we can make for the inference
    if local_facts.is_Atom:
        if key in known_facts_dict[local_facts]:
            return True
        if Not(key) in known_facts_dict[local_facts]:
            return False
    elif local_facts.func is And and all(k in known_facts_dict
                                         for k in local_facts.args):
        for assum in local_facts.args:
            if assum.is_Atom:
                if key in known_facts_dict[assum]:
                    return True
                if Not(key) in known_facts_dict[assum]:
                    return False
            elif assum.func is Not and assum.args[0].is_Atom:
                if key in known_facts_dict[assum]:
                    return False
                if Not(key) in known_facts_dict[assum]:
                    return True
    elif (isinstance(key, Predicate) and local_facts.func is Not
          and local_facts.args[0].is_Atom):
        if local_facts.args[0] in known_facts_dict[key]:
            return False

    # Failing all else, we do a full logical inference
    return ask_full_inference(key, local_facts, known_facts_cnf)
예제 #28
0
def test_fcode_Logical():
    x, y, z = symbols("x y z")
    # unary Not
    assert fcode(Not(x), source_format="free") == ".not. x"
    # binary And
    assert fcode(And(x, y), source_format="free") == "x .and. y"
    assert fcode(And(x, Not(y)), source_format="free") == "x .and. .not. y"
    assert fcode(And(Not(x), y), source_format="free") == "y .and. .not. x"
    assert fcode(And(Not(x), Not(y)), source_format="free") == \
        ".not. x .and. .not. y"
    assert fcode(Not(And(x, y), evaluate=False), source_format="free") == \
        ".not. (x .and. y)"
    # binary Or
    assert fcode(Or(x, y), source_format="free") == "x .or. y"
    assert fcode(Or(x, Not(y)), source_format="free") == "x .or. .not. y"
    assert fcode(Or(Not(x), y), source_format="free") == "y .or. .not. x"
    assert fcode(Or(Not(x), Not(y)), source_format="free") == \
        ".not. x .or. .not. y"
    assert fcode(Not(Or(x, y), evaluate=False), source_format="free") == \
        ".not. (x .or. y)"
    # mixed And/Or
    assert fcode(And(Or(y, z), x),
                 source_format="free") == "x .and. (y .or. z)"
    assert fcode(And(Or(z, x), y),
                 source_format="free") == "y .and. (x .or. z)"
    assert fcode(And(Or(x, y), z),
                 source_format="free") == "z .and. (x .or. y)"
    assert fcode(Or(And(y, z), x), source_format="free") == "x .or. y .and. z"
    assert fcode(Or(And(z, x), y), source_format="free") == "y .or. x .and. z"
    assert fcode(Or(And(x, y), z), source_format="free") == "z .or. x .and. y"
    # trinary And
    assert fcode(And(x, y, z), source_format="free") == "x .and. y .and. z"
    assert fcode(And(x, y, Not(z)), source_format="free") == \
        "x .and. y .and. .not. z"
    assert fcode(And(x, Not(y), z), source_format="free") == \
        "x .and. z .and. .not. y"
    assert fcode(And(Not(x), y, z), source_format="free") == \
        "y .and. z .and. .not. x"
    assert fcode(Not(And(x, y, z), evaluate=False), source_format="free") == \
        ".not. (x .and. y .and. z)"
    # trinary Or
    assert fcode(Or(x, y, z), source_format="free") == "x .or. y .or. z"
    assert fcode(Or(x, y, Not(z)), source_format="free") == \
        "x .or. y .or. .not. z"
    assert fcode(Or(x, Not(y), z), source_format="free") == \
        "x .or. z .or. .not. y"
    assert fcode(Or(Not(x), y, z), source_format="free") == \
        "y .or. z .or. .not. x"
    assert fcode(Not(Or(x, y, z), evaluate=False), source_format="free") == \
        ".not. (x .or. y .or. z)"
예제 #29
0
def piecewise_simplify(expr, **kwargs):
    expr = piecewise_simplify_arguments(expr, **kwargs)
    if not isinstance(expr, Piecewise):
        return expr
    args = list(expr.args)

    _blessed = lambda e: getattr(e.lhs, '_diff_wrt', False) and (getattr(
        e.rhs, '_diff_wrt', None) or isinstance(e.rhs,
                                                (Rational, NumberSymbol)))
    for i, (expr, cond) in enumerate(args):
        # try to simplify conditions and the expression for
        # equalities that are part of the condition, e.g.
        # Piecewise((n, And(Eq(n,0), Eq(n + m, 0))), (1, True))
        # -> Piecewise((0, And(Eq(n, 0), Eq(m, 0))), (1, True))
        if isinstance(cond, And):
            eqs, other = sift(cond.args,
                              lambda i: isinstance(i, Equality),
                              binary=True)
        elif isinstance(cond, Equality):
            eqs, other = [cond], []
        else:
            eqs = other = []
        if eqs:
            eqs = list(ordered(eqs))
            for j, e in enumerate(eqs):
                # these blessed lhs objects behave like Symbols
                # and the rhs are simple replacements for the "symbols"
                if _blessed(e):
                    expr = expr.subs(*e.args)
                    eqs[j + 1:] = [ei.subs(*e.args) for ei in eqs[j + 1:]]
                    other = [ei.subs(*e.args) for ei in other]
            cond = And(*(eqs + other))
            args[i] = args[i].func(expr, cond)
    # See if expressions valid for an Equal expression happens to evaluate
    # to the same function as in the next piecewise segment, see:
    # https://github.com/sympy/sympy/issues/8458
    prevexpr = None
    for i, (expr, cond) in reversed(list(enumerate(args))):
        if prevexpr is not None:
            if isinstance(cond, And):
                eqs, other = sift(cond.args,
                                  lambda i: isinstance(i, Equality),
                                  binary=True)
            elif isinstance(cond, Equality):
                eqs, other = [cond], []
            else:
                eqs = other = []
            _prevexpr = prevexpr
            _expr = expr
            if eqs and not other:
                eqs = list(ordered(eqs))
                for e in eqs:
                    # these blessed lhs objects behave like Symbols
                    # and the rhs are simple replacements for the "symbols"
                    if _blessed(e):
                        _prevexpr = _prevexpr.subs(*e.args)
                        _expr = _expr.subs(*e.args)
            # Did it evaluate to the same?
            if _prevexpr == _expr:
                # Set the expression for the Not equal section to the same
                # as the next. These will be merged when creating the new
                # Piecewise
                args[i] = args[i].func(args[i + 1][0], cond)
            else:
                # Update the expression that we compare against
                prevexpr = expr
        else:
            prevexpr = expr
    return Piecewise(*args)
예제 #30
0
def test_bool_minterm():
    x, y = symbols('x,y')
    assert bool_minterm(3, [x, y]) == And(x, y)
    assert bool_minterm([1, 0], [x, y]) == And(Not(y), x)