Esempio n. 1
0
def test_next():
    reset_env()
    arrtype = ArrayType(BVType(3), BVType(4))
    arr = Symbol("arr", arrtype)
    idx = Symbol("idx", BVType(3))
    parser = StringParser()
    [(_, f, _)] = parser.parse_formulae(["next(arr)[idx]"])
    assert (f.args()[1] == idx)
Esempio n. 2
0
def run_verification(config):
    reset_env()
    Logger.verbosity = config.verbosity

    coreir_parser = None
    ets_parser = None
    sts_parser = None

    if config.ltl:
        ltl_reset_env()

    hts = HTS("Top level")

    if config.strfiles[0][-4:] != ".pkl":
        ps = ProblemSolver()
        (hts, invar_props,
         ltl_props) = ps.parse_model("./",
                                     config.strfiles,
                                     config.abstract_clock,
                                     config.symbolic_init,
                                     deterministic=config.deterministic,
                                     boolean=config.boolean,
                                     no_clock=config.no_clock)
        config.parser = ps.parser

        if config.pickle_file:
            Logger.msg("Pickling model to %s\n" % (config.pickle_file), 1)
            sys.setrecursionlimit(50000)
            with open(config.pickle_file, "wb") as f:
                pickle.dump(hts, f)
    else:
        if config.pickle_file:
            raise RuntimeError("Don't need to re-pickle the input file %s" %
                               (config.strfile))

        Logger.msg("Loading pickle file %s\n" % (config.strfile), 0)
        with open(config.pickle_file, "rb") as f:
            hts = pickle.load(f)
        Logger.log("DONE", 0)

    printsmv = True

    mc_config = MCConfig()

    sparser = StringParser()
    sparser.remap_or2an = config.parser.remap_or2an
    ltlparser = LTLParser()

    # if equivalence checking wait to add assumptions to combined system
    if config.assumptions is not None and config.equivalence is None:
        Logger.log("Adding %d assumptions... " % len(config.assumptions), 1)
        assumps = [t[1] for t in sparser.parse_formulae(config.assumptions)]
        hts.assumptions = assumps

    lemmas = None
    if config.lemmas is not None:
        Logger.log("Adding %d lemmas... " % len(config.lemmas), 1)
        parsed_formulae = sparser.parse_formulae(config.lemmas)
        if list(set([t[2] for t in parsed_formulae]))[0][0] != False:
            Logger.error("Lemmas do not support \"next\" operators")
        lemmas = [t[1] for t in parsed_formulae]
        hts.lemmas = lemmas

    mc_config.smt2file = config.smt2file

    mc_config.full_trace = config.full_trace
    mc_config.trace_vars_change = config.trace_vars_change
    mc_config.trace_all_vars = config.trace_all_vars
    mc_config.prefix = config.prefix
    mc_config.strategy = config.strategy
    mc_config.skip_solving = config.skip_solving
    mc_config.map_function = config.parser.remap_an2or
    mc_config.solver_name = config.solver_name
    mc_config.vcd_trace = config.vcd
    mc_config.prove = config.prove
    mc_config.incremental = config.incremental

    if config.ltl:
        bmc_ltl = BMCLTL(hts, mc_config)
    else:
        bmc_safety = BMCSafety(hts, mc_config)

    if config.translate:
        Logger.log("Writing system to \"%s\"" % (config.translate), 0)
        printer = PrintersFactory.printer_by_name(config.printer)

        props = []
        if config.ltl:
            props += ltlparser.parse_formulae(config.properties)
            props += [(str(p), p, None) for p in ltl_props]
        else:
            props += sparser.parse_formulae(config.properties)
            props += [(str(p), p, None) for p in invar_props]

        with open(config.translate, "w") as f:
            f.write(printer.print_hts(hts, props))

    if config.simulate:
        count = 0
        if config.properties is None:
            props = [("True", TRUE(), None)]
        else:
            props = sparser.parse_formulae(config.properties)
        for (strprop, prop, _) in props:
            Logger.log("Simulation for property \"%s\":" % (strprop), 0)
            res, trace = bmc_safety.simulate(prop, config.bmc_length)
            if res == VerificationStatus.TRUE:
                count += 1
                print_trace("Execution", trace, count, config.prefix)
            else:
                Logger.log("No execution found", 0)

    if config.safety:
        count = 0
        props = sparser.parse_formulae(config.properties)
        props += [(str(p), p, None) for p in invar_props]
        if len(props) == 0:
            Logger.warning("Safety verification requires at least a property")

        for (strprop, prop, _) in props:
            Logger.log("Safety verification for property \"%s\":" % (strprop),
                       0)
            res, trace, t = bmc_safety.safety(prop, config.bmc_length,
                                              config.bmc_length_min)
            Logger.log("\nProperty is %s" % res, 0)
            if res == VerificationStatus.FALSE:
                count += 1
                print_trace("Counterexample", trace, count, config.prefix)

        return 0

    if config.equivalence or config.fsm_check:

        if config.equivalence:
            parser2 = CoreIRParser(config.abstract_clock, config.symbolic_init,
                                   config.run_passes)

            Logger.msg("Parsing file \"%s\"... " % (config.equivalence), 0)
            hts2 = parser2.parse_file(config.equivalence)
            Logger.log("DONE", 0)

            symb = " (symbolic init)" if config.symbolic_init else ""
            Logger.log(
                "Equivalence checking%s with k=%s:" %
                (symb, config.bmc_length), 0)

            if Logger.level(1):
                print(hts2.print_statistics("System 2", Logger.level(2)))
        else:
            hts2 = hts

        # TODO: Make incremental solving optional
        htseq, miter_out = Miter.combine_systems(hts, hts2, config.bmc_length,
                                                 config.symbolic_init,
                                                 config.properties, True)

        if config.assumptions is not None:
            Logger.log(
                "Adding %d assumptions to combined system... " %
                len(config.assumptions), 1)
            assumps = [
                t[1] for t in sparser.parse_formulae(config.assumptions)
            ]
            htseq.assumptions = assumps

        # create bmc object for combined system
        bmcseq = BMC(htseq, mc_config)
        res, trace, t = bmcseq.safety(miter_out, config.bmc_length,
                                      config.bmc_length_min)

        msg = "Systems are %s equivalent" if config.equivalence else "System is%s deterministic"

        if res == VerificationStatus.FALSE:
            Logger.log(msg % (" not"), 0)
            print_trace("Counterexample", trace, 1, config.prefix)
        elif res == VerificationStatus.UNK:
            if config.symbolic_init:
                # strong equivalence with symbolic initial state
                Logger.log(msg % (""), 0)
            else:
                Logger.log(msg % ("") + " up to k=%i" % t, 0)
        else:
            Logger.log(msg % ("") + " up to k=%i" % t, 0)

    if config.ltl:
        count = 0
        props = ltlparser.parse_formulae(config.properties)
        props += [(str(p), p, None) for p in ltl_props]
        if len(props) == 0:
            Logger.warning("LTL verification requires at least a property")

        for (strprop, prop, _) in props:
            Logger.log("LTL verification for property \"%s\":" % (strprop), 0)
            res, trace, t = bmc_ltl.ltl(prop, config.bmc_length,
                                        config.bmc_length_min)
            Logger.log("\nProperty is %s" % res, 0)
            if res == VerificationStatus.FALSE:
                count += 1
                print_trace("Counterexample", trace, count, config.prefix)

        return 0
