Exemplo n.º 1
0
 def upre_bdd(self,
              dst_states_bdd,
              env_strat=None,
              get_strat=False,
              use_trans=False):
     """
     UPRE = EXu.AXc.EL' : T(L,Xu,Xc,L') ^ dst(L') [^St(L,Xu)]
     """
     # take a transition step backwards
     # TECH NOTE: the restrict_fun=~dst... works ONLY because I will use the
     # result and take the union with dst_states afterwards...
     p_bdd = self.substitute_latches_next(dst_states_bdd,
                                          restrict_fun=~dst_states_bdd,
                                          use_trans=use_trans)
     # use the given strategy
     if env_strat is not None:
         p_bdd &= env_strat
     # there is an uncontrollable action such that for all contro...
     temp_bdd = p_bdd.univ_abstract(
         BDD.make_cube(
             imap(funcomp(BDD, symbol_lit),
                  self.iterate_controllable_inputs())))
     p_bdd = temp_bdd.exist_abstract(
         BDD.make_cube(
             imap(funcomp(BDD, symbol_lit),
                  self.iterate_uncontrollable_inputs())))
     # prepare the output
     if get_strat:
         return temp_bdd
     else:
         return p_bdd
Exemplo n.º 2
0
 def upre_bdd(self, dst_states_bdd, env_strat=None, get_strat=False,
              use_trans=False):
     """
     UPRE = EXu.AXc.EL' : T(L,Xu,Xc,L') ^ dst(L') [^St(L,Xu)]
     """
     # take a transition step backwards
     # TECH NOTE: the restrict_fun=~dst... works ONLY because I will use the
     # result and take the union with dst_states afterwards...
     p_bdd = self.substitute_latches_next(
         dst_states_bdd,
         restrict_fun=~dst_states_bdd,
         use_trans=use_trans)
     # use the given strategy
     if env_strat is not None:
         p_bdd &= env_strat
     # there is an uncontrollable action such that for all contro...
     temp_bdd = p_bdd.univ_abstract(
         BDD.make_cube(imap(funcomp(BDD, symbol_lit),
                            self.iterate_controllable_inputs())))
     p_bdd = temp_bdd.exist_abstract(
         BDD.make_cube(imap(funcomp(BDD, symbol_lit),
                            self.iterate_uncontrollable_inputs())))
     # prepare the output
     if get_strat:
         return temp_bdd
     else:
         return p_bdd
Exemplo n.º 3
0
 def __init__(self, aig):
     self.aig = aig
     self.uinputs = [x.lit for x in
                     self.aig.iterate_uncontrollable_inputs()]
     self.latches = [x.lit for x in self.aig.iterate_latches()]
     self.latch_cube = BDD.make_cube(imap(funcomp(BDD,
                                                  symbol_lit),
                                          self.aig.iterate_latches()))
     self.platch_cube = BDD.make_cube(imap(funcomp(BDD,
                                                   self.aig.get_primed_var,
                                                   symbol_lit),
                                           self.aig.iterate_latches()))
     self.cinputs_cube = BDD.make_cube(
         imap(funcomp(BDD, symbol_lit),
              self.aig.iterate_controllable_inputs()))
     self.pcinputs_cube = self.aig.prime_all_inputs_in_bdd(
         self.cinputs_cube)
     self.uinputs_cube = BDD.make_cube(
         imap(funcomp(BDD, symbol_lit),
              self.aig.iterate_uncontrollable_inputs()))
     self.init_state_bdd = self.aig.init_state_bdd()
     self.error_bdd = self.aig.lit2bdd(self.aig.error_fake_latch.lit)
     self.Venv = dict()
     self.Venv[self.init_state_bdd] = True
     self.succ_cache = dict()
Exemplo n.º 4
0
 def over_post_bdd(self, src_states_bdd, sys_strat=None):
     """ Over-approximated version of concrete post which can be done even
     without the transition relation """
     strat = BDD.true()
     if sys_strat is not None:
         strat &= sys_strat
     # to do this, we use an over-simplified transition relation, EXu,Xc
     b = BDD.true()
     for x in self.iterate_latches():
         temp = BDD.make_eq(BDD(self.get_primed_var(x.lit)),
                            self.lit2bdd(x.next))
         b &= temp.and_abstract(
             strat,
             BDD.make_cube(
                 imap(funcomp(BDD, symbol_lit),
                      self.iterate_controllable_inputs())))
         b = b.restrict(src_states_bdd)
     b &= src_states_bdd
     b = b.exist_abstract(
         BDD.make_cube(
             imap(
                 funcomp(BDD, symbol_lit),
                 chain(self.iterate_latches(),
                       self.iterate_uncontrollable_inputs()))))
     return self.unprime_latches_in_bdd(b)
