27.02.2015 Views

Sudoku Puzzle

Sudoku Puzzle

Sudoku Puzzle

SHOW MORE
SHOW LESS

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

<strong>Sudoku</strong> con AMPL<br />

Stefano Nasini<br />

Dept. of Statistics and Operations Research<br />

Universitat Politécnica de Catalunya<br />

La solución de un sudoku siempre es un cuadrado latino, es decir, una matriz de n×n elementos, en la<br />

que cada casilla está ocupada por uno de los n símbolos de tal modo que cada uno de ellos aparece<br />

exactamente una vez en cada columna y en cada fila, aunque el recíproco en general no es cierto ya que el<br />

sudoku establece la restricción añadida de que no se puede repetir un mismo número en una región.<br />

Para costruir un modelo de optimizaciòn que nos permita solucionar un <strong>Sudoku</strong> hace falta convertir<br />

en costricciones de un problema de programaciòn matematica las que son las reglas del juego.<br />

Dichas reglas son rellenar una cuadrícula de 9 × 9 celdas (81 casillas) dividida en subcuadrículas de<br />

3 × 3 (también llamadas "cajas" o "regiones") con las cifras del 1 al 9 partiendo de algunos números ya<br />

dispuestos en algunas de las celdas. El sudoku que querriamos solucionar es el siguiente:<br />

Antes que todo, nuestras variables de deciciones han de ser variables binarias que nos informan de la<br />

presencia o absencia de una cifra en una casilla. Asì que dicha variable de deciciòn estarà definida por tres<br />

subindices: fila, columna, digito, y tomaràvalor 1 en el caso en el que en una determinada casilla<br />

(identificada por sus coordenadas) hay un determinado digito.<br />

Imponemos que en cada celda solo haya un digito y no màs.<br />

1


9<br />

∑<br />

c=<br />

1<br />

Cell<br />

abc<br />

= 1<br />

Imponemos que un digito de 0 a 9 aparezca solo una vez por cada fila.<br />

9<br />

∑<br />

a=<br />

1<br />

Cell<br />

abc<br />

= 1<br />

Imponemos que un digito de 0 a 9 aparezca solo una vez por cada columna.<br />

9<br />

∑<br />

b=<br />

1<br />

Cell<br />

abc<br />

= 1<br />

Imponemos que en un cuadrado 3x3 un digito aparezca una sola vez.<br />

3<br />

3<br />

∑∑<br />

a= 1 b=<br />

1<br />

Cell<br />

abc<br />

= 1<br />

Imponemos que en un cuadrado 3x3 un dado digito aparezca una sola vez.<br />

3<br />

3<br />

∑∑<br />

a= 1 b=<br />

1<br />

6<br />

3<br />

∑∑<br />

a= 4 b=<br />

1<br />

9<br />

3<br />

∑∑<br />

a= 7 b=<br />

1<br />

3<br />

6<br />

Cell<br />

abc<br />

= 1 ∑∑Cell abc<br />

= 1 ∑∑Cell<br />

a= 1 b=<br />

4<br />

6<br />

6<br />

3<br />

9<br />

a= 1 b=<br />

7<br />

Cell<br />

abc<br />

= 1 ∑∑Cell abc<br />

= 1 ∑∑Cell<br />

a= 4 b=<br />

4<br />

7<br />

6<br />

6<br />

7<br />

a= 4 b=<br />

7<br />

Cell<br />

abc<br />

= 1 ∑∑Cell abc<br />

= 1 ∑∑Cell<br />

a= 7 b=<br />

4<br />

9<br />

9<br />

a= 7 b=<br />

7<br />

abc<br />

abc<br />

abc<br />

= 1<br />

= 1<br />

= 1<br />

De dicho problema buscamo una cualquiera soluciòn factible, asì que no hace falta poner ninguna<br />

funciòn objetivo. Lo implementamos en AMPL como problema de programaciòn entera de la forma<br />

siguiente.<br />

var Cell{1..9,1..9,1..9} binary;<br />

minimize Niente;<br />

subject to Somma_1 {a in 1..9,b in 1..9}:<br />

sum{c in 1..9} Cell[a,b,c]=1;<br />

subject to Somma_2 {a in 1..9,c in 1..9}:<br />

sum{b in 1..9} Cell[a,b,c]=1;<br />

subject to Somma_3 {b in 1..9,c in 1..9}:<br />

sum{a in 1..9} Cell[a,b,c]=1;<br />

subject to Riquadri_1 {c in 1..9}:<br />

sum{a in 1..3,b in 1..3} Cell[a,b,c]=1;<br />

subject to Riquadri_2 {c in 1..9}:<br />

sum{a in 1..3,b in 4..6} Cell[a,b,c]=1;<br />

subject to Riquadri_3 {c in 1..9}:<br />

sum{a in 1..3,b in 7..9} Cell[a,b,c]=1;<br />

