Algorithms
We now present an algorithm that finds all such chains in polynomial time. The first stage is to find the best bipartite matching using the Ford Fulkerson maximum flow algorithm or any other bipartite matching algorithm (see Introduction to Algorithms, Second Edition, by Thomas H. Cormen et al., MIT Press, 2001).
Let W
be the set of n
cells in a row, column, or subsquare.
That means that there are n
cells or vertices in W
when the entire Sudoku puzzle has n×n
cells or vertices. Let D
be the set of numbers that are matched to W
. In an n×n
Sudoku, D
is the set of numbers 1,2,3,...,n.
Let S
k be a subset of
k
cells out of the n
cells in which the possible numbers are exactly k<n
numbers T
k. We say that S
k is a "chain" if it doesn't contain a smaller set Q
r such that r<k
to which only r
numbers can be matched. Moreover, in our model, if the number v
in D
can be matched to the cell u
in W,
then we say that our Permutation Bipartite Graph G
contains the edge ∈ =(u,v
) between the vertex u
from W
and v
from D
. In addition, let M
denote a maximal match between W
and D.
A match is a set of edges connecting cells or vertices in W
to numbers or vertices in D
. Each cell in W
is allowed to have only one edge in M
that connects it to a number in D
.
Each number in D
is allowed to have only one edge in M
that connects it to a cell or vertex in W
. Let E
denote the entire set of possible vertices between W
and D
.
Because the vertices of S
k are only connected to vertices of T
k, the condition |M
|=|W
| implies that each element s∈
is matched to exactly one element Sk
t ∈ Tk
and vice versa. Start scanning a vertex u1 ∈ W
. Suppose u
1∈S
k. We check all the vertices v
i1 in D
such that the edges (u
1,v
i1) exist in E
. Because S
k is connected only to T
k,v
i1 are all in T
k. We mark u
1 such that we will not consider u
1 again. We remove u
1 from the list of vertices the algorithm will visit. Now we look for all the edges (u
i1,v
i1) in M
that are connected to one of these vertices v
i1. Obviously, u
i1 are in S
k for all indices i
1 because all the vertices in T
k are matched by M
to vertices in S
k. We continue the process recursively. Now, for each u
i1 we look for all v
i2 in D
that are connected to at least one of the u
i1 vertices by edges. We mark u
i1 such that these vertices will not be considered again. Again, the v
i2 must be in T
k and we continue and look for all the edges (u
i2,v
i1)∈M
. Obviously, u
i2 are in S
k.
Because u
1 and the vertices u
i1 were removed from the list of vertices that the algorithm visits, there are fewer vertices that can be visited by the algorithm. The process is repeated until all the vertices in W
it can visit are reached.
Because all the vertices it can reach are in S
k, what is left to prove is that there is no vertex u
in S
k that is not visited by the algorithm. Suppose there is such a vertex u.
Then, obviously, the vertex v
in T
k that is matched to u
could not be visited either; otherwise, u
could be visited. But then, v
is also not connected to any one of the vertices in S
k that were visited. So we can define Q
k-1=S
k-{u
}, which is connected to |S
k|-1 vertices in D.
That is a contradiction to the requirement that S
k is minimal.
A simpler algorithm is the Pile algorithm. Let G
be a Permutation Bipartite Graph. We would like to find if there exist vertices v
i1,...,v
ik in D
such that they are all connected to the same k
vertices in W
, u
j1,...,u
jk. Such vertices are called "Pile" or "Set." The algorithm is trivial. Start traversing the vertices v
k in D
serially in a loop. Activate a second loop within the first loop and count all the other vertices in D
that are connected to the same k
vertices u
j1,...,u
jk in W
that v
k is connected to. If there are k
such vertices v
i1,...,v
ik in D
, then you are done. Although this algorithm can be improved, it is efficient and its runtime is |W
|2/2.
After finding a chain, the algorithm can erase all the edges that are connected to the vertices in T
k that are not connected to S
k. This operation is called "Chain Exclusion." That is, if ∈=(u,v
) and v∈T
k and u∈S
k , then ∈ is removed from the Permutation Bipartite Graph G.
After finding a Pile, remove all the edges that connect u
j1,...,u
jk to D-
{v
i1,...,v
ik}.
Implementation
We've used the Chain Exclusion and Pile Exclusion algorithms described here to build a Windows-based Sudoku solver in Visual Studio C++ 6.00. Executables and the complete source code are available electronically here. You will need to rename the file Sudoku.ex1 to Sudoku.exe. Alternatively, you can compile the entire project Sudoku.dsw or Sudoku.dsp with Visual Studio 6.00. We've included a simple console application, Logic.ex1, that demonstrates Chain Exclusion. This file should be renamed to Logic.exe. In Sudoku.exe, the Logic button calls the class Square3.cpp, and Square3.cpp calls Bipartite.cpp. The Logic button fills as many cells as possible with numbers, by using logic only. You can generate puzzles that usually have more than one solution by clicking on the Test button when the Unique option doesn't have a check mark. If the Unique option is checked, the Sudoku puzzle is solved by logic only. The Very Hard option automatically checks the Unique option and takes 5 seconds. You can also enter your own puzzle and press either the Logic button or the OK button. If the puzzle can't be solved because of contradictions, OK won't fill it and Logic will fill as many cells as possible. When the contradiction is encountered, it inserts a double number in row, column, or square. That can be verified by the Check button.
In addition, Sudoku.exe also solves illogical puzzles via the OK button that calls recursion that in each iteration fills in numbers in locations in which there are less degrees of freedom. For more information on Sudoku puzzles, see the Daily Sudoku) or the Times Online).
Eytan, Raviv, and Eitan are software engineers in Israel. They can be contacted at [email protected], [email protected], and [email protected], respectively.