Example #1
0
        def check_step():
            self._reset_assertions(self.solver)
            self._add_assertion(self.solver,
                                self.at_time(And(trans, lemma), 0))
            self._add_assertion(self.solver, self.at_time(Not(lemma), 1))

            if self._solve(self.solver):
                if Logger.level(2):
                    Logger.log("Lemma \"%s\" failed for L & T -> L'" % lemma,
                               2)
                    if Logger.level(3):
                        (hr_trace, vcd_trace) = self.print_trace(
                            hts,
                            self._get_model(self.solver),
                            1,
                            prefix=prefix,
                            map_function=self.config.map_function)
                        if hr_trace or vcd_trace:
                            vcd_msg = ""
                            if vcd_trace:
                                vcd_msg = " and in \"%s\"" % (vcd_trace)
                            Logger.log(
                                "Counterexample stored in \"%s\"%s" %
                                (hr_trace, vcd_msg), 2)
                        else:
                            Logger.log("", 2)
                return False
            else:
                Logger.log("Lemma \"%s\" holds for L & T -> L'" % lemma, 2)

            return True
Example #2
0
    def run_passes(self):
        Logger.log("Running CoreIR passes...", 1)
        print_level = 3
        if not Logger.level(print_level):
            saved_stdout = suppress_output()

        self.context.run_passes(PASSES)

        if not Logger.level(print_level):
            restore_output(saved_stdout)
Example #3
0
    def parse_file(self, strfile, config, flags=None):
        if flags is None:
            Logger.error("Top module not provided")

        topmodule = flags[0]
        absstrfile = os.path.abspath(strfile)
        directory = "/".join(absstrfile.split("/")[:-1])
        filename = absstrfile.split("/")[-1]

        if self.single_file:
            files = [absstrfile]
        else:
            if self.files_from_dir:
                files = [
                    "%s/%s" % (directory, f) for f in os.listdir(directory)
                    if self._get_extension(f) in self.extensions
                ]
            else:
                files = [
                    "%s/%s" % (directory, f) for f in list(
                        set(self._collect_dependencies(directory, filename)))
                ]
                files.append(absstrfile)

        command = "%s -p \"%s\"" % (CMD, "; ".join(COMMANDS))
        command = command.format(FILES=" ".join(files), \
                                 TARGET=topmodule, \
                                 PASSES="; ".join(PASSES), \
                                 BTORFILE=TMPFILE)

        Logger.log("Command: %s" % command, 2)

        print_level = 3
        if not Logger.level(print_level):
            saved_stdout = suppress_output()

        retval = os.system(command)

        if not Logger.level(print_level):
            restore_output(saved_stdout)

        if retval != 0:
            Logger.error("Error in Verilog conversion")

        parser = BTOR2Parser()
        ret = parser.parse_file(TMPFILE, config)

        if not Logger.level(1):
            os.remove(TMPFILE)

        return ret
Example #4
0
    def parse_file(self, strfile, config, flags=None):
        if flags is None:
            Logger.error("Top module not provided")

        topmodule = flags[0]
        absstrfile = os.path.abspath(strfile)
        directory = "/".join(absstrfile.split("/")[:-1])
        filename = absstrfile.split("/")[-1]

        files = [absstrfile]

        with open(strfile, "r") as f:
            if topmodule not in f.read():
                Logger.error("Module \"%s\" not found"%topmodule)
            
        commands = "\n".join(COMMANDS)
        commands = commands.format(FILES=" ".join(files), \
                                   TARGET=topmodule, \
                                   FILE=TMPFILE)

        command = "%s -script_file %s"%(CMD, TMPCMDFILE)
        
        with open(TMPCMDFILE, "w") as f:
            f.write(commands)
        
        Logger.log("Commands: %s"%commands, 2)

        print_level = 3
        if not Logger.level(print_level):
            saved_stdout = suppress_output()
        
        retval = os.system(command)

        if not Logger.level(print_level):
            restore_output(saved_stdout)

        if retval != 0:
            Logger.error("Error in SystemVerilog conversion")
            
        parser = VerilogHTSParser()
        ret = parser.parse_file(TMPFILE, config, flags=flags)
        self.model_info = parser.get_model_info()

        if (not Logger.level(1)) and (not config.devel):
            os.remove(TMPFILE)
            os.remove(TMPCMDFILE)
        
        return ret
Example #5
0
    def _get_param_assignments(self, model, time, parameters, monotonic=True):
        p_ass = []

        fwd = False

        for p in parameters:
            p_time = model[TS.get_ptimed(p, 0)]
            if p.symbol_type() == BOOL:
                if monotonic:
                    if p_time == TRUE():
                        p_ass.append(p)
                else:
                    p_ass.append(p if p_time == TRUE() else Not(p))
            else:
                p_ass.append(EqualsOrIff(p, p_time))

        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)
Example #6
0
    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)
