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)
def lit2bdd(self, lit): """ Convert AIGER lit into BDD """ # query cache if lit in self.lit_to_bdd: return self.lit_to_bdd[lit] # get stripped lit stripped_lit = strip_lit(lit) (intput, latch, and_gate) = self.get_lit_type(stripped_lit) # is it an input, latch, gate or constant if intput or latch: result = BDD(stripped_lit) elif and_gate: result = (self.lit2bdd(and_gate.rhs0) & self.lit2bdd(and_gate.rhs1)) else: # 0 literal, 1 literal and errors result = BDD.false() # cache result self.lit_to_bdd[stripped_lit] = result self.bdd_to_lit[result] = stripped_lit # check for negation if lit_is_negated(lit): result = ~result self.lit_to_bdd[lit] = result self.bdd_to_lit[result] = lit return result
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])
def trans_rel_bdd(self): # check cache if self._cached_transition is not None: return self._cached_transition b = BDD.true() for x in self.iterate_latches(): b &= BDD.make_eq(BDD(self.get_primed_var(x.lit)), self.lit2bdd(x.next)) self._cached_transition = b log.BDD_DMP(b, "Composed and cached the concrete transition relation.") return b
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
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)
def init_state_bdd(self): b = BDD.true() for x in self.iterate_latches(): b &= ~BDD(x.lit) return b