def lit2formula(self, lit): if lit in self.lit_to_formula: return self.lit_to_formula[lit] # get stripped lit stripped_lit = strip_lit(lit) is_neg = lit_is_negated(lit) (input, latch, and_gate) = self.aig.get_lit_type(stripped_lit) # is it an input, latch, gate or constant if input or latch: # Boolean variables are encoded as 1-bit integers for now result = "({0})".format(self.name_of(stripped_lit)) elif and_gate: if numeric_mode: result = ("({0} * {1})".format(self.lit2formula(and_gate.rhs0), self.lit2formula( and_gate.rhs1))) else: result = ("({0} && {1})".format( self.lit2formula(and_gate.rhs0), self.lit2formula(and_gate.rhs1))) else: # 0 literal, 1 literal and errors result = "0" # this means false # cache result self.lit_to_formula[stripped_lit] = result if is_neg: if result == "0": result = "1" else: if numeric_mode: result = "(1-{0})".format(result) else: result = "!{0}".format(result) self.lit_to_formula[lit] = result return result
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 get_bdd_for_aig_lit(lit): """ Convert AIGER lit into BDD. param lit: 'signed' value of gate returns: BDD representation of the input literal """ # query cache if lit in lit_to_bdd: return lit_to_bdd[lit] # get stripped lit stripped_lit = aig.strip_lit(lit) if stripped_lit == error_fake_latch.lit: (intput, latch, and_gate) = (None, error_fake_latch, None) else: (intput, latch, and_gate) = aig.get_lit_type(stripped_lit) # is it an input, latch, gate or constant if intput or latch: result = bdd.BDD(stripped_lit) elif and_gate: result = (get_bdd_for_aig_lit(and_gate.rhs0) & get_bdd_for_aig_lit(and_gate.rhs1)) else: # 0 literal, 1 literal and errors result = bdd.false() # cache result lit_to_bdd[stripped_lit] = result bdd_to_lit[result] = stripped_lit # check for negation if aig.lit_is_negated(lit): result = ~result lit_to_bdd[lit] = result bdd_to_lit[result] = lit return result
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
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
def name_of(self, lit): assert(lit == strip_lit(lit)) ident = "P"+str(self.index) (intput, latch, and_gate) = self.aig.get_lit_type(lit) # is it an input, latch, gate or constant #print >> sys.stderr, "lit", lit, (input,latch,and_gate) if latch: return "L"+ident+self.aig.get_lit_name(lit).replace("<", "_").replace(">", "_"); elif input: # Boolean variables are encoded as 1-bit integers for now return "I"+ident+self.aig.get_lit_name(lit).replace("<", "_").replace(">", "_"); else: raise "And gates or constant inputs have no name"
def trans_rel_CNF(): global cached_tr_cnf # we create a fake latch for the error introduce_error_latch() if cached_tr_cnf is not None: return cached_tr_cnf # per latch, handle the next function T = sat.CNF() for l in iterate_latches(): # easy case, the latch just directly maps input or terminal (ii, ll, a) = get_lit_type(l.next) if not a: if l.next == 0 or l.next == 1: # is it a terminal? T.add_mand(get_primed_var(l.lit), [l.next]) else: # otherwise x = strip_lit(l.next) * -1 if lit_is_negated(l.next)\ else strip_lit(l.next) T.add_mand(get_primed_var(l.lit), [x]) else: # complicated case, l.next is an AND if lit_is_negated(l.next): A = set([strip_lit(l.next) * -1]) B = set([strip_lit(l.next)]) else: (A, B) = get_mand(l.next) T.add_mand(get_primed_var(l.lit), A) pending = B # handle CNF for each pending gate while pending: cur = pending.pop() (A, B) = get_mand(cur) pending |= B T.add_mand(cur, A) # handle caching cached_tr_cnf = T return T
def get_mand(lit): (A, B) = get_1l_land(lit) A2 = set(map(A, lambda x: strip_lit(x) * -1 if lit_is_negated(x) else x)) return (A2, B)
def get_primed_variable(lit): return aig.strip_lit(lit) + 1