Example #7
0
        def check_init():
            self._reset_assertions(self.solver)
            self._add_assertion(self.solver,
                                self.at_time(And(init, Not(lemma)), 0),
                                comment="Init check")
            res = self._solve(self.solver)

            prefix = None
            if self.config.prefix is not None:
                prefix = self.config.prefix + "-ind"

            if res:
                if Logger.level(2):
                    Logger.log("Lemma \"%s\" failed for I -> L" % lemma, 2)
                    (hr_trace, vcd_trace) = self.print_trace(
                        hts,
                        self._get_model(self.solver),
                        0,
                        prefix=prefix,
                        map_function=self.config.map_function)
                    Logger.log("", 2)
                    if hr_trace:
                        Logger.log("Counterexample: \n%s" % (hr_trace), 2)
                    else:
                        Logger.log("", 2)
                return False
            else:
                Logger.log("Lemma \"%s\" holds for I -> L" % lemma, 2)

            return True
Example #8
0
    def solve_safety_fwd(self, hts, prop, k, k_min):
        init = hts.single_init()
        trans = hts.single_trans()
        invar = hts.single_invar()

        t = k_min
        while (t < k+1):
            self._reset_assertions(self.solver)
            formula = And(init, invar)
            formula = self.at_time(formula, 0)
            Logger.log("Add init and invar", 2)
            self._add_assertion(self.solver, formula)

            trans_t = self.unroll(trans, invar, t)
            self._add_assertion(self.solver, trans_t)

            propt = self.at_time(Not(prop), t)
            Logger.log("Add property time %d"%t, 2)
            self._add_assertion(self.solver, propt)

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

            t += 1

        return (t-1, None)
Example #9
0
    def solve_safety_inc_zz(self, hts, prop, k):
        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()

        initt = self.at_time(And(init, invar), 0)
        Logger.log("Add init at_0", 2)
        self._add_assertion(self.solver, initt)

        propt = self.at_ptime(And(Not(prop), invar), -1)
        Logger.log("Add property pat_%d" % 0, 2)
        self._add_assertion(self.solver, propt)

        t = 0
        while (t < k + 1):
            self._push(self.solver)
            even = (t % 2) == 0
            th = int(t / 2)

            if even:
                eq = And([
                    EqualsOrIff(self.at_time(v, th), self.at_ptime(v, th - 1))
                    for v in hts.vars
                ])
            else:
                eq = And([
                    EqualsOrIff(self.at_time(v, th + 1),
                                self.at_ptime(v, th - 1)) for v in hts.vars
                ])

            Logger.log("Add equivalence time %d" % t, 2)
            self._add_assertion(self.solver, eq)

            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)

            if even:
                trans_t = self.unroll(trans, invar, th + 1, th)
            else:
                trans_t = self.unroll(trans, invar, th, th + 1)

            self._add_assertion(self.solver, trans_t)

            t += 1

        return (t - 1, None)
Example #10
0
    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)
