Exemple #1
0
    def Uop(bvop, bop, in_, out):
        # INVAR: (<op> in) = out)
        vars_ = [in_, out]
        comment = ""  #(bvop.__name__ + " (in, out) = (%s, %s)")%(tuple([x.symbol_name() for x in vars_]))
        Logger.log(comment, 3)

        in_B = get_type(in_).is_bool_type()
        outB = get_type(out).is_bool_type()

        bools = (1 if in_B else 0) + (1 if outB else 0)

        if bop == None:
            if in_B:
                in_ = B2BV(in_)
            if outB:
                out = B2BV(out)
            invar = EqualsOrIff(bvop(in_), out)
        else:
            if bools == 2:
                invar = EqualsOrIff(bop(in_), out)
            elif bools == 0:
                invar = EqualsOrIff(bvop(in_), out)
            else:
                if not in_B:
                    invar = EqualsOrIff(bop(BV2B(in_)), out)
                if not outB:
                    invar = EqualsOrIff(bop(in_), BV2B(out))

        ts = TS(comment)
        ts.vars, ts.invar = get_free_variables(invar), invar
        return ts
Exemple #2
0
 def to_prev(formula):
     varmap = []
     for v in get_free_variables(formula):
         vname = v.symbol_name()
         varmap.append((vname, TS.get_prev_name(vname)))
         varmap.append((TS.get_prime_name(vname), vname))
     return substitute(formula, dict(varmap))
Exemple #3
0
    def simulate(self, prop, k):
        if self.config.strategy == VerificationStrategy.NU:
            self._init_at_time(self.hts.vars, 1)
            (t, model) = self.sim_no_unroll(self.hts, prop, k)
        else:
            self._init_at_time(self.hts.vars, k)
            if prop == TRUE():
                self.config.incremental = False
                (t, model) = self.solve_safety_fwd(self.hts, Not(prop), k,
                                                   False)
            else:
                (t, model) = self.solve_safety(self.hts, Not(prop), k)

        model = self._remap_model(self.hts.vars, model, t)
        if (t > -1) and (model is not None):
            Logger.log("Execution found", 1)
            trace = self.print_trace(self.hts,
                                     model,
                                     t,
                                     get_free_variables(prop),
                                     map_function=self.config.map_function)
            return (VerificationStatus.TRUE, trace)
        else:
            Logger.log("Deadlock wit k=%s" % k, 1)
            return (VerificationStatus.FALSE, None)
Exemple #4
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)
Exemple #5
0
    def extend_ts(ts, modifier):

        affect_init = False

        if ts.ftrans is None:
            return (ts, [])

        new_ftrans = {}

        vars = []

        for (assign, cond_assign_list) in ts.ftrans.items():
            fv = get_free_variables(assign)
            assert len(fv) == 1
            var = fv.pop()
            is_next = TS.has_next(var)

            refvar = TS.get_ref_var(var)
            nomvar = Symbol(NOMIN % refvar.symbol_name(), var.symbol_type())
            fvar = Symbol(FAULT % refvar.symbol_name(), BOOL)

            vars.append(nomvar)
            vars.append(fvar)

            repldic = dict([(refvar.symbol_name(), nomvar.symbol_name()), \
                            (TS.get_prime(refvar).symbol_name(), TS.get_prime(nomvar).symbol_name())])

            # Remapping nominal behavior to new variable
            new_ftrans[substitute(assign,
                                  repldic)] = [(substitute(c[0], repldic),
                                                substitute(c[1], repldic))
                                               for c in cond_assign_list]

            # Definition of the nominal behavior
            new_ftrans[refvar] = [(Not(fvar), nomvar)]

            # Application of the faulty behavior
            new_ftrans[refvar].append(
                (fvar, modifier.get_behavior(nomvar, refvar)))

            ts.trans = And(ts.trans, Implies(fvar, TS.get_prime(fvar)))

            if affect_init:
                ts.init = substitute(ts.init, repldic)
            else:
                ts.init = And(ts.init, Not(fvar))

        # add the vars to the transition system
        for var in vars:
            ts.add_var(var)

        ts.ftrans = new_ftrans

        return (ts, vars)