subject to Riquadri_4 {c in 1..9}:<br />

2


sum{a in 4..6,b in 4..6} Cell[a,b,c]=1;<br />

subject to Riquadri_5 {c in 1..9}:<br />

sum{a in 4..6,b in 1..3} Cell[a,b,c]=1;<br />

subject to Riquadri_6 {c in 1..9}:<br />

sum{a in 4..6,b in 7..9} Cell[a,b,c]=1;<br />

subject to Riquadri_7 {c in 1..9}:<br />

sum{a in 7..9,b in 1..3} Cell[a,b,c]=1;<br />

subject to Riquadri_8 {c in 1..9}:<br />

sum{a in 7..9,b in 4..6} Cell[a,b,c]=1;<br />

subject to Riquadri_9 {c in 1..9}:<br />

sum{a in 7..9,b in 7..9} Cell[a,b,c]=1;<br />

subject to C1: Cell[1,1,5]=1;<br />

subject to C2: Cell[1,2,3]=1;<br />

subject to C3: Cell[1,5,7]=1;<br />

subject to C4: Cell[2,1,6]=1;<br />

subject to C5: Cell[2,4,1]=1;<br />

subject to C6: Cell[2,5,9]=1;<br />

subject to C7: Cell[2,6,5]=1;<br />

subject to C8: Cell[3,2,9]=1;<br />

subject to C9: Cell[3,3,8]=1;<br />

subject to C10: Cell[3,8,6]=1;<br />

subject to C11: Cell[4,1,8]=1;<br />

subject to C12: Cell[4,5,6]=1;<br />

subject to C13: Cell[4,9,3]=1;<br />

subject to C14: Cell[5,1,4]=1;<br />

subject to C15: Cell[5,4,8]=1;<br />

subject to C16: Cell[5,6,3]=1;<br />

subject to C17: Cell[5,9,1]=1;<br />

subject to C18: Cell[6,1,7]=1;<br />

subject to C19: Cell[6,5,2]=1;<br />

subject to C20: Cell[6,5,2]=1;<br />

subject to C21: Cell[6,9,6]=1;<br />

subject to C22: Cell[7,2,6]=1;<br />

subject to C23: Cell[7,7,2]=1;<br />

subject to C24: Cell[7,8,8]=1;<br />

subject to C25: Cell[8,4,4]=1;<br />

subject to C26: Cell[8,5,1]=1;<br />

subject to C27: Cell[8,6,9]=1;<br />

subject to C28: Cell[8,9,5]=1;<br />

subject to C29: Cell[9,5,8]=1;<br />

subject to C30: Cell[9,8,7]=1;<br />

subject to C31: Cell[9,9,9]=1;<br />

En el ultimo grupo de constricciones hemos impuesto los valores predefinidos de algunas celdas,<br />

como mostra la representaciòn grafica de la pagina anterior. Utilizando CPLEX como solver, optenemos la<br />

siguiente soluciòn binaria de nuestro problema.<br />

Cada matriz corresponde a una fila del sudoku. Los valores de fila de la matriz corresponden a las<br />

columnas del sudoku y los valores en columna a cala digito que puede ser introducido. Por ejemplo el valor<br />

Cell[1,1,1]=0 nos dice que en la celda(1,1) del sudoku el valor 1 no esta presente.<br />

ampl: model sudoku1.mod;<br />

ampl: solve;<br />

Solution determined by presolve;<br />

objective Niente = 0.<br />

3


ampl: display Cell;<br />

Cell [1,*,*]<br />

: 1 2 3 4 5 6 7 8 9 :=<br />

1 0 0 0 0 1 0 0 0 0<br />

2 0 0 1 0 0 0 0 0 0<br />

3 0 0 0 1 0 0 0 0 0<br />

4 0 0 0 0 0 1 0 0 0<br />

5 0 0 0 0 0 0 1 0 0<br />

6 0 0 0 0 0 0 0 1 0<br />

7 0 0 0 0 0 0 0 0 1<br />

8 1 0 0 0 0 0 0 0 0<br />

9 0 1 0 0 0 0 0 0 0<br />

[2,*,*]<br />

: 1 2 3 4 5 6 7 8 9 :=<br />

1 0 0 0 0 0 1 0 0 0<br />

2 0 0 0 0 0 0 1 0 0<br />

3 0 1 0 0 0 0 0 0 0<br />

4 1 0 0 0 0 0 0 0 0<br />

5 0 0 0 0 0 0 0 0 1<br />

6 0 0 0 0 1 0 0 0 0<br />

7 0 0 1 0 0 0 0 0 0<br />

8 0 0 0 1 0 0 0 0 0<br />

9 0 0 0 0 0 0 0 1 0<br />

[3,*,*]<br />

: 1 2 3 4 5 6 7 8 9 :=<br />