Example #11
0
    def solve_inc(self, hts, prop, k, all_vars=True):

        if all_vars:
            relevant_vars = hts.vars
        else:
            relevant_vars = hts.state_vars | hts.input_vars | hts.output_vars

        init = hts.single_init()
        trans = hts.single_trans()
        invar = hts.single_invar()

        init = And(init, invar)
        init_0 = self.at_time(init, 0)

        nprop = self.enc.to_nnf(Not(prop))

        self._reset_assertions(self.solver)
        self._add_assertion(self.solver, init_0)

        for t in range(1, k + 1, 1):

            trans_t = self.unroll(trans, invar, t)
            self._add_assertion(self.solver, trans_t)

            lb = self.all_simple_loopbacks(relevant_vars, t)

            self._push(self.solver)
            self._push(self.solver)

            nprop_k = self.enc.encode(nprop, 0, t)
            self._add_assertion(self.solver, And(nprop_k, Not(Or(lb))))

            if self._solve(self.solver):
                Logger.log("Counterexample (no-loop) found with k=%s" % (t), 1)
                model = self._get_model(self.solver)
                return (t, model)

            nltlprop = []

            self._pop(self.solver)

            for l in range(t + 1):
                nprop_l = self.enc.encode_l(nprop, 0, t, l)
                nltlprop.append(And(lb[l], nprop_l))

            self._add_assertion(self.solver, Or(nltlprop))

            if self._solve(self.solver):
                Logger.log("Counterexample (with-loop) 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)

        return (k - 1, None)
Example #12
0
    def is_available(self):
        if shutil.which(CMD) is None:
            return False

        print_level = 3
        if not Logger.level(print_level):
            saved_stdout = suppress_output()
        
        retval = os.system("%s -h"%CMD)

        if not Logger.level(print_level):
            restore_output(saved_stdout)

        if retval != 0:
            return False
        
        return True
Example #13
0
    def _solve(self, solver):
        self._write_smt2_log(solver, "(check-sat)")
        self._write_smt2_log(solver, "")

        if self.config.skip_solving:
            return None

        if Logger.level(2):
            timer = Logger.start_timer("Solve")

        r = solver.solver.solve()

        if Logger.level(2):
            self.total_time += Logger.get_timer(timer)
            Logger.log("Total time solve: %.2f sec" % self.total_time, 1)

        return r
Example #14
0
    def add_lemmas(self, hts, prop, lemmas):
        if len(lemmas) == 0:
            return (hts, False)

        self._reset_assertions(self.solver)

        h_init = hts.single_init()
        h_trans = hts.single_trans()

        holding_lemmas = []
        lindex = 1
        nlemmas = len(lemmas)
        tlemmas = 0
        flemmas = 0
        for lemma in lemmas:
            Logger.log("\nChecking Lemma %s/%s" % (lindex, nlemmas), 1)
            invar = hts.single_invar()
            init = And(h_init, invar)
            trans = And(invar, h_trans, TS.to_next(invar))
            if self._check_lemma(hts, lemma, init, trans):
                holding_lemmas.append(lemma)
                hts.add_assumption(lemma)
                hts.reset_formulae()

                Logger.log("Lemma %s holds" % (lindex), 1)
                tlemmas += 1
                if self._suff_lemmas(prop, holding_lemmas):
                    return (hts, True)
            else:
                Logger.log("Lemma %s does not hold" % (lindex), 1)
                flemmas += 1

            msg = "%s T:%s F:%s U:%s" % (status_bar(
                (float(lindex) / float(nlemmas)), False), tlemmas, flemmas,
                                         (nlemmas - lindex))
            Logger.inline(msg, 0, not (Logger.level(1)))
            lindex += 1

        Logger.clear_inline(0, not (Logger.level(1)))

        for lemma in holding_lemmas:
            hts.add_assumption(lemma)
        return (hts, False)
Example #15
0
    def solve(self, hts, prop, k, lemmas=None):
        if lemmas is not None:
            (hts, res) = self.add_lemmas(hts, prop, lemmas)
            if res:
                Logger.log("Lemmas imply the property", 1)
                Logger.log("", 0, not (Logger.level(1)))
                return (0, True)

        hts.reset_formulae()

        return self.solve_inc(hts, prop, k)
Example #16
0
def available(toolname, optiongrep=None):
    if shutil.which(toolname) is None:
        return False

    print_level = 3
    if not Logger.level(print_level):
        saved_status = suppress_output()

    # assuming there's a -h for the program
    # yosys and verific have it
    retval = os.system("{} -h".format(toolname))

    if not Logger.level(print_level):
        restore_output(saved_status)

    if optiongrep is not None:
        with open(saved_status[0].name, 'r') as f:
            output = f.read()
            if optiongrep not in output:
                return False

    return (retval == 0)
Example #17
0
    def solve_safety(self, hts, prop, k, k_min=0, lemmas=None, processes=1):
        if lemmas is not None:
            (hts, res) = self.add_lemmas(hts, prop, lemmas)
            if res:
                Logger.log("Lemmas imply the property", 1)
                Logger.log("", 0, not(Logger.level(1)))
                return (0, True)

        hts.reset_formulae()

        if self.config.incremental:
            return self.solve_safety_inc(hts, prop, k, k_min, processes)

        return self.solve_safety_ninc(hts, prop, k, k_min)
Example #18
0
    def solve_problems(self, problems, config):
        if len(problems.problems) == 0:
            Logger.error("No problems defined")

        if VerificationType.LTL in [
                problem.verification for problem in problems.problems
        ]:
            ltl_reset_env()

        # generate systems for each problem configuration
        systems = {}
        for si in problems.symbolic_inits:
            (systems[('hts', si)], _, _) = self.parse_model(problems.relative_path, \
                                                            problems.model_file, \
                                                            problems.abstract_clock, si, "System 1", \
                                                            boolean=problems.boolean, \
                                                            no_clock=problems.no_clock, \
                                                            run_passes=problems.run_coreir_passes)

        if problems.equivalence is not None:
            (systems[('hts2', si)], _, _) = self.parse_model(problems.relative_path, \
                                                             problems.equivalence, \
                                                             problems.abstract_clock, si, "System 2", \
                                                             boolean=problems.boolean, \
                                                             no_clock=problems.no_clock, \
                                                             run_passes=problems.run_coreir_passes)
        else:
            systems[('hts2', si)] = None

        for problem in problems.problems:
            problem.hts = systems[('hts', problem.symbolic_init)]
            problem.hts2 = systems[('hts2', problem.symbolic_init)]
            problem.abstract_clock = problems.abstract_clock
            problem.no_clock = problems.no_clock
            problem.run_coreir_passes = problems.run_coreir_passes
            problem.relative_path = problems.relative_path

            if config.time or problems.time:
                timer_solve = Logger.start_timer("Problem %s" % problem.name,
                                                 False)
            try:
                self.solve_problem(problem, config)
                Logger.msg(" %s\n" % problem.status, 0, not (Logger.level(1)))

                if config.time or problems.time:
                    problem.time = Logger.get_timer(timer_solve, False)

            except KeyboardInterrupt as e:
                Logger.msg("\b\b Skipped!\n", 0)
Example #19
0
    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)
