Repository: sympy/sympy
File: sympy/assumptions/ask.py (Python)

Code before:

        else:
            if args:
                facts.add(frozenset(args))
    return CNF(facts)

def _normalize_applied_predicates(expr):
    # Replace Q.gt(a,b) with Q.lt(b,a)
    expr = expr.replace(
        lambda e: hasattr(e, 'function') and e.function == Q.gt,
        lambda e: Q.lt(e.arguments[1], e.arguments[0])
    )
    # Replace Q.ge(a,b) with Q.le(b,a)
    expr = expr.replace(
        lambda e: hasattr(e, 'function') and e.function == Q.ge,
        lambda e: Q.le(e.arguments[1], e.arguments[0])
    )
    return expr

def _normalize_relations(expr):
    expr = expr.replace(Gt, lambda a, b: Q.lt(b, a))
    expr = expr.replace(Ge, lambda a, b: Q.le(b, a))
    expr = expr.replace(Lt, lambda a, b: Q.lt(a, b))
    expr = expr.replace(Le, lambda a, b: Q.le(a, b))
    expr = expr.replace(Eq, lambda a, b: Q.eq(a, b))
    expr = expr.replace(Ne, lambda a, b: Q.ne(a, b))
    return expr

def _normalize_expr(expr):
    expr = _normalize_relations(expr)
    expr = _normalize_applied_predicates(expr)
    return expr

def ask(proposition, assumptions=True, context=global_assumptions):
    """
    Function to evaluate the proposition with assumptions.

    Explanation
    ===========

    This function evaluates the proposition to ``True`` or ``False`` if
    the truth value can be determined. If not, it returns ``None``.

    It should be discerned from :func:`~.refine` which, when applied to a
    proposition, simplifies the argument to symbolic ``Boolean`` instead of
    Python built-in ``True``, ``False`` or ``None``.

    **Syntax**

        * ask(proposition)
            Evaluate the *proposition* in global assumption context.

Review comment (performance):
Is there a more efficient way to do multiple replaces at the same time? Having multiple replaces involves traversing the expression again each time. Furthermore, each time you replace, if there is actually something that's replaced that created a new expressions so you might unnecessarily end up creating a bunch of new expressions. 

Code after:

        else:
            if args:
                facts.add(frozenset(args))
    return CNF(facts)

def _normalize_applied_predicates(expr):
    # Replace Q.gt(a,b) with Q.lt(b,a)
    expr = expr.replace(
        lambda e: hasattr(e, 'function') and e.function == Q.gt,
        lambda e: Q.lt(e.arguments[1], e.arguments[0])
    )
    # Replace Q.ge(a,b) with Q.le(b,a)
    expr = expr.replace(
        lambda e: hasattr(e, 'function') and e.function == Q.ge,
        lambda e: Q.le(e.arguments[1], e.arguments[0])
    )
    return expr

def _normalize_relations(expr):
    def _filter(e):
        return isinstance(e, (Gt, Ge, Lt, Le, Eq, Ne))

    def _replace(e):
        a, b = e.args
        if isinstance(e, Gt):
            return Q.lt(b, a)
        elif isinstance(e, Ge):
            return Q.le(b, a)
        elif isinstance(e, Lt):
            return Q.lt(a, b)
        elif isinstance(e, Le):
            return Q.le(a, b)
        elif isinstance(e, Eq):
            return Q.eq(a, b)
        elif isinstance(e, Ne):
            return Q.ne(a, b)
        return e

    return expr.replace(_filter, _replace)


def _normalize_expr(expr):
    expr = _normalize_relations(expr)
    expr = _normalize_applied_predicates(expr)
    return expr

def ask(proposition, assumptions=True, context=global_assumptions):
    """
    Function to evaluate the proposition with assumptions.