def hard_phi(literals, k = 3): literals = shuffle(literals) n = len(literals) L = [prop.And(literals[i*n/k:(i+1)*n/k]) for i in range(n/k)] L.append(literals[0]) print L return prop.Or(L).cnf()
def random_phi(length = 10, vars = 10): V = ["phi"+str(i) for i in range(vars)] phi = [] i = 0 while i < length: tmp = [] if i >= length-3: break k = rnd.randint(3, length-i-1) for j in range(k): tmp_var = V[rnd.randint(0, vars-1)] # P(negacija formula) = 1/2? if rnd.randint(0, 5) <= 3: tmp.append(prop.Not(tmp_var) if rnd.randint(0,1) == 0 else tmp_var) # E[dolzina] = k * 3/5 else: break i = i+1 if len(prop.Or(tmp).l) > 0: phi.append(prop.Or(tmp)) # Protislovja spustimo (zato vrnemo formulo dolzine kvecjemu length :-) i = i+1 return prop.And(phi)
def hadamard2sat(n): assert n % 2 == 0 l = [] #naredi matrikco za lazje mislit ma3ka = {} for i in range(n): for j in range(n): ma3ka[(i, j)] = "v" + str(j) + "s" + str(i) #vjsi = vrstica j, stolpec i print ma3ka xOri = [] #nardimo xOre vrstic za vsak stolpec. for i in range(n - 1): for j in range(n): xOri.append( prop.Or([ prop.And([ma3ka[(i, j)], prop.Not(ma3ka[(i + 1, j)])]), prop.And([prop.Not(ma3ka[(i, j)]), ma3ka[(i + 1, j)]]) ])) #vse mozne true - false kombinacije a = list(itertools.combinations(xOri, len(xOri) / 2)) #generiramo mozne stolpce stolpec = [] for j in range(len(a)): stolpec.append( prop.And([x if x in a[j] else prop.Not(x) for x in xOri])) #nardimo or moznih stolpcev l.append(prop.Or(stolpec)) xOri = [] #vrnemo koncno formulo return prop.And(l)
def test1(): ## Sestavljanje in manipuliranje formul ## # Sestavimo zelo enostavno formulo u \/ v phi = prop.Or(["v", "u"]) ## Uporaba SAT solverjev ## # Test DPLL SAT solverja print "*" * 80 print "Testiram DPLL SAT solver" dpll_sat_test(phi) # Test bruteforce SAT solverja print "*" * 80 print "Testiram bruteforce SAT solver" bf_sat_test(phi) ## Prevedbe ## print "*" * 80 print "*" * 80 print "Testiram prevedbe" # k-barvanje grafov print "*" * 80 print "Barvanje grafov" k = 2 # dvodelnost G = (3, [(0, 1), (1, 2), (0, 2)]) phi = p.graph_coloring2sat(G, k) print phi # return # Sudoku print "*" * 80 print "Sudoku" S = h.get_sudoku('sudoku01a.in') phi = p.sudoku2sat(S) print phi x = sat.sat(phi.cnf()) print S print p.solveSudoku(S, x) # return # Hadamard print "*" * 80 print "Hadamard" phi = hadamard(4) print phi # return # Erdosev problem diskrepance print "*" * 80 print "Erdosev problem diskrepance" phi = edp(1, 5) print phi
def hadamard(n): #hadamardove matrike obstajajo le za sode n assert n % 2 == 0 if (n % 2 != 0): return prop.Fls() l = [] #predpostavka - prva vrstica so vsi True l.append(prop.And(["v0s%d" % i for i in range(n)])) #generiramo mozne kombinacije, tako da je n/2 clenov True in n/2 False a = list(itertools.combinations(range(n), n / 2)) #print a; #print a; #gneriraj vse mozne vrstice | v moz[i] so spravljenje vse mogoce kombinacije spremenljivk za vrstico i moz = [[]] for i in range(1, n): moz.append([]) for j in range(len(a)): moz[i].append( prop.And([ prop.Not("v" + str(i) + "s%d" % k) if (k not in a[j]) else "v" + str(i) + "s%d" % k for k in range(n) ])) #print moz; #generiraj vse mozne matrike, katerih vrstice bi ustrezale Hadamardovi matriki #b = list(itertools.combinations(range(1,n*len(a)), n-1)); #iz vseh moznih vrstic moramo izbrati n-1, ker prvo ze imamo #print b; moz2 = [] b = list(itertools.combinations(range(len(moz[1])), n - 1)) for j in range(1): #range(len(b)): moz2.append( prop.And( [l[0], prop.And([moz[i][b[j][i - 1]] for i in range(1, n)])])) print moz2 return prop.Or(moz2) """
def graph_coloring2sat(G, k): # G[0] naj bo stevilo povezav # G[1] naj bo seznam parov vozlics, a.k.a, seznan pobexzav # k > 0 je stevilo barv assert k > 0, "Premalo barv" l = [] # vsako vozlisce ima vsaj eno barvo l.append( prop.And([ prop.Or(["v%dc%d" % (i, j) for j in range(k)]) for i in range(G[0]) ])) # pari krajisc so razlicnih barv for (u, v) in G[1]: l.append( prop.And([ prop.And([ prop.Not( prop.And([ "v" + str(u) + "c" + str(c), "v" + str(v) + "c" + str(c) ])) for c in range(k) ]) ])) # vsako vozlisce je kvecjemu ene barve for v in range(G[0]): for i in range(k): for j in range(i + 1, k): l.append( prop.Not( prop.And([ "v" + str(v) + "c" + str(i), "v" + str(v) + "c" + str(j) ]))) phi = prop.And(l) #print phi return phi
def sudoku2sat(s): V = 81 #stevilo kvadratkov (vozlisc) k = 9 #stevilo barv l = [] #list logicnih formul # sudoku je oznacen: # # 1 2 3 4 5 6 7 8 9 # 10 11 12 13 14 15 16 17 18 # ... # # pretvori sudoku s v 1d seznam novS = [] for i in range(k): novS = novS + s[i] s = novS # print s; povVrst = [] # povezani kvadratki v vrsticah povStolp = [] # povezani kvadratki v stolpcih povKvadr = [] # povezani kvadratki v 3x3 kvadratih # Konstriramo graf, 9-barvljiv <==> Sudoku resljiv # povezemo kvadratke v vrsticah for k in range(0, 9): for i in range(1, 10): for j in range(i + 1, 10): povVrst.append((i + k * 9, j + k * 9)) #p ovezemo kvadratke v stolpcih for i in range(1, 10): # index stolpca v k-ti vrstici for k in range(0, 9): # index vrstice for j in range(k + 1, 9): # stoplci, ki se niso povezavi s k-tim stolpcem povStolp.append((i + 9 * k, i + 9 * j)) #povezemo kvadratke znotraj 3x3 kvadratov for i in range(0, 3): for j in range(1, 4): povKvadr.append(((j * 3 - 1) + (9 * (3 * i + 1) - 10), (j * 3 - 1) + (9 * (3 * i + 1)) + 10)) # Doda povezavo, ki je manjkala povKvadr.append(((j * 3 - 1) + (9 * (3 * i + 1)), (j * 3 - 1) + (9 * (3 * i + 1)) + 10)) povKvadr.append(((j * 3 - 1) + (9 * (3 * i + 1)), (j * 3 - 1) + (9 * (3 * i + 1)) - 10)) povKvadr.append(((j * 3 - 1) + (9 * (3 * i + 1) - 8), (j * 3 - 1) + (9 * (3 * i + 1)) + 8)) # Doda povezav, ki jo manjkala povKvadr.append(((j * 3 - 1) + (9 * (3 * i + 1)), (j * 3 - 1) + (9 * (3 * i + 1)) + 8)) povKvadr.append(((j * 3 - 1) + (9 * (3 * i + 1)), (j * 3 - 1) + (9 * (3 * i + 1)) - 8)) povKvadr.append(((j * 3 - 1) + (9 * (3 * i + 1) - 1), (j * 3 - 1) + (9 * (3 * i + 1)) - 9)) # / povKvadr.append(((j * 3 - 1) + (9 * (3 * i + 1) + 1), (j * 3 - 1) + (9 * (3 * i + 1)) - 9)) # \ povKvadr.append(((j * 3 - 1) + (9 * (3 * i + 1) - 1), (j * 3 - 1) + (9 * (3 * i + 1)) + 9)) # / povKvadr.append(((j * 3 - 1) + (9 * (3 * i + 1) + 1), (j * 3 - 1) + (9 * (3 * i + 1)) + 9)) # \ povezave = povVrst + povStolp + povKvadr # vsako vozlisce ima vsaj eno barvo # vozlisca v imajo stevilko v zacetnem sudoku-ju pobarvamo z znano barvo #l.append(prop.And([prop.Or(["v%dc%d" % (i, j) for j in range(k)]) for i in range(G[0])])) barveVoz = [] for i in range(1, V + 1): if ( s[i - 1] == None ): #ce je None, je lahko ubistvu kjerekoli barve, ce ne upostevamo pogojev barveVoz.append( prop.Or(["v%dc%d" % (i, j) for j in range(1, 9 + 1)])) else: #print str(i)+" "+s[i-1]; barveVoz.append("v%dc%d" % (i, int(s[i - 1]))) #ce ni None, ima ze tocno doloceno barvo... barveVoz = prop.And(barveVoz) l.append(barveVoz) barveKraj = [] # pari krajisc so razlicnih barv for (u, v) in povezave: if (s[u - 1] != None): barveKraj.append(prop.Not("v" + str(v) + "c" + s[u - 1])) elif (s[v - 1] != None): barveKraj.append(prop.Not("v" + str(u) + "c" + s[v - 1])) else: for c in range(1, 9 + 1): barveKraj.append( prop.Not( prop.And([ "v" + str(u) + "c" + str(c), "v" + str(v) + "c" + str(c) ]))) l.append(prop.And(barveKraj)) # vsako vozlisce je kvecjemu ene barve for v in range(1, V + 1): if (s[v - 1] == None): for i in range(1, 9 + 1): for j in range(i + 1, 9 + 1): l.append( prop.Not( prop.And([ "v" + str(v) + "c" + str(i), "v" + str(v) + "c" + str(j) ]))) return prop.And(l)
j = n = len(L) while True: R.append(L[1:]) j = n - 1 # NOTE: Changing `L[j] == 1' to `L[j] == mi' will generate [m1] x [m2] x ... x [mn], where [mi] denotes {1,2, ..., mi} while j > 0 and L[j] == 1: L[j] = 0 j = j - 1 L[j] = L[j] + 1 if j == 0: break return R # tries all possible assignments def brute_force(phi): # TODO: Get a list of variables from phi; then feed the list to comb() to get all possible assignments for asg in comb([0, 0, 0, 0, 0, 0, 0, 0]): print asg # print { i : asg[i] for i in range(len(asg)) } # Vstopna tocka if __name__ == "__main__": phi = prop.And([("a"), "a", prop.Or(prop.Not("b"), "d"), "c", prop.Or([prop.Not("b"), "a"])]).cnf() print phi print satBruteForce(phi) print sat(phi) print sat3(phi)
def edp2sat(fname): L = open(fname).read().split('\n') fmt = L[0] return prop.And([ prop.Or([clean(c) for c in clause.split()[:-1]]) for clause in L[1:-1] ])
def parse_output(fname = 'new.cnf'): L = open(fname).read().split('\n') fmt = L[0] return prop.And([prop.Or([clean(c) for c in clause.split()[:-1]]) for clause in L[1:-1]])
def rnd_cnf(literals, k = 3): literals = shuffle(literals) n = len(literals) return prop.And([prop.Or(literals[i*n/k:(i+1)*n/k]) for i in range(n/k)])
def sudoku(s): V = 81; #stevilo kvadratkov (vozlisc) k = 9; #stevilo barv l = []; #list logicnih formul #sudoku je oznacen: """ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 ... """ #pretvori sudoku s v 1d seznam novS = []; for i in range(k): novS = novS + s[i]; s = novS; #print s; povVrst = [] #povezani kvadratki v vrsticah povStolp = [] #povezani kvadratki v stolpcih povKvadr = [] #povezani kvadratki v 3x3 kvadratih """ for i in range(1, 82): if (i % 9 != 0 and i != 81): povVrst.append((i,i+1)); #delamo povezave vrstic if (i < 73): povStolp.append((i,9+i)); #delamo povezave stolpcev """ # Konstriramo graf, 9-barvljiv <==> Sudoku resljiv #povezemo kvadratke v vrsticah for k in range(0,9): for i in range(1,10): for j in range(i+1, 10): povVrst.append((i+k*9, j+k*9)); #povezemo kvadratke v stolpcih for i in range(1,10): # index stolpca v k-ti vrstici for k in range(0,9): # index vrstice for j in range(k+1, 9): # stoplci, ki se niso povezavi s k-tim stolpcem povStolp.append((i+9*k, i+9*j)); #print povVrst; #print povStolp; #povezemo kvadratke znotraj 3x3 kvadratov for i in range(0,3): for j in range(1,4): #povKvadr.append(((j*3-1)+(9*(3*i+1)), (j*3-1)+(9*(3*i+1))+1)); #povKvadr.append(((j*3-1)+(9*(3*i+1)), (j*3-1)+(9*(3*i+1))-1)); #povKvadr.append(((j*3-1)+(9*(3*i+1)), (j*3-1)+(9*(3*i+1))+9)); #povKvadr.append(((j*3-1)+(9*(3*i+1)), (j*3-1)+(9*(3*i+1))-9)); povKvadr.append(((j*3-1)+(9*(3*i+1)-10), (j*3-1)+(9*(3*i+1))+10)); # Doda povezavo, ki je manjkala povKvadr.append(((j*3-1)+(9*(3*i+1)), (j*3-1)+(9*(3*i+1))+10)); povKvadr.append(((j*3-1)+(9*(3*i+1)), (j*3-1)+(9*(3*i+1))-10)); povKvadr.append(((j*3-1)+(9*(3*i+1)-8), (j*3-1)+(9*(3*i+1))+8)); # Doda povezav, ki jo manjkala povKvadr.append(((j*3-1)+(9*(3*i+1)), (j*3-1)+(9*(3*i+1))+8)); povKvadr.append(((j*3-1)+(9*(3*i+1)), (j*3-1)+(9*(3*i+1))-8)); povKvadr.append(((j*3-1)+(9*(3*i+1)-1), (j*3-1)+(9*(3*i+1))-9)) # / povKvadr.append(((j*3-1)+(9*(3*i+1)+1), (j*3-1)+(9*(3*i+1))-9)) # \ povKvadr.append(((j*3-1)+(9*(3*i+1)-1), (j*3-1)+(9*(3*i+1))+9)) # / povKvadr.append(((j*3-1)+(9*(3*i+1)+1), (j*3-1)+(9*(3*i+1))+9)) # \ #print povKvadr; povezave = povVrst + povStolp + povKvadr; #povezave = povVrst + povKvadr; #povezave = list(set(povezave)); #odstranimo duplikate povezav #print povezave # vsako vozlisce ima vsaj eno barvo # vozlisca v imajo stevilko v zacetnem sudoku-ju pobarvamo z znano barvo #l.append(prop.And([prop.Or(["v%dc%d" % (i, j) for j in range(k)]) for i in range(G[0])])) barveVoz = []; for i in range(1, V+1): if(s[i-1] == None): #ce je None, je lahko ubistvu kjerekoli barve, ce ne upostevamo pogojev barveVoz.append(prop.Or(["v%dc%d" % (i, j) for j in range(1, 9+1)])); else: #print str(i)+" "+s[i-1]; barveVoz.append("v%dc%d" % (i, int(s[i-1]))); #ce ni None, ima ze tocno doloceno barvo... barveVoz = prop.And(barveVoz); l.append(barveVoz); #print barveVoz; barveKraj = []; # pari krajisc so razlicnih barv for (u, v) in povezave: if(s[u-1] != None): #barveKraj.append(prop.Not(prop.And(["v"+str(u)+"c"+s[u-1], "v"+str(v)+"c"+s[u-1]]))); barveKraj.append(prop.Not("v"+str(v)+"c"+s[u-1])); elif(s[v-1] != None): #barveKraj.append(prop.Not(prop.And(["v"+str(u)+"c"+s[v-1], "v"+str(v)+"c"+s[v-1]]))); barveKraj.append(prop.Not("v"+str(u)+"c"+s[v-1])); else: for c in range(1, 9+1): barveKraj.append(prop.Not(prop.And(["v"+str(u)+"c"+str(c), "v"+str(v)+"c"+str(c)]))); #l.append(prop.And([prop.And([prop.Not(prop.And(["v"+str(u)+"c"+str(c), "v"+str(v)+"c"+str(c)])) for c in range(k)])])) #print barveKraj; l.append(prop.And(barveKraj)); #print l; # print "BARVEEEEE", k # vsako vozlisce je kvecjemu ene barve for v in range(1, V+1): if(s[v-1] == None): for i in range(1, 9+1): for j in range(i+1, 9+1): l.append(prop.Not(prop.And(["v"+str(v)+"c"+str(i), "v"+str(v)+"c"+str(j)]))) l = prop.And(l); #print l; return l;