Example #20
0
    def solve_liveness(self,
                       hts,
                       prop,
                       k,
                       k_min=0,
                       eventually=False,
                       lemmas=None):
        if lemmas is not None:
            (hts, res) = self.add_lemmas(hts, prop, lemmas)
            if res:
                Logger.log("Lemmas imply the property", 1)
                Logger.log("", 0, not (Logger.level(1)))
                return (0, True)

        if self.config.incremental:
            return self.solve_liveness_inc(hts, prop, k, k_min, eventually)

        return self.solve_liveness_fwd(hts, prop, k)
Example #21
0
    def solve_safety_inc_fwd(self, hts, prop, k, k_min, \
                             all_vars=False, generalize=None, prove=None):

        add_unsat_cons = False
        prove = self.config.prove if prove is None else prove

        solver_name = "inc_fwd%s"%("_prove" if prove else "")
        solver = self.solver.copy(solver_name)

        self._reset_assertions(solver)

        if prove:
            solver_ind = self.solver.copy("%s_ind"%solver_name)
            self._reset_assertions(solver_ind)

            if all_vars:
                relevant_vars = hts.vars
            else:
                relevant_vars = hts.state_vars | hts.output_vars

        init = hts.single_init()
        trans = hts.single_trans()
        invar = hts.single_invar()

        acc_init = TRUE()
        acc_prop = TRUE()
        acc_loop_free = TRUE()
        trans_t = TRUE()

        if self.config.simplify:
            Logger.log("Simplifying the Transition System", 1)
            if Logger.level(2):
                timer = Logger.start_timer("Simplify")

            init = simplify(init)
            trans = simplify(trans)
            invar = simplify(invar)
            if Logger.level(2):
                Logger.get_timer(timer)

        n_prop_t = FALSE()
        init_0 = self.at_time(And(init, invar), 0)
        Logger.log("Add init and invar", 2)
        self._add_assertion(solver, init_0)

        if prove:
            # add invariants at time 0, but not init
            self._add_assertion(solver_ind, self.at_time(invar, 0), "invar")

        next_prop = TS.has_next(prop)
        if next_prop:
            if k < 1:
                Logger.error("Invariant checking with next variables requires at least k=1")
            k_min = 1

        skip_push = False

        constraints = TRUE()

        t = k_min
        for i in range(t):
            trans_t = self.unroll(trans, invar, i+1, i)
            self._add_assertion(solver, trans_t)
            Logger.msg("Unroll and call check-sat without property", 2)
            # Note: Seems to help a lot to call check-sat here
            #       without this some solvers will run out of memory on large problems
            #       it likely lets them do some internal clean up, and learn some things
            #       about the model
            self._solve(solver)
            Logger.msg("_", 0, not(Logger.level(1)))
        while (t < k+1):
            if not skip_push:
                self._push(solver)
                skip_push = False

            t_prop = t-1 if next_prop else t

            if k_min > 0:
                if (not next_prop) or (next_prop and t>0):
                    if n_prop_t == FALSE():
                        n_prop_t = self.at_time(Not(prop), t_prop)
                    else:
                        n_prop_t = Or(n_prop_t, self.at_time(Not(prop), t_prop))
            else:
                n_prop_t = self.at_time(Not(prop), t)

            Logger.log("Add not property at time %d"%t, 2)
            if not skip_push:
                self._add_assertion(solver, n_prop_t, "Property")

            if constraints != TRUE():
                self._add_assertion(solver, self.at_time(constraints, t), "Addditional Constraints")

            if t >= k_min:
                Logger.log("\nSolving for k=%s"%(t), 1)

                if self.preferred is not None:
                    try:
                        for (var, val) in self.preferred:
                            for j in range(t+1):
                                solver.solver.set_preferred_var(TS.get_timed(var, j), val)
                    except:
                        Logger.warning("Current solver does not support preferred variables")
                        self.preferred = None

                if self._solve(solver):
                    Logger.log("Counterexample found with k=%s"%(t), 1)
                    model = self._get_model(solver)

                    if generalize is not None:
                        constr, res = generalize(model, t)
                        if res:
                            return (t, model)
                        constraints = And(constraints, Not(constr))
                        skip_push = True
                        continue
                    else:
                        return (t, model)
                else:
                    Logger.log("No counterexample found with k=%s"%(t), 1)
                    Logger.msg(".", 0, not(Logger.level(1)))

                    if add_unsat_cons and prove:
                        self._add_assertion(solver, Implies(self.at_time(And(init, invar), 1), self.at_time(Not(prop), t_prop+1)))
                        self._add_assertion(solver, Not(n_prop_t))
            else:
                Logger.log("\nSkipping solving for k=%s (k_min=%s)"%(t,k_min), 1)
                Logger.msg("_", 0, not(Logger.level(1)))

            self._pop(solver)
            skip_push = False

            if prove:
                if t > k_min:
                    loop_free = self.loop_free(relevant_vars, t, t-1)

                    # Checking I & T & loopFree
                    acc_init = And(acc_init, self.at_time(Not(init), t))
                    acc_loop_free = And(acc_loop_free, loop_free)

                    self._push(solver)

                    self._add_assertion(solver, acc_init)
                    self._add_assertion(solver, acc_loop_free)

                    if self._solve(solver):
                        Logger.log("Induction (I & lF) failed with k=%s"%(t), 1)
                    else:
                        Logger.log("Induction (I & lF) holds with k=%s"%(t), 1)
                        return (t, True)

                    self._pop(solver)

                    # Checking T & loopFree & !P
                    self._add_assertion(solver_ind, trans_t, comment="trans")
                    self._add_assertion(solver_ind, loop_free, comment="loop_free")

                    self._push(solver_ind)

                    self._add_assertion(solver_ind, self.at_time(Not(prop), t_prop))

                    if self._solve(solver_ind):
                        Logger.log("Induction (lF & !P) failed with k=%s"%(t), 1)
                    else:
                        Logger.log("Induction (lF & !P) holds with k=%s"%(t), 1)
                        return (t, True)

                    self._pop(solver_ind)

                    self._add_assertion(solver_ind, self.at_time(prop, t_prop), "prop")
                else:
                    if not next_prop:
                        self._add_assertion(solver_ind, self.at_time(prop, t_prop), "prop")
                    else:
                        # add skipped transition
                        self._add_assertion(solver_ind, trans_t, comment="trans")


            trans_t = self.unroll(trans, invar, t+1, t)
            self._add_assertion(solver, trans_t)

            t += 1

        return (t-1, None)