Exemplo n.º 5
0
    def upost(self, q):
        assert isinstance(q, BDD)
        if q in self.succ_cache:
            return iter(self.succ_cache[q])
        A = BDD.true()
        M = set()
        while A != BDD.false():
            a = A.get_one_minterm(self.uinputs)
            trans = BDD.make_cube(
                imap(
                    lambda x: BDD.make_eq(
                        BDD(self.aig.get_primed_var(x.lit)),
                        self.aig.lit2bdd(x.next).and_abstract(
                            q, self.latch_cube)), self.aig.iterate_latches()))
            lhs = trans & a
            rhs = self.aig.prime_all_inputs_in_bdd(trans)
            simd = BDD.make_impl(lhs, rhs).univ_abstract(self.platch_cube)\
                .exist_abstract(self.pcinputs_cube)\
                .univ_abstract(self.cinputs_cube)
            simd = self.aig.unprime_all_inputs_in_bdd(simd)

            A &= ~simd
            Mp = set()
            for m in M:
                if not (BDD.make_impl(m, simd) == BDD.true()):
                    Mp.add(m)
            M = Mp
            M.add(a)
        log.DBG_MSG("Upost |M| = " + str(len(M)))
        self.succ_cache[q] = map(lambda x: (q, x), M)
        return iter(self.succ_cache[q])
Exemplo n.º 6
0
    def extract_output_funs(self, strategy, care_set=None):
        """
        Calculate BDDs for output functions given non-deterministic winning
        strategy.
        """
        if care_set is None:
            care_set = BDD.true()

        output_models = dict()
        all_outputs = [BDD(x.lit) for x in self.iterate_controllable_inputs()]
        for c_symb in self.iterate_controllable_inputs():
            c = BDD(c_symb.lit)
            others = set(set(all_outputs) - set([c]))
            if others:
                others_cube = BDD.make_cube(others)
                c_arena = strategy.exist_abstract(others_cube)
            else:
                c_arena = strategy
            # pairs (x,u) in which c can be true
            can_be_true = c_arena.cofactor(c)
            # pairs (x,u) in which c can be false
            can_be_false = c_arena.cofactor(~c)
            must_be_true = (~can_be_false) & can_be_true
            must_be_false = (~can_be_true) & can_be_false
            local_care_set = care_set & (must_be_true | must_be_false)
            # Restrict operation:
            #   on care_set: must_be_true.restrict(care_set) <-> must_be_true
            c_model = min([must_be_true.safe_restrict(local_care_set),
                          (~must_be_false).safe_restrict(local_care_set)],
                          key=lambda x: x.dag_size())
            output_models[c_symb.lit] = c_model
            log.DBG_MSG("Size of function for " + str(c.get_index()) + " = " +
                        str(c_model.dag_size()))
            strategy &= BDD.make_eq(c, c_model)
        return output_models
Exemplo n.º 7
0
    def upost(self, q):
        assert isinstance(q, BDD)
        if q in self.succ_cache:
            return iter(self.succ_cache[q])
        A = BDD.true()
        M = set()
        while A != BDD.false():
            a = A.get_one_minterm(self.uinputs)
            trans = BDD.make_cube(
                imap(lambda x: BDD.make_eq(BDD(self.aig.get_primed_var(x.lit)),
                                           self.aig.lit2bdd(x.next)
                                           .and_abstract(q, self.latch_cube)),
                     self.aig.iterate_latches()))
            lhs = trans & a
            rhs = self.aig.prime_all_inputs_in_bdd(trans)
            simd = BDD.make_impl(lhs, rhs).univ_abstract(self.platch_cube)\
                .exist_abstract(self.pcinputs_cube)\
                .univ_abstract(self.cinputs_cube)
            simd = self.aig.unprime_all_inputs_in_bdd(simd)

            A &= ~simd
            Mp = set()
            for m in M:
                if not (BDD.make_impl(m, simd) == BDD.true()):
                    Mp.add(m)
            M = Mp
            M.add(a)
        log.DBG_MSG("Upost |M| = " + str(len(M)))
        self.succ_cache[q] = map(lambda x: (q, x), M)
        return iter(self.succ_cache[q])