Esempio n. 3
0
    def combine_systems(hts,
                        hts2,
                        k,
                        symbolic_init,
                        eqprop=None,
                        inc=True,
                        non_deterministic=False):
        htseq = HTS("eq")

        hts1_varnames = [v.symbol_name() for v in hts.vars]
        hts2_varnames = [v.symbol_name() for v in hts2.vars]

        map1 = dict([(v, TS.get_prefix_name(v, S1)) for v in hts1_varnames]+\
                    [(TS.get_prime_name(v), TS.get_prefix_name(TS.get_prime_name(v), S1)) for v in hts1_varnames])
        map2 = dict([(v, TS.get_prefix_name(v, S2)) for v in hts2_varnames]+\
                    [(TS.get_prime_name(v), TS.get_prefix_name(TS.get_prime_name(v), S2)) for v in hts2_varnames])

        ts1_init = TRUE()
        ts2_init = TRUE()

        if not symbolic_init:
            ts1_init = substitute(hts.single_init(), map1)
            ts2_init = substitute(hts2.single_init(), map2)

        ts1 = TS()
        ts1.vars = set([TS.get_prefix(v, S1) for v in hts.vars])
        ts1.set_behavior(ts1_init,\
                         substitute(hts.single_trans(), map1),\
                         substitute(hts.single_invar(), map1))
        ts1.state_vars = set([TS.get_prefix(v, S1) for v in hts.state_vars])

        ts2 = TS()
        ts2.vars = set([TS.get_prefix(v, S2) for v in hts2.vars])
        ts2.set_behavior(ts2_init,\
                         substitute(hts2.single_trans(), map2),\
                         substitute(hts2.single_invar(), map2))
        ts2.state_vars = set([TS.get_prefix(v, S2) for v in hts2.state_vars])

        htseq.add_ts(ts1)
        htseq.add_ts(ts2)

        assumptions = []
        lemmas = []

        def sets_intersect(set1, set2):
            for el in set1:
                if not el in set2:
                    return False
            return True

        if hts.assumptions is not None:
            for assumption in hts.assumptions:
                assumptions.append(assumption)

        if hts.lemmas is not None:
            for lemma in hts.lemmas:
                lemmas.append(lemma)

        if hts2.assumptions is not None:
            for assumption in hts2.assumptions:
                assumptions.append(assumption)

        if hts2.lemmas is not None:
            for lemma in hts2.lemmas:
                lemmas.append(lemma)

        for assumption in assumptions:
            fv_assumption = get_free_variables(assumption)
            c_assumption = TRUE()

            if sets_intersect(fv_assumption, hts.vars):
                c_assumption = And(c_assumption, substitute(assumption, map1))
            if sets_intersect(fv_assumption, hts2.vars):
                c_assumption = And(c_assumption, substitute(assumption, map2))

            if c_assumption != TRUE():
                htseq.add_assumption(c_assumption)

        for lemma in lemmas:
            fv_lemma = get_free_variables(lemma)
            c_lemma = TRUE()

            if sets_intersect(fv_lemma, hts.vars):
                c_lemma = And(c_lemma, substitute(lemma, map1))
            if sets_intersect(fv_lemma, hts2.vars):
                c_lemma = And(c_lemma, substitute(lemma, map2))

            if c_lemma != TRUE():
                htseq.add_lemma(c_lemma)

        miter_out = Symbol(EQS, BOOL)

        inputs = hts.input_vars.intersection(hts2.input_vars)
        outputs = hts.output_vars.intersection(hts2.output_vars)

        htseq.input_vars = set([
            TS.get_prefix(v, S1) for v in hts.input_vars
        ]).union(set([TS.get_prefix(v, S2) for v in hts2.input_vars]))
        htseq.output_vars = set([
            TS.get_prefix(v, S1) for v in hts.output_vars
        ]).union(set([TS.get_prefix(v, S2) for v in hts2.output_vars]))

        if symbolic_init or (not non_deterministic):
            states = hts.state_vars.intersection(hts2.state_vars)
        else:
            states = []

        eqinputs = TRUE()
        eqoutputs = TRUE()
        eqstates = TRUE()

        for inp in inputs:
            eqinputs = And(
                eqinputs,
                EqualsOrIff(TS.get_prefix(inp, S1), TS.get_prefix(inp, S2)))

        for out in outputs:
            eqoutputs = And(
                eqoutputs,
                EqualsOrIff(TS.get_prefix(out, S1), TS.get_prefix(out, S2)))

        for svar in states:
            eqstates = And(
                eqstates,
                EqualsOrIff(TS.get_prefix(svar, S1), TS.get_prefix(svar, S2)))

        if eqprop is None:
            if symbolic_init or (not non_deterministic):
                invar = And(eqinputs,
                            Iff(miter_out, Implies(eqstates, eqoutputs)))
            else:
                invar = And(eqinputs, Iff(miter_out, eqoutputs))

            Logger.log('Inferring equivalence property: {}'.format(invar), 2)
        else:
            sparser = StringParser()
            eqprop = sparser.parse_formulae(eqprop)
            if len(eqprop) > 1:
                Logger.error("Expecting a single equivalence property")
            eqprop = eqprop[0][1]
            invar = Iff(miter_out, eqprop)
            Logger.log('Using provided equivalence property: {}'.format(invar),
                       2)

        tsmo = TS()
        tsmo.vars = set([miter_out])
        tsmo.invar = invar
        htseq.add_ts(tsmo)

        return (htseq, miter_out)