Example #22
0
    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)
Example #23
0
File: btor2.py Project: pllab/CoSA
    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)
Example #24
0
    def solve_safety_inc_bwd(self, hts, prop, k, assert_property=False, generalize=None):
        solver = self.solver.copy("inc_bwd")

        self._reset_assertions(solver)

        has_next = TS.has_next(prop)

        if has_next:
            prop = TS.to_prev(prop)

        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(solver, formula)

        skip_push = False
        constraints = TRUE()

        models = 0

        t = 0
        k_min = 1 if has_next else 0
        while (t < k+1):
            if not skip_push:
                self._push(solver)
                skip_push = False

            if not skip_push:
                pinit = self.at_ptime(init, t-1)
                Logger.log("Add init at time %d"%t, 2)
                self._add_assertion(solver, pinit)

            if constraints != TRUE():
                for j in range(t+1):
                    self._add_assertion(solver, self.at_ptime(constraints, j-1), "Addditional Constraints")

            if self.preferred is not None:
                try:
                    for (var, val) in self.preferred:
                        solver.solver.set_preferred_var(TS.get_timed(var, t), val)
                except:
                    Logger.warning("Current solver does not support preferred variables")
                    self.preferred = None

            if (t >= k_min) and self._solve(solver):
                Logger.log("Counterexample found with k=%s"%(t), 1)
                model = self._get_model(solver)
                models += 1

                if models > 20:
                    Logger.msg("R", 0, not(Logger.level(1)))
                    self._reset_solver(solver)
                    models = 0

                if generalize is not None:
                    constr, res = generalize(model, t)
                    if res:
                        return (t, model)
                    constraints = And(constraints, Not(constr))
                    skip_push = True
                    continue
                else:
                    return (t, model)
            else:
                Logger.log("No counterexample found with k=%s"%(t), 1)
                Logger.msg(".", 0, not(Logger.level(1)))

            self._pop(solver)
            skip_push = False

            trans_t = self.unroll(trans, invar, t, t+1)
            self._add_assertion(solver, trans_t)

            if assert_property and t > 0:
                prop_t = self.unroll(TRUE(), prop, t-1, t)
                self._add_assertion(solver, prop_t)

                Logger.log("Add property at time %d"%t, 2)

            t += 1

        return (t-1, None)