Exemplo n.º 8
0
    def post_bdd(self,
                 src_states_bdd,
                 sys_strat=None,
                 use_trans=False,
                 over_approx=False):
        """
        POST = EL.EXu.EXc : src(L) ^ T(L,Xu,Xc,L') [^St(L,Xu,Xc)]
        optional argument fixes possible actions for the environment
        """
        if not use_trans or over_approx:
            return self.over_post_bdd(src_states_bdd, sys_strat)
        transition_bdd = self.trans_rel_bdd()
        trans = transition_bdd
        if sys_strat is not None:
            trans &= sys_strat
        trans = trans.restrict(src_states_bdd)

        suc_bdd = trans.and_abstract(
            src_states_bdd,
            BDD.make_cube(
                imap(
                    funcomp(BDD, symbol_lit),
                    chain(self.iterate_controllable_inputs(),
                          self.iterate_uncontrollable_inputs(),
                          self.iterate_latches()))))
        return self.unprime_latches_in_bdd(suc_bdd)
Exemplo n.º 9
0
 def cpre_bdd(self, dst_states_bdd, get_strat=False, use_trans=False):
     """ CPRE = AXu.EXc.EL' : T(L,Xu,Xc,L') ^ dst(L') """
     # take a transition step backwards
     p_bdd = self.substitute_latches_next(dst_states_bdd,
                                          use_trans=use_trans)
     # for all uncontrollable action there is a contro...
     # note: if argument get_strat == True then we leave the "good"
     # controllable actions in the bdd
     if not get_strat:
         p_bdd = p_bdd.exist_abstract(
             BDD.make_cube(imap(funcomp(BDD, symbol_lit),
                                self.iterate_controllable_inputs())))
         p_bdd = p_bdd.univ_abstract(
             BDD.make_cube(imap(funcomp(BDD, symbol_lit),
                                self.iterate_uncontrollable_inputs())))
     return p_bdd
Exemplo n.º 10
0
 def strat_is_inductive(self, strat, use_trans=False):
     strat_dom = strat.exist_abstract(
         BDD.make_cube(imap(funcomp(BDD, symbol_lit),
                            chain(self.iterate_controllable_inputs(),
                                  self.iterate_uncontrollable_inputs()))))
     p_bdd = self.substitute_latches_next(strat_dom, use_trans=use_trans)
     return BDD.make_impl(strat, p_bdd) == BDD.true()
Exemplo n.º 11
0
 def cpre_bdd(self, dst_states_bdd, get_strat=False, use_trans=False):
     """ CPRE = AXu.EXc.EL' : T(L,Xu,Xc,L') ^ dst(L') """
     # take a transition step backwards
     p_bdd = self.substitute_latches_next(dst_states_bdd,
                                          use_trans=use_trans)
     # for all uncontrollable action there is a contro...
     # note: if argument get_strat == True then we leave the "good"
     # controllable actions in the bdd
     if not get_strat:
         p_bdd = p_bdd.exist_abstract(
             BDD.make_cube(
                 imap(funcomp(BDD, symbol_lit),
                      self.iterate_controllable_inputs())))
         p_bdd = p_bdd.univ_abstract(
             BDD.make_cube(
                 imap(funcomp(BDD, symbol_lit),
                      self.iterate_uncontrollable_inputs())))
     return p_bdd
Exemplo n.º 12
0
 def strat_is_inductive(self, strat, use_trans=False):
     strat_dom = strat.exist_abstract(
         BDD.make_cube(
             imap(
                 funcomp(BDD, symbol_lit),
                 chain(self.iterate_controllable_inputs(),
                       self.iterate_uncontrollable_inputs()))))
     p_bdd = self.substitute_latches_next(strat_dom, use_trans=use_trans)
     return BDD.make_impl(strat, p_bdd) == BDD.true()
