Você está na página 1de 8

Cuadros latinos por programacin lineal

entera

Kjetil Brinchmann Halvorsen

Enero 2017

ndice

1. Introduction 1

2. Equaciones que describe un cuadro latino 2

3. Solucin 6

4. Multiples soluciones 6

5. Como se hice este documento 8

1. Introduction

Primero hacer algunas definiciones y iniciar la sesin de R.

1
rm(list=ls()) # Debe siempre iniciar con una sesin de R limpia.
library(MASS) # Aqui se puede leer todos los paquetes que se usa
### Usamos el paquete (CRAN) lpSolve, que da soporte a programacin entera
### para tratar de construir cuadros latinos.

### Un simple ejemplo, 3 \times 3


###
### 1 2 3
### 2 3 1
### 3 1 2
library(lpSolve)
#library(help=lpSolve)

Vamos a ver como utilizar programacin lineal entera para construir cuadros
latinos. Al comienco, este es un problema combinatorico y no aparentemente
un problema de optimizacin. Pero, sin embargo, podemos usarlo como una
tecnologa para resolver equaciones cuando solo soluciones en enteros tiene
sentido.

Un ejemplo de un cuadro latino 3 3 es el suigiente:

kable(matrix(c(1, 2, 3, 2, 3, 1, 3, 1, 2), 3, 3, byrow=TRUE), digits=1)

1 2 3
2 3 1
3 1 2

Note que cada uno de los tres digitos 1, 2, 3 ocurre una vez en cafa fila, y una
vez en cada columna.

Para contruir cuadros asi, tenemos que describir el cuadro con equaciones.

2. Equaciones que describe un cuadro latino

Introducimos 9 3 = 27 variables para describir el cuadro. Para cada casilla,


este casilla puede contener un 1 o un 2 o un 3. Para cada posibilidad una

2
variable, que es 1 si esta posibilidad se realiza y zero en otro caso. Entonces
cada variable es binaria y la suma de los tres variables de una casilla es
siempre 1. Formalmente:

xkij = zero o uno, k = 1, 2, 3, i = 1, 2, 3, j = 1, 2, 3

donde el ndice k denota los digitos, i las filas y j las columnas. Por ejemplo,
si x221 = 1, esto significa que en fila 2 y columna 1 hay el dgito 2. En
este caso necesariamente x121 = x321 = 0. Finalmente, en cada fila/columna
ocurre exacta uno de dada dgito.

Las restricciones entonces son


X
xkij = 1 todo i, j (1)
k
XX
kxkij = 6 (2)
i k
XX
kxkij = 6 (3)
j k
X
xkij = 1 todo j, k (4)
i
X
xkij = 1 todo i, k (5)
j

por un total de 9 + 3 + 3 + 9 + 9 = 33 restricciones.

Para explicar estas equaciones, (1) dice que hay exactamente un dgito en
cada casilla. (2) dice que la suma de los dgitos en cada columna es 6, (3) lo
mismo para filas. Pero note que las restricciones (2), (3) permite soluciones
como 2,2,2, que es solucin falsa. (4) y (5) es necesaria para evitar estas
soluciones falsas, (4) dice que cada dgito k ocurre exactamente una vez en
cada columna, (5) lo mismo para filas.

Ahora tenemos que formular este como un sistema, matricialmente. La matriz


A del sistema es una matriz 15 33. Escribimos una funcin en R para gene-
rarla, hacemos la matriz tal que el primer ndice corre ms rpido, despues
el segundo, despues el ltimo:

print.matrix <- function(m){


write.table(format(m, justify="right"),
row.names=FALSE, col.names=FALSE, quote=FALSE)

3
} # Para debugear, imprime la matriz mas compacto!
make_Amat <- function() {
A <- matrix(0, 33, 27)
for (i in 1:9) A[i, ((i-1)*3+1):((i-1)*3+3)] <- 1
a <- c(1, 2, 3, 1, 2, 3, 1, 2, 3)
for (i in 1:3) A[9+i, ((i-1)*9+1):((i-1)*9+9)] <- a
A[13, ] <- rep(c(1, 2, 3, 0, 0, 0, 0, 0, 0), 3)
A[14, ] <- rep(c(0, 0, 0, 1, 2, 3, 0, 0, 0), 3)
A[15, ] <- rep(c(0, 0, 0, 0, 0, 0, 1, 2, 3), 3)
for (j in 1:3) for (k in 1:3) {
A[15+k+(j-1)*3, k+(0:2)*3+(j-1)*9] <- 1
}
for (i in 1:3) for (k in 1:3) {
A[24+k+(i-1)*3, k+(i-1)*3+(0:2)*9] <- 1
}
A
}
Amat <- make_Amat()
# Vector del lado derecha:
b <- c(rep(1, 9), rep(6, 6), rep(1, 18))
# Vector coeficiente de la funcion costo:
c <- rep(1, 27) # Un poco artificial como no tenemos en realidad un costo ...
print(Amat)

## 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0
## 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0
## 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0
## 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0
## 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1
## 1 2 3 1 2 3 1 2 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## 0 0 0 0 0 0 0 0 0 1 2 3 1 2 3 1 2 3 0 0 0 0 0 0 0 0 0
## 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 3 1 2 3 1 2 3
## 1 2 3 0 0 0 0 0 0 1 2 3 0 0 0 0 0 0 1 2 3 0 0 0 0 0 0
## 0 0 0 1 2 3 0 0 0 0 0 0 1 2 3 0 0 0 0 0 0 1 2 3 0 0 0
## 0 0 0 0 0 0 1 2 3 0 0 0 0 0 0 1 2 3 0 0 0 0 0 0 1 2 3
## 1 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

