if unsat(a) or sat(f): return f,a minj = f.index(min(f,key=len)) # clause with fewest literals if len(f[minj])==0: a[0] = UNSAT return f,a if len(f[minj])==1: fixliteral(f[minj][0], f, a) return backsat(f,a) #split: 2 possible bool. vals for literal f[minj][0] #print "split A:", f[minj][0] fcopy, acopy = mycopy(f,a) fixliteral(f[minj][0], f, a) # f[minj][0] True f,a = backsat(f,a) if sat(f): return f, a f,a = fcopy, acopy #print "split B:", -f[minj][0] fixliteral(-f[minj][0], f, a) # f[minj][0] False return backsat(f, a) #myf=[[-5,-6],[-3,5],[-2,5],[1,-6],[1,-4],[1,-3],[2,3],[2,6],[3,-5],[3,4],[4,-5],[5,-6]] #myf=[[-4,-5,6],[-4,5,-6],[-2,4,-5],[-2,5,-6],[-1,-3,-4],[-1,-3,4],[-1,4,-6],[1,-4,5],[1,-3,-5],[1,-3,4],[1,5,-6],[2,5,6],[3,-5,-6],[4,-5,6],[4,5,-6],[4,5,6]] n,m = 20,90 #max m is n choose k times 2^k, where k=2or3 myf = formula(n,3,m) print "\nrandom formula",n,"vars",m,"clauses" showf(myf) print '' asn = [UNKNOWN]*n f,a = backsat(myf,asn) showfa(f,a)
else: print('formula unsatisfiable') return f, a # else: # f is not the empty list, a is not the empty string ndx = ind_short(f) lenj = len(f[ndx]) if lenj == 1: # fix literal f, a = fix_literal(f[ndx][0], f, a) elif lenj >= 2: #try both possible values fcopy, acopy = deepcopy(f), a f, a = fix_literal(f[ndx][0], f, a) # try now newf, newa = fix_literal(-fcopy[ndx][0], fcopy, acopy) candidates.append((newf, newa)) # try later def backsolve(n, myf): asn = UNKNOWN * n backsat(myf, asn) n, k, m = 22, 3, 100 f = formula(n, k, m) #f = [[1, 2, 3], [1, 2, -3], [1, 2, -4], [1, -2, 3], [1, -2, -4], [1, 3, 4], [1, 3, -4], [-1, 2, -3], [-1, 2, -4], [-1, -2, -3], [-1, -2, 4], [-1, -2, -4], [-1, 3, 4], [2, -3, -4], [-2, 3, 4], [-2, -3, -4]] f2 = deepcopy(f) print('formula with', n, 'vars', m, 'clauses') print('') backsolve(n, f) print('\nverify with bfsolve') bfsolve(n, f2, True)
fcopy, acopy = mycopy(f,a) fixliteral(f[minj][0], f, a) # f[minj][0] True f,a = backsat(f,a) if sat(f): return f, a f,a = fcopy, acopy #print "split B:", -f[minj][0] fixliteral(-f[minj][0], f, a) # f[minj][0] False return backsat(f, a) def backsolve(n,myf): asn = [UNKNOWN]*n f,a = backsat(myf,asn) showfa(f,a) #n,myf=6,[[-5,-6],[-3,5],[-2,5],[1,-6],[1,-4],[1,-3],[2,3],[2,6],[3,-5],[3,4],[4,-5],[5,-6]] #n,myf=6,[[-4,-5,6],[-4,5,-6],[-2,4,-5],[-2,5,-6],[-1,-3,-4],[-1,-3,4],[-1,4,-6],[1,-4,5],[1,-3,-5],[1,-3,4],[1,5,-6],[2,5,6],[3,-5,-6],[4,-5,6],[4,5,-6],[4,5,6]] #max m: (n choose k)(2^k) #n, k, m = 20, 5, 400 # good example n, k, m = 30, 5, 600 # backtrack yes, bf too slow myf = formula(n,k,m) n,myf = 5, [[1,-5],[-2,-3],[3,4],[-4,-5],[2,5],[-1,-5]] n,myf = 5, [[1,-2],[1,3],[-2,-3],[2,4],[-3,-4],[3,-5],[3,5]] myf2 = deepcopy(myf) #print "\nrandom formula",n,"vars",m,"clauses" #showf(myf) #print '' backsolve(n,myf) bfsolve(n,myf2,TRUE)