Exemplo n.º 13
0
 def __init__(self, aig):
     self.aig = aig
     self.uinputs = [
         x.lit for x in self.aig.iterate_uncontrollable_inputs()
     ]
     self.latches = [x.lit for x in self.aig.iterate_latches()]
     self.latch_cube = BDD.make_cube(
         imap(funcomp(BDD, symbol_lit), self.aig.iterate_latches()))
     self.platch_cube = BDD.make_cube(
         imap(funcomp(BDD, self.aig.get_primed_var, symbol_lit),
              self.aig.iterate_latches()))
     self.cinputs_cube = BDD.make_cube(
         imap(funcomp(BDD, symbol_lit),
              self.aig.iterate_controllable_inputs()))
     self.pcinputs_cube = self.aig.prime_all_inputs_in_bdd(
         self.cinputs_cube)
     self.uinputs_cube = BDD.make_cube(
         imap(funcomp(BDD, symbol_lit),
              self.aig.iterate_uncontrollable_inputs()))
     self.init_state_bdd = self.aig.init_state_bdd()
     self.error_bdd = self.aig.lit2bdd(self.aig.error_fake_latch.lit)
     self.Venv = dict()
     self.Venv[self.init_state_bdd] = True
     self.succ_cache = dict()
Exemplo n.º 14
0
 def over_post_bdd(self, src_states_bdd, sys_strat=None):
     """ Over-approximated version of concrete post which can be done even
     without the transition relation """
     strat = BDD.true()
     if sys_strat is not None:
         strat &= sys_strat
     # to do this, we use an over-simplified transition relation, EXu,Xc
     b = BDD.true()
     for x in self.iterate_latches():
         temp = BDD.make_eq(BDD(self.get_primed_var(x.lit)),
                            self.lit2bdd(x.next))
         b &= temp.and_abstract(
             strat,
             BDD.make_cube(imap(
                 funcomp(BDD, symbol_lit),
                 self.iterate_controllable_inputs()
             )))
         b = b.restrict(src_states_bdd)
     b &= src_states_bdd
     b = b.exist_abstract(
         BDD.make_cube(imap(funcomp(BDD, symbol_lit),
                       chain(self.iterate_latches(),
                             self.iterate_uncontrollable_inputs()))))
     return self.unprime_latches_in_bdd(b)
Exemplo n.º 15
0
 def substitute_latches_next(self, b, use_trans=False, restrict_fun=None):
     if use_trans:
         transition_bdd = self.trans_rel_bdd()
         trans = transition_bdd
         if restrict_fun is not None:
             trans = trans.restrict(restrict_fun)
         primed_bdd = self.prime_latches_in_bdd(b)
         primed_latches = BDD.make_cube(
             imap(funcomp(BDD, self.get_primed_var, symbol_lit),
                  self.iterate_latches()))
         return trans.and_abstract(primed_bdd, primed_latches)
     else:
         latches = [x.lit for x in self.iterate_latches()]
         latch_funs = [self.lit2bdd(x.next) for x in self.iterate_latches()]
         if restrict_fun is not None:
             latch_funs = [x.restrict(restrict_fun) for x in latch_funs]
         # take a transition step backwards
         return b.compose(latches, latch_funs)
Exemplo n.º 16
0
 def substitute_latches_next(self, b, use_trans=False, restrict_fun=None):
     if use_trans:
         transition_bdd = self.trans_rel_bdd()
         trans = transition_bdd
         if restrict_fun is not None:
             trans = trans.restrict(restrict_fun)
         primed_bdd = self.prime_latches_in_bdd(b)
         primed_latches = BDD.make_cube(
             imap(funcomp(BDD, self.get_primed_var, symbol_lit),
                  self.iterate_latches()))
         return trans.and_abstract(primed_bdd,
                                   primed_latches)
     else:
         latches = [x.lit for x in self.iterate_latches()]
         latch_funs = [self.lit2bdd(x.next) for x in
                       self.iterate_latches()]
         if restrict_fun is not None:
             latch_funs = [x.restrict(restrict_fun) for x in latch_funs]
         # take a transition step backwards
         return b.compose(latches, latch_funs)
