1

First of -yes this IS a homework- but it's primarily a theoretical question rather than a practical one, I am simply asking a confirmation if I am thinking correctly or any hints if I am not.

I have been asked to compile a simple Sudoku solver (on Prolog but that is not so important right now) with the only limitation being that it must utilize a heuristic function using Best-First Algorithm. The only heuristic function I have been able to come up with is explained below:

1. Select an empty cell. 
  1a. If there are no empty cells and there is a solution return solution.
      Else return No.
2. Find all possible values it can hold. %% It can't take values currently assigned to cells on the same line/column/box.
3. Set to all those values a heuristic number starting from 1.
4. Pick the value whose heuristic number is the lowest && you haven't checked yet.
   4a. If there are no more values return no.
5. If a solution is not found: GoTo 1.
   Else Return Solution.

// I am sorry for errors in this "pseudo code." If you want any clarification let me know.

So am I doing this right or is there any other way around and mine is false? Thanks in advance.

Theocharis K.
  • 1,281
  • 1
  • 16
  • 43
  • What happens if the algorithm chooses the wrong value in step 4? What happens if the puzzle is not yet completed, but empty cells remain with no options left in step 2? – wildplasser Apr 13 '12 at 00:24
  • @wildplasser This is simply a pseudocode of the heuristic function, the function that will just put the values on the different "paths" the program can choose from. The errors etc will be taken care of in the main program if that's what you mean. That algorithm won't solve the sudoku, it will simply tell me what step to do next. – Theocharis K. Apr 13 '12 at 00:28
  • In addition to other answers here are some tactics you can use to avoid guessing as much as possible: http://stackoverflow.com/a/7696696/395718 – Dialecticus Apr 13 '12 at 16:28

3 Answers3

1

The heuristic I would use is this:

  1. Repeatedly find any empty spaces where there is only one possible number you can insert. Fill them with the number 1-9 that fits.
  2. If every empty space has two or more possibilities, push the game state onto a stack, then pick a random square to fill in with a random value.
  3. Go to step 1.

If you manage to fill every square, you've found a valid solution.

If you get to a point where there are no valid options, pop the last game state off the stack (i.e. backtrack to the last time you made a random choice.) Make a different choice and try again.


As an interesting sidenote, you've been told to do this using a greedy heuristic approach, but Sudoku can actually be reduced to a boolean satisfiability problem (SAT problem) and solved using a general-purpose SAT solver. This is very elegant and can actually be faster than a heuristic approach.

Li-aung Yip
  • 12,320
  • 5
  • 34
  • 49
  • That indeed seems a lot better than mine. But does mine count as a heuristic function? Just wondering... – Theocharis K. Apr 13 '12 at 02:09
  • @Aposperite: A "heuristic" is just a "rule" or a "rule of thumb". I'd say yours counts, even if it's imprecisely specified / the specification is overly complex. – Li-aung Yip Apr 13 '12 at 02:17
  • I would add that when you are forced to make a guess at a square, a good heuristic would be to pick a square that only has two possible choices (as opposed to nine possible choices.) The chances of getting a guess right are better if you have fewer choices. – Li-aung Yip Apr 13 '12 at 03:28
1

When I wrote a sudoku solver myself in Prolog, the algorithm I used was the following:

  1. filter out cells already solved (ie the given values at the start)
  2. for each cell, build a list containing all its neighbours (that's 20 cells).
  3. for each cell, build a list containing all the possible values it can take (easy to do once the above is done)
  4. in the list containing all the cells to solve, put one with the minimum number of values available on top
  5. if the top cell has 0 remaining possibility, go to 7, else, go to 6, if the list is empty, you have a solution.
  6. for the cell of the top of the list: pick a random number in the possible values of the cell. Remove this value in all the possible values of its neighbours. Go to 5.
  7. backtrack (ie, fail in Prolog)

This algorithm always sorts the "most solved" cell first and detects failure early enough. It reduces solving time quite a lot compared to an algorithm that solves a random cell.

m09
  • 7,490
  • 3
  • 31
  • 58
1

What you have described is Most Constrained Variable heuristic. It picks up the cell that has least number of possibilities and then branches recursively in depth starting from that cell. This heuristic is extremely fast in depth-first search algorithms because it detects collisions early, near the root, while the search tree is still small.

Here is the implementation of Most Constrained Variable heuristic in C#: Exercise #2: Sudoku Solver

This text also contains the analysis of total number of visits to Sudoku cells by this algorithm - it is surprisingly small. It almost looks like the heuristic solves Sudoku in the first try.

Zoran Horvat
  • 10,924
  • 3
  • 31
  • 43