Exemplo n.º 1
0
def get_initial_polarity_for_expression(expression: Expr,
                                        program: Program) -> (bool, bool):
    """
    Returns a sound estimate whether a given expression can initial be positive and negative. It does so
    by substituting the variable power in the given expression with all possible combination of lower and upper
    bounds of their respective supports.
    """
    variables = expression.free_symbols.intersection(program.variables)
    # First we can replace n and all variables which are deterministic initially (meaning they have exactly one branch)
    expression = expression.xreplace(
        {symbols("n", integer=True, positive=True): 0})
    for v in variables:
        if not expression.free_symbols & variables:
            continue
        if hasattr(program.initial_values[v], "branches") and len(
                program.initial_values[v].branches) == 1:
            expression = expression.subs(
                {v: program.initial_values[v].branches[0][0]})

    variables = expression.free_symbols.intersection(program.variables)
    if not variables:
        maybePos = bool(
            expression > 0) if (expression > 0).is_Boolean else True
        maybeNeg = bool(
            expression < 0) if (expression < 0).is_Boolean else True
        return maybePos, maybeNeg

    expression = expression.as_poly(variables)
    var_powers = set()
    monoms = get_monoms(expression)
    for m in monoms:
        m = m.as_poly(variables)
        powers = m.monoms()[0]
        var_powers.update([(v, p) for v, p in zip(m.gens, powers) if p > 0])
    initial_supports = get_initial_supports_for_variable_powers(
        var_powers, program)
    possible_substitutions = flatten_substitution_choices(initial_supports)
    expression = expression.as_expr()
    possible_initial_polarities = []
    for ps in possible_substitutions:
        pos = expression.subs(ps) > 0
        if pos.is_Boolean:
            possible_initial_polarities.append(bool(pos))
        else:
            possible_initial_polarities.append(None)

    allPositive = all([v is True for v in possible_initial_polarities])
    allNegative = all([v is False for v in possible_initial_polarities])

    maybePos = not allNegative
    maybeNeg = not allPositive

    return maybePos, maybeNeg
Exemplo n.º 2
0
def is_deterministic_invariant(expression: Expr) -> bool:
    """
    Checks whether an expression only containing n eventually stays <= 0
    """
    n = symbols("n", integer=True, positive=True)
    max_0 = get_max_0(expression, n)
    return expression.subs({n: max_0 + 1}) <= 0