Exemplo n.º 17
0
def decompose(aig, argv):
    if argv.decomp == 1:
        if lit_is_negated(aig.error_fake_latch.next):
            log.DBG_MSG("Decomposition opt possible (BIG OR case)")
            (A, B) = aig.get_1l_land(strip_lit(aig.error_fake_latch.next))
            return imap(
                lambda a: ConcGame(BDDAIG(aig).short_error(a),
                                   use_trans=argv.use_trans),
                merge_some_signals(BDD.true(), A, aig, argv))
        else:
            (A, B) = aig.get_1l_land(aig.error_fake_latch.next)
            if not B:
                log.DBG_MSG("No decomposition opt possible")
                return None
            else:
                log.DBG_MSG("Decomposition opt possible (A ^ [C v D] case)")
                log.DBG_MSG(str(len(A)) + " AND leaves: " + str(A))
            # critical heuristic: which OR leaf do we distribute?
            # here I propose to choose the one with the most children
            b = B.pop()
            (C, D) = aig.get_1l_land(b)
            for bp in B:
                (Cp, Dp) = aig.get_1l_land(bp)
                if len(Cp) > len(C):
                    b = bp
                    C = Cp
            log.DBG_MSG("Chosen OR: " + str(b))
            rem_AND_leaves = filter(lambda x: strip_lit(x) != b, A)
            rdeps = set()
            for r in rem_AND_leaves:
                rdeps |= aig.get_lit_deps(strip_lit(r))
            log.DBG_MSG("Rem. AND leaves' deps: " + str(rdeps))
            cube = BDD.make_cube(map(aig.lit2bdd, rem_AND_leaves))
            log.DBG_MSG(
                str(len(C)) + " OR leaves: " + str(map(aig.get_lit_name, C)))
            return imap(
                lambda a: ConcGame(BDDAIG(aig).short_error(a),
                                   use_trans=argv.use_trans),
                merge_some_signals(cube, C, aig, argv))
    elif argv.decomp == 2:
        raise NotImplementedError
Exemplo n.º 18
0
def decompose(aig, argv):
    if argv.decomp == 1:
        if lit_is_negated(aig.error_fake_latch.next):
            log.DBG_MSG("Decomposition opt possible (BIG OR case)")
            (A, B) = aig.get_1l_land(strip_lit(aig.error_fake_latch.next))
            return imap(lambda a: ConcGame(
                BDDAIG(aig).short_error(a),
                use_trans=argv.use_trans),
                merge_some_signals(BDD.true(), A, aig, argv))
        else:
            (A, B) = aig.get_1l_land(aig.error_fake_latch.next)
            if not B:
                log.DBG_MSG("No decomposition opt possible")
                return None
            else:
                log.DBG_MSG("Decomposition opt possible (A ^ [C v D] case)")
                log.DBG_MSG(str(len(A)) + " AND leaves: " + str(A))
            # critical heuristic: which OR leaf do we distribute?
            # here I propose to choose the one with the most children
            b = B.pop()
            (C, D) = aig.get_1l_land(b)
            for bp in B:
                (Cp, Dp) = aig.get_1l_land(bp)
                if len(Cp) > len(C):
                    b = bp
                    C = Cp
            log.DBG_MSG("Chosen OR: " + str(b))
            rem_AND_leaves = filter(lambda x: strip_lit(x) != b, A)
            rdeps = set()
            for r in rem_AND_leaves:
                rdeps |= aig.get_lit_deps(strip_lit(r))
            log.DBG_MSG("Rem. AND leaves' deps: " + str(rdeps))
            cube = BDD.make_cube(map(aig.lit2bdd, rem_AND_leaves))
            log.DBG_MSG(str(len(C)) + " OR leaves: " +
                        str(map(aig.get_lit_name, C)))
            return imap(lambda a: ConcGame(
                BDDAIG(aig).short_error(a),
                use_trans=argv.use_trans), merge_some_signals(cube, C, aig,
                                                              argv))
    elif argv.decomp == 2:
        raise NotImplementedError
Exemplo n.º 19
0
    def post_bdd(self, src_states_bdd, sys_strat=None,
                 use_trans=False, over_approx=False):
        """
        POST = EL.EXu.EXc : src(L) ^ T(L,Xu,Xc,L') [^St(L,Xu,Xc)]
        optional argument fixes possible actions for the environment
        """
        if not use_trans or over_approx:
            return self.over_post_bdd(src_states_bdd, sys_strat)
        transition_bdd = self.trans_rel_bdd()
        trans = transition_bdd
        if sys_strat is not None:
            trans &= sys_strat
        trans = trans.restrict(src_states_bdd)

        suc_bdd = trans.and_abstract(
            src_states_bdd,
            BDD.make_cube(imap(funcomp(BDD, symbol_lit), chain(
                self.iterate_controllable_inputs(),
                self.iterate_uncontrollable_inputs(),
                self.iterate_latches())
            )))
        return self.unprime_latches_in_bdd(suc_bdd)