Exemple #6
0
    def MultiOp(op, end_op, out, *inparams):
        cum = inparams[0]
        for el in inparams[1:]:
            cum = op(cum, el)

        if end_op is not None:
            cum = end_op(cum)

        formula = EqualsOrIff(cum, out)

        ts = TS()
        ts.vars, ts.invar = get_free_variables(formula), formula
        return ts
Exemple #7
0
    def safety(self, prop, k, k_min, processes=1):
        lemmas = self.hts.lemmas
        self._init_at_time(self.hts.vars, k)
        (t, model) = self.solve_safety(self.hts, prop, k, k_min, lemmas, processes)

        if model == True:
            return (VerificationStatus.TRUE, None, t)
        elif model is not None:
            model = self._remap_model(self.hts.vars, model, t)
            trace = self.generate_trace(model, t, get_free_variables(prop))
            return (VerificationStatus.FALSE, trace, t)
        else:
            return (VerificationStatus.UNK, None, t)
Exemple #8
0
    def parse_formulae(self, strforms):
        formulae = []

        if strforms is None:
            return formulae

        for strform in strforms:
            if ("#" not in strform) and (strform != ""):
                formula = self.parse_formula(strform)
                formula_fv = get_free_variables(formula)
                nextvars = [v for v in formula_fv if TS.is_prime(v)] != []
                prevvars = [v for v in formula_fv if TS.is_prev(v)] != []
                formulae.append((strform, formula, (nextvars, prevvars)))

        return formulae
Exemple #9
0
    def BopBool(op, in0, in1, out):
        # INVAR: (in0 <op> in1) = out
        vars_ = [in0,in1,out]
        comment = (op.__name__ + " (in0, in1, out) = (%s, %s, %s)")%(tuple([x.symbol_name() for x in vars_]))
        Logger.log(comment, 3)

        if out.symbol_type() == BOOL:
            bout = out
        else:
            bout = EqualsOrIff(out, BV(1, 1))

        invar = Iff(op(in0,in1), bout)
        ts = TS(comment)
        ts.vars, ts.invar = get_free_variables(invar), invar
        return ts
Exemple #10
0
    def ltl_generic(self, prop, k, k_min=0):
        lemmas = self.hts.lemmas
        
        self._init_at_time(self.hts.vars, k)
        self._init_v_time(self.hts.vars, k)

        (t, model) = self.solve(self.hts, prop, k, lemmas)

        if model == True:
            return (VerificationStatus.TRUE, None, t)
        elif model is not None:
            model = self._remap_model(self.hts.vars, model, t)
            trace = self.generate_trace(model, t, get_free_variables(prop), find_loop=True)
            return (VerificationStatus.FALSE, trace, t)
        else:
            return (VerificationStatus.UNK, None, t)
Exemple #11
0
    def safety(self, prop, k, k_min):
        lemmas = self.hts.lemmas
        self._init_at_time(self.hts.vars, k)
        (t, model) = self.solve_safety(self.hts, prop, k, k_min, lemmas)

        if model == True:
            return (VerificationStatus.TRUE, None, t)
        elif model is not None:
            model = self._remap_model(self.hts.vars, model, t)
            trace = self.print_trace(self.hts,
                                     model,
                                     t,
                                     get_free_variables(prop),
                                     map_function=self.config.map_function)
            return (VerificationStatus.FALSE, trace, t)
        else:
            return (VerificationStatus.UNK, None, t)
