Exemple #1
0
    def test_times_algebraic(self):
        from pysmt.constants import Numeral
        env = get_env()
        mgr = env.formula_manager
        r0 = Symbol("r0", REAL)
        p_2 = Real(2)
        m_5 = mgr._Algebraic(Numeral(-5))
        m_10 = mgr._Algebraic(Numeral(-10))

        # -5 * r0 * 2
        expr = Times(m_5, r0, p_2)
        res = expr.simplify()
        self.assertValid(Equals(expr, res))
        self.assertIn(m_10, res.args())
Exemple #2
0
    def test_plus_algebraic(self):
        from pysmt.constants import Numeral
        env = get_env()
        mgr = env.formula_manager
        r0 = Symbol("r0", REAL)
        p_2 = Real(2)
        m_5 = mgr._Algebraic(Numeral(-5))
        m_3 = mgr._Algebraic(Numeral(-3))

        # r0 + 2 - 5
        expr = Plus(r0, p_2, m_5)
        res = expr.simplify()
        self.assertValid(Equals(expr, res))
        self.assertIn(m_3, res.args())
Exemple #3
0
    def walk_minus(self, formula, args, **kwargs):
        assert len(args) == 2

        sl = args[0]
        sr = args[1]

        if sl.is_real_constant() and sr.is_real_constant():
            l = sl.constant_value()
            r = sr.constant_value()
            return self.manager.Real(l - r)

        if sl.is_int_constant() and sr.is_int_constant():
            l = sl.constant_value()
            r = sr.constant_value()
            return self.manager.Int(l - r)

        if sl.is_algebraic_constant() and \
           sr.is_algebraic_constant():
            from pysmt.constants import Numeral
            l = sl.constant_value()
            r = sr.constant_value()
            return self.mananger._Algebraic(Numeral(l - r))

        if sr.is_constant() and sr.is_zero():
            return sl

        if sl == sr:
            if self.env.stc.walk(sl) == types.REAL:
                return self.manager.Real(0)
            else:
                return self.manager.Int(0)

        return self.manager.Minus(sl, sr)
Exemple #4
0
    def walk_pow(self, formula, args, **kwargs):
        if args[0].is_real_constant():
            l = args[0].constant_value()
            r = args[1].constant_value()
            return self.manager.Real(l**r)

        if args[0].is_int_constant():
            l = args[0].constant_value()
            r = args[1].constant_value()
            return self.manager.Int(l**r)

        if args[0].is_algebraic_constant():
            from pysmt.constants import Numeral
            l = args[0].constant_value()
            r = args[1].constant_value()
            return self.manager._Algebraic(Numeral(l**r))

        return self.manager.Pow(args[0], args[1])
Exemple #5
0
    def walk_times(self, formula, args, **kwargs):
        new_args = []
        constant_mul = 1
        stack = list(args)
        ttype = self.env.stc.get_type(args[0])
        is_algebraic = False
        while len(stack) > 0:
            x = stack.pop()
            if x.is_constant():
                if x.is_algebraic_constant():
                    is_algebraic = True
                if x.is_zero():
                    constant_mul = 0
                    break
                else:
                    constant_mul *= x.constant_value()
            elif x.is_times():
                stack += x.args()
            else:
                new_args.append(x)

        const = None
        if is_algebraic:
            from pysmt.constants import Numeral
            const = self.manager._Algebraic(Numeral(constant_mul))
        elif ttype.is_real_type():
            const = self.manager.Real(constant_mul)
        else:
            assert ttype.is_int_type()
            const = self.manager.Int(constant_mul)

        if const.is_zero():
            return const
        else:
            if len(new_args) == 0:
                return const
            elif not const.is_one():
                new_args.append(const)

        new_args = sorted(new_args, key=FNode.node_id)
        return self.manager.Times(new_args)