Example #25
0
    def solve_problems(self, problems, config):
        encoder_config = self.problems2encoder_config(config, problems)

        self.sparser = StringParser(encoder_config)
        self.lparser = LTLParser()

        self.coi = ConeOfInfluence()

        invar_props = []
        ltl_props = []
        si = False

        if len(problems.symbolic_inits) == 0:
            problems.symbolic_inits.add(si)

        HTSM = 0
        HTS2 = 1
        HTSD = (HTSM, si)

        model_extension = config.model_extension if problems.model_extension is None else problems.model_extension
        assume_if_true = config.assume_if_true or problems.assume_if_true
        cache_files = config.cache_files or problems.cache_files
        clean_cache = config.clean_cache

        modifier = None
        if model_extension is not None:
            modifier = lambda hts: ModelExtension.extend(
                hts, ModelModifiersFactory.modifier_by_name(model_extension))

        # generate systems for each problem configuration
        systems = {}
        for si in problems.symbolic_inits:
            encoder_config.symbolic_init = si
            (systems[(HTSM, si)], invar_props, ltl_props) = self.parse_model(problems.relative_path, \
                                                                             problems.model_file, \
                                                                             encoder_config, \
                                                                             "System 1", \
                                                                             modifier, \
                                                                             cache_files=cache_files, \
                                                                             clean_cache=clean_cache)

        if problems.equivalence is not None:
            (systems[(HTS2, si)], _, _) = self.parse_model(problems.relative_path, \
                                                           problems.equivalence, \
                                                           encoder_config, \
                                                           "System 2", \
                                                           cache_files=cache_files, \
                                                           clean_cache=clean_cache)
        else:
            systems[(HTS2, si)] = None

        if config.safety or config.problems:
            for invar_prop in invar_props:
                inv_prob = problems.new_problem()
                inv_prob.verification = VerificationType.SAFETY
                inv_prob.name = invar_prop[0]
                inv_prob.description = invar_prop[1]
                inv_prob.formula = invar_prop[2]
                problems.add_problem(inv_prob)

        if config.ltl or config.problems:
            for ltl_prop in ltl_props:
                ltl_prob = problems.new_problem()
                ltl_prob.verification = VerificationType.LTL
                ltl_prob.name = ltl_prop[0]
                ltl_prob.description = ltl_prop[1]
                ltl_prob.formula = ltl_prop[2]
                problems.add_problem(ltl_prob)

        if HTSD in systems:
            problems._hts = systems[HTSD]

        for problem in problems.problems:
            problem.hts = systems[(HTSM, problem.symbolic_init)]

            if problems._hts is None:
                problems._hts = problem.hts
            problem.hts2 = systems[(HTS2, problem.symbolic_init)]
            if problems._hts2 is None:
                problems._hts2 = problem.hts2
            problem.vcd = problems.vcd or config.vcd or problem.vcd
            problem.abstract_clock = problems.abstract_clock or config.abstract_clock
            problem.add_clock = problems.add_clock or config.add_clock
            problem.coi = problems.coi or config.coi
            problem.run_coreir_passes = problems.run_coreir_passes
            problem.relative_path = problems.relative_path
            problem.cardinality = max(problems.cardinality, config.cardinality)

            if not problem.full_trace:
                problem.full_trace = problems.full_trace
            if not problem.trace_vars_change:
                problem.trace_vars_change = problems.trace_vars_change
            if not problem.trace_all_vars:
                problem.trace_all_vars = problems.trace_all_vars
            if not problem.clock_behaviors:
                clk_bhvs = [
                    p for p in
                    [problems.clock_behaviors, config.clock_behaviors]
                    if p is not None
                ]
                if len(clk_bhvs) > 0:
                    problem.clock_behaviors = ";".join(clk_bhvs)
            if not problem.generators:
                problem.generators = config.generators

            Logger.log(
                "Solving with abstract_clock=%s, add_clock=%s" %
                (problem.abstract_clock, problem.add_clock), 2)

            if problem.trace_prefix is not None:
                problem.trace_prefix = "".join(
                    [problem.relative_path, problem.trace_prefix])

            if config.time or problems.time:
                timer_solve = Logger.start_timer("Problem %s" % problem.name,
                                                 False)
            try:
                self.__solve_problem(problem, config)

                if problem.verification is None:
                    Logger.log("Unset verification", 2)
                    continue

                Logger.msg(" %s\n" % problem.status, 0, not (Logger.level(1)))

                if (assume_if_true) and \
                   (problem.status == VerificationStatus.TRUE) and \
                   (problem.assumptions == None) and \
                   (problem.verification == VerificationType.SAFETY):

                    ass_ts = TS("Previous assumption from property")
                    if TS.has_next(problem.formula):
                        ass_ts.trans = problem.formula
                    else:
                        ass_ts.invar = problem.formula
                    problem.hts.reset_formulae()

                    problem.hts.add_ts(ass_ts)

                if config.time or problems.time:
                    problem.time = Logger.get_timer(timer_solve, False)

            except KeyboardInterrupt as e:
                Logger.msg("\b\b Skipped!\n", 0)