1 1 0 0 0 0 0 0 0 0<br />

2 0 0 0 0 0 0 0 0 1<br />

3 0 0 0 0 0 0 0 1 0<br />

4 0 0 1 0 0 0 0 0 0<br />

5 0 0 0 1 0 0 0 0 0<br />

6 0 1 0 0 0 0 0 0 0<br />

7 0 0 0 0 1 0 0 0 0<br />

8 0 0 0 0 0 1 0 0 0<br />

9 0 0 0 0 0 0 1 0 0<br />

[4,*,*]<br />

: 1 2 3 4 5 6 7 8 9 :=<br />

1 0 0 0 0 0 0 0 1 0<br />

2 0 0 0 0 1 0 0 0 0<br />

3 0 0 0 0 0 0 0 0 1<br />

4 0 0 0 0 0 0 1 0 0<br />

5 0 0 0 0 0 1 0 0 0<br />

6 1 0 0 0 0 0 0 0 0<br />

7 0 0 0 1 0 0 0 0 0<br />

8 0 1 0 0 0 0 0 0 0<br />

9 0 0 1 0 0 0 0 0 0<br />

[5,*,*]<br />

: 1 2 3 4 5 6 7 8 9 :=<br />

1 0 0 0 1 0 0 0 0 0<br />

2 0 1 0 0 0 0 0 0 0<br />

3 0 0 0 0 0 1 0 0 0<br />

4 0 0 0 0 0 0 0 1 0<br />

5 0 0 0 0 1 0 0 0 0<br />

6 0 0 1 0 0 0 0 0 0<br />

7 0 0 0 0 0 0 1 0 0<br />

8 0 0 0 0 0 0 0 0 1<br />

9 1 0 0 0 0 0 0 0 0<br />

[6,*,*]<br />

: 1 2 3 4 5 6 7 8 9 :=<br />

1 0 0 0 0 0 0 1 0 0<br />

2 1 0 0 0 0 0 0 0 0<br />

3 0 0 1 0 0 0 0 0 0<br />

4 0 0 0 0 0 0 0 0 1<br />

5 0 1 0 0 0 0 0 0 0<br />

4


6 0 0 0 1 0 0 0 0 0<br />

7 0 0 0 0 0 0 0 1 0<br />

8 0 0 0 0 1 0 0 0 0<br />

9 0 0 0 0 0 1 0 0 0<br />

[7,*,*]<br />

: 1 2 3 4 5 6 7 8 9 :=<br />

1 0 0 0 0 0 0 0 0 1<br />

2 0 0 0 0 0 1 0 0 0<br />

3 1 0 0 0 0 0 0 0 0<br />

4 0 0 0 0 1 0 0 0 0<br />

5 0 0 1 0 0 0 0 0 0<br />

6 0 0 0 0 0 0 1 0 0<br />

7 0 1 0 0 0 0 0 0 0<br />

8 0 0 0 0 0 0 0 1 0<br />

9 0 0 0 1 0 0 0 0 0<br />

[8,*,*]<br />

: 1 2 3 4 5 6 7 8 9 :=<br />

1 0 1 0 0 0 0 0 0 0<br />

2 0 0 0 0 0 0 0 1 0<br />

3 0 0 0 0 0 0 1 0 0<br />

4 0 0 0 1 0 0 0 0 0<br />

5 1 0 0 0 0 0 0 0 0<br />

6 0 0 0 0 0 0 0 0 1<br />

7 0 0 0 0 0 1 0 0 0<br />

8 0 0 1 0 0 0 0 0 0<br />

9 0 0 0 0 1 0 0 0 0<br />

[9,*,*]<br />

: 1 2 3 4 5 6 7 8 9 :=<br />

1 0 0 1 0 0 0 0 0 0<br />

2 0 0 0 1 0 0 0 0 0<br />

3 0 0 0 0 1 0 0 0 0<br />

4 0 1 0 0 0 0 0 0 0<br />

5 0 0 0 0 0 0 0 1 0<br />

6 0 0 0 0 0 1 0 0 0<br />

7 1 0 0 0 0 0 0 0 0<br />

8 0 0 0 0 0 0 1 0 0<br />

9 0 0 0 0 0 0 0 0 1<br />

;<br />

ampl:<br />

Introduciendo en la tabla del sudoku dicha soluciòn obtenemos el siguiente resultado.<br />

5 3 4 6 7 8 9 1 2<br />

6 7 2 1 9 5 3 4 8<br />

1 9 8 3 4 2 5 6 7<br />

8 5 9 7 6 1 4 2 5<br />

4 2 6 8 5 3 7 9 1<br />

7 1 3 9 2 4 8 5 6<br />

9 6 1 5 3 7 2 8 4<br />

2 8 7 4 1 9 6 3 5<br />

3 4 5 2 8 6 1 7 9<br />

5

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!