Esempio n. 4
0
    def solve_problem(self, problem, config):
        Logger.log("\n*** Analyzing problem \"%s\" ***" % (problem), 1)
        Logger.msg("Solving \"%s\" " % problem.name, 0, not (Logger.level(1)))

        sparser = StringParser()
        lparser = LTLParser()

        mc_config = self.problem2mc_config(problem, config)
        bmc_safety = BMCSafety(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)

        parsing_defs = [
            mc_config.properties, mc_config.lemmas, mc_config.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

        [mc_config.properties, mc_config.lemmas,
         mc_config.assumptions] = parsing_defs

        assumps = None
        lemmas = None

        accepted_ver = False

        if problem.monitors is not None:

            varsdict = dict([(var.symbol_name(), var)
                             for var in problem.hts.vars])

            for strmonitor in problem.monitors.split(")"):
                strmonitor = strmonitor.replace(" ", "")
                if strmonitor == "":
                    continue
                instance, mtype = strmonitor.split("=")
                mtype, pars = mtype.split("(")
                pars = pars.split(",")

                monitor = MonitorsFactory.monitor_by_name(mtype)
                pars = [varsdict[v] if v in varsdict else v for v in pars]
                ts = monitor.get_sts(instance, pars)

                problem.hts.add_ts(ts)

        if problem.verification != VerificationType.EQUIVALENCE:
            assumps = [
                t[1] for t in sparser.parse_formulae(mc_config.assumptions)
            ]
            lemmas = [t[1] for t in sparser.parse_formulae(mc_config.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) = sparser.parse_formulae(mc_config.properties)[0]
            else:
                (strprop, prop,
                 types) = lparser.parse_formulae(mc_config.properties)[0]

        if problem.verification == VerificationType.SAFETY:
            accepted_ver = True
            res, trace, _ = bmc_safety.safety(prop, bmc_length, bmc_length_min)

        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.EQUIVALENCE:
            accepted_ver = True
            if problem.equivalence:
                (problem.hts2, _, _) = self.parse_model(problem.relative_path, \
                                                        problem.equivalence, \
                                                        problem.abstract_clock, \
                                                        problem.symbolic_init, "System 2", \
                                                        no_clock=problem.no_clock, \
                                                        run_passes=problem.run_coreir_passes)

            htseq, miter_out = Miter.combine_systems(problem.hts, \
                                                     problem.hts2, \
                                                     bmc_length, \
                                                     problem.symbolic_init, \
                                                     mc_config.properties, \
                                                     True)

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

            if mc_config.lemmas is not None:
                lemmas = [
                    t[1] for t in sparser.parse_formulae(mc_config.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)
            res, trace, t = bmcseq.safety(miter_out, bmc_length,
                                          bmc_length_min)

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

        problem.status = res
        problem.trace = trace

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

        Logger.log("\n*** Problem \"%s\" is %s ***" % (problem, res), 1)