Example #26
0
    def parse_model(self, \
                    relative_path, \
                    model_files, \
                    encoder_config, \
                    name=None, \
                    modifier=None, \
                    cache_files=False, \
                    clean_cache=False):

        hts = HTS(name if name is not None else "System")
        invar_props = []
        ltl_props = []

        models = model_files.split(FILE_SP)

        for strfile in models:
            (strfile, flags) = self.get_file_flags(strfile)
            filetype = strfile.split(".")[-1]
            strfile = strfile.replace("~", os.path.expanduser("~"))
            if strfile[0] != "/":
                strfile = relative_path + strfile
            parser = None

            for av_parser in ModelParsersFactory.get_parsers():
                assert av_parser.name is not None
                if filetype in av_parser.get_extensions():
                    parser = av_parser
                    if not self.parser:
                        self.parser = av_parser

            if parser is not None:
                if not os.path.isfile(strfile):
                    Logger.error("File \"%s\" does not exist" % strfile)

                if cache_files:
                    md5 = self.md5(strfile)
                    cf = "-".join(["1" if encoder_config.abstract_clock else "0", \
                                   "1" if encoder_config.add_clock else "0", \
                                   "1" if encoder_config.boolean else "0"])
                    cachefile = "%s-%s" % (md5, cf)
                    cachedir = "%s/%s" % ("/".join(
                        strfile.split("/")[:-1]), COSACACHEDIR)

                if cache_files and self._is_cached(cachedir, cachefile,
                                                   clean_cache):
                    Logger.msg(
                        "Loading from cache file \"%s\"... " % (strfile), 0)
                    (hts_a, inv_a, ltl_a,
                     model_info) = self._from_cache(cachedir, cachefile,
                                                    encoder_config, flags)
                else:
                    Logger.msg("Parsing file \"%s\"... " % (strfile), 0)
                    (hts_a, inv_a,
                     ltl_a) = parser.parse_file(strfile, encoder_config, flags)

                    model_info = parser.get_model_info()

                    if modifier is not None:
                        modifier(hts_a)

                    if cache_files and not clean_cache:
                        self._to_cache(cachedir, cachefile, hts_a, inv_a,
                                       ltl_a, model_info)

                self.model_info.combine(model_info)
                hts.combine(hts_a)

                invar_props += inv_a
                ltl_props += ltl_a

                Logger.log("DONE", 0)
                continue

            Logger.error(
                "Filetype \"%s\" unsupported or parser is not available" %
                filetype)

        if Logger.level(1):
            print(hts.print_statistics(name, Logger.level(2)))

        return (hts, invar_props, ltl_props)
Example #27
0
    def __solve_problem(self, problem, config):
        if problem.name is not None:
            Logger.log("\n*** Analyzing problem \"%s\" ***" % (problem), 1)
            Logger.msg("Solving \"%s\" " % problem.name, 0,
                       not (Logger.level(1)))

        parsing_defs = [problem.formula, problem.lemmas, problem.assumptions]
        for i in range(len(parsing_defs)):
            if parsing_defs[i] is not None:
                pdef_file = problem.relative_path + parsing_defs[i]
                if os.path.isfile(pdef_file):
                    with open(pdef_file) as f:
                        parsing_defs[i] = [
                            p.strip() for p in f.read().strip().split("\n")
                        ]
                else:
                    parsing_defs[i] = [
                        p.strip() for p in parsing_defs[i].split(MODEL_SP)
                    ]
            else:
                parsing_defs[i] = None

        [formulae, problem.lemmas, problem.assumptions] = parsing_defs

        ParametricBehavior.apply_to_problem(problem, self.model_info)

        assumps = None
        lemmas = None

        trace = None
        traces = None

        if formulae is None:
            if problem.verification == VerificationType.SIMULATION:
                formulae = ["True"]
            elif (problem.verification is not None) and (
                    problem.verification != VerificationType.EQUIVALENCE):
                Logger.error("Property not provided")

        accepted_ver = False

        if formulae is not None:
            problem.formula = formulae[0]

        precondition = config.precondition if config.precondition is not None else problem.precondition

        if precondition and problem.verification == VerificationType.SAFETY:
            problem.formula = "(%s) -> (%s)" % (precondition, problem.formula)

        if (problem.verification != VerificationType.EQUIVALENCE) and (
                problem.formula is not None):
            assumps = [
                t[1] for t in self.sparser.parse_formulae(problem.assumptions)
            ]
            lemmas = [
                t[1] for t in self.sparser.parse_formulae(problem.lemmas)
            ]
            for ass in assumps:
                problem.hts.add_assumption(ass)
            for lemma in lemmas:
                problem.hts.add_lemma(lemma)
            if problem.verification != VerificationType.LTL:
                (strprop, prop,
                 types) = self.sparser.parse_formulae([problem.formula])[0]
            else:
                (strprop, prop,
                 types) = self.lparser.parse_formulae([problem.formula])[0]

            problem.formula = prop

        if problem.verification is None:
            return problem

        if problem.coi:
            if Logger.level(2):
                timer = Logger.start_timer("COI")
            problem.hts = self.coi.compute(problem.hts, problem.formula)
            if Logger.level(2):
                Logger.get_timer(timer)

        mc_config = self.problem2mc_config(problem, config)
        bmc_safety = BMCSafety(problem.hts, mc_config)
        bmc_parametric = BMCParametric(problem.hts, mc_config)
        bmc_ltl = BMCLTL(problem.hts, mc_config)
        res = VerificationStatus.UNC
        bmc_length = max(problem.bmc_length, config.bmc_length)
        bmc_length_min = max(problem.bmc_length_min, config.bmc_length_min)

        if problem.verification == VerificationType.SAFETY:
            accepted_ver = True
            Logger.log("Property: %s" % (prop.serialize(threshold=100)), 2)
            res, trace, _ = bmc_safety.safety(prop, bmc_length, bmc_length_min,
                                              config.processes)

        if problem.verification == VerificationType.LTL:
            accepted_ver = True
            res, trace, _ = bmc_ltl.ltl(prop, bmc_length, bmc_length_min)

        if problem.verification == VerificationType.SIMULATION:
            accepted_ver = True
            res, trace = bmc_safety.simulate(prop, bmc_length)

        if problem.verification == VerificationType.PARAMETRIC:
            accepted_ver = True
            Logger.log("Property: %s" % (prop.serialize(threshold=100)), 2)
            res, traces, problem.region = bmc_parametric.parametric_safety(
                prop,
                bmc_length,
                bmc_length_min,
                ModelExtension.get_parameters(problem.hts),
                at_most=problem.cardinality)

        hts = problem.hts

        if problem.verification == VerificationType.EQUIVALENCE:
            accepted_ver = True
            htseq, miter_out = Miter.combine_systems(problem.hts, \
                                                     problem.hts2, \
                                                     bmc_length, \
                                                     problem.symbolic_init, \
                                                     problem.formula, \
                                                     True)

            if problem.assumptions is not None:
                assumps = [
                    t[1]
                    for t in self.sparser.parse_formulae(problem.assumptions)
                ]

            if problem.lemmas is not None:
                lemmas = [
                    t[1] for t in self.sparser.parse_formulae(problem.lemmas)
                ]

            if assumps is not None:
                for assumption in assumps:
                    htseq.add_assumption(assumption)

            if lemmas is not None:
                for lemma in lemmas:
                    htseq.add_lemma(lemma)

            bmcseq = BMCSafety(htseq, mc_config)
            hts = htseq
            res, trace, t = bmcseq.safety(miter_out, bmc_length,
                                          bmc_length_min)

        if not accepted_ver:
            Logger.error("Invalid verification type")

        problem.status = res
        if trace is not None:
            problem.traces = self.__process_trace(hts, trace, config, problem)

        if traces is not None:
            problem.traces = []
            for trace in traces:
                problem.traces += self.__process_trace(hts, trace, config,
                                                       problem)

        if problem.assumptions is not None:
            problem.hts.assumptions = None

        Logger.log("\n*** Problem \"%s\" is %s ***" % (problem, res), 1)
