class Xor: def __init__(self): # components: self.not1 = Not() self.not2 = Not() self.and1 = And() self.and2 = And() self.or1 = Or() # connections: self.a = self.and1.a self.not2.a = self.and1.a self.b = self.and2.b self.not1.a = self.and2.b self.and1.b = self.not1.x self.and2.a = self.not2.x self.or1.a = self.and1.x self.or1.b = self.and2.x self.x = self.or1.x def update(self): self.not1.update() self.not2.update() self.and1.update() self.and2.update() self.or1.update()
def Forced(G): """Find forced values for variables in a 2SAT instance. A variable's value is forced to x if every satisfying assignment assigns the same value x to that variable. We return a dictionary (possibly empty) in which the keys are the forced variables and their values are the values they are forced to. If the given instance is unsatisfiable, we return None.""" Force = {} Sym = Symmetrize(G) Con = Condensation(Sym) Map = {} for SCC in Con: for v in SCC: Map[v] = SCC Reach = Reachability(Con) for v in Sym: if Reach.reachable(Map[v], Map[Not(v)]): # v implies not v? value = False if isinstance(v, SymbolicNegation): v = Not(v) value = True if v in Force: # already added by negation? return None Force[v] = value return Force
def __init__(self): # components self.nand1 = Nand() self.not1 = Not() # connections self.nand1.x = self.not1.a self.a = self.nand1.a self.b = self.nand1.b self.x = self.not1.x
class TwoSatTest(unittest.TestCase): T1 = {1: [2, 3], 2: [Not(1), 3]} T2 = {1: [2], 2: [Not(1)], Not(1): [3], 3: [4, 2], 4: [1]} def testTwoSat(self): """Check that the correct problems are satisfiable.""" self.assertEqual(Satisfiable(self.T1), True) self.assertEqual(Satisfiable(self.T2), False) def testForced(self): """Check that we can correctly identify forced variables.""" self.assertEqual(Forced(self.T1), {1: False}) self.assertEqual(Forced(self.T2), None)
def Or(a, b, z): nota = Signal(0) notb = Signal(0) out = Signal(0) n1 = Not(a, nota) n2 = Not(b, notb) n3 = Nand(nota, notb, out) @always_comb def f(): z.next = out return f, n1, n2, n3
class And: def __init__(self): # components self.nand1 = Nand() self.not1 = Not() # connections self.nand1.x = self.not1.a self.a = self.nand1.a self.b = self.nand1.b self.x = self.not1.x def update(self): self.nand1.update() self.not1.update()
def Satisfiable(G): """Does this 2SAT instance have a satisfying assignment?""" G = Condensation(Symmetrize(G)) for C in G: for v in C: if Not(v) in C: return False return True
def Xor(a, b, z): nota = Signal(0) notb = Signal(0) andanotb = Signal(0) andbnota = Signal(0) out = Signal(0) n1 = Not(a,nota) n2 = Not(b,notb) n3 = And(a,notb,andanotb) n4 = And(b,nota,andbnota) n5 = Or(andanotb,andbnota,out) @always_comb def f(): z.next = out return f, n1, n2, n3, n4, n5
def Equivalence(a, b, z): notx = Signal(0) noty = Signal(0) andxy = Signal(0) andnotxnoty = Signal(0) out = Signal(0) n1 = Not(a, notx) n2 = Not(b, noty) n3 = And(a, b, andxy) n4 = And(notx, noty, andnotxnoty) n5 = Or(andxy, andnotxnoty, out) @always_comb def f(): z.next = out return f, n1, n2, n3, n4, n5
def Notx(a, b, z): out = Signal(0) n1 = Not(a, out) @always_comb def f(): z.next = out return f, n1
def X(x, y, out): out1 = Signal(0) r1 = Not(y, out1) @always_comb def f(): out.next = x return f, r1
def Symmetrize(G): """Expand implication graph to a larger symmetric form. If the 2SAT instance includes an implication A=>B, then it is also valid to conclude that ~B => ~A, and our 2SAT solver needs to have that second implication made explicit. But we do not want to force users to supply the contrapositives for each of the implications they include, so we use this routine to fill in any missing implications. """ H = copyGraph(G) for v in G: H.setdefault(Not(v), set()) # make sure all negations are included for w in G[v]: H.setdefault(w, set()) # as well as all implicants H.setdefault(Not(w), set()) # and negated implicants for v in G: for w in G[v]: H[Not(w)].add(Not(v)) return H
def Ifxtheny(a, b, z): notx = Signal(0) out = Signal(0) n1 = Not(a, notx) n2 = Or(notx, b, out) @always_comb def f(): z.next = out return f, n1, n2
def And(a, b, z): nandab = Signal(0) out = Signal(0) n1 = Nand(a, b, nandab) n2 = Not(nandab, out) @always_comb def f(): z.next = out return f, n1, n2
def Ifythenx(a, b, z): noty = Signal(0) out = Signal(0) n1 = Not(b, noty) n2 = Or(noty, a, out) @always_comb def f(): z.next = out return f, n1, n2
def Notxandy(a, b, z): notx = Signal(0) out = Signal(0) n1 = Not(a, notx) n2 = And(notx, b, out) @always_comb def f(): z.next = out return f, n1, n2
def Xandnoty(a, b, z): noty = Signal(0) out = Signal(0) n1 = Not(b, noty) n2 = And(a, noty, out) @always_comb def f(): z.next = out return f, n1, n2
def Notxandy(x, y, out): out1 = Signal(0) n1 = Signal(0) s1 = Not(x, n1) s2 = And(n1, y, out1) @always_comb def f(): out.next = out1 return f, s1, s2,
def And(x, y, out): a1 = Signal(0) out1 = Signal(0) s1 = Nand(x, y, a1) s2 = Not(a1, out1) @always_comb def f(): out.next = out1 return f, s1, s2,
def Nor(a, b, z): orab = Signal(0) out = Signal(0) n1 = Or(a, b, orab) n2 = Not(orab, out) @always_comb def f(): z.next = out return f, n1, n2
def Xandnoty(x , y , out): out1 = Signal(0) n1 = Signal(0) s1 = Not(y,n1) s2 = And(x , n1, out1) @always_comb def f(): out.next = out1 return f, s1 , s2,
def Noty(x, y, out): out1 = Signal(0) n1 = Signal(0) n2 = Signal(0) n3 = Signal(0) n4 = Signal(0) n5 = Signal(0) n6 = Signal(0) s1 = Not(y, out1) @always_comb def f(): out.next = out1 return f, s1
def constant0(x, y, out): out1 = Signal(0) n1 = Signal(0) n2 = Signal(0) n3 = Signal(0) n4 = Signal(0) n5 = Signal(0) n6 = Signal(0) s1 = Nand(x, 0, n1) s2 = Not(n1, out1) @always_comb def f(): out.next = out1 return f, s1, s2
def Ifxtheny(x, y, out): out1 = Signal(0) n1 = Signal(0) n2 = Signal(0) n3 = Signal(0) n4 = Signal(0) n5 = Signal(0) n6 = Signal(0) s1 = Not(x, n3) s2 = Or(n3, y, out1) @always_comb def f(): out.next = out1 return f, s1, s2
def Nor(x, y, out): out1 = Signal(0) n1 = Signal(0) n2 = Signal(0) n3 = Signal(0) n4 = Signal(0) n5 = Signal(0) n6 = Signal(0) s1 = Or(x, y, n1) s2 = Not(n1, out1) @always_comb def f(): out.next = out1 return f, s1, s2
self.assertEqual(Forced(self.T1), {1: False}) self.assertEqual(Forced(self.T2), None) if __name__ == "__main__": #unittest.main() a = open('e:\\2sat7.txt') head = 0 print 'test' T = {} for i in a: if head != 0: u = int(i.strip().split(' ')[0]) v = int(i.strip().split(' ')[1]) if u < 0: u1 = Not(u) else: u1 = u if v < 0: v1 = Not(v) else: v1 = v if u1 in T: T[u1].append(v1) else: T[u1] = [v1] head += 1 print T print Satisfiable(T)