Exemple #12
0
    def Bop(bvop, bop, in0, in1, out):
        # INVAR: (in0 <op> in1) = out
        vars_ = [in0, in1, out]
        comment = ""  #(bvop.__name__ + " (in0, in1, out) = (%s, %s, %s)")%(tuple([x.symbol_name() for x in vars_]))
        Logger.log(comment, 3)

        in0B = get_type(in0).is_bool_type()
        in1B = get_type(in1).is_bool_type()
        outB = get_type(out).is_bool_type()

        bools = (1 if in0B else 0) + (1 if in1B else 0) + (1 if outB else 0)

        if bop == None:
            if in0B:
                in0 = Ite(in0, BV(1, 1), BV(0, 1))
            if in1B:
                in1 = Ite(in1, BV(1, 1), BV(0, 1))
            if outB:
                out = Ite(out, BV(1, 1), BV(0, 1))

            invar = EqualsOrIff(bvop(in0, in1), out)

        else:
            if bools == 3:
                invar = EqualsOrIff(bop(in0, in1), out)
            elif bools == 0:
                invar = EqualsOrIff(bvop(in0, in1), out)
            elif bools == 1:
                if in0B:
                    invar = EqualsOrIff(bvop(B2BV(in0), in1), out)
                if in1B:
                    invar = EqualsOrIff(bvop(in0, B2BV(in1)), out)
                if outB:
                    invar = EqualsOrIff(BV2B(bvop(in0, in1)), out)
            else:
                if not in0B:
                    invar = EqualsOrIff(bop(BV2B(in0), in1), out)
                if not in1B:
                    invar = EqualsOrIff(bop(in0, BV2B(in1)), out)
                if not outB:
                    invar = EqualsOrIff(B2BV(bop(in0, in1)), out)

        ts = TS(comment)
        ts.vars, ts.invar = get_free_variables(invar), invar
        return ts
Exemple #13
0
    def eventually(self, prop, k, k_min):
        lemmas = self.hts.lemmas
        self._init_at_time(self.hts.vars, k)
        (t, model) = self.solve_liveness(self.hts, prop, k, k_min, True,
                                         lemmas)

        model = self._remap_model(self.hts.vars, model, t)

        if model == True:
            return (VerificationStatus.TRUE, None, t)
        elif model is not None:
            trace = self.generate_trace(model,
                                        t,
                                        get_free_variables(prop),
                                        find_loop=True)
            return (VerificationStatus.FALSE, trace, t)
        else:
            return (VerificationStatus.UNK, None, t)
Exemple #14
0
    def parse_formulae(self, str_or_fnodes):
        formulae = []

        if str_or_fnodes is None:
            return formulae

        for s in str_or_fnodes:
            if isinstance(s, str):
                if ('#' in s) or len(s) == 0:
                    continue
                formula = self.parse_formula(s)
            else:
                formula = s
            formula_fv = get_free_variables(formula)
            nextvars = [v for v in formula_fv if TS.is_prime(v)] != []
            prevvars = [v for v in formula_fv if TS.is_prev(v)] != []
            formulae.append((str(s), formula, (nextvars, prevvars)))

        return formulae
Exemple #15
0
    def parse_line(self, string:str)->Union[FNode, None]:
        if '=' not in string:
            raise RuntimeError("Expecting a single equality but got: {}".format(string))

        split = string.split("=")
        if len(split) > 2:
            raise RuntimeError("Expecting exactly one equality but got: {}".format(string))

        lhs, rhs = split

        try:
            lhs = self.parser.parse_formula(lhs)
            rhs = self.parser.parse_formula(rhs)
        except UndefinedSymbolError:
            return None

        for fv in get_free_variables(lhs):
            if not self._pysmt_formula_manager.is_state_symbol(fv):
                return None

        if not rhs.is_constant():
            raise RuntimeError("Expecting a constant on the right side but got: {}".format(rhs))

        return EqualsOrIff(lhs, rhs)
Exemple #16
0
    def _free_variables(self, formula):
        if formula not in self.fv_dict:
            fv = get_free_variables(formula)
            self.fv_dict[formula] = frozenset([TS.get_ref_var(v) for v in fv])

        return self.fv_dict[formula]
Exemple #17
0
 def has_next(formula):
     varlist = get_free_variables(formula)
     for v in varlist:
         if TS.is_prime(v):
             return True
     return False
