def main(): # example = counter(4) # bmcind = BMCInduction(example[0]) # pdr = PDR(example[0]) # for prop in example[1]: # bmcind.check_property(prop) # pdr.check_property(prop) # print("") from pysmt.typing import BVType x = Symbol("x", BVType(4)) xprime = next_var(x) y = Symbol("y", BVType(4)) yprime = next_var(y) var = [x, y] nvar = [xprime, yprime] init = x.Equals(0) & y.Equals(1) print(init) trans = xprime.Equals(x.Equals(15).Ite(BV( 15, 4), x + 1)) & yprime.Equals(x + y.BVULT(y).Ite(y, x + y)) print(trans) prop = y.BVUGT(0) print(prop) system = TransitionSystem(var, init, trans) bmcind = BMCInduction(system) pdr = PDR(system) pdr.check_property(prop) bmcind.check_property(prop) print("")
def test_next(): reset_env() arrtype = ArrayType(BVType(3), BVType(4)) arr = Symbol("arr", arrtype) idx = Symbol("idx", BVType(3)) parser = StringParser() [(_, f, _)] = parser.parse_formulae(["next(arr)[idx]"]) assert (f.args()[1] == idx)
def test_btor_get_array_element(self): with Solver(name="btor") as s: x = Symbol("a", ArrayType(BVType(16), BVType(16))) s.add_assertion(Equals(Select(x, BV(1, 16)), BV(1, 16))) s.add_assertion(Equals(Select(x, BV(2, 16)), BV(3, 16))) self.assertTrue(s.solve()) self.assertEqual(s.get_value(Select(x, BV(1, 16))), BV(1, 16)) self.assertIsNotNone(s.get_value(x))
def to_sbv(self, size: int) -> SMTBitVector: cls = type(self) ufs = _uf_table[cls]['to_usbv'] if size not in ufs: name = '.'.join((cls.__name__, f'to_sbv[{size}]')) ufs[size] = shortcuts.Symbol( name, FunctionType(BVType(size), (BVType(self.size), ))) return SMTBitVector[size](ufs[size](self._value))
def scan_const8_f(scan_var_8): x69 = scan_const5 if 16 not in og_design_free_vars: og_design_free_vars[16] = Symbol("x_max_og_design", BVType(16)) x16 = og_design_free_vars[16] x70 = BV(1, 16) x71 = BVSubExtend(x16, x70) x72 = BVEqualsExtend(x69, x71) if 19 not in og_design_free_vars: og_design_free_vars[19] = Symbol("y_stride_og_design", BVType(16)) x19 = og_design_free_vars[19] x73 = BVAddExtend(scan_var_8, x19) x74 = IteExtend(x72, x73, scan_var_8) return x74
def scan_const7_f(scan_var_7): x53 = scan_const5 if 16 not in og_design_free_vars: og_design_free_vars[16] = Symbol("x_max_og_design", BVType(16)) x16 = og_design_free_vars[16] x54 = BV(1, 16) x55 = BVSubExtend(x16, x54) x56 = BVEqualsExtend(x53, x55) x57 = BV(0, 16) if 18 not in og_design_free_vars: og_design_free_vars[18] = Symbol("x_stride_og_design", BVType(16)) x18 = og_design_free_vars[18] x58 = BVAddExtend(scan_var_7, x18) x59 = IteExtend(x56, x57, x58) return x59
def counter(bit_count): """Counter example with n bits and reset signal.""" # Example Counter System (SMV-like syntax) # # VAR bits: word[bit_count]; # reset: boolean; # # INIT: bits = 0 & reset = FALSE; # # TRANS: next(bits) = bits + 1 # TRANS: next(bits = 0) <-> next(reset) from pysmt.typing import BVType bits = Symbol("bits", BVType(bit_count)) nbits = next_var(bits) reset = Symbol("r", BOOL) nreset = next_var(reset) variables = [bits, reset] init = bits.Equals(0) & Not(reset) trans = nbits.Equals(bits + 1) &\ (nbits.Equals(0)).Iff(nreset) # A true invariant property: (reset -> bits = 0) true_prop = reset.Implies(bits.Equals(0)) # A false invariant property: (bits != 2**bit_count-1) false_prop = bits.NotEquals(2**bit_count - 1) return (TransitionSystem(variables, init, trans), [true_prop, false_prop])
def _get_basic_type(self, type_name, params=None): """ Returns the pysmt type representation for the given type name. If params is specified, the type is interpreted as a function type. """ if params is None or len(params) == 0: if isinstance(type_name, tuple): assert len(type_name) == 3 assert type_name[0] == "Array" return ArrayType(self._get_basic_type(type_name[1]), self._get_basic_type(type_name[2])) if type_name == "Bool": return BOOL elif type_name == "Int": return INT elif type_name == "Real": return REAL elif type_name.startswith("BV"): size = int(type_name[2:]) return BVType(size) else: res = self.cache.get(type_name) if res is not None: res = self._get_basic_type(res) return res else: rt = self._get_basic_type(type_name) pt = [self._get_basic_type(par) for par in params] return FunctionType(rt, pt)
def __init__(self, value=SMYBOLIC, *, name=AUTOMATIC): if name is not AUTOMATIC and value is not SMYBOLIC: raise TypeError('Can only name symbolic variables') elif name is not AUTOMATIC: if not isinstance(name, str): raise TypeError('Name must be string') elif name in _name_table: raise ValueError(f'Name {name} already in use') _name_table[name] = self T = BVType(self.size) if value is SMYBOLIC: if name is AUTOMATIC: value = shortcuts.FreshSymbol(T) else: value = shortcuts.Symbol(name, T) elif isinstance(value, pysmt.fnode.FNode): t = value.get_type() if t is not T: raise TypeError(f'Expected {T} not {t}') elif isinstance(value, type(self)): value = value._value elif isinstance(value, int): value = shortcuts.BV(value, self.size) else: raise TypeError(f"Can't coerce {value} to SMTFPVector") self._name = name self._value = value
def resize_bvs(self, formula): """ Resize the bitvector variables wrt to the maximum domain size """ subs_map = {} for (fvar, max_value) in self.fvars_maxval.iteritems(): old_enc_var = self.fvars2encvars.lookup_a(fvar) bv_size = self.get_size(max_value+1) new_enc_var = FreshSymbol(BVType(bv_size)) self.fvars2encvars.add(fvar, new_enc_var) val2val = self.fvars2values[fvar] for i in range(max_value + 1): old_value = BV(i, SymbolicGrounding.MAX_BV) new_value = BV(i, bv_size) fval = val2val.lookup_b(old_value) val2val.add(fval, new_value) old_f = Equals(old_enc_var, old_value) new_f = Equals(new_enc_var, new_value) subs_map[old_f] = new_f formula = substitute(formula, subs_map) return formula
def test_normalization(self): from pysmt.environment import Environment env2 = Environment() mgr2 = env2.formula_manager ty = ArrayType(BOOL, REAL) x = FreshSymbol(ty) fty = FunctionType(BOOL, (ty, )) f = FreshSymbol(fty) g = Function(f, (x, )) self.assertIsNotNone(g) self.assertNotIn(g, mgr2) g2 = mgr2.normalize(g) self.assertIn(g2, mgr2) # Since the types are from two different environments, they # should be different. x2 = g2.arg(0) ty2 = x2.symbol_type() self.assertFalse(ty2 is ty, ty) fname = g2.function_name() fty2 = fname.symbol_type() self.assertFalse(fty2 is fty, fty) # Test ArrayValue h = Array(BVType(4), BV(0, 4)) h2 = mgr2.normalize(h) self.assertEqual(h.array_value_index_type(), h2.array_value_index_type()) self.assertFalse(h.array_value_index_type() is \ h2.array_value_index_type())
def test_btor_get_non_bool_value(self): with Solver(name="btor") as s: x = Symbol("x", BVType(16)) s.add_assertion(Equals(x, BV(1, 16))) self.assertTrue(s.solve()) self.assertEqual(s.get_value(Equals(x, BV(1, 16))), TRUE()) self.assertEqual(s.get_value(BVAdd(x, BV(1, 16))), BV(2, 16))
def scan_const15_f(scan_var_15): x31 = scan_const14 if 4 not in op_design_free_vars: op_design_free_vars[4] = Symbol("offset_op_design", BVType(16)) x4 = op_design_free_vars[4] x32 = BVAddExtend(x31, x4) return x32
def scan_const14_f(scan_var_14): x12 = scan_const10 if 16 not in op_design_free_vars: op_design_free_vars[16] = Symbol("x_max_op_design", BVType(16)) x16 = op_design_free_vars[16] x34 = BV(1, 16) x35 = BVSubExtend(x16, x34) x36 = BVEqualsExtend(x12, x35) if 19 not in op_design_free_vars: op_design_free_vars[19] = Symbol("y_stride_op_design", BVType(16)) x19 = op_design_free_vars[19] if 18 not in op_design_free_vars: op_design_free_vars[18] = Symbol("x_stride_op_design", BVType(16)) x18 = op_design_free_vars[18] x37 = IteExtend(x36, x19, x18) x38 = BVAddExtend(scan_var_14, x37) return x38
def walk_bv_to_bv(self, formula, args, **kwargs): #pylint: disable=unused-argument # We check that all children are BV and the same size target_bv_type = BVType(formula.bv_width()) for a in args: if not a == target_bv_type: return None return target_bv_type
def walk_bv_rotate(self, formula, args, **kwargs): #pylint: disable=unused-argument target_width = formula.bv_width() if target_width < formula.bv_rotation_step() or target_width < 0: return None if target_width != args[0].width: return None return BVType(target_width)
def _define_var(self, varname, vartype): if vartype == T_BOOL: return Symbol(varname, BOOL) if vartype[0] == T_BV: vartype, size = vartype[0], vartype[1] return Symbol(varname, BVType(int(size))) Logger.error("Unsupported type: %s" % vartype)
def scan_const9_f(scan_var_9): x48 = scan_const7 x49 = scan_const8 x50 = BVAddExtend(x48, x49) if 4 not in og_design_free_vars: og_design_free_vars[4] = Symbol("offset_og_design", BVType(16)) x4 = og_design_free_vars[4] x51 = BVAddExtend(x50, x4) return x51
def _get_type(self, strtype): (vartype, size) = strtype if vartype == T_BV: return BVType(int(size[0])) if vartype == T_BOOL: return BOOL Logger.error("Unsupported type: %s" % vartype)
def _define_var(self, var, prefix=""): varname, (vartype, size) = var fullname = self._concat_names(prefix, varname) if vartype == T_BV: return Symbol(fullname, BVType(int(size[0]))) if vartype == T_BOOL: return Symbol(fullname, BOOL) Logger.error("Unsupported type: %s" % vartype)
def scan_const5_f(scan_var_5): if 16 not in og_design_free_vars: og_design_free_vars[16] = Symbol("x_max_og_design", BVType(16)) x16 = og_design_free_vars[16] x76 = BV(1, 16) x77 = BVSubExtend(x16, x76) x78 = BVEqualsExtend(scan_var_5, x77) x79 = BV(0, 16) x80 = BV(1, 16) x81 = BVAddExtend(scan_var_5, x80) x82 = IteExtend(x78, x79, x81) return x82
def is_bv_constant(self, value=None, width=None): """Test whether the formula is a BitVector constant. Optionally, check that the constant has the given value. """ if value is None and width is None: return self.node_type() == BV_CONSTANT if width is None: return self.is_constant(value=value) else: return self.is_constant(_type=BVType(width=width), value=value)
def scan_const10_f(scan_var_10): if 16 not in op_design_free_vars: op_design_free_vars[16] = Symbol("x_max_op_design", BVType(16)) x16 = op_design_free_vars[16] x40 = BV(1, 16) x41 = BVSubExtend(x16, x40) x42 = BVEqualsExtend(scan_var_10, x41) x43 = BV(0, 16) x44 = BV(1, 16) x45 = BVAddExtend(scan_var_10, x44) x46 = IteExtend(x42, x43, x45) return x46
def constant_type(self): """Return the type of the Constant.""" if self.node_type() == INT_CONSTANT: return INT elif self.node_type() == REAL_CONSTANT: return REAL elif self.node_type() == BOOL_CONSTANT: return BOOL else: assert self.node_type() == BV_CONSTANT,\ "Unsupported method constant_type '%s'" % self return BVType(width=self.bv_width())
def test_bv_div_by_zero(self): mgr = self.env.formula_manager bvx = mgr.Symbol("bv", BVType(8)) bvy = mgr.Symbol("dividend", BVType(8)) fudiv = mgr.Equals(mgr.BVUDiv(bvx, mgr.BV(0, 8)), mgr.BV(255, 8)) self.assertValid(fudiv) fsdiv = mgr.Equals( mgr.BVSDiv(bvx, mgr.BV(0, 8)), mgr.Ite(mgr.BVSGE(bvx, mgr.BV(0, 8)), mgr.BV(255, 8), mgr.BV(1, 8))) self.assertValid(fsdiv) furem = mgr.Equals(mgr.BVURem(bvx, mgr.BV(0, 8)), bvx) self.assertValid(furem) fsrem = mgr.Equals(mgr.BVSRem(bvx, mgr.BV(0, 8)), bvx) self.assertValid(fsrem) # Repeat tests with symbolic dividend fudiv = mgr.Implies(mgr.Equals(bvy, mgr.BV(0, 8)), mgr.Equals(mgr.BVUDiv(bvx, bvy), mgr.BV(255, 8))) self.assertValid(fudiv) fsdiv = mgr.Implies( mgr.Equals(bvy, mgr.BV(0, 8)), mgr.Equals( mgr.BVSDiv(bvx, mgr.BV(0, 8)), mgr.Ite(mgr.BVSGE(bvx, mgr.BV(0, 8)), mgr.BV(255, 8), mgr.BV(1, 8)))) self.assertValid(fsdiv) furem = mgr.Implies(mgr.Equals(bvy, mgr.BV(0, 8)), mgr.Equals(mgr.BVURem(bvx, mgr.BV(0, 8)), bvx)) self.assertValid(furem) fsrem = mgr.Implies(mgr.Equals(bvy, mgr.BV(0, 8)), mgr.Equals(mgr.BVSRem(bvx, mgr.BV(0, 8)), bvx)) self.assertValid(fsrem)
def walk_bv_concat(self, formula, args, **kwargs): # Width of BV operators are computed at construction time. # The type-checker only verifies that they are indeed # correct. try: l_width = args[0].width r_width = args[1].width target_width = formula.bv_width() except AttributeError: return None if not l_width + r_width == target_width: return None return BVType(target_width)
def __init_subclass__(cls): _uf_table[cls] = ufs = dict() T = BVType(cls.size) for method_name, *args in _SIGS: args = [T if x is None else x for x in args] rtype = args[-1] params = args[:-1] name = '.'.join((cls.__name__, method_name)) ufs[method_name] = shortcuts.Symbol(name, FunctionType(rtype, params)) ufs['to_sbv'] = dict() ufs['to_ubv'] = dict()
def __get_value(self, value): if value == T_FALSE: return (FALSE(), BOOL) if value == T_TRUE: return (TRUE(), BOOL) if T_US in value: width = int(value.split(T_US)[1]) value = int(value.split(T_US)[0]) else: width = len(value) * 4 value = int(("0x%s" % value).lower(), 0) return (BV(value, width), BVType(width))
def test_basic_types(self): self.assertTrue(BOOL.is_bool_type()) self.assertFalse(BOOL.is_function_type()) self.assertTrue(REAL.is_real_type()) self.assertFalse(REAL.is_bool_type()) self.assertTrue(INT.is_int_type()) self.assertFalse(INT.is_real_type()) ftype = FunctionType(REAL, [REAL, REAL]) self.assertTrue(ftype.is_function_type()) self.assertFalse(ftype.is_int_type()) self.assertNotEqual(BOOL, INT) self.assertEqual(REAL, REAL) AAIBR = ArrayType(ArrayType(INT, BOOL), REAL) self.assertEqual(str(AAIBR), "Array{Array{Int, Bool}, Real}") bt1 = BVType(4) bt2 = BVType(4) self.assertEqual(bt1, bt2) self.assertEqual(bt1.width, 4)
def walk_bv_extract(self, formula, args, **kwargs): arg = args[0] if not arg.is_bv_type(): return None base_width = arg.width target_width = formula.bv_width() start = formula.bv_extract_start() end = formula.bv_extract_end() if start >= base_width or end >= base_width: return None if base_width < target_width: return None if target_width != (end - start + 1): return None return BVType(target_width)