コード例 #1
0
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
コード例 #2
0
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
コード例 #4
0
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
コード例 #6
0
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
コード例 #7
0
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
コード例 #8
0
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
コード例 #9
0
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))
コード例 #10
0
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
コード例 #11
0
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