def is_adder(n, cktinputs): support = n.support() if len(support) != 2: return False support = list(support) support.sort(key=lambda n: n.is_keyinput()) if support[0].is_keyinput() or support[1].is_keyinput(): return False if support[0] not in cktinputs or support[1] not in cktinputs: return False return True x0, x1 = support[0], support[1] m1 = n ^ (x0 ^ x1) m2 = n ^ (~x0 ^ x1) m3 = n ^ (x0 ^ ~x1) m4 = n ^ (~x0 ^ ~x1) nmap = {} S = Solver() clauses = adapter.circuitToCNF(m1, nmap, lambda n: S.newVar()) clauses += adapter.circuitToCNF(m2, nmap, lambda n: S.newVar()) clauses += adapter.circuitToCNF(m3, nmap, lambda n: S.newVar()) clauses += adapter.circuitToCNF(m4, nmap, lambda n: S.newVar()) for cl in clauses: S.addClause(*cl) for m in [m1, m2, m3, m4]: l = nmap[m] if S.solve(l) == False: return True return False
def is_unate(gate): s = Solver() supports = gate.support() #print supports def newVar(n): return s.newVar() for inp in supports: s.push() node_to_literal_0 = {} node_to_literal_1 = {} for sup in supports: if sup != inp: node_to_literal_0[sup] = newVar(0) node_to_literal_1[sup] = node_to_literal_0[sup] ckt1 = ckt.NotGate(gate) ckt_cnf_0 = adapter.circuitToCNF(gate, node_to_literal_0, newVar) ckt_cnf_1 = adapter.circuitToCNF(gate, node_to_literal_1, newVar) for clause in ckt_cnf_0 + ckt_cnf_1: s.addClause(*clause) # Check counter example for positive unateness r1 = s.solve(-node_to_literal_0[inp], node_to_literal_1[inp], node_to_literal_0[gate], -node_to_literal_1[gate]) if r1: # Check counter example for negative unateness r2 = s.solve(-node_to_literal_0[inp], node_to_literal_1[inp], -node_to_literal_0[gate], node_to_literal_1[gate]) if r2: return False s.pop() return True
def isonecounter_v1(eq, ps, k): subs = {pi: ckt.InputNode(pi.name + '_') for pi in ps} eqp = eq.subst(subs) ds = [(pi ^ subs[pi]) for pi in ps] eqHD = hd(ds, 2 * k) y = ckt.AndGate(eq, eqp, eqHD) inps = [(pi, subs[pi]) for pi in ps] S = Solver() nmap = {} clauses = adapter.circuitToCNF(y, nmap, lambda n: S.newVar()) for pi, qi in inps: S.freeze(nmap[pi]) S.freeze(nmap[qi]) for c in clauses: S.addClause(*c) l = nmap[y] S.addClause(l) r = S.solve() if not r: return False, None # gather all the input values. ms, ns = [], [] for pi, qi in inps: ai, bi = nmap[pi], nmap[qi] mi = int(S.modelValue(ai)) ni = int(S.modelValue(bi)) ms.append(mi) ns.append(ni) # assert the obvious ones. key = {} for ((pi, qi), mi, ni) in itertools.izip(inps, ms, ns): ai, bi = nmap[pi], nmap[qi] if mi == ni: key[pi] = mi #S.addClause(valToLit(key[pi], ai)) #S.addClause(valToLit(key[pi], bi)) # now handle the rest. assumps = [] for ((pi, qi), mi, ni) in itertools.izip(inps, ms, ns): ai, bi = nmap[pi], nmap[qi] if mi != ni: r1 = S.solve(valToLit(mi, ai), valToLit(mi, bi)) r2 = S.solve(valToLit(ni, ai), valToLit(ni, bi)) if r1 == True and r2 == False: key[pi] = mi elif r1 == False and r2 == True: key[pi] = ni else: return False, None #S.addClause(valToLit(key[pi], ai)) #S.addClause(valToLit(key[pi], bi)) ks = [key[pi] for pi in ps] return True, ks
def is_fru(tuples, node): mit = ckt.Const0Node() nsupp = node.support() isupp = set() seltuples = [] for (n, ci, ki) in tuples: if ci in nsupp and ki in nsupp: isupp.add(ci) isupp.add(ki) seltuples.append((ci, ki)) print(len(nsupp), len(isupp)) print(nsupp) print(isupp) assert isupp == nsupp print('# of pairs of inputs in support: ' % len(seltuples)) for (ci, ki) in seltuples: eq = (ci ^ ki) mit = mit | eq comp = ckt.NotGate(mit) miter = (node ^ comp) S = Solver() nmap = {} clauses = adapter.circuitToCNF(miter, nmap, lambda n: S.newVar()) for cl in clauses: S.addClause(*cl) r1 = S.solve(nmap[miter]) if r1 == False: return True r2 = S.solve(-nmap[miter]) if r2 == False: return True
def checkKey(eq, ps, ks, k): qs = [~pi if ki else pi for (ki, pi) in itertools.izip(ks, ps)] eqP = hd(qs, k) miter = eq ^ eqP S = Solver() nmap = {} clauses = adapter.circuitToCNF(miter, nmap, lambda n: S.newVar()) for c in clauses: S.addClause(*c) S.addClause(nmap[miter]) r = S.solve() if r: return False else: return True
def is_cubestripper(gate, ps): # solver object s = Solver() # new variable. def newVar(n): return s.newVar() unates = [] for inp in ps: s.push() # create clauses. node_to_literal_0 = {} node_to_literal_1 = {} for sup in ps: if sup != inp: node_to_literal_0[sup] = newVar(0) node_to_literal_1[sup] = node_to_literal_0[sup] ckt1 = ckt.NotGate(gate) ckt_cnf_0 = adapter.circuitToCNF(gate, node_to_literal_0, newVar) ckt_cnf_1 = adapter.circuitToCNF(gate, node_to_literal_1, newVar) for clause in ckt_cnf_0 + ckt_cnf_1: s.addClause(*clause) # Check counter example for positive unateness r1 = s.solve(-node_to_literal_0[inp], node_to_literal_1[inp], node_to_literal_0[gate], -node_to_literal_1[gate]) if r1: # Check counter example for negative unateness r2 = s.solve(-node_to_literal_0[inp], node_to_literal_1[inp], -node_to_literal_0[gate], node_to_literal_1[gate]) if r2: return False, None else: unates.append(0) else: unates.append(1) s.pop() return True, unates
def getUnateNodes(outputs): S = Solver() supports = set() gates = set() for o in outputs: supports = supports.union(o.support()) gates = gates.union(o.transitiveFaninCone()) # topo sort. ckt.computeLevels(gates) def newVar(n): return S.newVar() cnf = [] nmap1 = {} nmap2 = {} cnf += adapter.gateSetToCNF(gates, nmap1, newVar) cnf += adapter.gateSetToCNF(gates, nmap2, newVar) iMap = {} for inp in supports: i1 = ckt.InputNode(inp.name + "__1") i2 = ckt.InputNode(inp.name + "__2") iEq = ckt.XnorGate(i1, i2) nmap = {i1: nmap1[inp], i2: nmap2[inp]} cnf += adapter.circuitToCNF(iEq, nmap, newVar) iMap[inp] = (nmap[i1], nmap[i2], nmap[iEq]) for c in cnf: S.addClause(*c) unates = set() for gate in gates: if gate.is_input(): continue f0 = nmap1[gate] f1 = nmap2[gate] unate = True for i in supports: c1 = checkUnate(S, i, f0, f1, iMap, 0) c2 = checkUnate(S, i, f0, f1, iMap, 1) if not c1 and not c2: unate = False break if unate: unates.add(gate) return unates
def is_comparator(n): support = n.support() if len(support) != 2: return False support = list(support) support.sort(key=lambda n: n.is_keyinput()) if support[0].is_keyinput() or (not support[1].is_keyinput()): return False x0, x1 = support[0], support[1] miter = n ^ (x0 ^ x1) nmap = {} S = Solver() clauses = adapter.circuitToCNF(miter, nmap, lambda n: S.newVar()) for cl in clauses: S.addClause(*cl) r1 = S.solve(nmap[miter]) if r1 == False: return True r2 = S.solve(-nmap[miter]) if r2 == False: return True return False
def test(): xs = [ckt.InputNode('x%d' % i) for i in range(32)] ys = onecount(xs) eq4 = ckt.AndGate(~ys[0], ~ys[1], ys[2], ~ys[3]) print(len(eq4)) return S = Solver() nmap = {} clauses = circuitToCNF(eq4, nmap, lambda n: S.newVar()) for c in clauses: S.addClause(*c) tt = [] while S.solve(): blockingClause = [] row = [] for xi in itertools.chain(reversed(xs)): li = nmap[xi] vi = S.modelValue(li) row.append(vi) if vi: blockingClause.append(-li) else: blockingClause.append(li) num_ones = sum(row) li = nmap[eq4] vi = S.modelValue(li) row.append(vi) tt.append(row) S.addClause(*blockingClause) assert (num_ones == 4) == vi tt.sort() for row in tt: def listToString(l): return ''.join(str(int(i)) for i in l) p1 = listToString(row[:len(xs)]) p2 = listToString(row[len(xs):]) print('%s | %s ' % (p1, p2))
def isonecounter_v3(eq, ps, k, log): subs = {pi: ckt.InputNode(pi.name + '_') for pi in ps} eqp = eq.subst(subs) ds = [(pi ^ subs[pi]) for pi in ps] eqHD = hd(ds, 2 * k) y = ckt.AndGate(eq, eqp, eqHD) inps = [(pi, subs[pi]) for pi in ps] S = Solver() nmap = {} clauses = adapter.circuitToCNF(y, nmap, lambda n: S.newVar()) # freeze literals for pi, qi in inps: S.freeze(nmap[pi]) S.freeze(nmap[qi]) for di in ds: S.freeze(nmap[di]) # add clauses. for c in clauses: S.addClause(*c) l = nmap[y] S.addClause(l) r = S.solve() if not r: return False, None # gather the first round of keys. assumps = [] key = {} for ((pi, qi), di) in itertools.izip(inps, ds): ai, bi = nmap[pi], nmap[qi] mi = int(S.modelValue(ai)) ni = int(S.modelValue(bi)) if mi == ni: key[pi] = mi else: li = nmap[di] assumps.append(-li) r = S.solve(*assumps) if not r: return False, None # and now the second round of keys. for ((pi, qi), di) in itertools.izip(inps, ds): ai, bi = nmap[pi], nmap[qi] mi = int(S.modelValue(ai)) ni = int(S.modelValue(bi)) if mi == ni: key[pi] = mi ks = [key[pi] for pi in ps] if log: pkl.dump(eq, log) pkl.dump(ps, log) pkl.dump(ks, log) log.flush() #log.close() if checkKey(eq, ps, ks, k): return True, ks else: return False, None
def isonecounter_v2(eq, ps, k): S = Solver() subs = {pi: ckt.InputNode(pi.name + '_') for pi in ps} eqp = eq.subst(subs) y = ckt.AndGate(eq, eqp) inps = [(pi, subs[pi]) for pi in ps] ds = [(pi ^ subs[pi]) for pi in ps] nmap = {} ckt_clauses = adapter.circuitToCNF(y, nmap, lambda n: S.newVar()) for di in ds: ckt_clauses += adapter.circuitToCNF(di, nmap, lambda n: S.newVar()) zeros = [] dlits = [nmap[di] for di in ds] while not isPowOf2(len(dlits)): zi = S.newVar() dlits.append(zi) zeros.append(zi) (snw_clauses, es) = sortNetwork(TWO_COMP_EQ, dlits, lambda: S.newVar()) for pi, qi in inps: S.freeze(nmap[pi]) S.freeze(nmap[qi]) for c in zeros: S.addClause(-c) for c in itertools.chain(ckt_clauses, snw_clauses): S.addClause(*c) l = nmap[y] S.addClause(l) for i, ei in enumerate(es): if i < 2 * k: S.addClause(ei) else: S.addClause(-ei) r = S.solve() if not r: return False, None # gather all the input values. ms, ns = [], [] for pi, qi in inps: ai, bi = nmap[pi], nmap[qi] mi = int(S.modelValue(ai)) ni = int(S.modelValue(bi)) ms.append(mi) ns.append(ni) # assert the obvious ones. key = {} for ((pi, qi), mi, ni) in itertools.izip(inps, ms, ns): ai, bi = nmap[pi], nmap[qi] if mi == ni: key[pi] = mi #S.addClause(valToLit(key[pi], ai)) #S.addClause(valToLit(key[pi], bi)) # now handle the rest. assumps = [] for ((pi, qi), mi, ni) in itertools.izip(inps, ms, ns): ai, bi = nmap[pi], nmap[qi] if mi != ni: r1 = S.solve(valToLit(mi, ai), valToLit(mi, bi)) r2 = S.solve(valToLit(ni, ai), valToLit(ni, bi)) if r1 == True and r2 == False: key[pi] = mi elif r1 == False and r2 == True: key[pi] = ni else: return False, None #S.addClause(valToLit(key[pi], ai)) #S.addClause(valToLit(key[pi], bi)) ks = [key[pi] for pi in ps] return True, ks