Exemplo n.º 20
0
    def extract_output_funs(self, strategy, care_set=None):
        """
        Calculate BDDs for output functions given non-deterministic winning
        strategy.
        """
        if care_set is None:
            care_set = BDD.true()

        output_models = dict()
        all_outputs = [BDD(x.lit) for x in self.iterate_controllable_inputs()]
        for c_symb in self.iterate_controllable_inputs():
            c = BDD(c_symb.lit)
            others = set(set(all_outputs) - set([c]))
            if others:
                others_cube = BDD.make_cube(others)
                c_arena = strategy.exist_abstract(others_cube)
            else:
                c_arena = strategy
            # pairs (x,u) in which c can be true
            can_be_true = c_arena.cofactor(c)
            # pairs (x,u) in which c can be false
            can_be_false = c_arena.cofactor(~c)
            must_be_true = (~can_be_false) & can_be_true
            must_be_false = (~can_be_true) & can_be_false
            local_care_set = care_set & (must_be_true | must_be_false)
            # Restrict operation:
            #   on care_set: must_be_true.restrict(care_set) <-> must_be_true
            c_model = min([
                must_be_true.safe_restrict(local_care_set),
                (~must_be_false).safe_restrict(local_care_set)
            ],
                          key=lambda x: x.dag_size())
            output_models[c_symb.lit] = c_model
            log.DBG_MSG("Size of function for " + str(c.get_index()) + " = " +
                        str(c_model.dag_size()))
            strategy &= BDD.make_eq(c, c_model)
        return output_models
Exemplo n.º 21
0
 def cpost(self, s):
     assert isinstance(s, tuple)
     q = s[0]
     au = s[1]
     if s in self.succ_cache:
         L = self.succ_cache[s]
     else:
         L = BDD.make_cube(
             imap(lambda x: BDD.make_eq(BDD(x.lit),
                                        self.aig.lit2bdd(x.next)
                                        .and_abstract(q & au,
                                                      self.latch_cube &
                                                      self.uinputs_cube)),
                  self.aig.iterate_latches()))\
             .exist_abstract(self.cinputs_cube)
         self.succ_cache[s] = L
     M = set()
     while L != BDD.false():
         l = L.get_one_minterm(self.latches)
         L &= ~l
         self.Venv[l] = True
         M.add(l)
     log.DBG_MSG("Cpost |M| = " + str(len(M)))
     return iter(M)
Exemplo n.º 22
0
 def cpost(self, s):
     assert isinstance(s, tuple)
     q = s[0]
     au = s[1]
     if s in self.succ_cache:
         L = self.succ_cache[s]
     else:
         L = BDD.make_cube(
             imap(lambda x: BDD.make_eq(BDD(x.lit),
                                        self.aig.lit2bdd(x.next)
                                        .and_abstract(q & au,
                                                      self.latch_cube &
                                                      self.uinputs_cube)),
                  self.aig.iterate_latches()))\
             .exist_abstract(self.cinputs_cube)
         self.succ_cache[s] = L
     M = set()
     while L != BDD.false():
         l = L.get_one_minterm(self.latches)
         L &= ~l
         self.Venv[l] = True
         M.add(l)
     log.DBG_MSG("Cpost |M| = " + str(len(M)))
     return iter(M)