Example #28
0
    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)
Example #29
0
    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)
Example #30
0
    def solve_safety_inc_int(self, hts, prop, k):
        init = hts.single_init()
        trans = hts.single_trans()
        invar = hts.single_invar()

        solver_proof = self.solver.copy("inc_int_proof")
        solver = self.solver.copy("inc_int")

        has_next = TS.has_next(prop)

        map_10 = dict([(TS.get_timed_name(v.symbol_name(), 1), TS.get_timed_name(v.symbol_name(), 0)) for v in hts.vars])

        itp = Interpolator(logic=get_logic(trans))
        init = And(init, invar)
        nprop = Not(prop)

        def check_overappr(Ri, R):
            self._reset_assertions(solver_proof)
            self._add_assertion(solver_proof, And(Ri, Not(R)))

            if not self._solve(solver_proof):
                Logger.log("Proof found with k=%s"%(t), 1)
                return TRUE()

            Logger.log("Extending initial states (%s)"%int_c, 1)
            return Or(R, Ri)

        t = 1 if has_next else 0

        trans_t = self.unroll(trans, invar, k+1, gen_list=True)

        pivot = 2
        trans_tA = And(trans_t[:pivot])
        init_0 = self.at_time(init, 0)

        is_sat = True
        Ri = None

        self._reset_assertions(solver)

        while (t < k+1):
            Logger.log("\nSolving for k=%s"%t, 1)
            int_c = 0
            R = init_0

            # trans_t is composed as trans_i, invar_i, trans_i+1, invar_i+1, ...
            self._add_assertion(solver, trans_t[2*t])
            self._add_assertion(solver, trans_t[(2*t)+1])

            while True:
                Logger.log("Add init and invar", 2)
                self._push(solver)
                self._add_assertion(solver, R)

                npropt = self.at_time(nprop, t-1 if has_next else t)
                Logger.log("Add property time %d"%t, 2)
                self._add_assertion(solver, npropt)

                Logger.log("Interpolation at k=%s"%(t), 2)

                if t > 0:
                    trans_tB = And(trans_t[pivot:(t*2)])
                    Ri = And(itp.binary_interpolant(And(R, trans_tA), And(trans_tB, npropt)))
                    is_sat = Ri == None

                if is_sat and self._solve(solver):
                    if R == init_0:
                        Logger.log("Counterexample found with k=%s"%(t), 1)
                        model = self._get_model(solver)
                        return (t, model)
                    else:
                        Logger.log("No counterexample or proof found with k=%s"%(t), 1)
                        Logger.msg(".", 0, not(Logger.level(1)))
                        self._pop(solver)
                        break
                else:
                    self._pop(solver)
                    if Ri is None:
                        break

                    Ri = substitute(Ri, map_10)
                    res = check_overappr(Ri, R)

                    if res == TRUE():
                        Logger.log("Proof found with k=%s"%(t), 1)
                        return (t, True)

                    R = res
                    int_c += 1

            t += 1

        return (t-1, None)