Escolar Documentos
Profissional Documentos
Cultura Documentos
entera
Enero 2017
ndice
1. Introduction 1
3. Solucin 6
4. Multiples soluciones 6
1. Introduction
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.
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.
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
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:
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.
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.
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).
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
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
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
devtools::session_info()
## Session info