Exemple #6
0
    def _back_single_term(self, expr, args, model=None):
        assert z3.is_expr(expr)

        if z3.is_quantifier(expr):
            raise NotImplementedError(
                "Quantified back conversion is currently not supported")

        assert not len(args) > 2 or \
            (z3.is_and(expr) or z3.is_or(expr) or
             z3.is_add(expr) or z3.is_mul(expr) or
             (len(args) == 3 and (z3.is_ite(expr) or z3.is_array_store(expr)))),\
            "Unexpected n-ary term: %s" % expr

        res = None
        try:
            decl = z3.Z3_get_app_decl(expr.ctx_ref(), expr.as_ast())
            kind = z3.Z3_get_decl_kind(expr.ctx.ref(), decl)
            # Try to get the back-conversion function for the given Kind
            fun = self._back_fun[kind]
            return fun(args, expr)
        except KeyError as ex:
            pass

        if z3.is_const(expr):
            # Const or Symbol
            if z3.is_rational_value(expr):
                n = expr.numerator_as_long()
                d = expr.denominator_as_long()
                f = Fraction(n, d)
                return self.mgr.Real(f)
            elif z3.is_int_value(expr):
                n = expr.as_long()
                return self.mgr.Int(n)
            elif z3.is_bv_value(expr):
                n = expr.as_long()
                w = expr.size()
                return self.mgr.BV(n, w)
            elif z3.is_as_array(expr):
                if model is None:
                    raise NotImplementedError("As-array expressions cannot be" \
                                              " handled as they are not " \
                                              "self-contained")
                else:
                    interp_decl = z3.get_as_array_func(expr)
                    interp = model[interp_decl]
                    default = self.back(interp.else_value(), model=model)
                    assign = {}
                    for i in xrange(interp.num_entries()):
                        e = interp.entry(i)
                        assert e.num_args() == 1
                        idx = self.back(e.arg_value(0), model=model)
                        val = self.back(e.value(), model=model)
                        assign[idx] = val
                    arr_type = self._z3_to_type(expr.sort())
                    return self.mgr.Array(arr_type.index_type, default, assign)
            elif z3.is_algebraic_value(expr):
                # Algebraic value
                return self.mgr._Algebraic(Numeral(expr))
            else:
                # it must be a symbol
                try:
                    return self.mgr.get_symbol(str(expr))
                except UndefinedSymbolError:
                    import warnings
                    symb_type = self._z3_to_type(expr.sort())
                    warnings.warn("Defining new symbol: %s" % str(expr))
                    return self.mgr.FreshSymbol(symb_type, template="__z3_%d")
        elif z3.is_function(expr):
            # This needs to be after we try to convert regular Symbols
            fsymbol = self.mgr.get_symbol(expr.decl().name())
            return self.mgr.Function(fsymbol, args)

        # If we reach this point, we did not manage to translate the expression
        raise ConvertExpressionError(message=("Unsupported expression: %s" %
                                              (str(expr))),
                                     expression=expr)
Exemple #7
0
    def walk_plus(self, formula, args, **kwargs):
        to_sum = []
        to_sub = []
        constant_add = 0
        stack = list(args)
        ttype = self.env.stc.get_type(args[0])
        is_algebraic = False
        while len(stack) > 0:
            x = stack.pop()
            if x.is_constant():
                if x.is_algebraic_constant():
                    is_algebraic = True
                constant_add += x.constant_value()
            elif x.is_plus():
                stack += x.args()
            elif x.is_minus():
                to_sum.append(x.arg(0))
                to_sub.append(x.arg(1))
            elif x.is_times() and x.args()[-1].is_constant():
                const = x.args()[-1]
                const_val = const.constant_value()
                if const_val < 0:
                    new_times = list(x.args()[:-1])
                    if const_val != -1:
                        const_val = -const_val
                        if const.is_algebraic_constant():
                            from pysmt.constants import Numeral
                            const = self.manager._Algebraic(Numeral(const_val))
                        elif ttype.is_real_type():
                            const = self.manager.Real(const_val)
                        else:
                            assert ttype.is_int_type()
                            const = self.manager.Int(const_val)
                        new_times.append(const)
                    new_times = self.manager.Times(new_times)
                    to_sub.append(new_times)
                else:
                    to_sum.append(x)
            else:
                to_sum.append(x)

        const = None
        if is_algebraic:
            from pysmt.constants import Numeral
            const = self.manager._Algebraic(Numeral(constant_add))
        elif ttype.is_real_type():
            const = self.manager.Real(constant_add)
        else:
            assert ttype.is_int_type()
            const = self.manager.Int(constant_add)

        if len(to_sum) == 0 and len(to_sub) == 0:
            return const
        if not const.is_zero():
            to_sum.append(const)

        assert to_sum or to_sub

        res = self.manager.Plus(to_sum) if to_sum else None

        if to_sub:
            sub = self.manager.Plus(to_sub)
            if res:
                res = self.manager.Minus(res, sub)
            else:
                if ttype.is_int_type():
                    m_1 = self.manager.Int(-1)
                else:
                    assert ttype.is_real_type()
                    m_1 = self.manager.Real(-1)
                res = self.manager.Times(m_1, sub)
        return res