def solve_safety_inc_bwd(self, hts, prop, k, assert_property=False): self._reset_assertions(self.solver) if TS.has_next(prop): Logger.error( "Invariant checking with next variables only supports FWD strategy" ) init = hts.single_init() trans = hts.single_trans() invar = hts.single_invar() formula = self.at_ptime(And(Not(prop), invar), -1) Logger.log("Add not property at time %d" % 0, 2) self._add_assertion(self.solver, formula) t = 0 while (t < k + 1): self._push(self.solver) pinit = self.at_ptime(init, t - 1) Logger.log("Add init at time %d" % t, 2) self._add_assertion(self.solver, pinit) if self._solve(self.solver): Logger.log("Counterexample found with k=%s" % (t), 1) model = self._get_model(self.solver) return (t, model) else: Logger.log("No counterexample found with k=%s" % (t), 1) Logger.msg(".", 0, not (Logger.level(1))) self._pop(self.solver) trans_t = self.unroll(trans, invar, t, t + 1) self._add_assertion(self.solver, trans_t) if assert_property and t > 0: prop_t = self.unroll(TRUE(), prop, t - 1, t) self._add_assertion(self.solver, prop_t) Logger.log("Add property at time %d" % t, 2) t += 1 return (t - 1, None)
def test_iss171(self): auto_env = AutoEnv(get_env(), False) auto = Automaton(auto_env) s0 = auto._add_new_state(True, True) s1 = auto._add_new_state(False, False) s2 = auto._add_new_state(False, True) l1 = auto_env.new_label(Symbol('l1')) true_label = auto_env.new_label(TRUE()) auto._add_trans(s0, s1, l1) auto._add_trans(s0, s2, l1) auto._add_trans(s1, s2, true_label) auto._add_trans(s1, s2, true_label) auto.klenee_star()
def test_3(self): # need 2 bits var_name = "counter_3" self.enc.add_var(var_name, 3) b0 = self.enc._get_bitvar(var_name,0) b1 = self.enc._get_bitvar(var_name,1) e = self.enc.eq_val(var_name, 0) self._is_eq(e, And(Not(b0), Not(b1))) e = self.enc.eq_val(var_name, 1) self._is_eq(e, And(b0, Not(b1))) e = self.enc.eq_val(var_name, 2) self._is_eq(e, And(Not(b0), b1)) e = self.enc.eq_val(var_name, 3) self._is_eq(e, And(b0, b1)) mask = self.enc.get_mask(var_name) self._is_eq(mask, TRUE())
def normalize(self, new_support, conjoin_old_support=True, paths=True): # type: (FNode, bool, bool) -> Optional[FNode] if not os.path.exists(XaddEngine.path()): raise RuntimeError( "The XADD engine requires the XADD library JAR file which is currently not installed." ) if conjoin_old_support: new_support = self.support & new_support with self.temp_file() as f: with TemporaryFile() as f2: Density(self.domain, new_support, Real(1.0)).to_file(f2) with TemporaryFile() as f3: Density(self.domain, TRUE(), Real(1.0)).to_file(f3) try: cmd_args = [ "java", "-jar", XaddEngine.path(), "normalize", f, f2, "-p" if paths else "-t", f3, ] logger.info("> {}".format(" ".join(cmd_args))) output = subprocess.check_output( cmd_args, timeout=self.timeout).decode(sys.stdout.encoding) # print(output.replace("Academic license - for non-commercial use only\n", "")) return XaddEngine.import_normalized(f3) except subprocess.CalledProcessError as e: logger.warning(e.output) raise except subprocess.TimeoutExpired: logger.warning("Timeout") except ValueError: logger.warning(output) raise return None
def simulate(self, prop, k): if self.config.strategy == VerificationStrategy.NU: self._init_at_time(self.hts.vars, 1) (t, model) = self.sim_no_unroll(self.hts, prop, k) else: self._init_at_time(self.hts.vars, k) if prop == TRUE(): (t, model) = self.solve_safety_fwd(self.hts, Not(prop), k, k) else: (t, model) = self.solve_safety(self.hts, Not(prop), k) model = self._remap_model(self.hts.vars, model, t) if (t > -1) and (model is not None): Logger.log("Execution found", 1) trace = self.generate_trace(model, t, get_free_variables(prop)) return (VerificationStatus.TRUE, trace) else: Logger.log("Deadlock with k=%s"%k, 1) return (VerificationStatus.FALSE, None)
def __print_single_hts(self, hts, printed_vars): has_comment = len(hts.comment) > 0 if has_comment: lenstr = len(hts.comment) + 3 self.write("\n%s\n" % ("-" * lenstr)) self.write("-- %s\n" % hts.comment) self.write("%s\n" % ("-" * lenstr)) locvars = [v for v in hts.vars if v not in printed_vars] for v in hts.vars: printed_vars.add(v) if locvars: self.write("\nVAR\n") for var in locvars: sname = self.names(var.symbol_name()) if var.symbol_type() == BOOL: self.write("%s : boolean;\n" % (sname)) else: self.write("%s : word[%s];\n" % (sname, var.symbol_type().width)) sections = [((hts.init), "INIT"), ((hts.invar), "INVAR"), ((hts.trans), "TRANS")] for (formula, keyword) in sections: if formula not in [TRUE(), FALSE()]: self.write("\n%s\n" % keyword) cp = list(conjunctive_partition(formula)) for i in range(len(cp)): f = simplify(cp[i]) self.printer(f) if i < len(cp) - 1: self.write(" &\n") self.write(";\n") if has_comment: self.write("\n%s\n" % ("-" * lenstr)) return printed_vars
def test_incrementality(self): with Portfolio(["cvc4", "msat", "yices"], logic=QF_UFLIRA, environment=self.env, incremental=True, generate_models=True) as s: x, y = Symbol("x"), Symbol("y") s.add_assertion(Implies(x, y)) s.push() s.add_assertion(x) res = s.solve() self.assertTrue(res) v = s.get_value(y) self.assertTrue(v, TRUE()) s.pop() s.add_assertion(x) res = s.solve() self.assertTrue(res) v = s.get_value(x) self.assertTrue(v, FALSE())
def check_property(self, prop): """Property Directed Reachability approach without optimizations.""" print("Checking property %s..." % prop) while True: cube = self.get_bad_state(prop) if cube is not None: # Blocking phase of a bad state if self.recursive_block(cube): print("--> Bug found at step %d" % (len(self.frames))) break else: print(" [PDR] Cube blocked '%s'" % str(cube)) else: # Checking if the last two frames are equivalent i.e., are inductive if self.inductive(): print("--> The system is safe!") break else: print(" [PDR] Adding frame %d..." % (len(self.frames))) self.frames.append(TRUE())
def loop_free(self, vars_, k_end, k_start=0): Logger.log("Simple path from %s to %s"%(k_start, k_end), 2) if k_end == k_start: return TRUE() def not_eq_states(vars1, vars2): assert len(vars1) == len(vars2) eqvars = [] for i in range(len(vars1)): eqvars.append(EqualsOrIff(vars1[i], vars2[i])) return Not(And(eqvars)) lvars = list(vars_) end_vars = [TS.get_timed(v, k_end) for v in lvars] formula = [] for t in range(k_start, k_end, 1): formula.append(not_eq_states(end_vars, [TS.get_timed(v, t) for v in lvars])) return And(formula)
def add_negatives(domain, data, labels, thresholds, sample_count, background_knowledge=None, distance_measure=None): # type: (Domain, np.ndarray, np.ndarray, Dict, int, FNode, Any) -> Tuple[np.ndarray, np.ndarray] new_data = uniform(domain, sample_count) background_knowledge = background_knowledge or TRUE() supported_indices = evaluate(domain, background_knowledge, new_data) boolean_indices = [ i for i, v in enumerate(domain.variables) if domain.is_bool(v) ] real_indices = [ i for i, v in enumerate(domain.variables) if domain.is_real(v) ] for j in range(new_data.shape[0]): valid_negative = True for i in range(data.shape[0]): # noinspection PyTypeChecker if labels[i] and all( data[i, boolean_indices] == new_data[j, boolean_indices]): in_range = True for ri, v in zip(real_indices, domain.real_vars): t = thresholds[v] if isinstance( thresholds, dict) else thresholds[i, ri] if abs(data[i, ri] - new_data[j, ri]) > t: in_range = False break valid_negative = valid_negative and (not in_range) if not valid_negative: break supported_indices[j] = supported_indices[j] and valid_negative new_data = new_data[supported_indices == 1, :] return np.concatenate([data, new_data], axis=0), np.concatenate( [labels, np.zeros(new_data.shape[0])])
def __print_single_ts(self, ts, printed_vars): 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)) locvars = [v for v in ts.vars if v not in printed_vars] for v in ts.vars: printed_vars.add(v) if locvars: self.write("\nVAR\n") for var in locvars: self.write("{} : {};\n".format(var.symbol_name(), to_smv_type(var.get_type()))) sections = [((ts.init), "INIT"), ((ts.invar), "INVAR"), ((ts.trans), "TRANS")] for (formula, keyword) in sections: if formula not in [TRUE(), FALSE()]: self.write("\n%s\n" % keyword) cp = list(conjunctive_partition(formula)) for i in range(len(cp)): f = simplify(cp[i]) self.printer(f) if i < len(cp) - 1: self.write(" &\n") self.write(";\n") if has_comment: self.write("\n%s\n" % ("-" * lenstr)) return printed_vars
def set_axiom_formula(self, unbounded): axiomS = [] for cl in self._faxioms: if unbounded: cl = self.system.replaceDefinitions(cl, 1) axiomS.append(cl) for cl in self.system.curr._axiom: if unbounded: cl = self.system.replaceDefinitions(cl, 1) axiomS.append(cl) if True or (not unbounded): for k, v in self.system.curr._definitions.items(): axiomS.append(v) if len(self.system._sort2fin) == len(self.system._sorts): if self.ordered == "zero": cl = self.system.get_ordered_zero() axiomS.append(cl) if self.ordered == "partial": cl = self.system.get_ordered_le() axiomS.append(cl) # assert(0) if self.quorums != "none": cl = self.system.get_quorum_axiom() axiomS.append(cl) # assert(0) if not axiomS: res = TRUE() else: res = And(axiomS) res = self.get_formula_qf(res) self._axiom_formula = res return res
def test_enum_trans(self): env = AutoEnv.get_global_auto_env() solver = env.sat_solver symbols = [Symbol(chr(i), BOOL) for i in range(ord('a'), ord('z') + 1)] false_label = env.new_label(FALSE()) true_label = env.new_label(TRUE()) a = env.new_label(symbols[0]) b = env.new_label(symbols[1]) c = env.new_label(symbols[2]) a_and_b = a.intersect(b) results = Automaton.enum_trans([false_label], env.sat_solver) self.assertTrue(len(results) == 1) results = Automaton.enum_trans([true_label], env.sat_solver) self.assertTrue(len(results) == 1) results = Automaton.enum_trans([a, b, c], env.sat_solver) self.assertTrue(len(results) == 8) results = Automaton.enum_trans([a, b, a_and_b], env.sat_solver) self.assertTrue(len(results) == 4)
def _build_trace(self, model, steps): """Extract the trace from the satisfying assignment.""" vars_to_use = [self.ts.state_vars, self.ts.input_vars] cex = [] for i in range(steps + 1): if (i not in self.helper.time_memo): self.helper.get_formula_at_i(self.all_vars, TRUE(), i) cex_i = {} # skip the input variables in the last step if (i >= steps): vars_to_use = [self.ts.state_vars] for vs in vars_to_use: for var in vs: assert var is not None var_i = self.helper.get_var_at_time(var, i) assert var_i is not None cex_i[var] = model.get_py_value(var_i, True) cex.append(cex_i) return cex
def get_full_example_formulae(environment=None): """Return a list of Examples using the given environment.""" if environment is None: environment = get_env() with environment: x = Symbol("x", BOOL) y = Symbol("y", BOOL) p = Symbol("p", INT) q = Symbol("q", INT) r = Symbol("r", REAL) s = Symbol("s", REAL) aii = Symbol("aii", ARRAY_INT_INT) ari = Symbol("ari", ArrayType(REAL, INT)) arb = Symbol("arb", ArrayType(REAL, BV8)) abb = Symbol("abb", ArrayType(BV8, BV8)) nested_a = Symbol("a_arb_aii", ArrayType(ArrayType(REAL, BV8), ARRAY_INT_INT)) rf = Symbol("rf", FunctionType(REAL, [REAL, REAL])) rg = Symbol("rg", FunctionType(REAL, [REAL])) ih = Symbol("ih", FunctionType(INT, [REAL, INT])) ig = Symbol("ig", FunctionType(INT, [INT])) bf = Symbol("bf", FunctionType(BOOL, [BOOL])) bg = Symbol("bg", FunctionType(BOOL, [BOOL])) bv8 = Symbol("bv1", BV8) bv16 = Symbol("bv2", BV16) result = [ # Formula, is_valid, is_sat, is_qf Example(hr="(x & y)", expr=And(x, y), is_valid=False, is_sat=True, logic=pysmt.logics.QF_BOOL), Example(hr="(x <-> y)", expr=Iff(x, y), is_valid=False, is_sat=True, logic=pysmt.logics.QF_BOOL), Example(hr="((x | y) & (! (x | y)))", expr=And(Or(x, y), Not(Or(x, y))), is_valid=False, is_sat=False, logic=pysmt.logics.QF_BOOL), Example(hr="(x & (! y))", expr=And(x, Not(y)), is_valid=False, is_sat=True, logic=pysmt.logics.QF_BOOL), Example(hr="(False -> True)", expr=Implies(FALSE(), TRUE()), is_valid=True, is_sat=True, logic=pysmt.logics.QF_BOOL), # # LIA # Example(hr="((q < p) & (x -> y))", expr=And(GT(p, q), Implies(x, y)), is_valid=False, is_sat=True, logic=pysmt.logics.QF_IDL), Example(hr="(((p + q) = 5) & (q < p))", expr=And(Equals(Plus(p, q), Int(5)), GT(p, q)), is_valid=False, is_sat=True, logic=pysmt.logics.QF_LIA), Example(hr="((q <= p) | (p <= q))", expr=Or(GE(p, q), LE(p, q)), is_valid=True, is_sat=True, logic=pysmt.logics.QF_IDL), Example(hr="(! (p < (q * 2)))", expr=Not(LT(p, Times(q, Int(2)))), is_valid=False, is_sat=True, logic=pysmt.logics.QF_LIA), Example(hr="(p < (p - (5 - 2)))", expr=GT(Minus(p, Minus(Int(5), Int(2))), p), is_valid=False, is_sat=False, logic=pysmt.logics.QF_IDL), Example(hr="((x ? 7 : ((p + -1) * 3)) = q)", expr=Equals( Ite(x, Int(7), Times(Plus(p, Int(-1)), Int(3))), q), is_valid=False, is_sat=True, logic=pysmt.logics.QF_LIA), Example(hr="(p < (q + 1))", expr=LT(p, Plus(q, Int(1))), is_valid=False, is_sat=True, logic=pysmt.logics.QF_LIA), # # LRA # Example(hr="((s < r) & (x -> y))", expr=And(GT(r, s), Implies(x, y)), is_valid=False, is_sat=True, logic=pysmt.logics.QF_RDL), Example(hr="(((r + s) = 28/5) & (s < r))", expr=And(Equals(Plus(r, s), Real(Fraction("5.6"))), GT(r, s)), is_valid=False, is_sat=True, logic=pysmt.logics.QF_LRA), Example(hr="((s <= r) | (r <= s))", expr=Or(GE(r, s), LE(r, s)), is_valid=True, is_sat=True, logic=pysmt.logics.QF_RDL), Example(hr="(! ((r * 2.0) < (s * 2.0)))", expr=Not(LT(Div(r, Real((1, 2))), Times(s, Real(2)))), is_valid=False, is_sat=True, logic=pysmt.logics.QF_LRA), Example(hr="(! (r < (r - (5.0 - 2.0))))", expr=Not(GT(Minus(r, Minus(Real(5), Real(2))), r)), is_valid=True, is_sat=True, logic=pysmt.logics.QF_RDL), Example(hr="((x ? 7.0 : ((s + -1.0) * 3.0)) = r)", expr=Equals( Ite(x, Real(7), Times(Plus(s, Real(-1)), Real(3))), r), is_valid=False, is_sat=True, logic=pysmt.logics.QF_LRA), # # EUF # Example(hr="(bf(x) <-> bg(x))", expr=Iff(Function(bf, (x, )), Function(bg, (x, ))), is_valid=False, is_sat=True, logic=pysmt.logics.QF_UF), Example(hr="(rf(5.0, rg(r)) = 0.0)", expr=Equals(Function(rf, (Real(5), Function(rg, (r, )))), Real(0)), is_valid=False, is_sat=True, logic=pysmt.logics.QF_UFLRA), Example(hr="((rg(r) = (5.0 + 2.0)) <-> (rg(r) = 7.0))", expr=Iff(Equals(Function(rg, [r]), Plus(Real(5), Real(2))), Equals(Function(rg, [r]), Real(7))), is_valid=True, is_sat=True, logic=pysmt.logics.QF_UFLRA), Example( hr="((r = (s + 1.0)) & (rg(s) = 5.0) & (rg((r - 1.0)) = 7.0))", expr=And([ Equals(r, Plus(s, Real(1))), Equals(Function(rg, [s]), Real(5)), Equals(Function(rg, [Minus(r, Real(1))]), Real(7)) ]), is_valid=False, is_sat=False, logic=pysmt.logics.QF_UFLRA), # # BV # Example(hr="((1_32 & 0_32) = 0_32)", expr=Equals(BVAnd(BVOne(32), BVZero(32)), BVZero(32)), is_valid=True, is_sat=True, logic=pysmt.logics.QF_BV), Example(hr="((! 2_3) = 5_3)", expr=Equals(BVNot(BV("010")), BV("101")), is_valid=True, is_sat=True, logic=pysmt.logics.QF_BV), Example(hr="((7_3 xor 0_3) = 0_3)", expr=Equals(BVXor(BV("111"), BV("000")), BV("000")), is_valid=False, is_sat=False, logic=pysmt.logics.QF_BV), Example(hr="((bv1::bv1) u< 0_16)", expr=BVULT(BVConcat(bv8, bv8), BVZero(16)), is_valid=False, is_sat=False, logic=pysmt.logics.QF_BV), Example(hr="(1_32[0:7] = 1_8)", expr=Equals(BVExtract(BVOne(32), end=7), BVOne(8)), is_valid=True, is_sat=True, logic=pysmt.logics.QF_BV), Example(hr="(0_8 u< (((bv1 + 1_8) * 5_8) u/ 5_8))", expr=BVUGT( BVUDiv(BVMul(BVAdd(bv8, BVOne(8)), BV(5, width=8)), BV(5, width=8)), BVZero(8)), is_valid=False, is_sat=True, logic=pysmt.logics.QF_BV), Example(hr="(0_16 u<= bv2)", expr=BVUGE(bv16, BVZero(16)), is_valid=True, is_sat=True, logic=pysmt.logics.QF_BV), Example(hr="(0_16 s<= bv2)", expr=BVSGE(bv16, BVZero(16)), is_valid=False, is_sat=True, logic=pysmt.logics.QF_BV), Example( hr="((0_32 u< (5_32 u% 2_32)) & ((5_32 u% 2_32) u<= 1_32))", expr=And( BVUGT(BVURem(BV(5, width=32), BV(2, width=32)), BVZero(32)), BVULE(BVURem(BV(5, width=32), BV(2, width=32)), BVOne(32))), is_valid=True, is_sat=True, logic=pysmt.logics.QF_BV), Example(hr="((((1_32 + (- 1_32)) << 1_32) >> 1_32) = 1_32)", expr=Equals( BVLShr(BVLShl(BVAdd(BVOne(32), BVNeg(BVOne(32))), 1), 1), BVOne(32)), is_valid=False, is_sat=False, logic=pysmt.logics.QF_BV), Example(hr="((1_32 - 1_32) = 0_32)", expr=Equals(BVSub(BVOne(32), BVOne(32)), BVZero(32)), is_valid=True, is_sat=True, logic=pysmt.logics.QF_BV), # Rotations Example(hr="(((1_32 ROL 1) ROR 1) = 1_32)", expr=Equals(BVRor(BVRol(BVOne(32), 1), 1), BVOne(32)), is_valid=True, is_sat=True, logic=pysmt.logics.QF_BV), # Extensions Example(hr="((0_5 ZEXT 11) = (0_1 SEXT 15))", expr=Equals(BVZExt(BVZero(5), 11), BVSExt(BVZero(1), 15)), is_valid=True, is_sat=True, logic=pysmt.logics.QF_BV), Example(hr="((bv2 - bv2) = 0_16)", expr=Equals(BVSub(bv16, bv16), BVZero(16)), is_valid=True, is_sat=True, logic=pysmt.logics.QF_BV), Example(hr="((bv2 - bv2)[0:7] = bv1)", expr=Equals(BVExtract(BVSub(bv16, bv16), 0, 7), bv8), is_valid=False, is_sat=True, logic=pysmt.logics.QF_BV), Example(hr="((bv2[0:7] bvcomp bv1) = 1_1)", expr=Equals(BVComp(BVExtract(bv16, 0, 7), bv8), BVOne(1)), is_valid=False, is_sat=True, logic=pysmt.logics.QF_BV), Example(hr="((bv2 bvcomp bv2) = 0_1)", expr=Equals(BVComp(bv16, bv16), BVZero(1)), is_valid=False, is_sat=False, logic=pysmt.logics.QF_BV), Example(hr="(bv2 s< bv2)", expr=BVSLT(bv16, bv16), is_valid=False, is_sat=False, logic=pysmt.logics.QF_BV), Example(hr="(bv2 s< 0_16)", expr=BVSLT(bv16, BVZero(16)), is_valid=False, is_sat=True, logic=pysmt.logics.QF_BV), Example(hr="((bv2 s< 0_16) | (0_16 s<= bv2))", expr=Or(BVSGT(BVZero(16), bv16), BVSGE(bv16, BVZero(16))), is_valid=True, is_sat=True, logic=pysmt.logics.QF_BV), Example(hr="(bv2 u< bv2)", expr=BVULT(bv16, bv16), is_valid=False, is_sat=False, logic=pysmt.logics.QF_BV), Example(hr="(bv2 u< 0_16)", expr=BVULT(bv16, BVZero(16)), is_valid=False, is_sat=False, logic=pysmt.logics.QF_BV), Example(hr="((bv2 | 0_16) = bv2)", expr=Equals(BVOr(bv16, BVZero(16)), bv16), is_valid=True, is_sat=True, logic=pysmt.logics.QF_BV), Example(hr="((bv2 & 0_16) = 0_16)", expr=Equals(BVAnd(bv16, BVZero(16)), BVZero(16)), is_valid=True, is_sat=True, logic=pysmt.logics.QF_BV), Example(hr="((0_16 s< bv2) & ((bv2 s/ 65535_16) s< 0_16))", expr=And(BVSLT(BVZero(16), bv16), BVSLT(BVSDiv(bv16, SBV(-1, 16)), BVZero(16))), is_valid=False, is_sat=True, logic=pysmt.logics.QF_BV), Example(hr="((0_16 s< bv2) & ((bv2 s% 1_16) s< 0_16))", expr=And(BVSLT(BVZero(16), bv16), BVSLT(BVSRem(bv16, BVOne(16)), BVZero(16))), is_valid=False, is_sat=False, logic=pysmt.logics.QF_BV), Example(hr="((bv2 u% 1_16) = 0_16)", expr=Equals(BVURem(bv16, BVOne(16)), BVZero(16)), is_valid=True, is_sat=True, logic=pysmt.logics.QF_BV), Example(hr="((bv2 s% 1_16) = 0_16)", expr=Equals(BVSRem(bv16, BVOne(16)), BVZero(16)), is_valid=True, is_sat=True, logic=pysmt.logics.QF_BV), Example(hr="((bv2 s% (- 1_16)) = 0_16)", expr=Equals(BVSRem(bv16, BVNeg(BVOne(16))), BVZero(16)), is_valid=True, is_sat=True, logic=pysmt.logics.QF_BV), Example(hr="((bv2 a>> 0_16) = bv2)", expr=Equals(BVAShr(bv16, BVZero(16)), bv16), is_valid=True, is_sat=True, logic=pysmt.logics.QF_BV), Example(hr="((0_16 s<= bv2) & ((bv2 a>> 1_16) = (bv2 >> 1_16)))", expr=And( BVSLE(BVZero(16), bv16), Equals(BVAShr(bv16, BVOne(16)), BVLShr(bv16, BVOne(16)))), is_valid=False, is_sat=True, logic=pysmt.logics.QF_BV), # # Quantification # Example(hr="(forall y . (x -> y))", expr=ForAll([y], Implies(x, y)), is_valid=False, is_sat=True, logic=pysmt.logics.BOOL), Example(hr="(forall p, q . ((p + q) = 0))", expr=ForAll([p, q], Equals(Plus(p, q), Int(0))), is_valid=False, is_sat=False, logic=pysmt.logics.LIA), Example( hr="(forall r, s . (((0.0 < r) & (0.0 < s)) -> ((r - s) < r)))", expr=ForAll([r, s], Implies(And(GT(r, Real(0)), GT(s, Real(0))), (LT(Minus(r, s), r)))), is_valid=True, is_sat=True, logic=pysmt.logics.LRA), Example(hr="(exists x, y . (x -> y))", expr=Exists([x, y], Implies(x, y)), is_valid=True, is_sat=True, logic=pysmt.logics.BOOL), Example(hr="(exists p, q . ((p + q) = 0))", expr=Exists([p, q], Equals(Plus(p, q), Int(0))), is_valid=True, is_sat=True, logic=pysmt.logics.LIA), Example(hr="(exists r . (forall s . (r < (r - s))))", expr=Exists([r], ForAll([s], GT(Minus(r, s), r))), is_valid=False, is_sat=False, logic=pysmt.logics.LRA), Example(hr="(forall r . (exists s . (r < (r - s))))", expr=ForAll([r], Exists([s], GT(Minus(r, s), r))), is_valid=True, is_sat=True, logic=pysmt.logics.LRA), Example(hr="(x & (forall r . ((r + s) = 5.0)))", expr=And(x, ForAll([r], Equals(Plus(r, s), Real(5)))), is_valid=False, is_sat=False, logic=pysmt.logics.LRA), Example(hr="(exists x . ((x <-> (5.0 < s)) & (s < 3.0)))", expr=Exists([x], (And(Iff(x, GT(s, Real(5))), LT(s, Real(3))))), is_valid=False, is_sat=True, logic=pysmt.logics.LRA), # # UFLIRA # Example(hr="((p < ih(r, q)) & (x -> y))", expr=And(GT(Function(ih, (r, q)), p), Implies(x, y)), is_valid=False, is_sat=True, logic=pysmt.logics.QF_UFLIRA), Example( hr= "(((p - 3) = q) -> ((p < ih(r, (q + 3))) | (ih(r, p) <= p)))", expr=Implies( Equals(Minus(p, Int(3)), q), Or(GT(Function(ih, (r, Plus(q, Int(3)))), p), LE(Function(ih, (r, p)), p))), is_valid=True, is_sat=True, logic=pysmt.logics.QF_UFLIRA), Example( hr= "(((ToReal((p - 3)) = r) & (ToReal(q) = r)) -> ((p < ih(ToReal((p - 3)), (q + 3))) | (ih(r, p) <= p)))", expr=Implies( And(Equals(ToReal(Minus(p, Int(3))), r), Equals(ToReal(q), r)), Or( GT( Function( ih, (ToReal(Minus(p, Int(3))), Plus(q, Int(3)))), p), LE(Function(ih, (r, p)), p))), is_valid=True, is_sat=True, logic=pysmt.logics.QF_UFLIRA), Example( hr= "(! (((ToReal((p - 3)) = r) & (ToReal(q) = r)) -> ((p < ih(ToReal((p - 3)), (q + 3))) | (ih(r, p) <= p))))", expr=Not( Implies( And(Equals(ToReal(Minus(p, Int(3))), r), Equals(ToReal(q), r)), Or( GT( Function(ih, (ToReal(Minus( p, Int(3))), Plus(q, Int(3)))), p), LE(Function(ih, (r, p)), p)))), is_valid=False, is_sat=False, logic=pysmt.logics.QF_UFLIRA), Example( hr= """("Did you know that any string works? #yolo" & "10" & "|#somesolverskeepthe||" & " ")""", expr=And(Symbol("Did you know that any string works? #yolo"), Symbol("10"), Symbol("|#somesolverskeepthe||"), Symbol(" ")), is_valid=False, is_sat=True, logic=pysmt.logics.QF_BOOL), # # Arrays # Example(hr="((q = 0) -> (aii[0 := 0] = aii[0 := q]))", expr=Implies( Equals(q, Int(0)), Equals(Store(aii, Int(0), Int(0)), Store(aii, Int(0), q))), is_valid=True, is_sat=True, logic=pysmt.logics.QF_ALIA), Example(hr="(aii[0 := 0][0] = 0)", expr=Equals(Select(Store(aii, Int(0), Int(0)), Int(0)), Int(0)), is_valid=True, is_sat=True, logic=pysmt.logics.QF_ALIA), Example(hr="((Array{Int, Int}(0)[1 := 1] = aii) & (aii[1] = 0))", expr=And(Equals(Array(INT, Int(0), {Int(1): Int(1)}), aii), Equals(Select(aii, Int(1)), Int(0))), is_valid=False, is_sat=False, logic=pysmt.logics.get_logic_by_name("QF_ALIA*")), Example(hr="((Array{Int, Int}(0)[1 := 3] = aii) & (aii[1] = 3))", expr=And(Equals(Array(INT, Int(0), {Int(1): Int(3)}), aii), Equals(Select(aii, Int(1)), Int(3))), is_valid=False, is_sat=True, logic=pysmt.logics.get_logic_by_name("QF_ALIA*")), Example(hr="((Array{Real, Int}(10) = ari) & (ari[6/5] = 0))", expr=And(Equals(Array(REAL, Int(10)), ari), Equals(Select(ari, Real((6, 5))), Int(0))), is_valid=False, is_sat=False, logic=pysmt.logics.get_logic_by_name("QF_AUFBVLIRA*")), Example( hr= "((Array{Real, Int}(0)[1.0 := 10][2.0 := 20][3.0 := 30][4.0 := 40] = ari) & (! ((ari[0.0] = 0) & (ari[1.0] = 10) & (ari[2.0] = 20) & (ari[3.0] = 30) & (ari[4.0] = 40))))", expr=And( Equals( Array( REAL, Int(0), { Real(1): Int(10), Real(2): Int(20), Real(3): Int(30), Real(4): Int(40) }), ari), Not( And(Equals(Select(ari, Real(0)), Int(0)), Equals(Select(ari, Real(1)), Int(10)), Equals(Select(ari, Real(2)), Int(20)), Equals(Select(ari, Real(3)), Int(30)), Equals(Select(ari, Real(4)), Int(40))))), is_valid=False, is_sat=False, logic=pysmt.logics.get_logic_by_name("QF_AUFBVLIRA*")), Example( hr= "((Array{Real, Int}(0)[1.0 := 10][2.0 := 20][3.0 := 30][4.0 := 40][5.0 := 50] = ari) & (! ((ari[0.0] = 0) & (ari[1.0] = 10) & (ari[2.0] = 20) & (ari[3.0] = 30) & (ari[4.0] = 40) & (ari[5.0] = 50))))", expr=And( Equals( Array( REAL, Int(0), { Real(1): Int(10), Real(2): Int(20), Real(3): Int(30), Real(4): Int(40), Real(5): Int(50) }), ari), Not( And(Equals(Select(ari, Real(0)), Int(0)), Equals(Select(ari, Real(1)), Int(10)), Equals(Select(ari, Real(2)), Int(20)), Equals(Select(ari, Real(3)), Int(30)), Equals(Select(ari, Real(4)), Int(40)), Equals(Select(ari, Real(5)), Int(50))))), is_valid=False, is_sat=False, logic=pysmt.logics.get_logic_by_name("QF_AUFBVLIRA*")), Example( hr= "((a_arb_aii = Array{Array{Real, BV{8}}, Array{Int, Int}}(Array{Int, Int}(7))) -> (a_arb_aii[arb][42] = 7))", expr=Implies( Equals(nested_a, Array(ArrayType(REAL, BV8), Array(INT, Int(7)))), Equals(Select(Select(nested_a, arb), Int(42)), Int(7))), is_valid=True, is_sat=True, logic=pysmt.logics.get_logic_by_name("QF_AUFBVLIRA*")), Example(hr="(abb[bv1 := y_][bv1 := z_] = abb[bv1 := z_])", expr=Equals( Store(Store(abb, bv8, Symbol("y_", BV8)), bv8, Symbol("z_", BV8)), Store(abb, bv8, Symbol("z_", BV8))), is_valid=True, is_sat=True, logic=pysmt.logics.QF_ABV), Example(hr="((r / s) = (r * s))", expr=Equals(Div(r, s), Times(r, s)), is_valid=False, is_sat=True, logic=pysmt.logics.QF_NRA), Example(hr="(2.0 = (r * r))", expr=Equals(Real(2), Times(r, r)), is_valid=False, is_sat=True, logic=pysmt.logics.QF_NRA), Example(hr="((p ^ 2) = 0)", expr=Equals(Pow(p, Int(2)), Int(0)), is_valid=False, is_sat=True, logic=pysmt.logics.QF_NIA), Example(hr="((r ^ 2.0) = 0.0)", expr=Equals(Pow(r, Real(2)), Real(0)), is_valid=False, is_sat=True, logic=pysmt.logics.QF_NRA), Example(hr="((r * r * r) = 25.0)", expr=Equals(Times(r, r, r), Real(25)), is_valid=False, is_sat=True, logic=pysmt.logics.QF_NRA), Example(hr="((5.0 * r * 5.0) = 25.0)", expr=Equals(Times(Real(5), r, Real(5)), Real(25)), is_valid=False, is_sat=True, logic=pysmt.logics.QF_LRA), Example(hr="((p * p * p) = 25)", expr=Equals(Times(p, p, p), Int(25)), is_valid=False, is_sat=False, logic=pysmt.logics.QF_NIA), Example(hr="((5 * p * 5) = 25)", expr=Equals(Times(Int(5), p, Int(5)), Int(25)), is_valid=False, is_sat=True, logic=pysmt.logics.QF_LIA), Example(hr="(((1 - 1) * p * 1) = 0)", expr=Equals(Times(Minus(Int(1), Int(1)), p, Int(1)), Int(0)), is_valid=True, is_sat=True, logic=pysmt.logics.QF_LIA), # Huge Fractions: Example( hr= "((r * 1606938044258990275541962092341162602522202993782792835301376/7) = -20480000000000000000000000.0)", expr=Equals(Times(r, Real(Fraction(2**200, 7))), Real(-200**11)), is_valid=False, is_sat=True, logic=pysmt.logics.QF_LRA), Example(hr="(((r + 5.0 + s) * (s + 2.0 + r)) = 0.0)", expr=Equals( Times(Plus(r, Real(5), s), Plus(s, Real(2), r)), Real(0)), is_valid=False, is_sat=True, logic=pysmt.logics.QF_NRA), Example( hr= "(((p + 5 + q) * (p - (q - 5))) = ((p * p) + (10 * p) + 25 + (-1 * q * q)))", expr=Equals( Times(Plus(p, Int(5), q), Minus(p, Minus(q, Int(5)))), Plus(Times(p, p), Times(Int(10), p), Int(25), Times(Int(-1), q, q))), is_valid=True, is_sat=True, logic=pysmt.logics.QF_NIA), ] return result
def test_nested(self): f = Exists([self.x], ForAll([self.y], Or(self.x, self.y))) g = qelim(f, solver_name="shannon") g = g.simplify() self.assertEqual(g, TRUE())
def solve_liveness_inc_fwd(self, hts, prop, k, k_min, eventually=False): self._reset_assertions(self.solver) init = hts.single_init() trans = hts.single_trans() invar = hts.single_invar() if self.config.simplify: Logger.log("Simplifying the Transition System", 1) if Logger.level(1): timer = Logger.start_timer("Simplify") init = simplify(init) trans = simplify(trans) invar = simplify(invar) if Logger.level(1): Logger.get_timer(timer) heqvar = None if not eventually: heqvar = Symbol(HEQVAR, BOOL) self._init_at_time(hts.vars.union(set([heqvar])), k) if self.config.prove: self.solver_klive = self.solver.copy("klive") self._reset_assertions(self.solver_klive) self._add_assertion(self.solver_klive, self.at_time(invar, 0)) if eventually: self._add_assertion(self.solver_klive, self.at_time(init, 0)) propt = FALSE() formula = And(init, invar) formula = self.at_time(formula, 0) Logger.log("Add init and invar", 2) self._add_assertion(self.solver, formula) next_prop = TS.has_next(prop) if next_prop: if k < 1: Logger.error( "Liveness checking with next variables requires at least k=1" ) k_min = 1 t = 0 while (t < k + 1): self._push(self.solver) loopback = FALSE() if t > 0: loopback = self.all_loopbacks(self.hts.vars, t, heqvar) Logger.log("Add loopbacks at time %d" % t, 2) self._add_assertion(self.solver, loopback) if t >= k_min: self._write_smt2_comment(self.solver, "Solving for k=%s" % (t)) Logger.log("\nSolving for k=%s" % (t), 1) if self._solve(self.solver): Logger.log("Counterexample found with k=%s" % (t), 1) model = self._get_model(self.solver) return (t, model) else: Logger.log("No counterexample found with k=%s" % (t), 1) Logger.msg(".", 0, not (Logger.level(1))) else: Logger.log("Skipping solving for k=%s (k_min=%s)" % (t, k_min), 1) Logger.msg(".", 0, not (Logger.level(1))) self._pop(self.solver) n_prop = Not(prop) if not eventually: n_prop = Or(n_prop, Not(heqvar)) if next_prop: if t > 0: propt = self.at_time(n_prop, t - 1) else: propt = self.at_time(n_prop, t) self._add_assertion(self.solver, propt) if self.config.prove: if t > 0: self._add_assertion(self.solver_klive, trans_t) self._write_smt2_comment(self.solver_klive, "Solving for k=%s" % (t)) if next_prop: if t > 0: propt = self.at_time(Not(prop), t - 1) else: propt = self.at_time(Not(prop), t) self._add_assertion(self.solver_klive, propt) if t >= k_min: if self._solve(self.solver_klive): Logger.log("K-Liveness failed with k=%s" % (t), 1) else: Logger.log("K-Liveness holds with k=%s" % (t), 1) return (t, True) else: self._add_assertion(self.solver_klive, self.at_time(Not(prop), 0)) # self._push(self.solver_klive) # self._add_assertion(self.solver_klive, self.at_time(prop, 0)) # res = self._solve(self.solver_klive) # self._pop(self.solver_klive) # if res: # self._add_assertion(self.solver_klive, self.at_time(prop, 0)) # else: # self._add_assertion(self.solver_klive, self.at_time(Not(prop), 0)) trans_t = self.unroll(trans, invar, t + 1, t) self._add_assertion(self.solver, trans_t) if self.assert_property: prop_t = self.unroll(TRUE(), prop, t, t - 1) self._add_assertion(self.solver, prop_t) Logger.log("Add property at time %d" % t, 2) t += 1 return (t - 1, None)
def test_trivial_true_times(self): x, y, z = (Symbol(name, REAL) for name in "xyz") f = Equals(Times(x, z, y), Times(z, y, x)) self.assertEqual(f.simplify(), TRUE())
def test_trivial_true_or(self): x, y, z = (Symbol(name) for name in "xyz") f = Or(x, y, z, Not(x)) self.assertEqual(f.simplify(), TRUE())
def _flatten_rec(self, path=[]): self.is_flatten = True vardic = dict([(v.symbol_name(), v) for v in self.vars]) def full_path(name, path): ret = ".".join(path + [name]) if ret[0] == ".": return ret[1:] return ret for sub in self.subs: instance, actual, module = sub module.is_flatten = True formal = module.params ts = TS(FLATTEN) (ts.vars, \ ts.state_vars, \ ts.input_vars, \ ts.output_vars, \ ts.init, \ ts.trans, \ ts.ftrans, \ ts.invar) = module._flatten_rec(path+[instance]) self.add_ts(ts, reset=False) links = {} for i in range(len(actual)): # Unset parameter if actual[i] == None: continue if type(actual[i]) == str: local_expr = vardic[full_path(actual[i], path)] else: local_vars = [(v.symbol_name(), v.symbol_name().replace(self.name, ".".join(path))) \ for v in get_free_variables(actual[i])] local_expr = substitute(actual[i], dict(local_vars)) module_var = sub[2].newname(formal[i].symbol_name(), path + [sub[0]]) assert sub[2].name != "" if module_var not in vardic: modulevar = Symbol(module_var, formal[i].symbol_type()) self.vars.add(modulevar) vardic[module_var] = modulevar if vardic[module_var] in self.output_vars: links[local_expr] = [(TRUE(), vardic[module_var])] else: links[vardic[module_var]] = [(TRUE(), local_expr)] ts = TS(LINKS) ts.ftrans = links self.add_ts(ts, reset=False) s_init = self.single_init() s_invar = self.single_invar(include_ftrans=False) s_trans = self.single_trans(include_ftrans=False) replace_dic = dict([(v.symbol_name(), self.newname(v.symbol_name(), path)) for v in self.vars] + \ [(TS.get_prime_name(v.symbol_name()), self.newname(TS.get_prime_name(v.symbol_name()), path)) \ for v in self.vars]) substitute_dic = {} def substitute_mem(f, dic): if f in substitute_dic: return substitute_dic[f] ret = substitute(f, dic) substitute_dic[f] = ret return ret s_init = substitute_mem(s_init, replace_dic) s_invar = substitute_mem(s_invar, replace_dic) s_trans = substitute_mem(s_trans, replace_dic) s_ftrans = {} local_vars = [] local_state_vars = [] local_input_vars = [] local_output_vars = [] single_ftrans = self.single_ftrans() for var in list(self.vars): newsym = Symbol(replace_dic[var.symbol_name()], var.symbol_type()) local_vars.append(newsym) if var in self.state_vars: local_state_vars.append(newsym) if var in self.input_vars: local_input_vars.append(newsym) if var in self.output_vars: local_output_vars.append(newsym) if var in single_ftrans: cond_assign_list = single_ftrans[var] s_ftrans[newsym] = [(substitute_mem(condition, replace_dic), \ substitute_mem(value, replace_dic)) \ for (condition, value) in cond_assign_list] del (single_ftrans[var]) for var, cond_assign_list in single_ftrans.items(): s_ftrans[substitute_mem(var, replace_dic)] = [(substitute_mem(condition, replace_dic), \ substitute_mem(value, replace_dic)) \ for (condition, value) in cond_assign_list] return (local_vars, local_state_vars, local_input_vars, local_output_vars, s_init, s_trans, s_ftrans, s_invar)
def sim_no_unroll(self, hts, cover, k, all_vars=True, inc=False): init = hts.single_init() invar = hts.single_invar() trans = hts.single_trans() init_0 = self.at_time(init, 0) invar_0 = self.at_time(invar, 0) trans_01 = self.unroll(trans, invar, 1) cover_1 = self.at_time(cover, 1) full_model = {} if all_vars: relevant_vars = hts.vars else: relevant_vars = hts.state_vars | hts.output_vars relevant_vars_0 = [TS.get_timed(v, 0) for v in relevant_vars] relevant_vars_1 = [TS.get_timed(v, 1) for v in relevant_vars] relevant_vars_01 = [(TS.get_timed(v, 0), TS.get_timed(v, 1), v) for v in relevant_vars] self._reset_assertions(self.solver) # Picking Initial State Logger.log("\nSolving for k=0", 1) self._add_assertion(self.solver, And(init_0, invar_0)) if self._solve(self.solver): init_model = self._get_model(self.solver, relevant_vars_0) init_0 = And([EqualsOrIff(v, init_model[v]) for v in relevant_vars_0]) for v in relevant_vars_0: full_model[v] = init_model[v] Logger.msg(".", 0, not(Logger.level(1))) else: return (0, None) self._reset_assertions(self.solver) if inc: self._add_assertion(self.solver, trans_01) self._add_assertion(self.solver, invar_0) init_model = None for t in range(1, k + 1): Logger.log("\nSolving for k=%s"%(t), 1) if not inc: self._reset_assertions(self.solver, True) formula = And(init_0, invar_0) self._add_assertion(self.solver, trans_01) else: formula = init_0 self._push(self.solver) self._add_assertion(self.solver, formula) res_step = self._solve(self.solver) if res_step: Logger.msg(".", 0, not(Logger.level(1))) Logger.log("Able to step forward at k=%s"%(t), 2) if all_vars: init_model = self._get_model(self.solver) else: init_model = self._get_model(self.solver, relevant_vars_1) model = init_model else: Logger.log("System deadlocked at k=%s"%(t), 2) return (-1, full_model) # Use previous model as initial state for next sat call init_0 = [] init_1 = [] for v in relevant_vars_01: if v[1] not in init_model: continue val = init_model[v[1]] full_model[TS.get_timed(v[2], t)] = val init_0.append(EqualsOrIff(v[0], val)) init_1.append(EqualsOrIff(v[1], val)) init_0 = And(init_0) if cover != TRUE(): init_1 = And(init_1) self._add_assertion(self.solver, init_1) self._add_assertion(self.solver, cover_1) res_cont = self._solve(self.solver) if res_cont: Logger.log('Reached cover in no unroll simulation at k=%s'%(t), 2) model = init_model return (t, full_model) else: Logger.log('Cover not reached at k=%s'%t, 2) if inc: self._pop(self.solver) return (t, full_model)
def expr_to_pysmt(context: TranslationContext, expr: Expr, *, is_expectation: bool = False, allow_infinity: bool = False) -> FNode: """ Translate a pGCL expression to a pySMT formula. Note that substitution expressions are not allowed here (they are not supported in pySMT). You can pass in the optional `is_expectation` parameter to have all integer values converted to real values. If `allow_infinity` is `True`, then infinity expressions will be mapped directly to the `infinity` variable of the given :py:class:`TranslationContext`. Take care to appropriately constrain the `infinity` variable! Note that arithmetic expressions may not contain infinity, to prevent expressions like `infinity - infinity`. .. doctest:: >>> from probably.pgcl.parser import parse_expr >>> from pysmt.shortcuts import Symbol >>> from pysmt.typing import INT >>> expr = parse_expr("x + 4 * 13") >>> context = TranslationContext({"x": Symbol("x", INT)}) >>> expr_to_pysmt(context, expr) (x + (4 * 13)) """ if isinstance(expr, BoolLitExpr): return TRUE() if expr.value else FALSE() elif isinstance(expr, NatLitExpr): if is_expectation: return ToReal(Int(expr.value)) else: return Int(expr.value) elif isinstance(expr, FloatLitExpr): if expr.is_infinite(): if not allow_infinity: raise Exception( f"Infinity is not allowed in this expression: {expr}") return context.infinity else: return Real(Fraction(expr.value)) elif isinstance(expr, VarExpr): var = context.variables[expr.var] if is_expectation and get_type(var) == INT: var = ToReal(var) return var elif isinstance(expr, UnopExpr): operand = expr_to_pysmt(context, expr.expr, is_expectation=False, allow_infinity=allow_infinity) if expr.operator == Unop.NEG: return Not(operand) elif expr.operator == Unop.IVERSON: return Ite(operand, Real(1), Real(0)) elif isinstance(expr, BinopExpr): # `is_expectation` is disabled if we enter a non-arithmetic expression # (we do not convert integers to reals within a boolean expression such # as `x == y`, for example). # # Similarly, `allow_infinity` is disabled if we enter an arithmetic # expression because calculations with infinity are hard to make sense of. is_arith_op = expr.operator in [Binop.PLUS, Binop.MINUS, Binop.TIMES] is_expectation = is_expectation # TODO: and is_arith_op allow_infinity = allow_infinity # TODO: and not is_arith_op?!??! lhs = expr_to_pysmt(context, expr.lhs, is_expectation=is_expectation, allow_infinity=allow_infinity) rhs = expr_to_pysmt(context, expr.rhs, is_expectation=is_expectation, allow_infinity=allow_infinity) if expr.operator == Binop.OR: return Or(lhs, rhs) elif expr.operator == Binop.AND: return And(lhs, rhs) elif expr.operator == Binop.LEQ: return LE(lhs, rhs) elif expr.operator == Binop.LE: return LT(lhs, rhs) elif expr.operator == Binop.EQ: return EqualsOrIff(lhs, rhs) elif expr.operator == Binop.PLUS: return Plus(lhs, rhs) elif expr.operator == Binop.MINUS: return Ite(LE(lhs, rhs), (Int(0) if get_type(lhs) == INT else Real(0)), Minus(lhs, rhs)) elif expr.operator == Binop.TIMES: return Times(lhs, rhs) elif isinstance(expr, SubstExpr): raise Exception("Substitution expression is not allowed here.") raise Exception("unreachable")
def parse_string(self, strinput): hts = HTS() ts = TS() nodemap = {} node_covered = set([]) # list of tuples of var and cond_assign_list # cond_assign_list is tuples of (condition, value) # where everything is a pysmt FNode # for btor, the condition is always True ftrans = [] initlist = [] invarlist = [] invar_props = [] ltl_props = [] prop_count = 0 # clean string input, remove special characters from names for sc, rep in special_char_replacements.items(): strinput = strinput.replace(sc, rep) def getnode(nid): node_covered.add(nid) if int(nid) < 0: return Ite(BV2B(nodemap[str(-int(nid))]), BV(0, 1), BV(1, 1)) return nodemap[nid] def binary_op(bvop, bop, left, right): if (get_type(left) == BOOL) and (get_type(right) == BOOL): return bop(left, right) return bvop(B2BV(left), B2BV(right)) def unary_op(bvop, bop, left): if (get_type(left) == BOOL): return bop(left) return bvop(left) for line in strinput.split(NL): linetok = line.split() if len(linetok) == 0: continue if linetok[0] == COM: continue (nid, ntype, *nids) = linetok if ntype == SORT: (stype, *attr) = nids if stype == BITVEC: nodemap[nid] = BVType(int(attr[0])) node_covered.add(nid) if stype == ARRAY: nodemap[nid] = ArrayType(getnode(attr[0]), getnode(attr[1])) node_covered.add(nid) if ntype == WRITE: nodemap[nid] = Store(*[getnode(n) for n in nids[1:4]]) if ntype == READ: nodemap[nid] = Select(getnode(nids[1]), getnode(nids[2])) if ntype == ZERO: nodemap[nid] = BV(0, getnode(nids[0]).width) if ntype == ONE: nodemap[nid] = BV(1, getnode(nids[0]).width) if ntype == ONES: width = getnode(nids[0]).width nodemap[nid] = BV((2**width) - 1, width) if ntype == REDOR: width = get_type(getnode(nids[1])).width zeros = BV(0, width) nodemap[nid] = BVNot(BVComp(getnode(nids[1]), zeros)) if ntype == REDAND: width = get_type(getnode(nids[1])).width ones = BV((2**width) - 1, width) nodemap[nid] = BVComp(getnode(nids[1]), ones) if ntype == CONSTD: width = getnode(nids[0]).width nodemap[nid] = BV(int(nids[1]), width) if ntype == CONST: width = getnode(nids[0]).width try: nodemap[nid] = BV(bin_to_dec(nids[1]), width) except ValueError: if not all([i == 'x' or i == 'z' for i in nids[1]]): raise RuntimeError( "If not a valid number, only support " "all don't cares or high-impedance but got {}". format(nids[1])) # create a fresh variable for this non-deterministic constant nodemap[nid] = Symbol('const_' + nids[1], BVType(width)) ts.add_state_var(nodemap[nid]) Logger.warning( "Creating a fresh symbol for unsupported X/Z constant %s" % nids[1]) if ntype == STATE: if len(nids) > 1: nodemap[nid] = Symbol(nids[1], getnode(nids[0])) else: nodemap[nid] = Symbol((SN % nid), getnode(nids[0])) ts.add_state_var(nodemap[nid]) if ntype == INPUT: if len(nids) > 1: nodemap[nid] = Symbol(nids[1], getnode(nids[0])) else: nodemap[nid] = Symbol((SN % nid), getnode(nids[0])) ts.add_input_var(nodemap[nid]) if ntype == OUTPUT: # unfortunately we need to create an extra symbol just to have the output name # we could be smarter about this, but then this parser can't be greedy original_symbol = B2BV(getnode(nids[0])) output_symbol = Symbol(nids[1], original_symbol.get_type()) nodemap[nid] = EqualsOrIff(output_symbol, original_symbol) invarlist.append(nodemap[nid]) node_covered.add(nid) ts.add_output_var(output_symbol) if ntype == AND: nodemap[nid] = binary_op(BVAnd, And, getnode(nids[1]), getnode(nids[2])) if ntype == CONCAT: nodemap[nid] = BVConcat(B2BV(getnode(nids[1])), B2BV(getnode(nids[2]))) if ntype == XOR: nodemap[nid] = binary_op(BVXor, Xor, getnode(nids[1]), getnode(nids[2])) if ntype == XNOR: nodemap[nid] = BVNot( binary_op(BVXor, Xor, getnode(nids[1]), getnode(nids[2]))) if ntype == NAND: bvop = lambda x, y: BVNot(BVAnd(x, y)) bop = lambda x, y: Not(And(x, y)) nodemap[nid] = binary_op(bvop, bop, getnode(nids[1]), getnode(nids[2])) if ntype == IMPLIES: nodemap[nid] = BVOr(BVNot(getnode(nids[1])), getnode(nids[2])) if ntype == NOT: nodemap[nid] = unary_op(BVNot, Not, getnode(nids[1])) if ntype == NEG: nodemap[nid] = unary_op(BVNeg, Not, getnode(nids[1])) if ntype == UEXT: nodemap[nid] = BVZExt(B2BV(getnode(nids[1])), int(nids[2])) if ntype == SEXT: nodemap[nid] = BVSExt(B2BV(getnode(nids[1])), int(nids[2])) if ntype == OR: nodemap[nid] = binary_op(BVOr, Or, getnode(nids[1]), getnode(nids[2])) if ntype == ADD: nodemap[nid] = BVAdd(B2BV(getnode(nids[1])), B2BV(getnode(nids[2]))) if ntype == SUB: nodemap[nid] = BVSub(B2BV(getnode(nids[1])), B2BV(getnode(nids[2]))) if ntype == UGT: nodemap[nid] = BVUGT(B2BV(getnode(nids[1])), B2BV(getnode(nids[2]))) if ntype == UGTE: nodemap[nid] = BVUGE(B2BV(getnode(nids[1])), B2BV(getnode(nids[2]))) if ntype == ULT: nodemap[nid] = BVULT(B2BV(getnode(nids[1])), B2BV(getnode(nids[2]))) if ntype == ULTE: nodemap[nid] = BVULE(B2BV(getnode(nids[1])), B2BV(getnode(nids[2]))) if ntype == SGT: nodemap[nid] = BVSGT(B2BV(getnode(nids[1])), B2BV(getnode(nids[2]))) if ntype == SGTE: nodemap[nid] = BVSGE(B2BV(getnode(nids[1])), B2BV(getnode(nids[2]))) if ntype == SLT: nodemap[nid] = BVSLT(B2BV(getnode(nids[1])), B2BV(getnode(nids[2]))) if ntype == SLTE: nodemap[nid] = BVSLE(B2BV(getnode(nids[1])), B2BV(getnode(nids[2]))) if ntype == EQ: nodemap[nid] = BVComp(B2BV(getnode(nids[1])), B2BV(getnode(nids[2]))) if ntype == NEQ: nodemap[nid] = BVNot(BVComp(getnode(nids[1]), getnode(nids[2]))) if ntype == MUL: nodemap[nid] = BVMul(B2BV(getnode(nids[1])), B2BV(getnode(nids[2]))) if ntype == SLICE: nodemap[nid] = BVExtract(B2BV(getnode(nids[1])), int(nids[3]), int(nids[2])) if ntype == SLL: nodemap[nid] = BVLShl(getnode(nids[1]), getnode(nids[2])) if ntype == SRA: nodemap[nid] = BVAShr(getnode(nids[1]), getnode(nids[2])) if ntype == SRL: nodemap[nid] = BVLShr(getnode(nids[1]), getnode(nids[2])) if ntype == ITE: if (get_type(getnode(nids[2])) == BOOL) or (get_type( getnode(nids[3])) == BOOL): nodemap[nid] = Ite(BV2B(getnode(nids[1])), B2BV(getnode(nids[2])), B2BV(getnode(nids[3]))) else: nodemap[nid] = Ite(BV2B(getnode(nids[1])), getnode(nids[2]), getnode(nids[3])) if ntype == NEXT: if (get_type(getnode(nids[1])) == BOOL) or (get_type( getnode(nids[2])) == BOOL): lval = TS.get_prime(getnode(nids[1])) rval = B2BV(getnode(nids[2])) else: lval = TS.get_prime(getnode(nids[1])) rval = getnode(nids[2]) nodemap[nid] = EqualsOrIff(lval, rval) ftrans.append((lval, [(TRUE(), rval)])) if ntype == INIT: if (get_type(getnode(nids[1])) == BOOL) or (get_type( getnode(nids[2])) == BOOL): nodemap[nid] = EqualsOrIff(BV2B(getnode(nids[1])), BV2B(getnode(nids[2]))) elif get_type(getnode(nids[1])).is_array_type(): _type = get_type(getnode(nids[1])) nodemap[nid] = EqualsOrIff( getnode(nids[1]), Array(_type.index_type, default=getnode(nids[2]))) else: nodemap[nid] = EqualsOrIff(getnode(nids[1]), getnode(nids[2])) initlist.append(getnode(nid)) if ntype == CONSTRAINT: nodemap[nid] = BV2B(getnode(nids[0])) invarlist.append(getnode(nid)) if ntype == BAD: nodemap[nid] = getnode(nids[0]) if len(nids) > 1: assert_name = nids[1] description = "Embedded assertion: {}".format(assert_name) else: assert_name = 'embedded_assertion_%i' % prop_count description = 'Embedded assertion number %i' % prop_count prop_count += 1 # Following problem format (name, description, strformula) invar_props.append( (assert_name, description, Not(BV2B(getnode(nid))))) if nid not in nodemap: Logger.error("Unknown node type \"%s\"" % ntype) # get wirename if it exists if ntype not in {STATE, INPUT, OUTPUT, BAD}: # disregard comments at the end of the line try: symbol_idx = nids.index(';') symbol_idx -= 1 # the symbol should be before the comment except: # the symbol is just the end symbol_idx = -1 # check for wirename, if it's an integer, then it's a node ref try: a = int(nids[symbol_idx]) except: try: name = str(nids[symbol_idx]) # use the exact name, unless it has already been used wire = Symbol(name, getnode(nids[0])) if wire in ts.vars: wire = FreshSymbol(getnode(nids[0]), template=name + "%d") invarlist.append(EqualsOrIff(wire, B2BV(nodemap[nid]))) ts.add_var(wire) except: pass if Logger.level(1): name = lambda x: str(nodemap[x]) if nodemap[x].is_symbol() else x uncovered = [name(x) for x in nodemap if x not in node_covered] uncovered.sort() if len(uncovered) > 0: Logger.warning("Unlinked nodes \"%s\"" % ",".join(uncovered)) if not self.symbolic_init: init = simplify(And(initlist)) else: init = TRUE() invar = simplify(And(invarlist)) # instead of trans, we're using the ftrans format -- see below ts.set_behavior(init, TRUE(), invar) # add ftrans for var, cond_assign_list in ftrans: ts.add_func_trans(var, cond_assign_list) hts.add_ts(ts) return (hts, invar_props, ltl_props)
def parse_string(self, strinput): hts = HTS() ts = TS() nodemap = {} node_covered = set([]) # list of tuples of var and cond_assign_list # cond_assign_list is tuples of (condition, value) # where everything is a pysmt FNode # for btor, the condition is always True ftrans = [] initlist = [] invarlist = [] invar_props = [] ltl_props = [] prop_count = 0 # clean string input, remove special characters from names for sc, rep in special_char_replacements.items(): strinput = strinput.replace(sc, rep) def getnode(nid): node_covered.add(nid) if int(nid) < 0: return Ite(BV2B(nodemap[str(-int(nid))]), BV(0,1), BV(1,1)) return nodemap[nid] def binary_op(bvop, bop, left, right): if (get_type(left) == BOOL) and (get_type(right) == BOOL): return bop(left, right) return bvop(B2BV(left), B2BV(right)) def unary_op(bvop, bop, left): if (get_type(left) == BOOL): return bop(left) return bvop(left) for line in strinput.split(NL): linetok = line.split() if len(linetok) == 0: continue if linetok[0] == COM: continue (nid, ntype, *nids) = linetok if ntype == SORT: (stype, *attr) = nids if stype == BITVEC: nodemap[nid] = BVType(int(attr[0])) node_covered.add(nid) if stype == ARRAY: nodemap[nid] = ArrayType(getnode(attr[0]), getnode(attr[1])) node_covered.add(nid) if ntype == WRITE: nodemap[nid] = Store(*[getnode(n) for n in nids[1:4]]) if ntype == READ: nodemap[nid] = Select(getnode(nids[1]), getnode(nids[2])) if ntype == ZERO: nodemap[nid] = BV(0, getnode(nids[0]).width) if ntype == ONE: nodemap[nid] = BV(1, getnode(nids[0]).width) if ntype == ONES: width = getnode(nids[0]).width nodemap[nid] = BV((2**width)-1, width) if ntype == REDOR: width = get_type(getnode(nids[1])).width zeros = BV(0, width) nodemap[nid] = BVNot(BVComp(getnode(nids[1]), zeros)) if ntype == REDXOR: width = get_type(getnode(nids[1])).width nodemap[nid] = BV(0, width) zeros = BV(0, width) for yx_i in range(width): tmp = BV(1 << yx_i, width) tmp_2 = BVAnd(tmp, B2BV(getnode(nids[1]))) tmp_3 = BVZExt(B2BV(BVComp(tmp_2, zeros)), int(width - 1)) nodemap[nid] = BVAdd(tmp_3, nodemap[nid]) nodemap[nid] = BVComp(BVAnd(BV(1, width), nodemap[nid]), BV(1, width)) if ntype == REDAND: width = get_type(getnode(nids[1])).width ones = BV((2**width)-1, width) nodemap[nid] = BVComp(getnode(nids[1]), ones) if ntype == CONSTD: width = getnode(nids[0]).width nodemap[nid] = BV(int(nids[1]), width) if ntype == CONST: width = getnode(nids[0]).width nodemap[nid] = BV(bin_to_dec(nids[1]), width) if ntype == STATE: if len(nids) > 1: nodemap[nid] = Symbol(nids[1], getnode(nids[0])) else: nodemap[nid] = Symbol((SN%nid), getnode(nids[0])) ts.add_state_var(nodemap[nid]) if ntype == INPUT: if len(nids) > 1: nodemap[nid] = Symbol(nids[1], getnode(nids[0])) else: nodemap[nid] = Symbol((SN%nid), getnode(nids[0])) ts.add_input_var(nodemap[nid]) if ntype == OUTPUT: # unfortunately we need to create an extra symbol just to have the output name # we could be smarter about this, but then this parser can't be greedy original_symbol = getnode(nids[0]) output_symbol = Symbol(nids[1], original_symbol.get_type()) nodemap[nid] = EqualsOrIff(output_symbol, original_symbol) invarlist.append(nodemap[nid]) node_covered.add(nid) ts.add_output_var(output_symbol) if ntype == AND: nodemap[nid] = binary_op(BVAnd, And, getnode(nids[1]), getnode(nids[2])) if ntype == CONCAT: nodemap[nid] = BVConcat(B2BV(getnode(nids[1])), B2BV(getnode(nids[2]))) if ntype == XOR: nodemap[nid] = binary_op(BVXor, Xor, getnode(nids[1]), getnode(nids[2])) if ntype == XNOR: nodemap[nid] = BVNot(binary_op(BVXor, Xor, getnode(nids[1]), getnode(nids[2]))) if ntype == NAND: bvop = lambda x,y: BVNot(BVAnd(x, y)) bop = lambda x,y: Not(And(x, y)) nodemap[nid] = binary_op(bvop, bop, getnode(nids[1]), getnode(nids[2])) if ntype == IMPLIES: nodemap[nid] = BVOr(BVNot(getnode(nids[1])), getnode(nids[2])) if ntype == NOT: nodemap[nid] = unary_op(BVNot, Not, getnode(nids[1])) if ntype == NEG: nodemap[nid] = unary_op(BVNeg, Not, getnode(nids[1])) if ntype == UEXT: nodemap[nid] = BVZExt(B2BV(getnode(nids[1])), int(nids[2])) if ntype == SEXT: nodemap[nid] = BVSExt(B2BV(getnode(nids[1])), int(nids[2])) if ntype == OR: nodemap[nid] = binary_op(BVOr, Or, getnode(nids[1]), getnode(nids[2])) if ntype == ADD: nodemap[nid] = BVAdd(B2BV(getnode(nids[1])), B2BV(getnode(nids[2]))) if ntype == SUB: nodemap[nid] = BVSub(B2BV(getnode(nids[1])), B2BV(getnode(nids[2]))) if ntype == UGT: nodemap[nid] = BVUGT(B2BV(getnode(nids[1])), B2BV(getnode(nids[2]))) if ntype == UGTE: nodemap[nid] = BVUGE(B2BV(getnode(nids[1])), B2BV(getnode(nids[2]))) if ntype == ULT: nodemap[nid] = BVULT(B2BV(getnode(nids[1])), B2BV(getnode(nids[2]))) if ntype == ULTE: nodemap[nid] = BVULE(B2BV(getnode(nids[1])), B2BV(getnode(nids[2]))) if ntype == SGT: nodemap[nid] = BVSGT(B2BV(getnode(nids[1])), B2BV(getnode(nids[2]))) if ntype == SGTE: nodemap[nid] = BVSGE(B2BV(getnode(nids[1])), B2BV(getnode(nids[2]))) if ntype == SLT: nodemap[nid] = BVSLT(B2BV(getnode(nids[1])), B2BV(getnode(nids[2]))) if ntype == SLTE: nodemap[nid] = BVSLE(B2BV(getnode(nids[1])), B2BV(getnode(nids[2]))) if ntype == EQ: nodemap[nid] = BVComp(B2BV(getnode(nids[1])), B2BV(getnode(nids[2]))) if ntype == NEQ: nodemap[nid] = BVNot(BVComp(getnode(nids[1]), getnode(nids[2]))) if ntype == MUL: nodemap[nid] = BVMul(B2BV(getnode(nids[1])), B2BV(getnode(nids[2]))) if ntype == SLICE: nodemap[nid] = BVExtract(B2BV(getnode(nids[1])), int(nids[3]), int(nids[2])) if ntype == SLL: nodemap[nid] = BVLShl(getnode(nids[1]), getnode(nids[2])) if ntype == SRA: nodemap[nid] = BVAShr(getnode(nids[1]), getnode(nids[2])) if ntype == SRL: nodemap[nid] = BVLShr(getnode(nids[1]), getnode(nids[2])) if ntype == ITE: if (get_type(getnode(nids[2])) == BOOL) or (get_type(getnode(nids[3])) == BOOL): nodemap[nid] = Ite(BV2B(getnode(nids[1])), B2BV(getnode(nids[2])), B2BV(getnode(nids[3]))) else: nodemap[nid] = Ite(BV2B(getnode(nids[1])), getnode(nids[2]), getnode(nids[3])) if ntype == NEXT: if (get_type(getnode(nids[1])) == BOOL) or (get_type(getnode(nids[2])) == BOOL): lval = TS.get_prime(getnode(nids[1])) rval = BV2B(getnode(nids[2])) else: lval = TS.get_prime(getnode(nids[1])) rval = getnode(nids[2]) nodemap[nid] = EqualsOrIff(lval, rval) ftrans.append( (lval, [(TRUE(), rval)]) ) if ntype == INIT: if (get_type(getnode(nids[1])) == BOOL) or (get_type(getnode(nids[2])) == BOOL): nodemap[nid] = EqualsOrIff(BV2B(getnode(nids[1])), BV2B(getnode(nids[2]))) else: nodemap[nid] = EqualsOrIff(getnode(nids[1]), getnode(nids[2])) initlist.append(getnode(nid)) if ntype == CONSTRAINT: nodemap[nid] = BV2B(getnode(nids[0])) invarlist.append(getnode(nid)) if ntype == BAD: nodemap[nid] = getnode(nids[0]) if ASSERTINFO in line: filename_lineno = os.path.basename(nids[3]) assert_name = 'embedded_assertion_%s'%filename_lineno description = "Embedded assertion at line {1} in {0}".format(*filename_lineno.split(COLON_REP)) else: assert_name = 'embedded_assertion_%i'%prop_count description = 'Embedded assertion number %i'%prop_count prop_count += 1 # Following problem format (name, description, strformula) invar_props.append((assert_name, description, Not(BV2B(getnode(nid))))) if nid not in nodemap: Logger.error("Unknown node type \"%s\""%ntype) # get wirename if it exists if ntype not in {STATE, INPUT, OUTPUT, BAD}: # check for wirename, if it's an integer, then it's a node ref try: a = int(nids[-1]) except: try: wire = Symbol(str(nids[-1]), getnode(nids[0])) invarlist.append(EqualsOrIff(wire, B2BV(nodemap[nid]))) ts.add_var(wire) except: pass if Logger.level(1): name = lambda x: str(nodemap[x]) if nodemap[x].is_symbol() else x uncovered = [name(x) for x in nodemap if x not in node_covered] uncovered.sort() if len(uncovered) > 0: Logger.warning("Unlinked nodes \"%s\""%",".join(uncovered)) if not self.symbolic_init: init = simplify(And(initlist)) else: init = TRUE() invar = simplify(And(invarlist)) # instead of trans, we're using the ftrans format -- see below ts.set_behavior(init, TRUE(), invar) # add ftrans for var, cond_assign_list in ftrans: ts.add_func_trans(var, cond_assign_list) hts.add_ts(ts) return (hts, invar_props, ltl_props)
def test_normalization(): def get_normalization_file(filename): return path.join(path.dirname(__file__), "res", "renorm_bug", filename) for i in range(5): domain = Domain.from_file(get_normalization_file("domain.json")) support = read_smtlib(get_normalization_file("vanilla.support")) weight = read_smtlib(get_normalization_file("vanilla.weight")) new_support = read_smtlib( get_normalization_file("renorm_chi_{}.support".format(i))) # print(smt_to_nested(support)) clean_support = normalize_formula(support) clean_new_support = normalize_formula(new_support) clean_weight = normalize_formula(weight) print(smt_to_nested(clean_weight)) assert (RejectionEngine(domain, ~Iff(support, clean_support), Real(1.0), 1000000).compute_volume() == 0) assert (RejectionEngine(domain, ~Iff(new_support, clean_new_support), Real(1.0), 1000000).compute_volume() == 0) # plot_formula("new_support", domain, new_support, ["r0", "r1"]) # plot_formula("clean_new_support", domain, clean_new_support, ["r0", "r1"]) support = clean_support new_support = clean_new_support weight = clean_weight # print(RejectionEngine(domain, Iff(weight, ~clean_weight), Real(1.0), 1000000).compute_volume()) # print(smt_to_nested(support)) print("Problem", i) engine = XaddEngine(domain, support, weight, "original") print("Volume before starting", engine.compute_volume()) new_weight = engine.normalize(new_support, paths=False) Density(domain, new_support, new_weight).to_file("normalized.json") illegal_volume = XaddEngine(domain, ~new_support, new_weight, "mass").compute_volume() assert illegal_volume == pytest.approx(0, rel=EXACT_REL_ERROR) computed_volume = XaddEngine(domain, TRUE(), new_weight, "mass").compute_volume() computed_volume_within = XaddEngine(domain, new_support, new_weight, "mass").compute_volume() computed_volume_within2 = XaddEngine(domain, new_support, new_weight).compute_volume() computed_volume_within3 = RejectionEngine(domain, new_support, new_weight, 1000000).compute_volume() print( "pa new_support new_weight", computed_volume_within, "xadd new_support new_weight:", computed_volume_within2, "rej new_support new_weight:", computed_volume_within3, ) assert computed_volume_within == pytest.approx(computed_volume_within2, EXACT_REL_ERROR) print( "pa true new_weight:", computed_volume, "pa new_support new_weight", computed_volume_within, "pa outside new_support new_weight", illegal_volume, ) assert computed_volume == pytest.approx(1, rel=EXACT_REL_ERROR) assert computed_volume_within == pytest.approx(1, rel=EXACT_REL_ERROR) illegal_volume = engine.copy_with(support=~new_support, weight=new_weight).compute_volume() assert illegal_volume == pytest.approx(0, rel=EXACT_REL_ERROR)
def test_contains(self): x, y, z = [FreshSymbol() for _ in xrange(3)] d = {x: TRUE(), y: FALSE()} model = EagerModel(assignment=d) self.assertTrue(x in model) self.assertFalse(z in model)
def comb_attack(self): # dis generator solver_name = 'btor' solver_obf = Solver(name=solver_name) solver_key = Solver(name=solver_name) solver_oracle = Solver(name=solver_name) attack_formulas = FormulaGenerator(self.oracle_cir, self.obf_cir) f = attack_formulas.dip_gen_ckt # f = simplify(f) solver_obf.add_assertion(f) f = attack_formulas.key_inequality_ckt # f = simplify(f) solver_obf.add_assertion(f) iteration = 0 while 1: # query dip generator if solver_obf.solve(): dip_formula = [] dip_boolean = [] for l in self.obf_cir.input_wires: t = Symbol(l) if solver_obf.get_py_value(t): dip_formula.append(t) dip_boolean.append(TRUE()) else: dip_formula.append(Not(t)) dip_boolean.append(FALSE()) logging.info(dip_formula) # query oracle dip_out = [] for l in self.oracle_cir.output_wires: t = self.oracle_cir.wire_objs[l].formula solver_oracle.reset_assertions() solver_oracle.add_assertion(t) if solver_oracle.solve(dip_formula): dip_out.append(TRUE()) else: dip_out.append(FALSE()) logging.info(dip_out) # add dip checker f = [] for i in range(len(attack_formulas.dip_chk1)): f.append(And(Iff(dip_out[i], attack_formulas.dip_chk1[i]), Iff(dip_out[i], attack_formulas.dip_chk2[i]))) f = And(f) subs = {} for i in range(len(self.obf_cir.input_wires)): subs[Symbol(self.obf_cir.input_wires[i])] = dip_boolean[i] # f = simplify(f) f = substitute(f, subs) solver_obf.add_assertion(f) solver_key.add_assertion(f) iteration += 1 logging.warning('iteration: {}'.format(iteration)) else: logging.warning('print keys') if solver_key.solve(): key = '' for i in range(len(self.obf_cir.key_wires)): k = 'keyinput{}_0'.format(i) if solver_key.get_py_value(Symbol(k)): key += '1' else: key += '0' print("key=%s" % key) else: logging.critical('key solver returned UNSAT') return
def times_neutral(self): return TRUE()
def parse_string(self, lines): [none, var, state, input, output, init, invar, trans, ftrans] = range(9) section = none inits = TRUE() invars = TRUE() transs = TRUE() ftranss = {} sparser = StringParser() count = 0 vars = set([]) states = set([]) inputs = set([]) outputs = set([]) invar_props = [] ltl_props = [] for line in lines: count += 1 if (line.strip() in ["", "\n"]) or line[0] == T_COM: continue if T_VAR == line[:len(T_VAR)]: section = var continue if T_STATE == line[:len(T_STATE)]: section = state continue if T_INPUT == line[:len(T_INPUT)]: section = input continue if T_OUTPUT == line[:len(T_OUTPUT)]: section = output continue if T_INIT == line[:len(T_INIT)]: section = init continue if T_INVAR == line[:len(T_INVAR)]: section = invar continue if T_TRANS == line[:len(T_TRANS)]: section = trans continue if T_FTRANS == line[:len(T_FTRANS)]: section = ftrans continue if section in [var, state, input, output]: varname, vartype = line[:-2].replace(" ", "").split(":") if varname[0] == "'": varname = varname[1:-1] vartype = parse_typestr(vartype) vardef = self._define_var(varname, vartype) vars.add(vardef) if section == state: states.add(vardef) if section == input: inputs.add(vardef) if section == output: outputs.add(vardef) if section in [init, invar, trans]: line = line.replace(T_SC, "").strip() qline = quote_names(line, replace_ops=False) if section == init: inits = And(inits, sparser.parse_formula(qline)) if section == invar: invars = And(invars, sparser.parse_formula(qline)) if section == trans: transs = And(transs, sparser.parse_formula(qline)) if section == ftrans: strvar = line[:line.find(":=")] var = sparser.parse_formula( quote_names(strvar, replace_ops=False)) cond_ass = line[line.find(":=") + 2:].strip() ftranss[var] = [] for cond_as in cond_ass.split("{"): if cond_as == "": continue cond = cond_as[:cond_as.find(",")] ass = cond_as[cond_as.find(",") + 1:cond_as.find("}")] ftranss[var].append((sparser.parse_formula( quote_names(cond, replace_ops=False)), sparser.parse_formula( quote_names(ass, replace_ops=False)))) hts = HTS("STS") ts = TS() ts.vars = vars ts.state_vars = states ts.input_vars = inputs ts.output_vars = outputs ts.init = inits ts.invar = invars ts.trans = transs ts.ftrans = ftranss hts.add_ts(ts) return (hts, invar_props, ltl_props)
def _test_auto_aux(self, auto_env): def _check_auto_tautologies(auto): self.assertTrue(auto.is_equivalent(auto)) self.assertTrue(auto.is_equivalent(auto.copy_reachable())) self.assertTrue(auto.is_equivalent(auto.complete())) self.assertTrue(auto.is_equivalent(auto.determinize())) self.assertTrue(auto.is_equivalent(auto.union(auto))) self.assertTrue(auto.is_equivalent((auto.reverse()).reverse())) self.assertTrue(auto.is_equivalent(auto.minimize())) symbols = [Symbol(chr(i), BOOL) for i in range(ord('a'), ord('z') + 1)] a = auto_env.new_label(symbols[0]) b = auto_env.new_label(symbols[1]) c = auto_env.new_label(symbols[2]) # test copy auto_a = Automaton.get_singleton(a, auto_env) self.assertTrue(auto_a.is_equivalent(auto_a)) copy_1 = auto_a.copy_reachable() copy_2 = copy_1.copy_reachable() det = auto_a.determinize() twice_neg = auto_a.complement().complement() complete = auto_a.complete() for auto in [auto_a, copy_1, copy_2, twice_neg, complete]: self.assertFalse(auto.is_empty()) self.assertTrue(auto.accept([a])) self.assertFalse(auto.accept([a, a])) _check_auto_tautologies(auto) auto_a_neg = auto_a.complement() self.assertFalse(auto_a_neg.accept([a])) self.assertTrue(auto_a_neg.accept([a, a])) self.assertTrue(auto_a_neg.accept([b])) # aa auto_aa = auto_a.concatenate(auto_a) det = auto_aa.determinize() twice_neg = auto_aa.complement().complement() complete = auto_aa.complete() for auto in [auto_aa, det, twice_neg, complete]: self.assertFalse(auto.is_empty()) self.assertFalse(auto.accept([a])) self.assertTrue(auto.accept([a, a])) self.assertFalse(auto.accept([a, a, a])) _check_auto_tautologies(auto) auto_aa_neg = auto_aa.complement() self.assertTrue(auto_aa_neg.accept([a])) self.assertTrue(auto_aa_neg.accept([b])) self.assertFalse(auto_aa_neg.accept([a, a])) self.assertTrue(auto_aa_neg.accept([a, a, a])) # a[*] auto_astar = auto_a.klenee_star() det = auto_astar.determinize() twice_neg = auto_astar.complement().complement() complete = auto_astar.complete() for auto in [auto_astar, det, twice_neg, complete]: self.assertFalse(auto.is_empty()) self.assertTrue(auto.accept([])) self.assertTrue(auto.accept([a, a])) self.assertTrue(auto.accept([a, a, a])) _check_auto_tautologies(auto) # TRUE aut_true = Automaton.get_singleton(auto_env.new_label(TRUE()), auto_env) twice_neg = aut_true.complement().complement() det = aut_true.determinize() complete = aut_true.complete() for auto in [aut_true, det, twice_neg, complete]: self.assertFalse(det.is_empty()) self.assertFalse(det.accept([])) self.assertTrue(det.accept([a])) self.assertTrue(det.accept([b])) self.assertTrue(det.accept([c])) self.assertFalse(det.accept([a, b])) _check_auto_tautologies(auto) # TRUE[*] aut_truestar = aut_true.klenee_star() twice_neg = aut_truestar.complement().complement() det = aut_truestar.determinize() complete = aut_truestar.complete() for auto in [aut_truestar, det, twice_neg, complete]: self.assertFalse(auto.is_empty()) self.assertTrue(auto.accept([])) self.assertTrue(auto.accept([a])) self.assertTrue(auto.accept([b])) self.assertTrue(auto.accept([c])) self.assertTrue(auto.accept([a, b])) _check_auto_tautologies(auto) a = Automaton() self.assertTrue(a.is_empty()) a = Automaton.get_empty(auto_env) self.assertTrue(a.is_empty())