def _build_var_deps(self, hts): if self.var_deps is not None: return self.var_deps = {} ftrans = hts.single_ftrans() for var, cond_assign_list in ftrans.items(): for refvar in self._free_variables(var): if refvar not in self.var_deps: self.var_deps[refvar] = [] for cass in cond_assign_list: self.var_deps[refvar] += list(self._free_variables( cass[0])) self.var_deps[refvar] += list(self._free_variables( cass[1])) trans = list( conjunctive_partition(hts.single_trans(include_ftrans=False))) invar = list( conjunctive_partition(hts.single_invar(include_ftrans=False))) init = list(conjunctive_partition(hts.single_init())) for ts_formula in [invar, trans, init]: for f in ts_formula: fv = self._free_variables(f) for v in fv: if v not in self.var_deps: self.var_deps[v] = [] self.var_deps[v] += list(fv) self.var_deps[v] = [ x for x in set(self.var_deps[v]) if x != v ]
def analyse_unsat(Formulas): conj = conjunctive_partition(Formulas) ucore = get_unsat_core(conj) print("Unsat core:") for f in ucore: print(f.serialize()) return ucore
def _add_assertion(self, solver, formula, comment=None): if not self.config.skip_solving: solver.solver.add_assertion(formula) if Logger.level(3): buf = cStringIO() printer = SmtPrinter(buf) printer.printer(formula) print(buf.getvalue() + "\n") if solver.trace_file is not None: if comment: self._write_smt2_comment(solver, "%s: START" % comment) formula_fv = get_free_variables(formula) for v in formula_fv: if v in solver.smt2vars: continue if v.symbol_type() == BOOL: self._write_smt2_log( solver, "(declare-fun %s () Bool)" % (v.symbol_name())) elif v.symbol_type().is_array_type(): st = v.symbol_type() assert st.index_type.is_bv_type(), "Expecting BV indices" assert st.elem_type.is_bv_type(), "Expecting BV elements" self._write_smt2_log( solver, "(declare-fun %s () (Array (_ BitVec %s) (_ BitVec %s)))" % (v.symbol_name(), st.index_type.width, st.elem_type.width)) elif v.symbol_type().is_bv_type(): self._write_smt2_log( solver, "(declare-fun %s () (_ BitVec %s))" % (v.symbol_name(), v.symbol_type().width)) else: Logger.error("Unhandled type in smt2 translation") self._write_smt2_log(solver, "") for v in formula_fv: solver.smt2vars.add(v) if formula.is_and(): for f in conjunctive_partition(formula): buf = cStringIO() printer = SmtPrinter(buf) printer.printer(f) self._write_smt2_log(solver, "(assert %s)" % buf.getvalue()) else: buf = cStringIO() printer = SmtPrinter(buf) printer.printer(formula) self._write_smt2_log(solver, "(assert %s)" % buf.getvalue()) if comment: self._write_smt2_comment(solver, "%s: END" % comment)
def test_conj_partitioning(self): for (f, _, _, logic) in get_example_formulae(): if get_env().factory.has_solvers(logic=logic): conjuncts = list(conjunctive_partition(f)) try: ok = is_valid(Iff(f, And(conjuncts)), logic=logic) except SolverReturnedUnknownResultError: ok = not logic.quantifier_free self.assertTrue(ok)
def test_conj_partitioning(self): for (f, _, _, logic) in get_example_formulae(): if self.env.factory.has_solvers(logic=logic): conjuncts = list(conjunctive_partition(f)) try: ok = is_valid(Iff(f, And(conjuncts)), logic=logic) except SolverReturnedUnknownResultError: ok = not logic.quantifier_free self.assertTrue(ok)
def unsat_core(self): res = self.solver.solve() if not res: print('Assertions:', self.fml) conj = conjunctive_partition(self.fml) ucore = get_unsat_core(conj) print("UNSAT-Core size '%d'" % len(ucore)) for f in ucore: print(f.serialize())
def get_model_or_print_ucore(formula): m = s.get_model(formula) if not m: print('unsat') from pysmt.rewritings import conjunctive_partition conj = conjunctive_partition(s.And(formula)) ucore = s.get_unsat_core(conj) print("UNSAT-Core size '%d'" % len(ucore)) for f in ucore: print(f.serialize()) return return m
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 _simplify_cp(self, cp): random.shuffle(cp) newcp = [] last = False step = 3 for i in range(0, len(cp) - (step - 1), step): if i == len(cp) - step: last = True formula = simplify(And([cp[i + j] for j in range(step)])) newcp += list(conjunctive_partition(formula)) if not last: for i in range(-1, -step, -1): newcp.append(cp[i]) return newcp
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 __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
print("UNSAT") # We first check whether the constraints on the domain and problem # are satisfiable in isolation. assert is_sat(facts) assert is_sat(domain) assert is_unsat(problem) # In isolation they are both fine, rules from both are probably # interacting. # # The problem is given by a nesting of And(). # conjunctive_partition can be used to obtain a "flat" # structure, i.e., a list of conjuncts. # from pysmt.rewritings import conjunctive_partition conj = conjunctive_partition(problem) ucore = get_unsat_core(conj) print("UNSAT-Core size '%d'" % len(ucore)) for f in ucore: print(f.serialize()) # The exact version of the UNSAT-Core depends on the solver in # use. Nevertheless, this represents a starting point for your # debugging. A possible way to approach the result is to look for # clauses of size 1 (i.e., unit clauses). In the facts list there # are only 2 facts: # 2_drink_milk # 0_nat_norwegian # # The clause ("1_color_blue" <-> "0_nat_norwegian") # Implies that "1_color_blue"
print("Generate model") model = get_model(facts_domain, solver_name=args.solver) #print model if model is None: print("UNSAT") print("Please verify that the student fields are correct.") # In isolation they are both fine, rules from both are probably # interacting. # # The problem is given by a nesting of And(). # conjunctive_partition can be used to obtain a "flat" # structure, i.e., a list of conjuncts. # from pysmt.rewritings import conjunctive_partition conj = conjunctive_partition(facts_domain) ucore = get_unsat_core(conj) print("UNSAT-Core size '%d'" % len(ucore)) for f in ucore: print(f.serialize()) else: f1_classes = [] s1_classes = [] f2_classes = [] s2_classes = [] f3_classes = [] s3_classes = [] f4_classes = [] s4_classes = [] for x in model: if x[1]._content.payload == 1:
def compute(self, hts, prop): Logger.log("Building COI", 1) self._build_var_deps(hts) coi_vars = set(self._free_variables(prop)) if (len(coi_vars) < 1) or (self.var_deps == {}): return hts if hts.assumptions is not None: for assumption in hts.assumptions: for v in self._free_variables(assumption): coi_vars.add(v) if hts.lemmas is not None: for lemma in hts.lemmas: for v in self._free_variables(lemma): coi_vars.add(v) coits = TS("COI") coi_vars = list(coi_vars) i = 0 visited = set([]) while i < len(coi_vars): var = coi_vars[i] if (var in visited) or (var not in self.var_deps): i += 1 continue coi_vars = coi_vars[:i + 1] + list( self.var_deps[var]) + coi_vars[i + 1:] visited.add(var) i += 1 coi_vars = frozenset(coi_vars) trans = list( conjunctive_partition(hts.single_trans(include_ftrans=True))) invar = list( conjunctive_partition(hts.single_invar(include_ftrans=True))) init = list(conjunctive_partition(hts.single_init())) coits.trans = [ f for f in trans if self._intersect(coi_vars, self._free_variables(f)) ] coits.invar = [ f for f in invar if self._intersect(coi_vars, self._free_variables(f)) ] coits.init = [ f for f in init if self._intersect(coi_vars, self._free_variables(f)) ] Logger.log("COI statistics:", 1) Logger.log(" Vars: %s -> %s" % (len(hts.vars), len(coi_vars)), 1) Logger.log(" Init: %s -> %s" % (len(init), len(coits.init)), 1) Logger.log(" Invar: %s -> %s" % (len(invar), len(coits.invar)), 1) Logger.log(" Trans: %s -> %s" % (len(trans), len(coits.trans)), 1) coits.trans = And(coits.trans) coits.invar = And(coits.invar) coits.init = And(coits.init) coits.vars = set([]) for bf in [init, invar, trans]: for f in bf: for v in self._free_variables(f): coits.vars.add(v) coits.input_vars = set([v for v in coi_vars if v in hts.input_vars]) coits.output_vars = set([v for v in coi_vars if v in hts.output_vars]) coits.state_vars = set([v for v in coi_vars if v in hts.state_vars]) new_hts = HTS("COI") new_hts.add_ts(coits) if self.save_model: printer = HTSPrintersFactory.printer_by_name("STS") with open("/tmp/coi_model.ssts", "w") as f: f.write(printer.print_hts(new_hts, [])) return new_hts
def __print_single_ts(self, ts, ftrans=False): 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 = [("INPUT", ts.input_vars),\ ("OUTPUT", ts.output_vars),\ ("STATE", ts.state_vars),\ ("VAR", [x for x in ts.vars if x not in list(ts.state_vars)+list(ts.input_vars)+list(ts.output_vars)])] for (sname, vars) in sections: if len(vars) > 0: self.write("%s\n"%sname) varsort = sort_system_variables(vars) for var in varsort: 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) cp = [x for x in cp if x.is_equals()]+[x for x in cp if not x.is_equals()] for i in range(len(cp)): f = cp[i] if self.simplify: f = simplify(f) if f == TRUE(): continue self.printer(f) self.write(";\n") if f == FALSE(): break self.write("\n") if ftrans: if ts.ftrans is not None: self.write("FUNC\n") for var, var_ass in ts.ftrans.items(): self.printer(var) self.write(" :=") for cond, value in var_ass: self.write(" {") self.printer(cond) self.write(", ") self.printer(value) self.write("}") self.write(";\n") if has_comment: self.write("\n%s\n"%("-"*lenstr))
def parametric_safety(self, prop, k_max, k_min, parameters, monotonic=True, at_most=-1): if len(parameters) == 0: Logger.error("Parameters size cannot be 0") lemmas = self.hts.lemmas self._init_at_time(self.hts.vars, k_max) monotonic = True # if monotonic: # for p in parameters: # self.set_preferred((p, False)) self.region = FALSE() generalize = lambda model, t: self._get_param_assignments( model, t, parameters, monotonic) if at_most == -1: cardinality = len(parameters) else: cardinality = at_most prev_cs_count = 0 prove = self.config.prove step = 5 same_res_counter = 0 k = step end = False has_next = TS.has_next(prop) # Strategy selection increase_k = False if cardinality == -2: (t, status) = self.solve_safety_inc_fwd(self.hts, prop, k_max, k_min, all_vars=False, generalize=generalize) else: sn = SortingNetwork.sorting_network(parameters) if increase_k: # Approach with incremental increase of bmc k while k < k_max + 1: for at in range(cardinality): Logger.msg("[%d,%d]" % ((at + 1), k), 0, not (Logger.level(1))) sn_k = sn[at + 1] if at + 1 < len(sn) else FALSE() bound_constr = Or(sn_k, self.region) bound_constr = bound_constr if not has_next else Or( bound_constr, TS.to_next(bound_constr)) self.config.prove = False (t, status) = self.solve_safety_inc_bwd( self.hts, Or(prop, bound_constr), k, generalize=generalize) if (prev_cs_count == self.cs_count): same_res_counter += 1 else: same_res_counter = 0 prev_cs_count = self.cs_count if (prove == True) and ((same_res_counter > 1) or (at == cardinality - 1)): Logger.msg("[>%d,%d]" % ((at + 1), k), 0, not (Logger.level(1))) if (at_most > -1) and (at_most < cardinality): sn_k = sn[at_most - 1] else: sn_k = FALSE() bound_constr = Or(sn_k, self.region) bound_constr = bound_constr if not has_next else Or( bound_constr, TS.to_next(bound_constr)) self.config.prove = True (t, status) = self.solve_safety( self.hts, Or(prop, bound_constr), k, max(k_min, k - step)) if status == True: end = True break if (same_res_counter > 2) and (k < k_max): break if end: break k += step else: # Approach with fixed bmc k for at in range(cardinality): Logger.msg("[%d]" % ((at + 1)), 0, not (Logger.level(1))) sn_k = sn[at + 1] if at + 1 < len(sn) else FALSE() bound_constr = Or(sn_k, self.region) bound_constr = bound_constr if not has_next else Or( bound_constr, TS.to_next(bound_constr)) self.config.prove = False (t, status) = self.solve_safety_inc_bwd( self.hts, Or(prop, bound_constr), k_max, generalize=generalize) if simplify(self.region) == TRUE(): break if (prev_cs_count == self.cs_count): same_res_counter += 1 else: same_res_counter = 0 prev_cs_count = self.cs_count if (prove == True) and ((same_res_counter > 1) or (at == cardinality - 1)): Logger.msg("[>%d]" % ((at + 1)), 0, not (Logger.level(1))) if (at_most > -1) and (at_most < cardinality): sn_k = sn[at_most - 1] else: sn_k = FALSE() bound_constr = Or(sn_k, self.region) bound_constr = bound_constr if not has_next else Or( bound_constr, TS.to_next(bound_constr)) self.config.prove = True (t, status) = self.solve_safety(self.hts, Or(prop, bound_constr), k_max, k_min) if status == True: break traces = None if (self.models is not None) and (simplify(self.region) not in [TRUE(), FALSE()]): traces = [] for (model, time) in self.models: model = self._remap_model(self.hts.vars, model, time) trace = self.generate_trace(model, time, get_free_variables(prop)) traces.append(trace) region = [] dass = {} # Sorting result by size for ass in list(disjunctive_partition(self.region)): cp = list(conjunctive_partition(ass)) size = len(cp) if size not in dass: dass[size] = [] dass[size].append(ass) indexes = list(dass.keys()) indexes.sort() for size in indexes: region += dass[size] if status == True: return (VerificationStatus.TRUE, traces, region) elif status is not None: return (VerificationStatus.FALSE, traces, region) else: return (VerificationStatus.UNK, traces, region)