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 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 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 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 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)
def sat3(phi, d=None, variables=None): #Izboljsan sta solver z hevristiko, in sicer definirajmo a kot kolikokrat se je pojavila spremenljivka, #in b kot dolzino najmanjsega izraza, kjer je spremenljivka nastopala. Hevristika je enaka a/b. #Ustvarimo si slovar in mnozico vseh spremenljivk, ce jih ze nimamo if not type(d) == dict: d = {} if not type(variables) == set: variables = set() prop.allVariables(phi, variables) cleanVariables = set() unCleanVariables = set() heuristicInfo = defaultdict( lambda: [0, -1 * sys.maxint + 1 ]) #prva komponenta shranjuje, kolikokrat se je spremenljivka #pojavila, druga pa, kaksna je velikost najmanjsega izraza, v katerem je sodelovala if isinstance(phi, prop.Tru): return prop.Tru(), d elif isinstance(phi, prop.Fls): return prop.Fls(), None elif isinstance(phi, prop.Or) and len(phi.l) == 0: return prop.Fls( ), None #Vcasih se zgodi, da dobimo prazen Or namesto prop.Fls elif isinstance(phi, prop.And): if len(phi.l) == 0: return prop.Tru(), d #prazen And pomeni prop.Tru() #print len(phi.l) for lit in phi.l: if isinstance(lit, prop.Fls): return prop.Fls( ), None #ce je vsaj eden od elementov Fls, vrnemo fls elif isinstance(lit, prop.Or): if len(lit.l) == 0: return prop.Fls( ), None #Prazen stavek, zgolj zaradi varnosti, ampak mislim, da vcasih funkcija apply vrne prazen Or for lit2 in lit.l: #Literali v Or if isinstance(lit2, prop.Not): heuristicInfo[lit2.t.p][1] = min( len(lit.l), heuristicInfo[lit2.t.p][1]) heuristicInfo[lit2.t.p][0] += 1 if lit2.t in unCleanVariables: pass #spremenljivka je umazana elif lit2 in cleanVariables: pass #spremenljivka ostaja cista elif lit2.t in cleanVariables: # spremenljivka se je umazala unCleanVariables.add( lit2.t) #spremenljivka gre v umazano sobo cleanVariables.remove(lit2.t) elif lit2 not in cleanVariables and lit2.t not in cleanVariables: #spremenljivka ima moznost postati cista cleanVariables.add(lit2) else: assert False, "Tu ni vec nic za narediti" elif isinstance(lit2, prop.Literal): heuristicInfo[lit2.p][1] = min( len(lit.l), heuristicInfo[lit2.p][1]) heuristicInfo[lit2.p][0] += 1 if lit2 in unCleanVariables: pass #spremenljivka je umazana, zanjo ni resitve elif lit2 in cleanVariables: pass #spremenljivka je cista, se je upanje elif prop.Not( lit2 ) in cleanVariables: #umazali smo spremenljivko cleanVariables.remove(prop.Not(lit2)) unCleanVariables.add(lit2) elif lit2 not in cleanVariables and prop.Not( lit2 ) not in cleanVariables: #spremenljivka ima moznost postati cista cleanVariables.add(lit2) else: assert False, "Tu ni vec nic za narediti" else: assert False, "You shall not pass this door" elif isinstance(lit, prop.Not): if lit.t.p not in d: #ce spremenljivke se nismo obravnavali d[lit.t.p] = prop.Fls() variables.remove(lit.t.p) #smo jo nastavili elif lit.t.p in d and d[lit.t.p] == prop.Tru(): return prop.Fls( ), None #ce smo jo obravnavali in jo postavili obratno else: pass #enkrat smo ze nastavljali to spremenljivko elif isinstance(lit, prop.Literal): #naredimo skoraj enako kot prej if lit.p not in d: #ce spremenljivke se nismo obravnavali d[lit.p] = prop.Tru() #phi = phi.apply(d) variables.remove(lit.p) #smo jo nastavili elif lit.p in d and d[lit.p] == prop.Fls(): return prop.Fls(), None else: pass #enkrat smo ze nastavljali to spremenljivko else: print lit.__class__.__name__ assert False, "Nemogoce: Je formula res CNF?" #pogledamo, ali imamo kaksne ciste spremenljivke, ki jih se nismo spremenili for clean in cleanVariables: if isinstance(clean, prop.Not): if clean.t.p in variables: #spremenljivke se nismo nastavljali d[clean.t.p] = prop.Fls() variables.remove(clean.t.p) else: pass elif isinstance(clean, prop.Literal): if clean.p in variables: #spremenljivke se nismo nastavljali d[clean.p] = prop.Tru() variables.remove(clean.p) if len(variables) != 0: #Nismo se porabili vseh spremenljivk candidates = sorted([(1.0 * value[0] / (1.0 * value[1]), key) for key, value in heuristicInfo.iteritems()], reverse=True) i = 0 while (candidates[i][1] not in variables): i += 1 var = candidates[i][1] while (var not in variables): i += 1 var = candidates[i][1] variables.remove(var) d1 = dict(d) d1[var] = prop.Tru() result, d1 = sat(phi.apply(d1), d1, set(variables)) if result == prop.Tru(): return result, d1 d2 = dict(d) d2[var] = prop.Fls() result, d2 = sat(phi.apply(d2), d2, set(variables)) if result == prop.Tru(): return result, d2 return prop.Fls(), None else: return sat( phi.apply(d), d, variables ) #koncali delo, stavki na zacetku funkcije poskrbijo za uspesno koncanje metode
def sat(phi, d=None, variables=None): #Ustvarimo si slovar in mnozico vseh spremenljivk, ce jih ze nimamo if not type(d) == dict: d = {} if not type(variables) == set: variables = set() prop.allVariables(phi, variables) cleanVariables = set() unCleanVariables = set() if isinstance(phi, prop.Tru): return prop.Tru(), d elif isinstance(phi, prop.Fls): return prop.Fls(), None elif isinstance(phi, prop.Or) and len(phi.l) == 0: return prop.Fls( ), None #Vcasih se zgodi, da dobimo prazen Or namesto prop.Fls elif isinstance(phi, prop.And): if len(phi.l) == 0: return prop.Tru(), d #prazen And pomeni prop.Tru() #print len(phi.l) for lit in phi.l: if isinstance(lit, prop.Fls): return prop.Fls( ), None #ce je vsaj eden od elementov Fls, vrnemo fls elif isinstance(lit, prop.Or): if len(lit.l) == 0: return prop.Fls( ), None #Prazen stavek, zgolj zaradi varnosti, ampak mislim, da vcasih funkcija apply vrne prazen Or for lit2 in lit.l: #Literali v Or if isinstance(lit2, prop.Not): if lit2.t in unCleanVariables: pass #spremenljivka je umazana elif lit2 in cleanVariables: pass #spremenljivka ostaja cista elif lit2.t in cleanVariables: # spremenljivka se je umazala unCleanVariables.add( lit2.t) #spremenljivka gre v umazano sobo cleanVariables.remove(lit2.t) elif lit2 not in cleanVariables and lit2.t not in cleanVariables: #spremenljivka ima moznost postati cista cleanVariables.add(lit2) else: assert False, "Tu ni vec nic za narediti" elif isinstance(lit2, prop.Literal): if lit2 in unCleanVariables: pass #spremenljivka je umazana, zanjo ni resitve elif lit2 in cleanVariables: pass #spremenljivka je cista, se je upanje elif prop.Not( lit2 ) in cleanVariables: #umazali smo spremenljivko cleanVariables.remove(prop.Not(lit2)) unCleanVariables.add(lit2) elif lit2 not in cleanVariables and prop.Not( lit2 ) not in cleanVariables: #spremenljivka ima moznost postati cista cleanVariables.add(lit2) else: assert False, "Tu ni vec nic za narediti" else: assert False, "You shall not pass this door" elif isinstance(lit, prop.Not): if lit.t.p not in d: #ce spremenljivke se nismo obravnavali d[lit.t.p] = prop.Fls() variables.remove(lit.t.p) #smo jo nastavili elif lit.t.p in d and d[lit.t.p] == prop.Tru(): return prop.Fls( ), None #ce smo jo obravnavali in jo postavili obratno else: pass #enkrat smo ze nastavljali to spremenljivko elif isinstance(lit, prop.Literal): #naredimo skoraj enako kot prej if lit.p not in d: #ce spremenljivke se nismo obravnavali d[lit.p] = prop.Tru() #phi = phi.apply(d) variables.remove(lit.p) #smo jo nastavili elif lit.p in d and d[lit.p] == prop.Fls(): return prop.Fls(), None else: pass #enkrat smo ze nastavljali to spremenljivko else: print lit.__class__.__name__ assert False, "NNemogoce: Je formula res CNF?" #pogledamo, ali imamo kaksne ciste spremenljivke, ki jih se nismo spremenili for clean in cleanVariables: if isinstance(clean, prop.Not): if clean.t.p in variables: #spremenljivke se nismo nastavljali d[clean.t.p] = prop.Fls() variables.remove(clean.t.p) else: pass elif isinstance(clean, prop.Literal): if clean.p in variables: #spremenljivke se nismo nastavljali d[clean.p] = prop.Tru() variables.remove(clean.p) if len(variables) != 0: #Nismo se porabili vseh spremenljivk var = random.sample(variables, 1)[0] #si izberemo eno variables.remove(var) d1 = dict(d) d1[var] = prop.Tru() result, d1 = sat(phi.apply(d1), d1, set(variables)) if result == prop.Tru(): return result, d1 d2 = dict(d) d2[var] = prop.Fls() result, d2 = sat(phi.apply(d2), d2, set(variables)) if result == prop.Tru(): return result, d2 return prop.Fls(), None else: return sat( phi.apply(d), d, variables ) #koncali delo, stavki na zacetku funkcije poskrbijo za uspesno koncanje metode
def sat2(phi, d=None, variables=None): #Izboljsan sta solver z hevristiko. Izberemo spremenljivko, ki se je pojavila v najmanjsem izrazu; # v primeru izenacenja izberemo tisto, ki se je pojavila najveckrat #Ustvarimo si slovar in mnozico vseh spremenljivk, ce jih ze nimamo if not type(d) == dict: d = {} if not type(variables) == set: variables = set() prop.allVariables(phi, variables) cleanVariables = set() unCleanVariables = set() expressionSize = PriorityQueue( ) #struktura bo shranjevala, v kako velikem izrazu se spremenljivka pojavi. nrOfApperances = defaultdict(lambda: 0) if isinstance(phi, prop.Tru): return prop.Tru(), d elif isinstance(phi, prop.Fls): return prop.Fls(), None elif isinstance(phi, prop.Or) and len(phi.l) == 0: return prop.Fls( ), None #Vcasih se zgodi, da dobimo prazen Or namesto prop.Fls elif isinstance(phi, prop.And): if len(phi.l) == 0: return prop.Tru(), d #prazen And pomeni prop.Tru() #print len(phi.l) for lit in phi.l: if isinstance(lit, prop.Fls): return prop.Fls( ), None #ce je vsaj eden od elementov Fls, vrnemo fls elif isinstance(lit, prop.Or): if len(lit.l) == 0: return prop.Fls( ), None #Prazen stavek, zgolj zaradi varnosti, ampak mislim, da vcasih funkcija apply vrne prazen Or for lit2 in lit.l: #Literali v Or if isinstance(lit2, prop.Not): expressionSize.put((len(lit.l), lit2.t.p)) nrOfApperances[lit2.t.p] += 1 if lit2.t in unCleanVariables: pass #spremenljivka je umazana elif lit2 in cleanVariables: pass #spremenljivka ostaja cista elif lit2.t in cleanVariables: # spremenljivka se je umazala unCleanVariables.add( lit2.t) #spremenljivka gre v umazano sobo cleanVariables.remove(lit2.t) elif lit2 not in cleanVariables and lit2.t not in cleanVariables: #spremenljivka ima moznost postati cista cleanVariables.add(lit2) else: assert False, "Tu ni vec nic za narediti" elif isinstance(lit2, prop.Literal): expressionSize.put((len(lit.l), lit2.p)) nrOfApperances[lit2.p] += 1 if lit2 in unCleanVariables: pass #spremenljivka je umazana, zanjo ni resitve elif lit2 in cleanVariables: pass #spremenljivka je cista, se je upanje elif prop.Not( lit2 ) in cleanVariables: #umazali smo spremenljivko cleanVariables.remove(prop.Not(lit2)) unCleanVariables.add(lit2) elif lit2 not in cleanVariables and prop.Not( lit2 ) not in cleanVariables: #spremenljivka ima moznost postati cista cleanVariables.add(lit2) else: assert False, "Tu ni vec nic za narediti" else: assert False, "You shall not pass this door" elif isinstance(lit, prop.Not): if lit.t.p not in d: #ce spremenljivke se nismo obravnavali d[lit.t.p] = prop.Fls() variables.remove(lit.t.p) #smo jo nastavili elif lit.t.p in d and d[lit.t.p] == prop.Tru(): return prop.Fls( ), None #ce smo jo obravnavali in jo postavili obratno else: pass #enkrat smo ze nastavljali to spremenljivko elif isinstance(lit, prop.Literal): #naredimo skoraj enako kot prej if lit.p not in d: #ce spremenljivke se nismo obravnavali d[lit.p] = prop.Tru() #phi = phi.apply(d) variables.remove(lit.p) #smo jo nastavili elif lit.p in d and d[lit.p] == prop.Fls(): return prop.Fls(), None else: pass #enkrat smo ze nastavljali to spremenljivko else: print lit.__class__.__name__ assert False, "Nemogoce: Je formula res CNF?" #pogledamo, ali imamo kaksne ciste spremenljivke, ki jih se nismo spremenili for clean in cleanVariables: if isinstance(clean, prop.Not): if clean.t.p in variables: #spremenljivke se nismo nastavljali d[clean.t.p] = prop.Fls() variables.remove(clean.t.p) else: pass elif isinstance(clean, prop.Literal): if clean.p in variables: #spremenljivke se nismo nastavljali d[clean.p] = prop.Tru() variables.remove(clean.p) if len(variables) != 0: #Nismo se porabili vseh spremenljivk candidates = [] if (expressionSize.empty() == True): assert False, "Morajo biti vsaj nekatere spremenljivke" cand = expressionSize.get() while (cand[1] not in variables ): #Izberemo prvo spremenljivko, ki se ni bila dolocena if (expressionSize.empty() == True): assert False, "Morajo biti vsaj nekatere spremenljivke" cand = expressionSize.get() candidates.append(cand) while (not (expressionSize.empty() == True)): #dodamo vse, ki so izenacene cand = expressionSize.get() if candidates[0][0] != cand[0]: break candidates.append(cand) candidates = sorted([(nrOfApperances[cand[1]], cand[1]) for cand in candidates], reverse=True) i = 0 var = candidates[i][1] while (var not in variables): i += 1 var = candidates[i][1] variables.remove(var) d1 = dict(d) d1[var] = prop.Tru() result, d1 = sat(phi.apply(d1), d1, set(variables)) if result == prop.Tru(): return result, d1 d2 = dict(d) d2[var] = prop.Fls() result, d2 = sat(phi.apply(d2), d2, set(variables)) if result == prop.Tru(): return result, d2 return prop.Fls(), None else: return sat( phi.apply(d), d, variables ) #koncali delo, stavki na zacetku funkcije poskrbijo za uspesno koncanje metode
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)
# # Klicemo rahlo spremenjen zunanji C++ program, ki sta ga objavila B. Konev in A. Lisista. Program # vrne SAT instanco v CNF, ki ustreza Erdosevemu problemu diskrepance za dane parametre. Formulo # pretvorimo v primerno obliko in jo nahranimo nasemu solverju. # import prop import math import re import itertools import sat import os clean = lambda v: prop.Not("v" + v[1:]) if v[0] == '-' else "v" + v 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] ]) if __name__ == '__main__': length = 4 discrepancy = 1 bits = 5 cmd = 'sat14 %d %d %d > out.cnf' % (length, discrepancy, bits) print "Compiling sat14.cc..." os.system('g++ sat14.cc -o sat14')
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) # Vzame seznam literalov; ga nakljucno permutira; razbije na k delov; vrne konjunkcijo. (Hvala prof. Bauerju za kul predlog. :-) 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)]) # Vrne ``tezko'' instanco SAT problema # Ideja: Generiraj DNF na enak nacin pri rnd_cnf; vrni CNF. 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() # Vstopna tocka; nekaj testov; samo za okus if __name__ == "__main__": j=6 literals = [prop.Not("v"+str(i)) for i in range(j)] literals = literals + ["v"+str(i) for i in range(j)] phi = hard_phi(literals, 3) print phi print sat.sat(phi) print sat.sat2(phi)
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;