4
## 0 1 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## 0 0 1 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
## 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0
## 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0
## 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0
## 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 1 0 0
## 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 1 0
## 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 1
## 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0
## 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0
## 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0
## 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0
## 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0
## 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0
## 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0
## 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0
## 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1

Para entender este cdigo, mire que Amat es un array con tres dimensiones.
Arrays es una generalizacin de matrices donde matrices son arrays con dos
dimensiones. Para los clculos, necesitamos pensar en representar los tres in-
dces k, i, j como n ndice lineal, es decir, representarlo con n solo nmero.
Para este fin, note que, como k, i, j solo toman los valores 1,2,3, se puede
pensarlo como una representacin de un nmero entero en base 3! Note que
en el cdigo k corre ms rpido, lo que dice que k representa el dgito menos
significativo. Es decir, k, i, j en realidad representa el nmero (base 3) jik.
Otro detalle es que en base 3 usualmente usamos los simbolos 0,1,2, mientras
aqui usamos 1,2,3. Es decir, en traducir formulas usuales de base tres, tene-
mos que representar k con k 1, etc. Al final, ay que sumar un uno extra,
porque nuestro sistema de ndices (en R) comienza en uno y no en cero. (Si
habamos usado un lenguaje como C, donde ndices comienza en 0, esto no
sera necesaria).

En base 3, jik usualmente representa el nmero k + 3i + 32 j, por lo indicado


arriba esto tenemos que modificar a (k 1) + (i 1)3 + (j 1)9 + 1. Conestas
indicaciones es fcil escribir el codigo, note que A es una matriz donde el
primer ndice es un orden en realidad arbitraria de las ecuaciones, y el segundo
ndice es la linearizacin del triple ndice explicado arriba. As, por ejemplo
la ecuacin (5) da lugar al cdigo

5
for (i in 1:3) for (k in 1:3) {
A[24+k+(i-1)*3, k+(i-1)*3+(0:2)*9] <- 1
}

donde el ndice j, que no se suma sobre, esta representado por todos sus
valores 1,2,3, en R representado como 0:2, puesto en su lugar en la expansin
de base tres. Los otros sumatorios se pueden desarollar de la misma manera.

3. Solucin

SOL <- lp("max", c, Amat, rep("=", 33), b, all.bin=TRUE)


# el vector de soluciones esta contenido en SOL$solution

x <- SOL$solution
square_from_lp <- function(x) {
res <- matrix(0, 3, 3)
for (j in 1:3) for (i in 1:3) for (k in 1:3) {
ind <- (k-1) + (i-1)*3 + (j-1) * 9 + 1
if (x[ind]==1) res[i, j] <- k
}
res
}
Cuadro <- square_from_lp(x)
kable(Cuadro)

3 1 2
1 2 3
2 3 1

4. Multiples soluciones

Arriba solo hemos encontrado una solucin, pero el problema evidentemente


tiene multiples soluciones. La funcin lp que usamos puede encontrar multi-
ples soluciones. Ahora veremos como.

6
SOL <- lp("max", c, Amat, rep("=", 33), b, all.bin=TRUE, num.bin.solns=12)
### Se sabe (Wikipedia) que existe solo 12 soluciones
# el vector de soluciones esta contenido en SOL$solution

x <- SOL$solution
xx <- matrix(x[1:324],12,27,byrow=TRUE)
square_from_lp <- function(x) { # Este se puede simplificar!
res <- matrix(0, 3, 3)
for (j in 1:3) for (i in 1:3) for (k in 1:3) {
ind <- (k-1) + (i-1)*3 + (j-1) * 9 + 1
if (x[ind]==1) res[i, j] <- k
}
res
}
### Hacer un super-cuadro con los 12 en uno:
xxx <- matrix(0, 15, 11)
for (i in 1:4) for (j in 1:3) {
tab <- (i-1)*3+j
xxx[(1+(i-1)*4):(3+(i-1)*4), (1+(j-1)*4):(3+(j-1)*4)] <-
square_from_lp(xx[tab, ])
}
kable(xxx, digits=1, format.args=list(zero.print=FALSE))

3 1 2 2 1 3 2 1 3
1 2 3 1 3 2 3 2 1
2 3 1 3 2 1 1 3 2

2 3 1 3 2 1 2 3 1
1 2 3 1 3 2 3 1 2
3 1 2 2 1 3 1 2 3

1 3 2 1 2 3 1 3 2
3 2 1 2 3 1 2 1 3
2 1 3 3 1 2 3 2 1

1 2 3 3 1 2 3 2 1
3 1 2 2 3 1 2 1 3
2 3 1 1 2 3 1 3 2

7
5. Ejercicios
1. Modificar el cdigo R para poner extra requerimientos sobre los cuadros
latinos generados, que la suma de ambos diagonales es 6

2. dots para que ambos diagonales contienen 1,2,3.

3. Generalizar el cdigo para generar cuadros latinos de cualquier tamao


n n por nmeros enteros n.

6. Como se hice este documento

devtools::session_info()

## Session info

## Error in print.matrix(m, ..., quote = quote, right = right): unused


arguments (quote = quote, right = right)

Você também pode gostar