def solve(self, cnf): s = Solution() infile = NamedTemporaryFile(mode='w') outfile = NamedTemporaryFile(mode='r') io = DimacsCnf() infile.write(io.tostring(cnf)) infile.flush() ret = call(self.command % (infile.name, outfile.name), shell=True) infile.close() if ret != 10: return s s.success = True lines = outfile.readlines()[1:] for line in lines: varz = line.split(" ")[:-1] for v in varz: v = v.strip() value = v[0] != '-' v = v.lstrip('-') vo = io.varobj(v) s.varmap[vo] = value # Close deletes the tmp files outfile.close() return s
def solve(self, cnf): s = Solution() # NamedTemporaryFile doesn't work on Windows, see https://stackoverflow.com/questions/15169101/how-to-create-a-temporary-file-that-can-be-read-by-a-subprocess infile, infilename = tempfile.mkstemp(suffix="cnf") try: io = DimacsCnf() os.write(infile, io.tostring(cnf)) os.close(infile) try: cmd = self.command % (infilename.replace("\\", "/")) check_output(cmd, stderr=STDOUT, shell=True) # Lingeling and most SAT-solvers use a non-zero return code, which in most POSIX command indicates an error. # That's why python raises an exception, but here it's expected except CalledProcessError as call: if call.returncode != 10 and call.returncode != 20: s.error = call.output return s finally: os.remove(infilename) if call.returncode != 10: return s s.success = True for line in call.output.split("\n"): # Solution line example: v 1 -2 3 -4 5 6 0 if len(line) > 0 and line[0] == 'v': varz = line.split(" ")[1:-1] for v in varz: v = v.strip() value = v[0] != '-' v = v.lstrip('-') vo = io.varobj(v) s.varmap[vo] = value return s
def solve(self, cnf): s = Solution() # NamedTemporaryFile doesn't work on Windows, see https://stackoverflow.com/questions/15169101/how-to-create-a-temporary-file-that-can-be-read-by-a-subprocess infile, infilename = tempfile.mkstemp(suffix="cnf") try: io = DimacsCnf() os.write(infile, io.tostring(cnf)) os.close(infile) try: cmd = self.command % (infilename.replace("\\","/")) check_output(cmd, stderr=STDOUT, shell=True) # Lingeling and most SAT-solvers use a non-zero return code, which in most POSIX command indicates an error. # That's why python raises an exception, but here it's expected except CalledProcessError as call: if call.returncode != 10 and call.returncode != 20: s.error = call.output return s finally: os.remove(infilename) if call.returncode != 10: return s s.success = True for line in call.output.split("\n"): # Solution line example: v 1 -2 3 -4 5 6 0 if len(line) > 0 and line[0] == 'v': varz = line.split(" ")[1:-1] for v in varz: v = v.strip() value = v[0] != '-' v = v.lstrip('-') vo = io.varobj(v) s.varmap[vo] = value return s
def solve(self, cnf): s = Solution() with NamedTemporaryFile(mode='w') as infile, \ NamedTemporaryFile(mode='r') as outfile: io = DimacsCnf() infile.write(io.tostring(cnf)) infile.flush() try: output = check_output( [self.command, infile.name, outfile.name], universal_newlines=True, timeout=self.timeout) except CalledProcessError as ex: s.success = (ex.returncode == 10) output = ex.output s.stats = parse_stats(output) if not s.success: return s lines = outfile.readlines()[1:] for line in lines: varz = line.split(" ")[:-1] for v in varz: v = v.strip() value = v[0] != '-' v = v.lstrip('-') vo = io.varobj(v) s.varmap[vo] = value return s
def propositional_nqueens(n): rules = 0 t1 = time() exprs = Cnf() queens_by_point = {} queens_by_name = {} points_by_name = {} by_rows = [[] for x in xrange(n)] by_cols = [[] for x in xrange(n)] for point in points(n): name = 'queen_%d_%d' % point by_rows[point[1]].append(name) by_cols[point[0]].append(name) queen = Variable(name) queens_by_point[point] = queen queens_by_name[name] = queen points_by_name[name] = point for row_of_names in by_rows: orexp = Cnf() for name in row_of_names: orexp = orexp | queens_by_name[name] rules += 1 exprs &= orexp for col_of_names in by_cols: orexp = Cnf() for name in col_of_names: orexp |= queens_by_name[name] rules += 1 exprs &= orexp for row in xrange(n): for col in xrange(n): antecedent_name = by_rows[row][col] consequent_names = [by_rows[row][a] for a in xrange(n) if a != col] # queen_X_Y => (not(queen_X1_Y1) & not(queen_X2_Y2)) # translates to # (not(queen_X_Y) or not(queen_X1_Y1)) and (not(queen_X_Y) or not(queen_X2_Y2)) #andexpr = Cnf() #for name in consequent_names: #andexpr &= (-queens_by_name[name]) #exprs &= (queens_by_name[antecedent_name] >> andexpr) for name in consequent_names: rules += 1 exprs &= -queens_by_name[antecedent_name] | -queens_by_name[name] for col in xrange(n): for row in xrange(n): antecedent_name = by_cols[col][row] consequent_names = [by_cols[col][a] for a in xrange(n) if a != row] # queen_X_Y => (not(queen_X1_Y1) & not(queen_X2_Y2)) # translates to # (not(queen_X_Y) or not(queen_X1_Y1)) and (not(queen_X_Y) or not(queen_X2_Y2)) #andexpr = Cnf() #for name in consequent_names: #andexpr &= (-queens_by_name[name]) #exprs &= (queens_by_name[antecedent_name] >> andexpr) for name in consequent_names: rules += 1 exprs &= -queens_by_name[antecedent_name] | -queens_by_name[name] for point1 in points(n): for point2 in points(n): if point1 == point2: continue if are_diagonal(point1, point2): rules += 1 #exprs &= (queens_by_point[point1] >> (-queens_by_point[point2])) exprs &= -queens_by_point[point1] | -queens_by_point[point2] for point in points(n): for slope in points(n, 1, 1): if slope == (1,1): continue lines = [ ] line = points_along_line(point, slope[0], slope[1], n) if len(line) >= 2: lines.append(line) line = points_along_line(point, -slope[0], slope[1], n) if len(line) >= 2: lines.append(line) if len(lines) == 0: continue for points1 in lines: for point1 in points1: #andexpr = Cnf() for point2 in points1: if point2 != point1: #andexpr &= (-queens_by_point[point2]) rules += 1 exprs &= -queens_by_point[point] | -queens_by_point[point1] | -queens_by_point[point2] #exprs &= ((queens_by_point[point] & queens_by_point[point1]) >> andexpr) t2 = time() print('# defined %d rules in %f seconds' % (rules, t2 - t1)) t1 = time() with open('/media/rust/%d.cnf' % n, 'w') as f: io = DimacsCnf() f.write(io.tostring(exprs)) t2 = time() print('# wrote rules in %f seconds' % (t2 - t1)) t1 = time() #return s = Minisat() #s = Lingeling(command='/home/bburns/projects/nqueens-solver/lingeling-bal-2293bef-151109/lingeling --witness=1 --verbose=1 %s') solution = s.solve(exprs) t2 = time() print('# solved in %f seconds' % (t2 - t1)) if solution.error: raise Exception(solution.error) if solution.success: results = [] #for a in solution.varmap: #if solution.varmap[a]: #results.append(points_by_name[a.name]) for point in queens_by_point: if solution[queens_by_point[point]]: results.append(point) results.sort() return results else: raise Exception('Unsat.')
def propositional_nqueens(n): rules = 0 t1 = time() exprs = Cnf() queens_by_point = {} queens_by_name = {} points_by_name = {} by_rows = [[] for x in xrange(n)] by_cols = [[] for x in xrange(n)] for point in points(n): name = 'queen_%d_%d' % point by_rows[point[1]].append(name) by_cols[point[0]].append(name) queen = Variable(name) queens_by_point[point] = queen queens_by_name[name] = queen points_by_name[name] = point for row_of_names in by_rows: orexp = Cnf() for name in row_of_names: orexp = orexp | queens_by_name[name] rules += 1 exprs &= orexp for col_of_names in by_cols: orexp = Cnf() for name in col_of_names: orexp |= queens_by_name[name] rules += 1 exprs &= orexp for row in xrange(n): for col in xrange(n): antecedent_name = by_rows[row][col] consequent_names = [by_rows[row][a] for a in xrange(n) if a != col] # queen_X_Y => (not(queen_X1_Y1) & not(queen_X2_Y2)) # translates to # (not(queen_X_Y) or not(queen_X1_Y1)) and (not(queen_X_Y) or not(queen_X2_Y2)) #andexpr = Cnf() #for name in consequent_names: #andexpr &= (-queens_by_name[name]) #exprs &= (queens_by_name[antecedent_name] >> andexpr) for name in consequent_names: rules += 1 exprs &= -queens_by_name[antecedent_name] | -queens_by_name[ name] for col in xrange(n): for row in xrange(n): antecedent_name = by_cols[col][row] consequent_names = [by_cols[col][a] for a in xrange(n) if a != row] # queen_X_Y => (not(queen_X1_Y1) & not(queen_X2_Y2)) # translates to # (not(queen_X_Y) or not(queen_X1_Y1)) and (not(queen_X_Y) or not(queen_X2_Y2)) #andexpr = Cnf() #for name in consequent_names: #andexpr &= (-queens_by_name[name]) #exprs &= (queens_by_name[antecedent_name] >> andexpr) for name in consequent_names: rules += 1 exprs &= -queens_by_name[antecedent_name] | -queens_by_name[ name] for point1 in points(n): for point2 in points(n): if point1 == point2: continue if are_diagonal(point1, point2): rules += 1 #exprs &= (queens_by_point[point1] >> (-queens_by_point[point2])) exprs &= -queens_by_point[point1] | -queens_by_point[point2] for point in points(n): for slope in points(n, 1, 1): if slope == (1, 1): continue lines = [] line = points_along_line(point, slope[0], slope[1], n) if len(line) >= 2: lines.append(line) line = points_along_line(point, -slope[0], slope[1], n) if len(line) >= 2: lines.append(line) if len(lines) == 0: continue for points1 in lines: for point1 in points1: #andexpr = Cnf() for point2 in points1: if point2 != point1: #andexpr &= (-queens_by_point[point2]) rules += 1 exprs &= -queens_by_point[point] | -queens_by_point[ point1] | -queens_by_point[point2] #exprs &= ((queens_by_point[point] & queens_by_point[point1]) >> andexpr) t2 = time() print('# defined %d rules in %f seconds' % (rules, t2 - t1)) t1 = time() with open('/media/rust/%d.cnf' % n, 'w') as f: io = DimacsCnf() f.write(io.tostring(exprs)) t2 = time() print('# wrote rules in %f seconds' % (t2 - t1)) t1 = time() #return s = Minisat() #s = Lingeling(command='/home/bburns/projects/nqueens-solver/lingeling-bal-2293bef-151109/lingeling --witness=1 --verbose=1 %s') solution = s.solve(exprs) t2 = time() print('# solved in %f seconds' % (t2 - t1)) if solution.error: raise Exception(solution.error) if solution.success: results = [] #for a in solution.varmap: #if solution.varmap[a]: #results.append(points_by_name[a.name]) for point in queens_by_point: if solution[queens_by_point[point]]: results.append(point) results.sort() return results else: raise Exception('Unsat.')
for i in range(args.clause): c = Cnf() k = sample(v, args.literal) for j in k: if random() >= 0.5: c |= j else: c |= -j exp &= c solver = Minisat() solution = solver.solve(exp) dimacsCnf = DimacsCnf() print(dimacsCnf.tostring(exp)) if solution.error != False: print("Error:") print(solution.error) elif solution.success: print("Success:") for i in range(args.variable): print(v[i], solution[v[i]]) fo = open('%s.in' % (args.file_name), "w") fo.write(dimacsCnf.tostring(exp)) fo.close() fo = open('answer.dat', "w") for i in range(args.variable):