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())
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())
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)
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])
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)
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)
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