Exemple #18
0
    def _flatten_rec(self, path=[]):
        self.is_flatten = True
        vardic = dict([(v.symbol_name(), v) for v in self.vars])

        def full_path(name, path):
            ret = ".".join(path + [name])
            if ret[0] == ".":
                return ret[1:]
            return ret

        for sub in self.subs:
            instance, actual, module = sub
            module.is_flatten = True
            formal = module.params

            ts = TS(FLATTEN)

            (ts.vars, \
             ts.state_vars, \
             ts.input_vars, \
             ts.output_vars, \
             ts.init, \
             ts.trans, \
             ts.ftrans, \
             ts.invar) = module._flatten_rec(path+[instance])

            self.add_ts(ts, reset=False)

            links = {}
            for i in range(len(actual)):
                # Unset parameter
                if actual[i] == None:
                    continue
                if type(actual[i]) == str:
                    local_expr = vardic[full_path(actual[i], path)]
                else:
                    local_vars = [(v.symbol_name(), v.symbol_name().replace(self.name, ".".join(path))) \
                                  for v in get_free_variables(actual[i])]
                    local_expr = substitute(actual[i], dict(local_vars))
                module_var = sub[2].newname(formal[i].symbol_name(),
                                            path + [sub[0]])
                assert sub[2].name != ""
                if module_var not in vardic:
                    modulevar = Symbol(module_var, formal[i].symbol_type())
                    self.vars.add(modulevar)
                    vardic[module_var] = modulevar
                if vardic[module_var] in self.output_vars:
                    links[local_expr] = [(TRUE(), vardic[module_var])]
                else:
                    links[vardic[module_var]] = [(TRUE(), local_expr)]

            ts = TS(LINKS)
            ts.ftrans = links
            self.add_ts(ts, reset=False)

        s_init = self.single_init()
        s_invar = self.single_invar(include_ftrans=False)
        s_trans = self.single_trans(include_ftrans=False)

        replace_dic = dict([(v.symbol_name(), self.newname(v.symbol_name(), path)) for v in self.vars] + \
                           [(TS.get_prime_name(v.symbol_name()), self.newname(TS.get_prime_name(v.symbol_name()), path)) \
                            for v in self.vars])

        substitute_dic = {}

        def substitute_mem(f, dic):
            if f in substitute_dic:
                return substitute_dic[f]
            ret = substitute(f, dic)
            substitute_dic[f] = ret
            return ret

        s_init = substitute_mem(s_init, replace_dic)
        s_invar = substitute_mem(s_invar, replace_dic)
        s_trans = substitute_mem(s_trans, replace_dic)

        s_ftrans = {}

        local_vars = []
        local_state_vars = []
        local_input_vars = []
        local_output_vars = []

        single_ftrans = self.single_ftrans()

        for var in list(self.vars):
            newsym = Symbol(replace_dic[var.symbol_name()], var.symbol_type())

            local_vars.append(newsym)
            if var in self.state_vars:
                local_state_vars.append(newsym)
            if var in self.input_vars:
                local_input_vars.append(newsym)
            if var in self.output_vars:
                local_output_vars.append(newsym)

            if var in single_ftrans:
                cond_assign_list = single_ftrans[var]
                s_ftrans[newsym] = [(substitute_mem(condition, replace_dic), \
                                     substitute_mem(value, replace_dic)) \
                                    for (condition, value) in cond_assign_list]
                del (single_ftrans[var])

        for var, cond_assign_list in single_ftrans.items():
            s_ftrans[substitute_mem(var, replace_dic)] = [(substitute_mem(condition, replace_dic), \
                                                           substitute_mem(value, replace_dic)) \
                                                          for (condition, value) in cond_assign_list]

        return (local_vars, local_state_vars, local_input_vars,
                local_output_vars, s_init, s_trans, s_ftrans, s_invar)
