def main(): print("\n\n\nEnter the maze number that you want to solve.") mazeNumber = int(input("[1]. maze1.txt \t 2. maze2.txt \t 3. maze3.txt\n")) print("\n\nEnter algorithm number you would like to use.") algoPref = int( input( "[1]. Djikstra's \n 2. Breadth First Searh \n 3. Depth First Search \n 4. Backtracking\n" )) print("\n\nDo you want to get the output in color?") color = input("[Y]es\t\tNo\n") maze, start, end = mazes(mazeNumber) if algoPref == 4: path = backtracking(maze, start) elif algoPref == 3: path = dfs(maze, start) elif algoPref == 2: path = bfs(maze, start) else: path = djikstras(maze, start) # Printing the maze with the solution for the respective path finding algorithm currNode = end while currNode != (0, 1): nextNode = path[currNode] connectTwoCells(maze, currNode, nextNode) currNode = nextNode if color == "Y" or color == "y" or color.capitalize() == "Yes": printMazeInColor(maze) else: printMaze(maze)
def main(): """ Shows how backtracking is applied Renders the unsolved and solution of the given sudoku puzzle """ # Create a blank Sudoku board board = create_empty_board() # Sample Board config board[0] = [0, 0, 0, 2, 6, 0, 7, 0, 1] board[1] = [6, 8, 0, 0, 7, 0, 0, 9, 0] board[2] = [1, 9, 0, 0, 0, 4, 5, 0, 0] board[3] = [8, 2, 0, 1, 0, 0, 0, 4, 0] board[4] = [0, 0, 4, 6, 0, 2, 9, 0, 0] board[5] = [0, 5, 0, 0, 0, 3, 0, 2, 8] board[6] = [0, 0, 9, 3, 0, 0, 0, 7, 4] board[7] = [0, 4, 0, 0, 5, 0, 0, 3, 6] board[8] = [7, 0, 3, 0, 1, 8, 0, 0, 0] solved_board, steps = backtracking(deepcopy(board)) # Show unsolved puzzle cv2.imshow("Unsolved", draw_puzzle(board)) cv2.waitKey(0) if steps: # Show solved puzzle cv2.imshow(f"Solved in {steps} steps", draw_puzzle(solved_board)) cv2.waitKey(0) else: print("Invalid puzzle") # Close all windows cv2.destroyAllWindows()
def solve(self, d_i_list): for d_i in d_i_list: print 'DoF', d_i, self.hv_counts[d_i], self.dof[d_i] dim = self.dim candidates = self.candidates cand_counts = [None, None] prev_cand_counts = [None, None] size = len([x for x in self.dof if x <= 500]) while True: print 'Size =', size for d_i in d_i_list[:size]: self.d_i = d_i this_dim = dim[d_i[0]] that_dim = dim[1 - d_i[0]] this_idx = d_i[1] self.candidates[d_i] = [] for candidate in backtracking(range(this_dim), Choices, self.box_assignable): if candidate not in self.candidates[d_i]: self.candidates[d_i].append(candidate) print 'D%d %2d %d/%d' % (d_i[0], d_i[1], len(self.candidates[d_i]), self.dof[d_i]) for d in (0, 1): cand_counts[d] = [len(self.candidates[(d, idx)]) for idx in xrange(dim[1-d]) if (d, idx) in self.candidates] print cand_counts[0] print cand_counts[1] if cand_counts[0] == prev_cand_counts[0] and cand_counts[1] == prev_cand_counts[1]: print 'Candidate counts remain the same. Increasing size by', 4 size += 4 for d in (0, 1): prev_cand_counts[d] = cand_counts[d] if len(cand_counts[0]) == dim[0] and len(set(cand_counts[0])) == 1 and cand_counts[0][0] == 1: print '** Found unique solution' break for y in xrange(dim[1]): print ''.join([candidates[(0, y)][0][x] for x in xrange(dim[0])])
def test_findUnassignedLocation(self): tempPuzzle = np.array([[7, 5, 6, 1, 3, 2, 8, 9, 4],[8, 9, 2, 6, 7, 4, 5, 3, 1],[4, 3, 1, 8, 5, 9, 6, 2, 7],[5, 4, 3, 9, 6, 8, 1, 7, 2],[2, 8, 9, 3, 0, 7, 4, 5, 6],[1, 6, 7, 4, 2, 5, 3, 8, 9],[3, 7, 4, 5, 9, 6, 2, 1, 8],[9, 1, 8, 2, 4, 3, 7, 6, 5],[6, 2, 5, 7, 8, 1, 9, 4, 3]]) position = [0,0] b = backtracking.backtracking(tempPuzzle) b.findUnassignedLocation(tempPuzzle, position) self.assertEqual(position, [4,4], "Puzzle finds position wrong")
def test_not_fun_puzzles(not_fun_puzzles): # Unpack puzzles, solutions = not_fun_puzzles for puzzle, solution in zip(puzzles, solutions): solved, step = backtracking(puzzle) assert (solved == solution).all() assert step != 0
def test_difficult_puzzles(difficult_puzzles): # Unpack puzzles, solutions = difficult_puzzles for puzzle, solution in zip(puzzles, solutions): solved, step = backtracking(puzzle) assert (solved == solution).all() assert step != 0
def test_intermediate_puzzles(intermediate_puzzles): # Unpack puzzles, solutions = intermediate_puzzles for puzzle, solution in zip(puzzles, solutions): solved, step = backtracking(puzzle) assert (solved == solution).all() assert step != 0
def run(): path = input( "Which method do you want to use? \nBrute force (1), Dynamic (2), Best First Branch Bound (3), or Backtracking (4)?\nOr press q to quit : " ) if path == '1': time1 = datetime.datetime.now() print(bruteforce.bruteforce(W, items[2], items[1], len(items[0]))) time2 = datetime.datetime.now() tdelta = time2 - time1 print("Brute force: Time taken: %s ms" % int(tdelta.total_seconds() * 1000)) print("\n") run() elif path == '2': time1 = datetime.datetime.now() print(dynamic.dynamic(W, items[2], items[1], len(items[0]))) time2 = datetime.datetime.now() tdelta = time2 - time1 print("Dynamic: Time taken: %s ms" % int(tdelta.total_seconds() * 1000)) print("\n") run() elif path == '3': time1 = datetime.datetime.now() print( firstBranchBound.firstBranchBound(W, items[2], items[1], len(items[0]))) time2 = datetime.datetime.now() tdelta = time2 - time1 print("Best First Branch Bound: Time taken: %s ms" % int(tdelta.total_seconds() * 1000)) print("\n") run() elif path == '4': time1 = datetime.datetime.now() print(backtracking.backtracking(W, items[2], items[1], len(items[0]))) time2 = datetime.datetime.now() tdelta = time2 - time1 print("Backtracking: Time taken: %s ms" % int(tdelta.total_seconds() * 1000)) print("\n") run() elif path == 'q': sys.exit("See ya!") else: print("Error: no valid option chosen. Please try again.") print("\n") run()
def GradientDescent(f, d_f, x0, epson=0.0001): from backtracking import backtracking x = [x0] while True: # determine d_x d_x = -d_f(x[-1]) if d_x**2 <= epson: break t = backtracking(f, d_f, x[-1], d_x) x.append(x[-1] + t * d_x) # print "%3.3f,%.3f,%.3f" % (d_x,t,x[-1]) # print "Final x: ",x[-1] return x
def NewtonMethod(f, d_f, dd_f, x0, epson=0.0001): from backtracking import backtracking x = [x0] while True: df = d_f(x[-1]) ddf = dd_f(x[-1]) if (df**2 / ddf) / 2 <= epson: break d_x = -df / ddf t = backtracking(f, d_f, x[-1], d_x) x.append(x[-1] + t * d_x) # print "%3.3f,%.3f,%.3f" % (d_x,t,x[-1]) # print "Final x: %.3f" % (x[-1]) return x
def gradientdescent(f, df, x0, e, alpha, beta): x_vals = [] x = x0 k = 0 #number of iteration while 1: #print k, x, f(x) # store each x, f(x) into separate list x_vals.append(x) dx = -df(x) t = backtracking(f, df, x, dx, alpha, beta) x = x + t * dx if (abs(df(x)) <= e): return x_vals, k k = k + 1
def run(): path = input("Which method do you want to use? \nBrute force (1), Dynamic (2), Best First Branch Bound (3), or Backtracking (4)?\nOr press q to quit : ") if path == '1': time1 = datetime.datetime.now() print( bruteforce.bruteforce(W, items[2], items[1], len(items[0])) ) time2 = datetime.datetime.now() tdelta = time2 - time1 print("Brute force: Time taken: %s ms" % int(tdelta.total_seconds()*1000) ) print("\n") run() elif path == '2': time1 = datetime.datetime.now() print( dynamic.dynamic(W, items[2], items[1], len(items[0])) ) time2 = datetime.datetime.now() tdelta = time2 - time1 print("Dynamic: Time taken: %s ms" % int(tdelta.total_seconds()*1000) ) print("\n") run() elif path == '3': time1 = datetime.datetime.now() print( firstBranchBound.firstBranchBound(W, items[2], items[1], len(items[0])) ) time2 = datetime.datetime.now() tdelta = time2 - time1 print("Best First Branch Bound: Time taken: %s ms" % int(tdelta.total_seconds()*1000) ) print("\n") run() elif path == '4': time1 = datetime.datetime.now() print( backtracking.backtracking(W, items[2], items[1], len(items[0])) ) time2 = datetime.datetime.now() tdelta = time2 - time1 print("Backtracking: Time taken: %s ms" % int(tdelta.total_seconds()*1000) ) print("\n") run() elif path == 'q': sys.exit("See ya!") else: print("Error: no valid option chosen. Please try again.") print("\n") run()
def test_usedInBox(self): b = backtracking.backtracking(puzzle) self.assertTrue(b.usedInBox(puzzle, 3, 3, 7), "not finding box duplicates")
def test_invalid_puzzles(invalid_puzzles): for puzzle in invalid_puzzles: solved, step = backtracking(puzzle) assert (solved == puzzle).all() assert step == 0
def test_usedInRow(self): b = backtracking.backtracking(puzzle) self.assertTrue(b.usedInRow(puzzle, 6, 3), "not finding row duplicates")
def test_usedInCol(self): b = backtracking.backtracking(puzzle) self.assertTrue(b.usedInCol(puzzle, 2, 1), "not finding column duplicates")
def main(img_path): sudoku_solver('0000.png') board = digit_recognizer() backtracking(board)
from classes import Board from backtracking import backtracking #https://dlbeer.co.nz/articles/sudoku.html def board_loader(board): with open(board) as f: board = csv.reader(f) board = [i for i in board] return board if __name__ == "__main__": board = sys.argv[1] board = board_loader(board) board = Board(board) sol = backtracking(board, 0) if sol: total = sol[0] moves = sol[1:] for i in moves: board.board[i[0]][i[1]] = i[2] print("success") else: print("fail")
def minimize_f(x0, f, grad_f, bounds = None, method = 'projected_gradient'): """Solution of convex optimization problem, possibly with constraints. Inputs: x0: Starting point f: Objective function grad_f: Gradient of f bounds: Upper and lower bounds of the optimization problem. If specified, it must be of the form [(lower_b, upper_b)] and its length must be the same as the dimension of the problem method: Method used for solving the optimization problem Outputs: x: Solution of the optimization problem f_x: Value of the function at x grad_x: Gradient at x it: Number of iterations needed """ x = x0.copy() fun_obj = lambda x: (f(x), grad_f(x)) f_x, grad_x = fun_obj(x) c1 = 1e-1 ls_interp = 1 ls_multi = 1 convergence = False precision = 1e-5 it = 0 it_max = 5000 if bounds == None: l_bounds = -np.inf * np.ones(x.shape) u_bounds = np.inf * np.ones(x.shape) else: l_bounds = np.array([l for (l,u) in bounds]) u_bounds = np.array([u for (l,u) in bounds]) while not convergence: it += 1 d = -grad_x.copy() gtd = np.inner(d, grad_x) t = 1 t, x_new, f_new, g_new, _ = backtracking(x, t, d, f_x, grad_x, f_x, \ gtd, c1, ls_interp = ls_interp, ls_multi = ls_multi, \ fun_obj = fun_obj) x = x_new.copy() x = np.maximum(x, l_bounds) x = np.minimum(x, u_bounds) if (x != x_new).any(): f_new = f(x) g_new = grad_f(x) convergence = np.inner(f_new - f_x, f_new - f_x) < precision ** 2 \ and it < it_max f_x = f_new.copy() grad_x = g_new.copy() return (x, f_x, grad_x, it)
for i in range(0, len(inputArray)): for j in range(0, len(inputArray[i])): if (type(inputArray[i][j]) == int): if (inputArray[i][j] > n): raise error_incorrect_input else: if (inputArray[i][j] != '_'): raise error_incorrect_input checkInput(inputArray, nmkArray) print("Which would you like to implement: ") print("\t1. Backtracking + MRV heuristic") print("\t2. Backtracking + MRV + Forward Checking") print("\t3. Backtracking + MRV + Constraint Propagation") num = input("") temp = "None" if (num == "2"): temp = "FC" elif (num == "3"): temp = "CP" backtracking.backtracking(inputArray, nmkArray, temp) except error_incorrect_input: print("\nIncorrect input, please try again!\n") except FileNotFoundError: print("\nThis file does not exist, please try again!\n") # testInput2.txt # testInput.txt
def main(): """ Loops through all unsolved sudoku puzzle images, and perform all operations from grid extraction, cell extraction, digit classification to backtracking to find the solution of the puzzle Once a solution is found, renders the answers on the unsolved sudoku image """ # Load trained model model = tf.keras.models.load_model('digits_classifier/models/model.h5') image_directory = "images/unsolved" for file_name in os.listdir(image_directory): # Load image image = cv2.imread(filename=os.path.join(image_directory, file_name), flags=cv2.IMREAD_COLOR) # Check if image is too big # If so, Standardise image size to avoid error in cell image manipulation # Cells must fit in 28x28 for the model, big images will exceed this threshold with aspect ratio resize if image.shape[1] > 700: image = imutils.resize(image, width=700) # Extract grid grid_coordinates = get_grid_dimensions(image) # Check if grid is found if grid_coordinates is not None: # Crop grid with transformation grid = transform_grid(image, grid_coordinates) # Image preprocessing, reduce noise such as numbers/dots, cover all numbers thresh = reduce_noise(grid) # Contour detection again, this time we are extracting the grid cnts, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) # Filter out non square contours cnts = filter_non_square_contours(cnts) # Convert contours into data to work with # Do a check if grid is fully extracted, no missing, no duplicates etc if len(cnts) == 81: # Sort grid into nested list format same as sudoku grid_contours = sort_grid_contours(cnts) # Create a blank Sudoku board board = create_empty_board() # Run digit classifier for row_index, row in enumerate(grid_contours): for box_index, box in enumerate(row): # Extract cell ROI from contour x, y, width, height = cv2.boundingRect(box) roi = grid[y:y + height, x:x + width] # Convert to greyscale roi = cv2.cvtColor(roi, cv2.COLOR_BGR2GRAY) # Image thresholding & invert image digit_inv = cv2.adaptiveThreshold( roi, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 27, 11) # Remove surrounding noise digit = sudoku_cells_reduce_noise(digit_inv) # Digit present if digit is not None: # Reshape to fit model input digit = digit.reshape((1, 28, 28, 1)) # Make prediction board[row_index][box_index] = np.argmax( model.predict(digit), axis=-1)[0] + 1 # Perform backtracking to solve detected puzzle solved_board, steps = backtracking(copy.deepcopy(board)) # Check if puzzle is valid if steps: # Solved # Draw answers on the sudoku image for row_index, row in enumerate(board): for box_index, box in enumerate(row): # Filter for BLANK_STATES if box == BLANK_STATE: x, y, width, height = cv2.boundingRect( grid_contours[row_index][box_index]) # Calculate font size for num in np.arange(1.0, 10.0, 0.1): text_size = cv2.getTextSize( str(solved_board[row_index] [box_index]), fontFace=cv2.FONT_HERSHEY_DUPLEX, fontScale=num, thickness=2) font_size = num if text_size[0][ 0] > width // 2 or text_size[0][ 1] > height // 2: break # Fill in answers in sudoku image cv2.putText( image, str(solved_board[row_index][box_index]), (x + grid_coordinates[0][0] + (width * 1 // 4), y + grid_coordinates[0][1] + (height * 3 // 4)), cv2.FONT_HERSHEY_SIMPLEX, font_size, (0, 255, 0), 2) # Fill in information at bottom left cv2.putText(image, f"Solved in {steps} steps", (0, image.shape[0]), cv2.FONT_HERSHEY_SIMPLEX, font_size, (0, 255, 0), 2) # Save answers in solved directory cv2.imwrite( f"images/solved/{os.path.splitext(file_name)[0]}.png", image) print(f"File: {file_name}, Solved in {steps} steps") else: # Cannot be solved (Wrong/invalid puzzle) # Reasons can be invalid puzzle or grid/digits detected wrongly print( f"File: {file_name}, Invalid puzzle or digit detection error" ) else: # Unable to tally 81 boxes print(f"File: {file_name}: Unable to detect 81 cells in grid") else: # Fail to detect grid print(f"File: {file_name}, Unable to detect grid")