Exemplo n.º 23
0
def comp_synth4(games, gen_game):
    s = None
    cum_s = None
    cum_w = None
    cnt = 0
    triple_list = []
    for game in games:
        assert isinstance(game, BackwardGame)
        w = backward_safety_synth(game)
        cnt += 1
        # short-circuit a negative response
        if w is None:
            log.DBG_MSG("Short-circuit exit 1 after sub-game #" + str(cnt))
            return None
        s = game.cpre(w, get_strat=True)
        if cum_s is None:
            cum_s = s
            cum_w = w
        else:
            cum_s &= s
            cum_w &= w
        # another short-circuit exit
        if (not cum_s or not game.init() & cum_s):
            log.DBG_MSG("Short-circuit exit 2 after sub-game #" + str(cnt))
            return None
        triple_list.append((game, s, w))
    log.DBG_MSG("Solved " + str(cnt) + " sub games.")
    # lets simplify transition functions
    gen_game.aig.restrict_latch_next_funs(cum_s)
    # what comes next is a fixpoint computation using a UPRE
    # step at a time in the global game and using it to get more
    # information from the local sub-games
    lose = BDD.true()
    lose_next = ~cum_w | gen_game.error()
    while lose_next != lose:
        lose = lose_next
        log.DBG_MSG("Doing global UPRE")
        lose_next = lose | gen_game.upre(lose)
        for i in range(len(triple_list)):
            wt = triple_list[i][2]
            gamet = triple_list[i][0]
            local_deps = set([x.lit for x in gamet.aig.iterate_latches()])
            rem_lats = gen_game.aig.get_bdd_latch_deps(lose_next) - local_deps
            pt = lose_next
            if rem_lats:
                pt = lose_next.univ_abstract(BDD.make_cube(map(BDD, rem_lats)))
            # log.BDD_DMP(lose_next, "global losing area iterate")
            # log.BDD_DMP(pt, "new losing area")
            assert BDD.make_impl(~wt, pt) == BDD.true()
            if BDD.make_impl(pt, ~wt) != BDD.true():
                gamet.short_error = pt
                wt = backward_safety_synth(gamet)
                if (wt is None or not gamet.init() & wt):
                    log.DBG_MSG("Short-circuit exit 3")
                    return None
                st = gamet.cpre(wt, get_strat=True)
                gen_game.aig.restrict_latch_next_funs(wt)
                triple_list[i] = (gamet, st, wt)
        for t in triple_list:
            lose_next |= ~t[2]
    # after the fixpoint has been reached we can compute the error
    win = ~lose
    if (not win or not gen_game.init() & win):
        return None
    else:
        return win
Exemplo n.º 24
0
def comp_synth4(games, gen_game):
    s = None
    cum_s = None
    cum_w = None
    cnt = 0
    triple_list = []
    for game in games:
        assert isinstance(game, BackwardGame)
        w = backward_safety_synth(game)
        cnt += 1
        # short-circuit a negative response
        if w is None:
            log.DBG_MSG("Short-circuit exit 1 after sub-game #" + str(cnt))
            return None
        s = game.cpre(w, get_strat=True)
        if cum_s is None:
            cum_s = s
            cum_w = w
        else:
            cum_s &= s
            cum_w &= w
        # another short-circuit exit
        if (not cum_s or not game.init() & cum_s):
            log.DBG_MSG("Short-circuit exit 2 after sub-game #" + str(cnt))
            return None
        triple_list.append((game, s, w))
    log.DBG_MSG("Solved " + str(cnt) + " sub games.")
    # lets simplify transition functions
    gen_game.aig.restrict_latch_next_funs(cum_s)
    # what comes next is a fixpoint computation using a UPRE
    # step at a time in the global game and using it to get more
    # information from the local sub-games
    lose = BDD.true()
    lose_next = ~cum_w | gen_game.error()
    while lose_next != lose:
        lose = lose_next
        log.DBG_MSG("Doing global UPRE")
        lose_next = lose | gen_game.upre(lose)
        for i in range(len(triple_list)):
            wt = triple_list[i][2]
            gamet = triple_list[i][0]
            local_deps = set([x.lit for x in gamet.aig.iterate_latches()])
            rem_lats = gen_game.aig.get_bdd_latch_deps(lose_next) - local_deps
            pt = lose_next
            if rem_lats:
                pt = lose_next.univ_abstract(
                    BDD.make_cube(map(BDD, rem_lats)))
            # log.BDD_DMP(lose_next, "global losing area iterate")
            # log.BDD_DMP(pt, "new losing area")
            assert BDD.make_impl(~wt, pt) == BDD.true()
            if BDD.make_impl(pt, ~wt) != BDD.true():
                gamet.short_error = pt
                wt = backward_safety_synth(gamet)
                if (wt is None or not gamet.init() & wt):
                    log.DBG_MSG("Short-circuit exit 3")
                    return None
                st = gamet.cpre(wt, get_strat=True)
                gen_game.aig.restrict_latch_next_funs(wt)
                triple_list[i] = (gamet, st, wt)
        for t in triple_list:
            lose_next |= ~t[2]
    # after the fixpoint has been reached we can compute the error
    win = ~lose
    if (not win or not gen_game.init() & win):
        return None
    else:
        return win