def all_loopbacks(self, vars, k, heqvar=None): lvars = list(vars) vars_k = [TS.get_timed(v, k) for v in lvars] loopback = FALSE() eqvar = None heqvars = None if heqvar is not None: eqvar = Symbol(EQVAR, BOOL) heqvars = [] peqvars = FALSE() for i in range(k): vars_i = [TS.get_timed(v, i) for v in lvars] eq_k_i = And( [EqualsOrIff(vars_k[j], vars_i[j]) for j in range(len(lvars))]) if heqvar is not None: eqvar_i = TS.get_timed(eqvar, i) peqvars = Or(peqvars, eqvar_i) eq_k_i = And(eqvar_i, Iff(eqvar_i, eq_k_i)) heqvars.append(Iff(TS.get_timed(heqvar, i), peqvars)) loopback = Or(loopback, eq_k_i) if heqvar is not None: loopback = And(loopback, And(heqvars)) return loopback
def test_solving_under_assumption_theory(self): x = Symbol("x", REAL) y = Symbol("y", REAL) v1 = GT(x, Real(10)) v2 = LE(y, Real(2)) xor = Or(And(v1, Not(v2)), And(Not(v1), v2)) for name in get_env().factory.all_solvers(logic=QF_LRA): with Solver(name=name) as solver: solver.add_assertion(xor) res1 = solver.solve(assumptions=[v1, Not(v2)]) model1 = solver.get_model() res2 = solver.solve(assumptions=[Not(v1), v2]) model2 = solver.get_model() res3 = solver.solve(assumptions=[v1, v2]) self.assertTrue(res1) self.assertTrue(res2) self.assertFalse(res3) self.assertEqual(model1.get_value(v1), TRUE()) self.assertEqual(model1.get_value(v2), FALSE()) self.assertEqual(model2.get_value(v1), FALSE()) self.assertEqual(model2.get_value(v2), TRUE())
def test_get_value_of_function_bool(self): """Proper handling of models with functions with bool args.""" hr = Symbol("hr", FunctionType(REAL, [BOOL, REAL, REAL])) hb = Symbol("hb", FunctionType(BOOL, [BOOL, REAL, REAL])) hr_0_1 = Function(hr, (TRUE(), Real(0), Real(1))) hb_0_1 = Function(hb, (TRUE(), Real(0), Real(1))) hbx = Function(hb, (Symbol("x"), Real(0), Real(1))) f = GT(hr_0_1, Real(0)) g = hb_0_1 for sname in get_env().factory.all_solvers(logic=QF_UFLIRA): with Solver(name=sname) as solver: # First hr solver.add_assertion(f) res = solver.solve() self.assertTrue(res) v = solver.get_value(hr_0_1) self.assertIsNotNone(solver.get_value(v)) # Now hb solver.add_assertion(g) res = solver.solve() self.assertTrue(res) v = solver.get_value(hb_0_1) self.assertIsNotNone(v in [TRUE(), FALSE()]) # Hbx solver.add_assertion(hbx) res = solver.solve() self.assertTrue(res) v = solver.get_value(hbx) self.assertIsNotNone(v in [TRUE(), FALSE()]) # Get model model = solver.get_model() self.assertIsNotNone(model)
def test_construction(self): """Build an eager model out of a dictionary""" x, y = FreshSymbol(), FreshSymbol() d = {x: TRUE(), y: FALSE()} model = EagerModel(assignment=d) self.assertEqual(model.get_value(x), TRUE()) self.assertEqual(model.get_value(y), FALSE()) self.assertEqual(model.get_value(And(x, y)), FALSE())
def __print_single_ts(self, ts): has_comment = len(ts.comment) > 0 if has_comment: lenstr = len(ts.comment) + 3 self.write("\n%s\n" % ("-" * lenstr)) self.write("# %s\n" % ts.comment) self.write("%s\n" % ("-" * lenstr)) sections = [("VAR", [x for x in ts.vars if x not in list(ts.state_vars)+list(ts.input_vars)+list(ts.output_vars)]),\ ("STATE", ts.state_vars),\ ("INPUT", ts.input_vars),\ ("OUTPUT", ts.output_vars)] for (sname, vars) in sections: if len(vars) > 0: self.write("%s\n" % sname) for var in vars: sname = self.names(var.symbol_name()) if var.symbol_type() == BOOL: self.write("%s : Bool;\n" % (sname)) else: self.write("%s : BV(%s);\n" % (sname, var.symbol_type().width)) self.write("\n") sections = [((ts.init), "INIT"), ((ts.invar), "INVAR"), ((ts.trans), "TRANS")] for (formula, keyword) in sections: if formula not in [TRUE(), FALSE()]: self.write("%s\n" % keyword) cp = list(conjunctive_partition(formula)) if self.simplify: cp = self._simplify_cp(cp) for i in range(len(cp)): f = simplify(cp[i]) if f == TRUE(): continue self.printer(f) self.write(";\n") if f == FALSE(): break self.write("\n") if has_comment: self.write("\n%s\n" % ("-" * lenstr))
def test_simplify_exit_callin(self): spec_list = Spec.get_specs_from_string( "SPEC [CB] [EXIT] [l] void m1() |- [CI] [ENTRY] [l] void m3()") assert spec_list is not None ctrace = CTrace() cb = CCallback(1, 1, "", "void m1()", [TestGrounding._get_obj("1", "string")], None, [TestGrounding._get_fmwkov("", "void m1()", False)]) ctrace.add_msg(cb) ci = CCallin(1, 1, "", "void m3()", [TestGrounding._get_obj("1", "string")], None) cb.add_msg(ci) cb2 = CCallback(1, 1, "", "void m2()", [TestGrounding._get_obj("1", "string")], None, [TestGrounding._get_fmwkov("", "void m2()", False)]) ctrace.add_msg(cb2) ts_enc = TSEncoder(ctrace, spec_list, True) ts_enc.trace.print_trace(sys.stdout) self.assertTrue(3 == ts_enc.trace_length) ts = ts_enc.get_ts_encoding() trace_enc = ts_enc.get_trace_encoding() print trace_enc self.assertTrue(len(trace_enc) == 3) bmc = BMC(ts_enc.helper, ts, FALSE()) (step, cex, _) = bmc.simulate(trace_enc) self.assertTrue(cex is not None)
def get_valid_branches(self) -> List[bool]: """ Returns the valid branches (True, False or both) """ simplified = self.test if simplified not in [TRUE(), FALSE()]: if self.is_bool(): simplified = simplify(simplified) else: simplified = simplify(self.inequality.to_smt()) if simplified == TRUE(): return [True] elif simplified == FALSE(): return [False] else: return [True, False]
def test_z3_conversion_ite(self): with Solver(name='z3') as solver: x = Symbol('x') y = Symbol('y') f = Ite(x, y, FALSE()) solver.add_assertion(f) self.assertTrue(solver.solve())
def _get_param_assignments(self, model, time, parameters, monotonic=True): p_ass = [] fwd = False for p in parameters: # search the trace for any enabled faults ever_true = False for t in range(time + 1): p_time = model[TS.get_ptimed(p, 0)] if p.symbol_type() == BOOL: if p_time == TRUE(): ever_true = True break if ever_true: p_ass.append(p) elif not monotonic: p_ass.append(EqualsOrIff(p, FALSE())) p_ass = And(p_ass) self.region = simplify(Or(self.region, p_ass)) if self.models is None: self.models = [] self.models.append((model, time)) Logger.msg("+", 0, not (Logger.level(1))) self.cs_count += 1 Logger.log( "Found assignment \"%s\"" % (p_ass.serialize(threshold=100)), 1) return (p_ass, False)
def export_rules(self, formula): ex = self.export_expr uvars, formula = self.extract_universal(formula) precondition = None if formula.is_implies(): precondition = formula.arg(0) formula = formula.arg(1) if formula.is_equals() or formula.is_iff(): if uvars: re = {v: self._qvar_from_symbol(v) for v in uvars} formula = formula.substitute(re) uvars = re.values() uvars = set(uvars) fv = lambda phi: get_free_variables(phi) & uvars lhs, rhs = formula.args() for lhs, rhs in [(lhs, rhs), (rhs, lhs)]: if ((lhs not in uvars) and # avoid e.g. x => x + 0 fv(lhs) >= fv(rhs)): if precondition is not None: yield SExpression([ '=>', self._fresh('rule%d'), ex(Implies(precondition, formula)) ]) else: yield SExpression( ['=>', self._fresh('rule%d'), ex(lhs), ex(rhs)]) elif not (formula.is_not() and self.extract_universal(formula.args()[0])[0]): # this is either a not exp or an expr if uvars: re = {v: self._qvar_from_symbol(v) for v in uvars} formula = formula.substitute(re) uvars = re.values() uvars = set(uvars) equals_to = TRUE() if formula.is_not(): formula = formula.args()[0] equals_to = FALSE() op = '<=>' if uvars: op = '=>' if precondition is not None: yield SExpression([ op, self._fresh('rule%d'), ex(Implies(precondition, Iff(formula, equals_to))) ]) else: yield SExpression( [op, self._fresh('rule%d'), ex(formula), ex(equals_to)])
def get_mask(self, var_name): """ Returns the bitmask needed to ignore the additional unused bits used to encode the counter var_name. """ # minimum number of bits to represent max_value assert var_name in self.vars2bound max_value = self.vars2bound[var_name] bitsize = CounterEnc._get_bitsize(max_value) # construct the bitmask: we do NOT want all the models i = max_value + 1 mask = FALSE() max_value_with_bit = int(math.pow(2, bitsize)) - 1 # print "Maximum value %d" % max_value # print "Number of bits %d" % bitsize # print "max_repr_value %d" % max_value_with_bit while i <= max_value_with_bit: single_val = self.eq_val(var_name, i, True) mask = Or(mask, single_val) i = i + 1 assert (mask != None) mask = Not(mask) # TODO: get a compact representation using BDDs if (self.use_bdds): bdd_mask = self.bdd_converter.convert(mask) mask = self.bdd_converter.back(bdd_mask) return mask
def test_incremental(self): a = Symbol('a', BOOL) b = Symbol('b', BOOL) c = Symbol('c', BOOL) for name in get_env().factory.all_solvers(logic=QF_BOOL): with Solver(name) as solver: solver.add_assertion(Or(a, b)) solver.add_assertion(Or(Not(b), c)) self.assertTrue(solver.solve()) try: solver.push(1) except NotImplementedError: # if push not implemented, pop shouldn't be either self.assertRaises(NotImplementedError, solver.pop) continue solver.add_assertion(And(Not(a), Not(c))) self.assertFalse(solver.solve()) solver.pop(1) self.assertTrue(solver.solve()) solver.add_assertion(FALSE()) self.assertFalse(solver.solve()) solver.reset_assertions() solver.add_assertion(a) self.assertTrue(solver.solve())
def get_counter_value(self, var_name, model, python_model=True): """ Return the value assigned to var_name in the model """ assert var_name in self.vars2bound counter_value = 0 max_value = self.vars2bound[var_name] bitsize = CounterEnc._get_bitsize(max_value) power = 1 for i in range(bitsize): bitvar = self._get_bitvar(var_name, i) bitvar_value = model[bitvar] if (python_model): trueValue = True falseValue = False else: # pysmt model trueValue = TRUE() falseValue = FALSE() assert (bitvar_value == trueValue or bitvar_value == falseValue) if bitvar_value == trueValue: counter_value += power power = power * 2 return counter_value
def get_behavior(self, input_var, output_var): vartype = get_type(output_var) if vartype.is_bool_type(): return FALSE() assert vartype.is_bv_type() return BV(0, vartype.width)
def all_simple_loopbacks(self, vars, k): lvars = list(vars) vars_k = [TS.get_timed(v, k) for v in lvars] loopback = [] eqvar = None heqvars = None peqvars = FALSE() for i in range(k): vars_i = [TS.get_timed(v, i) for v in lvars] eq_k_i = And([EqualsOrIff(vars_k[j], vars_i[j]) for j in range(len(lvars))]) loopback.append(eq_k_i) loopback.append(FALSE()) return loopback
def test_simple_sorts(self): # (define-sort I () Int) # (define-sort Set (T) (Array T Bool)) I = INT SET = PartialType("Set", lambda t1: ArrayType(t1, BOOL)) self.assertEqual(ArrayType(INT, BOOL), SET(I)) # (declare-const s1 (Set I)) # (declare-const a I) # (declare-const b Int) s1 = FreshSymbol(SET(I)) a = FreshSymbol(I) b = FreshSymbol(INT) # (= (select s1 a) true) # (= (select s1 b) false) f1 = EqualsOrIff(Select(s1, a), TRUE()) f2 = EqualsOrIff(Select(s1, b), FALSE()) self.assertIsNotNone(f1) self.assertIsNotNone(f2) # Cannot instantiate a PartialType directly: with self.assertRaises(PysmtValueError): FreshSymbol(SET) # (declare-sort A 0) # Uninterpreted sort A = Type("A", 0) B = Type("B") c1 = FreshSymbol(A) c2 = FreshSymbol(A) c3 = FreshSymbol(Type("A")) c4 = FreshSymbol(B) EqualsOrIff(c1, c2) EqualsOrIff(c2, c3) with self.assertRaises(PysmtTypeError): EqualsOrIff(c1, c4) with self.assertRaises(PysmtValueError): Type("A", 1) C = Type("C", 1) CA = self.env.type_manager.get_type_instance(C, A) CB = self.env.type_manager.get_type_instance(C, B) c5 = FreshSymbol(CA) c6 = FreshSymbol(CB) self.assertIsNotNone(c5) with self.assertRaises(PysmtTypeError): EqualsOrIff(c5, c6) # Nesting self.env.enable_infix_notation = True ty = C(C(C(C(C(A))))) self.assertIsNotNone(FreshSymbol(ty)) pty = PartialType("pty", lambda S, T: S(S(S(S(S(T)))))) self.assertEqual(pty(C, A), ty)
def walk_bool_constant(self, formula, **kwargs): if formula == TRUE(): res = "TRUE" elif formula == FALSE(): res = "FALSE" else: res = formula.serialize() return res
def aux_yesterday(self, sig, left, t): if t > 0: y_var = sig[left, t-1] return y_var else: # y_var = And(Not(sig[left, t]), sig[left, t]) # y_var = Not(sig[left, t]) y_var = FALSE() return y_var
def Const(out, value): if value is None: return None if out.symbol_type() == BOOL: const = TRUE() if value == 1 else FALSE() else: const = BV(value, out.symbol_type().width) return (out, const)
def test_yices_push(self): with Solver(name="yices") as solver: solver.add_assertion(FALSE()) res = solver.solve() self.assertFalse(res) solver.push() solver.add_assertion(TRUE()) res = solver.solve() self.assertFalse(res) solver.pop()
def print_problem_result(pbm:NamedTuple, problems_config:ProblemsManager): status = problems_config.get_problem_status(pbm) if problems_config.has_problem_trace(pbm): traces = problems_config.get_problem_traces(pbm) else: traces = [] general_config = problems_config.general_config count = len(traces) + 1 if pbm.name is None: return (0, []) ret_status = 0 unk_k = "" if status != VerificationStatus.UNK else "\nBMC depth: %s"%pbm.bmc_length Logger.log("\n** Problem %s **"%(pbm.name), 0) if pbm.description is not None: Logger.log("Description: %s"%(pbm.description), 0) if pbm.properties is not None: Logger.log("Formula: %s"%(pbm.properties), 1) Logger.log("Result: %s%s"%(status, unk_k), 0) if pbm.verification == VerificationType.PARAMETRIC: region = problems_config.get_problem_region(pbm) if region in [TRUE(),FALSE(),None]: Logger.log("Region: %s"%(region), 0) else: Logger.log("Region:\n - %s"%(" or \n - ".join([x.serialize(threshold=100) for x in region])), 0) if (pbm.expected is not None): expected = VerificationStatus.convert(pbm.expected) Logger.log("Expected: %s"%(expected), 0) correct = VerificationStatus.compare(VerificationStatus.convert(pbm.expected), status) if not correct: Logger.log("%s != %s <<<---------| ERROR"%(status, expected), 0) ret_status = 1 assert not(general_config.force_expected and (pbm.expected is None)) prefix = pbm.trace_prefix traces_results = [] if (traces is not None) and (len(traces) > 0): if (pbm.verification == VerificationType.PARAMETRIC) and (status != VerificationStatus.FALSE): traces_results = print_traces("Execution", traces, pbm.name, prefix, count) if (pbm.verification != VerificationType.SIMULATION) and (status == VerificationStatus.FALSE): traces_results = print_traces("Counterexample", traces, pbm.name, prefix, count) if (pbm.verification == VerificationType.SIMULATION) and (status == VerificationStatus.TRUE): traces_results = print_traces("Execution", traces, pbm.name, prefix, count) if general_config.time: time = problems_config.get_problem_time(pbm) Logger.log("Time: %.2f sec"%(time), 0) return (ret_status, traces_results)
def print_problem_result(pbm, config, count=-1): if pbm.name is None: return (0, []) ret_status = 0 unk_k = "" if pbm.status != VerificationStatus.UNK else "\nBMC depth: %s" % pbm.bmc_length Logger.log("\n** Problem %s **" % (pbm.name), 0) if pbm.description is not None: Logger.log("Description: %s" % (pbm.description), 0) if pbm.formula is not None: Logger.log("Formula: %s" % (pbm.formula.serialize(threshold=100)), 1) Logger.log("Result: %s%s" % (pbm.status, unk_k), 0) if pbm.verification == VerificationType.PARAMETRIC: if pbm.region in [TRUE(), FALSE(), None]: Logger.log("Region: %s" % (pbm.region), 0) else: Logger.log( "Region:\n - %s" % (" or \n - ".join( [x.serialize(threshold=100) for x in pbm.region])), 0) if (pbm.expected is not None): expected = VerificationStatus.convert(pbm.expected) Logger.log("Expected: %s" % (expected), 0) correct = VerificationStatus.compare( VerificationStatus.convert(pbm.expected), pbm.status) if not correct: Logger.log("%s != %s <<<---------| ERROR" % (pbm.status, expected), 0) ret_status = 1 assert not (config.force_expected and (pbm.expected is None)) prefix = config.prefix if config.prefix is not None else pbm.trace_prefix traces = [] if (pbm.traces is not None) and (len(pbm.traces) > 0): if (pbm.verification == VerificationType.PARAMETRIC) and ( pbm.status != VerificationStatus.FALSE): traces = print_traces("Execution", pbm.traces, pbm.name, prefix, count) if (pbm.verification != VerificationType.SIMULATION) and ( pbm.status == VerificationStatus.FALSE): traces = print_traces("Counterexample", pbm.traces, pbm.name, prefix, count) if (pbm.verification == VerificationType.SIMULATION) and ( pbm.status == VerificationStatus.TRUE): traces = print_traces("Execution", pbm.traces, pbm.name, prefix, count) if pbm.time: Logger.log("Time: %.2f sec" % (pbm.time), 0) return (ret_status, traces)
def test_solving_under_assumption(self): v1, v2 = [FreshSymbol() for _ in xrange(2)] xor = Or(And(v1, Not(v2)), And(Not(v1), v2)) for name in get_env().factory.all_solvers(): with Solver(name=name) as solver: solver.add_assertion(xor) res1 = solver.solve(assumptions=[v1, Not(v2)]) model1 = solver.get_model() res2 = solver.solve(assumptions=[Not(v1), v2]) model2 = solver.get_model() res3 = solver.solve(assumptions=[v1, v2]) self.assertTrue(res1) self.assertTrue(res2) self.assertFalse(res3) self.assertEqual(model1.get_value(v1), TRUE()) self.assertEqual(model1.get_value(v2), FALSE()) self.assertEqual(model2.get_value(v1), FALSE()) self.assertEqual(model2.get_value(v2), TRUE())
def query_oracle(self, dip_formula): # query oracle dip_out = [] if not self.solver_oracle.solve(dip_formula): logging.critical('something is wrong with oracle circuit') exit() for l in self.oracle_cir.output_wires: if self.solver_oracle.get_py_value(Symbol(l.name)): dip_out.append(TRUE()) else: dip_out.append(FALSE()) return dip_out
def _encode_lineq(psi, s: dict, t): def _symbolic_term(term): if (term.id, t) not in s: s[(term.id, t)] = Symbol(f"{term}[{t}]", REAL) return float(term.coeff) * s[(term.id, t)] x = Plus([_symbolic_term(term) for term in psi.terms]) eq = GET_OP[psi.op](x, psi.const) if eq is False: return FALSE() elif eq is True: return TRUE() return eq
def test_simplification(self): constA, constB = String("Hello"), String("World") test_set = [ (StrLength(constA), Int(5)), (StrConcat(constA, constB), String("HelloWorld")), (StrContains(constA, String("H")), TRUE()), (StrContains(constB, String("H")), FALSE()), (StrIndexOf(constA, String("e"), Int(0)), Int(1)), (StrReplace(constA, String("l"), String(" ")), String("He lo")), (StrSubstr(constA, Int(1), Int(2)), String("el")), (StrPrefixOf(constA, constB), FALSE()), (StrPrefixOf(String("He"), constA), TRUE()), (StrSuffixOf(constA, constB), FALSE()), (StrSuffixOf(String("lo"), constB), FALSE()), (StrToInt(constA), Int(-1)), (StrToInt(String("55")), Int(55)), (IntToStr(Int(10)), String("10")), (IntToStr(Int(-1)), String("")), (StrCharAt(constA, Int(2)), String("l")), ] for (f, simplified) in test_set: self.assertEqual(f.simplify(), simplified)
def Const(out, value): invar = TRUE() if value is not None: if out.symbol_type() == BOOL: const = TRUE() if value == 1 else FALSE() else: const = BV(value, out.symbol_type().width) invar = EqualsOrIff(out, const) comment = "Const (out, val) = (" + out.symbol_name() + ", " + str(value) + ")" Logger.log(comment, 3) ts = TS(comment) ts.vars, ts.invar = set([out]), invar return ts
def _encode_ap(psi, s: dict, t): if (psi, t) not in s: s[(psi.id, t)] = Symbol(f"{psi.id}[{t}]", BOOL) eq = s[(psi.id, t)] if eq is False: # TODO: hack to encode false return FALSE() elif eq is True: # TODO: hack to encode true return TRUE() return eq
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 rewrite(self, phi, varmap): if isinstance(phi, QuantifiedFormula): return self.rewrite_quantified_formula(phi, varmap) elif isinstance(phi, Tautology): return TRUE() elif isinstance(phi, Contradiction): return FALSE() elif isinstance(phi, CompoundFormula): pysmt_fun = get_pysmt_connective(phi.connective) return pysmt_fun(*(self.rewrite(psi, varmap) for psi in phi.subformulas)) elif isinstance(phi, (Atom, CompoundTerm)): if phi.symbol.builtin: if len(phi.subterms) != 2: raise TransformationError( f"Unsupported non-binary builtin expression {phi}") lhs, rhs = (self.rewrite(psi, varmap) for psi in phi.subterms) return get_pysmt_predicate(phi.symbol.symbol)(lhs, rhs) return self.smt_fun_application(phi, varmap) # if phi.symbol in self.nested_symbols: # # Even if phi is a state variable, if its head symbol appears nested elsewhere, we'll need to deal # # with it as an uninterpreted function # return self.smt_fun_application(phi, t, subt) # # elif self.is_state_variable(phi): # # For a state variable, simply return the (possibly cached) variable corresponding to it # return self.smt_variable(phi, t) # # return self.smt_fun_application(phi, t, subt) elif isinstance(phi, Variable): if phi.symbol not in varmap: raise TransformationError( f'Free variable "{phi}" not allowed in transformation to SMT' ) return varmap[phi.symbol] elif isinstance(phi, Constant): return self.resolve_constant(phi) raise TransformationError( f"Don't know how to translate formula '{phi}'")