Esempio n. 1
0
    def flatten(self, path=[]):

        vardic = dict([(v.symbol_name(), v) for v in self.vars])
        for sub in self.subs:
            instance, actual, module = sub
            formal = module.params

            ts = TS("FLATTEN")
            (ts.init, ts.trans, ts.invar) = module.flatten(path + [instance])
            self.add_ts(ts)

            links = TRUE()
            for i in range(len(actual)):
                local_var = ".".join(path + [actual[i]])
                module_var = sub[2].newname(formal[i].symbol_name(),
                                            path + [sub[0]])
                links = And(links,
                            EqualsOrIff(vardic[local_var], vardic[module_var]))

            ts = TS("LINKS")
            ts.invar = links
            self.add_ts(ts)

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

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

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

        return (s_init, s_trans, s_invar)
Esempio n. 2
0
    def apply_var_prefix(self, prefix):
        p_vars = set([Symbol(apply_prefix(v.symbol_name(), prefix), v.symbol_type()) for v in self.vars])
        p_state_vars = set([Symbol(apply_prefix(v.symbol_name(), prefix), v.symbol_type()) for v in self.state_vars])
        p_input_vars = set([Symbol(apply_prefix(v.symbol_name(), prefix), v.symbol_type()) for v in self.input_vars])
        p_output_vars = set([Symbol(apply_prefix(v.symbol_name(), prefix), v.symbol_type()) for v in self.output_vars])
        p_hidden_vars = set([Symbol(apply_prefix(v.symbol_name(), prefix), v.symbol_type()) for v in self.hidden_vars])
        remapdic = dict([(v.symbol_name(), apply_prefix(v.symbol_name(), prefix)) for v in self.vars]+\
                        [(TS.get_prime(v).symbol_name(), apply_prefix(TS.get_prime(v).symbol_name(), prefix)) for v in self.vars])

        p_init = substitute(self.init, remapdic)
        p_trans = substitute(self.trans, remapdic)
        p_invar = substitute(self.invar, remapdic)

        p_ftrans = None

        if self.ftrans is not None:
            p_ftrans = {}
            for var, cond_assign_list in self.ftrans.items():
                p_ftrans[substitute(var, remapdic)] = [(substitute(condition, remapdic), substitute(value, remapdic)) for (condition, value) in cond_assign_list]

        self.vars = p_vars
        self.state_vars = p_state_vars
        self.input_vars = p_input_vars
        self.output_vars = p_output_vars
        self.hidden_vars = p_hidden_vars
        self.init = p_init
        self.trans = p_trans
        self.ftrans = p_ftrans
        self.invar = p_invar

        return self
Esempio n. 3
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)
Esempio n. 4
0
 def to_prev(formula):
     varmap = []
     for v in get_free_variables(formula):
         vname = TS.get_ref_name(v.symbol_name())
         varmap.append((vname, TS.get_prev_name(vname)))
         varmap.append((TS.get_prime_name(vname), vname))
     return substitute(formula, dict(varmap))
Esempio n. 5
0
    def apply_var_prefix(self, prefix):
        remapdic = dict([(v.symbol_name(), apply_prefix(v.symbol_name(), prefix)) for v in self.vars]+\
                        [(TS.get_prime(v).symbol_name(), apply_prefix(TS.get_prime(v).symbol_name(), prefix)) for v in self.vars])

        p_init = None
        p_trans = None
        p_invar = None
        p_assumptions = None
        p_lemmas = None

        if self.assumptions is not None:
            p_assumptions = [substitute(a, remapdic) for a in self.assumptions]
        if self.lemmas is not None:
            p_lemmas = [substitute(l, remapdic) for l in self.lemmas]
        p_params = [
            Symbol(apply_prefix(v.symbol_name(), prefix), v.symbol_type())
            for v in self.params
        ]

        self.vars = set([])
        self.state_vars = set([])
        self.input_vars = set([])
        self.output_vars = set([])
        self.hidden_vars = set([])

        self._s_init = None
        self._s_trans = None
        self._s_ftrans_t = None
        self._s_ftrans_i = None
        self._s_ftrans = None
        self._s_invar = None

        self.assumptions = p_assumptions
        self.lemmas = p_lemmas
        self.params = p_params

        tss = self.tss
        self.tss = set([])
        for ts in tss:
            self.add_ts(ts.apply_var_prefix(prefix), reset=False)

        self.reset_formulae()
Esempio n. 6
0
 def substitute_mem(f, dic):
     if f in substitute_dic:
         return substitute_dic[f]
     ret = substitute(f, dic)
     substitute_dic[f] = ret
     return ret
Esempio n. 7
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)
Esempio n. 8
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)
Esempio n. 9
0
    def solve_safety_int(self, hts, prop, k):
        init = hts.single_init()
        trans = hts.single_trans()
        invar = hts.single_invar()

        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)

        pivot = 2

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

            trans_t = self.unroll(trans, invar, t, gen_list=True)
            trans_tA = And(trans_t[:pivot]) if t > 0 else TRUE()
            trans_tB = And(trans_t[pivot:]) if t > 0 else TRUE()

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

                self._add_assertion(self.solver, And(trans_tA, trans_tB))

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

                if self._solve(self.solver):
                    if R == init_0:
                        Logger.log("Counterexample found with k=%s"%(t), 1)
                        model = self._get_model(self.solver)
                        return (t, model)
                    else:
                        Logger.log("No counterexample or proof found with k=%s"%(t), 1)
                        Logger.msg(".", 0, not(Logger.level(1)))
                        break
                else:
                    if len(trans_t) < 2:
                        Logger.log("No counterexample found with k=%s"%(t), 1)
                        Logger.msg(".", 0, not(Logger.level(1)))
                        break

                    Ri = And(itp.binary_interpolant(And(R, trans_tA), And(trans_tB, npropt)))
                    Ri = substitute(Ri, map_10)

                    self._reset_assertions(self.solver)
                    self._add_assertion(self.solver, And(Ri, Not(R)))

                    if not self._solve(self.solver):
                        Logger.log("Proof found with k=%s"%(t), 1)
                        return (t, True)
                    else:
                        R = Or(R, Ri)
                        int_c += 1

                    Logger.log("Extending initial states (%s)"%int_c, 1)

            t += 1

        return (t-1, None)
Esempio n. 10
0
 def at_ptime(self, formula, t):
     return substitute(formula, self.varmapb_t[t])
Esempio n. 11
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)