rule(expression_bits[i + 2], expression_bits[i + 1], expression_bits[i]) for i in range(N) ] bis_txt = open(BIS_FILE, "rb").read(N_B) bis_enc = open(BIS_FILE_ENCRYPTED, "rb").read(N_B) # get first 32 bytes from keystream key_stream = int.from_bytes(bis_txt, 'little') ^ int.from_bytes( bis_enc, 'little') # get expression to calculate next value expression = get_expression(bits) solver = Minisat() # loop 128 times for i in range(128): exp = Cnf() # create expression for j in range(N): bit_value = ((1 << j) & key_stream) >= 1 exp &= (expression[j] if bit_value is True else -expression[j]) # get solution solution = solver.solve(exp) # update key stream if solution.success:
def __init__(self): self.solver = Minisat()
def knight(N=8): white_knight_at = [[ Variable("W_{" + str(i) + str(j) + "}") for i in range(N) ] for j in range(N)] black_knight_at = [[ Variable("B_{" + str(i) + str(j) + "}") for i in range(N) ] for j in range(N)] formula = Cnf() # the overall formula # at least one black and white knight in each row for i in range(N): oneinthisrow_w = Cnf() oneinthisrow_b = Cnf() for j in range(N): oneinthisrow_w |= white_knight_at[i][j] oneinthisrow_b |= black_knight_at[i][j] formula &= (oneinthisrow_w & oneinthisrow_b) # at least one black and white knight in each column for j in range(N): oneinthiscolumn_w = Cnf() oneinthiscolumn_b = Cnf() for i in range(N): oneinthiscolumn_w |= white_knight_at[i][j] oneinthiscolumn_b |= black_knight_at[i][j] & ( -white_knight_at[i][j]) formula &= (oneinthiscolumn_w & oneinthiscolumn_b) # Each row and column has exactly 1 black and white knight for i1 in range(N): for j1 in range(N): for i2 in range(N): for j2 in range(N): if N * i1 + j1 < N * i2 + j2: # Eliminate mirrors if (i1 == i2) | ( j1 == j2 ): # If two possible placements share the same row or column formula &= ((-white_knight_at[i1][j1]) | (-white_knight_at[i2][j2])) & ( (-black_knight_at[i1][j1]) | (-black_knight_at[i2][j2])) # Can't attack same color for i1 in range(N): for j1 in range(N): for i2 in range(N): for j2 in range(N): if N * i1 + j1 < N * i2 + j2: # Eliminate mirrors if ((i1 - i2)**2 + (j1 - j2)**2 == 5) & ( (i1 - i2 <= 2) & (j1 - j2 <= 2)): # "L" shape attack formula &= ((-white_knight_at[i1][j1]) | (-white_knight_at[i2][j2])) & ( (-black_knight_at[i1][j1]) | (-black_knight_at[i2][j2])) # White must attack at least one enemy for i1 in range(N): for j1 in range(N): white_must_attack_one = Cnf() for i2 in range(N): for j2 in range(N): if ((i1 - i2)**2 + (j1 - j2)**2 == 5) & ( (i1 - i2 <= 2) & (j1 - j2 <= 2)): # "L" shape attack white_must_attack_one |= (white_knight_at[i1][j1]) & ( black_knight_at[i2][j2]) formula &= (white_knight_at[i1][j1] >> white_must_attack_one) # Black must attack at least one enemy for i1 in range(N): for j1 in range(N): black_must_attack_one = Cnf() for i2 in range(N): for j2 in range(N): if ((i1 - i2)**2 + (j1 - j2)**2 == 5) & ( (i1 - i2 <= 2) & (j1 - j2 <= 2)): # "L" shape attack black_must_attack_one |= (black_knight_at[i1][j1]) & ( white_knight_at[i2][j2]) formula &= (black_knight_at[i1][j1] >> black_must_attack_one) solution = Minisat().solve(formula) if solution.error is True: print("Error: " + solution.error) elif solution.success: chessboard = "" for i in range(N): for j in range(N): if solution[white_knight_at[i][j]]: chessboard += "1" elif solution[black_knight_at[i][j]]: chessboard += "2" else: chessboard += "0" chessboard += "\n" print(chessboard) else: print("No valid solution")
def solve(num_wizards, num_constraints, wizards, constraints): """ Write your algorithm here. Input: num_wizards: Number of wizards num_constraints: Number of constraints wizards: An array of wizard names, in no particular order constraints: A 2D-array of constraints, where constraints[0] may take the form ['A', 'B', 'C']i Output: An array of wizard names in the ordering your algorithm returns """ maxVal = 0 maxRet = wizards iteration = 0 while True: constraintToVariable = dict() exp = None g1 = Graph(num_wizards) g2 = Graph(num_wizards) for constraint in constraints: wiz1 = constraint[0] wiz2 = constraint[1] wiz3 = constraint[2] clause1 = wiz3 + " " + wiz1 clause2 = wiz3 + " " + wiz2 clause3 = wiz1 + " " + wiz3 clause4 = wiz2 + " " + wiz3 g1.addEdge(wiz3, wiz1) g1.addEdge(wiz3, wiz2) g2.addEdge(wiz1, wiz3) g2.addEdge(wiz2, wiz3) if clause1 in constraintToVariable: v1 = constraintToVariable[clause1] else: constraintToVariable[clause1] = Variable(clause1) v1 = constraintToVariable[clause1] if clause2 in constraintToVariable: v2 = constraintToVariable[clause2] else: constraintToVariable[clause2] = Variable(clause2) v2 = constraintToVariable[clause2] if clause3 in constraintToVariable: v3 = constraintToVariable[clause3] else: constraintToVariable[clause3] = Variable(clause3) v3 = constraintToVariable[clause3] if clause4 in constraintToVariable: v4 = constraintToVariable[clause4] else: constraintToVariable[clause4] = Variable(clause4) v4 = constraintToVariable[clause4] literal = ((v1 & v2 & -v3 & -v4) ^ (v3 & v4 & -v1 & -v2)) if exp is None: exp = literal else: exp = exp & literal solver = Minisat() solution = solver.solve(exp) if solution.success: graph = dict() g = Graph(num_wizards) for wizard in wizards: graph[wizard] = set() for constraint in constraintToVariable: v = constraintToVariable[constraint] if solution[v] == True: # print(v) w = str(v).split() vertexU = w[0] vertexV = w[1] graph[vertexU].add(vertexV) g.addEdge(vertexU, vertexV) cycle = False try: topological(graph) except ValueError: cycle = True if cycle: graph[vertexU].remove(vertexV) graph[vertexV].add(vertexU) cycle = False try: topSortGraph = topological(graph) except ValueError: cycle = True graph = {} if not cycle: ans = list(topSortGraph) comp = checkConstraintsWithList(constraints, ans) if comp > maxVal: maxVal = comp maxRet = ans if iteration > 100: return maxRet # print(comp) iteration += 1 shuffle(wizards) shuffle(constraints)
def solve(num_wizards, num_constraints, wizards, constraints, zakiFirst): """ Write your algorithm here. Input: num_wizards: Number of wizards num_constraints: Number of constraints wizards: An array of wizard names, in no particular order constraints: A 2D-array of constraints, where constraints[0] may take the form ['A', 'B', 'C']i Output: An array of wizard names in the ordering your algorithm returns """ sameDictionary = [] constraintToVariable = dict() exp = None for constraint in constraints: wiz1 = constraint[0] wiz2 = constraint[1] wiz3 = constraint[2] clause1 = wiz3 + " " + wiz1 clause2 = wiz3 + " " + wiz2 clause3 = wiz1 + " " + wiz3 clause4 = wiz2 + " " + wiz3 if clause1 in constraintToVariable: v1 = constraintToVariable[clause1] else: constraintToVariable[clause1] = Variable(clause1) v1 = constraintToVariable[clause1] if clause2 in constraintToVariable: v2 = constraintToVariable[clause2] else: constraintToVariable[clause2] = Variable(clause2) v2 = constraintToVariable[clause2] if clause3 in constraintToVariable: v3 = constraintToVariable[clause3] else: constraintToVariable[clause3] = Variable(clause3) v3 = constraintToVariable[clause3] if clause4 in constraintToVariable: v4 = constraintToVariable[clause4] else: constraintToVariable[clause4] = Variable(clause4) v4 = constraintToVariable[clause4] literal = ((v1 & v2 & -v3 & -v4) ^ (v3 & v4 & -v1 & -v2)) if exp is None: exp = literal else: exp = exp & literal solver = Minisat() solution = solver.solve(exp) if solution.success: graph = dict() for wizard in wizards: graph[wizard] = set() for constraint in constraintToVariable: v = constraintToVariable[constraint] if solution[v] == True: w = str(v).split() vertexU = w[0] vertexV = w[1] graph[vertexU].add(vertexV) cycle = False try: topSortGraph = topological(graph) except ValueError: cycle = True iteration = 0 graph = {} if not cycle: return list(topSortGraph) else: while True: dictCompare = {} g = Graph(num_wizards) for wiz, neighbors in graph.items(): for n in neighbors: g.addEdge(wiz, n) badOnes = [] sccs = g.getSCCs() for scc in sccs: badGroup = set() if len(scc) > 1: for u in scc: for v in scc: if g.containsEdge(u, v): badGroup.add(u + " " + v) g.removeEdge(u, v) badOnes.append(badGroup) print("number of cycles:", len(badOnes)) for count, i in enumerate(badOnes): print("length of cycle", count + 1, ":", len(i)) for group in badOnes: lit = None for b in group: v = constraintToVariable[b] if lit is None: lit = v else: lit = lit & v exp = -(lit) & exp solver = Minisat() solution = solver.solve(exp) if solution.success: graph = dict() for wizard in wizards: graph[wizard] = set() for constraint in constraintToVariable: v = constraintToVariable[constraint] dictCompare[v] = solution[v] if solution[v] == True: w = str(v).split() vertexU = w[0] vertexV = w[1] graph[vertexU].add(vertexV) cycle = False try: topSortGraph = topological(graph) except ValueError: cycle = True else: print("SOMETHING WENT HORRIBLY WRONG") if not cycle: return list(topSortGraph) print("iteration: ", iteration) if iteration == 100: return solveAlt(num_wizards, num_constraints, wizards, constraints, zakiFirst) iteration += 1 if dictCompare in sameDictionary: print("YOU'VE BEEN IN THIS STATE BEFORE") else: print("new state :)") sameDictionary.append(dictCompare)
for j1 in gnodes: for j2 in gnodes: if i1 != i2: exp &= -varz[i][j1] | -varz[i][j2] # Edge print "Adding edge clauses..." for j in xrange(lennodes): print j for i in gnodes: for k in gnodes: if i != k and k not in g.neighbors(i): exp &= -varz[i][j] | -varz[k][(j + 1) % lennodes] # Enabling minisat to write to stdout solver = Minisat('minisat %s %s') print "Solving..." solution = solver.solve(exp) if not solution.success: print "There is no Hamilton cycle in the graph." exit() print "Extracting solution..." path = [] for n in g.nodes(): nodepos = -1 for j in xrange(lennodes): if solution[varz[n][j]]: nodepos = j
def solve(nrow, ncol, pieces): t0 = time.time() npieces = len(pieces) formula = Cnf() # create literals lits = [] for i in range(nrow): row = [] for j in range(ncol): col = [] for k in range(npieces): piece = [] for l in range(4): piece.append( Variable("x_{0}_{1}_{2}_{3}".format(i, j, k, l))) col.append(piece) row.append(col) lits.append(row) t1 = time.time() print("Time spent to create the literals:", t1 - t0) # construct formula # constraints set 1 : exactly one square by case for i in range(nrow): for j in range(ncol): squares = [] for piece in lits[i][j]: for square in piece: squares.append(square) formula &= exactly_one(squares) t2 = time.time() print("Time spent to build the first constraint set", t2 - t1) # constraints set 2 : exactly one case by square for k in range(len(pieces)): for l in range(4): cases = [] for row in lits: for col in row: cases.append(col[k][l]) formula &= exactly_one(cases) t3 = time.time() print("Time spent to build the second constraint set", t3 - t2) # constraints set 3 : pieces shapes for i in range(nrow): for j in range(ncol): for k in range(npieces): if pieces[k] == 1: # bar orientation1 = orientation(lits, i, j + 1, i, j + 2, i, j + 3, k) orientation2 = orientation(lits, i + 1, j, i + 2, j, i + 3, j, k) clause = lits[i][j][k][0] >> (orientation1 | orientation2) elif pieces[k] == 2: # 2*2 square orientation1 = orientation(lits, i, j + 1, i + 1, j, i + 1, j + 1, k) clause = lits[i][j][k][0] >> orientation1 elif pieces[k] == 3: # L orientation1 = orientation(lits, i + 1, j, i + 2, j, i + 2, j + 1, k) orientation2 = orientation(lits, i, j + 1, i, j + 2, i - 1, j + 2, k) orientation3 = orientation(lits, i - 1, j, i - 2, j, i - 2, j - 1, k) orientation4 = orientation(lits, i, j - 1, i, j - 2, i + 1, j - 2, k) clause = lits[i][j][k][0] >> (orientation1 | orientation2 | orientation3 | orientation4) elif pieces[k] == 4: # reversed L orientation1 = orientation(lits, i + 1, j, i + 2, j, i + 2, j - 1, k) orientation2 = orientation(lits, i, j + 1, i, j + 2, i + 1, j + 2, k) orientation3 = orientation(lits, i - 1, j, i - 2, j, i - 2, j + 1, k) orientation4 = orientation(lits, i, j - 1, i, j - 2, i - 1, j - 2, k) clause = lits[i][j][k][0] >> (orientation1 | orientation2 | orientation3 | orientation4) elif pieces[k] == 5: # snake orientation1 = orientation(lits, i, j + 1, i - 1, j + 1, i - 1, j + 2, k) orientation2 = orientation(lits, i + 1, j, i + 1, j + 1, i + 2, j + 1, k) clause = lits[i][j][k][0] >> (orientation1 | orientation2) elif pieces[k] == 6: # reversed snake orientation1 = orientation(lits, i, j + 1, i + 1, j + 1, i + 1, j + 2, k) orientation2 = orientation(lits, i + 1, j, i + 1, j - 1, i + 2, j - 1, k) clause = lits[i][j][k][0] >> (orientation1 | orientation2) elif pieces[k] == 7: # castle orientation1 = orientation(lits, i + 1, j - 1, i + 1, j, i + 1, j + 1, k) orientation2 = orientation(lits, i - 1, j - 1, i, j - 1, i + 1, j - 1, k) orientation3 = orientation(lits, i - 1, j - 1, i - 1, j, i - 1, j + 1, k) orientation4 = orientation(lits, i - 1, j + 1, i, j + 1, i + 1, j + 1, k) clause = lits[i][j][k][0] >> (orientation1 | orientation2 | orientation3 | orientation4) formula &= clause t2 = time.time() print("Time spent to build the third constraint set", t2 - t1) # solve using minisat solver = Minisat() t3 = time.time() print("Time spent to solve the SAT problem", t3 - t2) print("Total time", t3 - t0) return solver.solve(formula), lits
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.')