Exemple #19
0
    def parametric_safety(self,
                          prop,
                          k_max,
                          k_min,
                          parameters,
                          monotonic=True,
                          at_most=-1):
        if len(parameters) == 0:
            Logger.error("Parameters size cannot be 0")

        lemmas = self.hts.lemmas
        self._init_at_time(self.hts.vars, k_max)

        monotonic = True

        # if monotonic:
        #     for p in parameters:
        #         self.set_preferred((p, False))

        self.region = FALSE()

        generalize = lambda model, t: self._get_param_assignments(
            model, t, parameters, monotonic)

        if at_most == -1:
            cardinality = len(parameters)
        else:
            cardinality = at_most

        prev_cs_count = 0

        prove = self.config.prove

        step = 5
        same_res_counter = 0
        k = step
        end = False
        has_next = TS.has_next(prop)

        # Strategy selection
        increase_k = False

        if cardinality == -2:
            (t, status) = self.solve_safety_inc_fwd(self.hts,
                                                    prop,
                                                    k_max,
                                                    k_min,
                                                    all_vars=False,
                                                    generalize=generalize)
        else:
            sn = SortingNetwork.sorting_network(parameters)

            if increase_k:
                # Approach with incremental increase of bmc k
                while k < k_max + 1:
                    for at in range(cardinality):
                        Logger.msg("[%d,%d]" % ((at + 1), k), 0,
                                   not (Logger.level(1)))

                        sn_k = sn[at + 1] if at + 1 < len(sn) else FALSE()
                        bound_constr = Or(sn_k, self.region)
                        bound_constr = bound_constr if not has_next else Or(
                            bound_constr, TS.to_next(bound_constr))

                        self.config.prove = False
                        (t, status) = self.solve_safety_inc_bwd(
                            self.hts,
                            Or(prop, bound_constr),
                            k,
                            generalize=generalize)

                        if (prev_cs_count == self.cs_count):
                            same_res_counter += 1
                        else:
                            same_res_counter = 0

                        prev_cs_count = self.cs_count

                        if (prove == True) and ((same_res_counter > 1) or
                                                (at == cardinality - 1)):
                            Logger.msg("[>%d,%d]" % ((at + 1), k), 0,
                                       not (Logger.level(1)))

                            if (at_most > -1) and (at_most < cardinality):
                                sn_k = sn[at_most - 1]
                            else:
                                sn_k = FALSE()
                            bound_constr = Or(sn_k, self.region)
                            bound_constr = bound_constr if not has_next else Or(
                                bound_constr, TS.to_next(bound_constr))

                            self.config.prove = True
                            (t, status) = self.solve_safety(
                                self.hts, Or(prop, bound_constr), k,
                                max(k_min, k - step))

                            if status == True:
                                end = True
                                break

                        if (same_res_counter > 2) and (k < k_max):
                            break

                    if end:
                        break
                    k += step
            else:
                # Approach with fixed bmc k
                for at in range(cardinality):
                    Logger.msg("[%d]" % ((at + 1)), 0, not (Logger.level(1)))

                    sn_k = sn[at + 1] if at + 1 < len(sn) else FALSE()
                    bound_constr = Or(sn_k, self.region)
                    bound_constr = bound_constr if not has_next else Or(
                        bound_constr, TS.to_next(bound_constr))

                    self.config.prove = False
                    (t, status) = self.solve_safety_inc_bwd(
                        self.hts,
                        Or(prop, bound_constr),
                        k_max,
                        generalize=generalize)

                    if simplify(self.region) == TRUE():
                        break

                    if (prev_cs_count == self.cs_count):
                        same_res_counter += 1
                    else:
                        same_res_counter = 0

                    prev_cs_count = self.cs_count

                    if (prove == True) and ((same_res_counter > 1) or
                                            (at == cardinality - 1)):
                        Logger.msg("[>%d]" % ((at + 1)), 0,
                                   not (Logger.level(1)))

                        if (at_most > -1) and (at_most < cardinality):
                            sn_k = sn[at_most - 1]
                        else:
                            sn_k = FALSE()
                        bound_constr = Or(sn_k, self.region)
                        bound_constr = bound_constr if not has_next else Or(
                            bound_constr, TS.to_next(bound_constr))

                        self.config.prove = True
                        (t,
                         status) = self.solve_safety(self.hts,
                                                     Or(prop, bound_constr),
                                                     k_max, k_min)
                        if status == True:
                            break

        traces = None
        if (self.models is not None) and (simplify(self.region)
                                          not in [TRUE(), FALSE()]):
            traces = []
            for (model, time) in self.models:
                model = self._remap_model(self.hts.vars, model, time)
                trace = self.generate_trace(model, time,
                                            get_free_variables(prop))
                traces.append(trace)

        region = []
        dass = {}

        # Sorting result by size
        for ass in list(disjunctive_partition(self.region)):
            cp = list(conjunctive_partition(ass))
            size = len(cp)
            if size not in dass:
                dass[size] = []
            dass[size].append(ass)

        indexes = list(dass.keys())
        indexes.sort()
        for size in indexes:
            region += dass[size]

        if status == True:
            return (VerificationStatus.TRUE, traces, region)
        elif status is not None:
            return (VerificationStatus.FALSE, traces, region)
        else:
            return (VerificationStatus.UNK, traces, region)
    def generate_STS(self, lines):
        ts = TS("Additional system")
        init = TRUE()
        trans = TRUE()
        invar = TRUE()

        states = {}
        assigns = set([])
        varsmap = {}

        def def_var(name, vtype):
            if name in varsmap:
                return varsmap[name]
            var = Symbol(name, vtype)
            ts.add_state_var(var)
            return var

        for line in lines:
            if line.comment:
                continue
            if line.init:
                if T_I not in states:
                    states[T_I] = TRUE()

                if line.init.varname != "":
                    (value, typev) = self.__get_value(line.init.value)
                    ivar = def_var(line.init.varname, typev)
                    state = EqualsOrIff(ivar, value)
                else:
                    state = TRUE() if line.init.value == T_TRUE else FALSE()

                states[T_I] = And(states[T_I], state)

                # Optimization for the initial state assignment
                init = And(init, state)

            state = TRUE()
            if line.state:
                sname = T_S + line.state.id
                if (line.state.varname != ""):
                    (value, typev) = self.__get_value(line.state.value)
                    ivar = def_var(line.state.varname, typev)
                    state = EqualsOrIff(ivar, value)
                    assval = (sname, line.state.varname)
                    if assval not in assigns:
                        assigns.add(assval)
                    else:
                        Logger.error(
                            "Double assignment for variable \"%s\" at state \"%s\""
                            % (line.state.varname, sname))
                else:
                    state = TRUE() if line.state.value == T_TRUE else FALSE()

                if sname not in states:
                    states[sname] = TRUE()

                states[sname] = And(states[sname], state)

        stateid_width = math.ceil(math.log(len(states)) / math.log(2))
        stateid_var = Symbol(self.new_state_id(), BVType(stateid_width))

        init = And(init, EqualsOrIff(stateid_var, BV(0, stateid_width)))
        invar = And(
            invar,
            Implies(EqualsOrIff(stateid_var, BV(0, stateid_width)),
                    states[T_I]))
        states[T_I] = EqualsOrIff(stateid_var, BV(0, stateid_width))

        count = 1
        state_items = list(states.keys())
        state_items.sort()
        for state in state_items:
            if state == T_I:
                continue
            invar = And(
                invar,
                Implies(EqualsOrIff(stateid_var, BV(count, stateid_width)),
                        states[state]))
            states[state] = EqualsOrIff(stateid_var, BV(count, stateid_width))
            count += 1

        transdic = {}

        for line in lines:
            if line.comment:
                continue

            if line.trans:
                if states[line.trans.start] not in transdic:
                    transdic[states[line.trans.start]] = []
                transdic[states[line.trans.start]].append(
                    states[line.trans.end])

        for transition in transdic:
            (start, end) = (transition, transdic[transition])
            trans = And(trans, Implies(start, TS.to_next(Or(end))))

        vars_ = [v for v in get_free_variables(trans) if not TS.is_prime(v)]
        vars_ += get_free_variables(init)
        vars_ += get_free_variables(invar)

        invar = And(invar, BVULE(stateid_var, BV(count - 1, stateid_width)))
        ts.set_behavior(init, trans, invar)
        ts.add_state_var(stateid_var)

        hts = HTS("ETS")
        hts.add_ts(ts)
        invar_props = []
        ltl_props = []

        return (hts, invar_props, ltl_props)
Exemple #21
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)