Los métodos de optimizacion heuristica son alternativas a los metodos basados en el gradiente. Algunos, como los algoritmos evolutivos y las coloinas de hormicas, se inspiran en paradigmas de la biologia.
El objetivo de este trabajo es la aplicacion de metodos heuristicos.
Considere las siguientes funciones de prueba:
Función de Rosenbrock: \(f(x_1, x_2) = 100(x_1-x_2^2)+(1-x_1)^2, 2_i \in [-2.048,2.048]\), \(i?1,2\). Alcanza su valor minimo en \(x_1 = 1\) y \(x_2 = 1\).
Función de Rastrigin: \(f(x1,x2)= 20 + ∑_{i=1}^2 x_i^2 − 10cos(2\pi x_i) , x_i∈[−5.12,5.12]\), \(i=1,2\). Alcanza su valor minimo en \(x_1 = 0\) y \(x_2 = 0\).
Función de Schwefel: \(f(x1,x2) = -∑_{i=1}^2 x_i sin(\sqrt{|xi|}), xi∈[−500,500]\), \(i=1,2\). Alcanza su valor mínimo en \(x1=420.9687\) y \(x2=420.9687\).
Función de Griewank: \(f(x1,x2)=∑_{i=1}^2 \frac{x_i^2}{4000} − ∏_{i=1}^2 cos(\frac{x_i}{\sqrt{i}}) +1, xi∈[−600,600]\), \(i=1,2\). Alcanza su valor mínimo en \(x1=0\) y \(x2=0\).
Función Goldstein-Price: \(f(x_1,x_2)=[1+(x_1+x_2+1)^2(19−14x_1+3x_1^2−14x_2+6x_1x_2+3x_2^2)]\) \(×[30+(2x_1−3x_2)^2(18−32x_1+12x_1^2+48x_2−36x_1x_2+27x_2^2)]\), \(x_i∈[−2,2]\), \(i=1,2\). Alcanza su valor mínimo en \(x_1=0\) y \(x_2=−1\).
Funcion de las seis jorobas de cabello (six-humpcamel back): \(f(x1,x2)=(4−2.1x_1^2+x_1^{4/3})x_1^2+x_1x_2+(−4+4x_2^2)x_2^2\), \(x_1∈[−3,3]\) y \(x_2∈[−2,2]\). Alcanza su valor mínimo en \(x_1=−0.0898\) y \(x_2=0.7126\) y también en \(x_1=0.0898\) y \(x_2=0.7126\).
Escoja dos funciones de prueba
Optimice las funciones en dos y tres dimensiones usando un metodo de descenso por gradiente con condicion inicial aleatoria
Optimice las funciones en dos y tres dimnensiones usando: algoritmos evolutivos, optimizacion de particulas y evolucion diferencial
Represente con un gif animado o un video el proceso de optimizacion de descenso por gradiente y el proceso usando el metodo heuristico.
Este este apartado se aplican metodos heuristicos para resolver el problema del vendedor viajero.
Un vendedor debe hacer un recorrido por las siguientes cuidades de colombia en su carro (no necesariamente en este orden):
Utilice colonias de hormigas y algotirmos geneticos para encontrar el orden optimo. El costo de desplazamiento entre ciudades es la suma del valor de la hora del vendedor (es un parámetro que debe estudiarse), el costo de los peajes y el costo del combustible. CAada equipo debe definir que carro hace el recorrido del vendedor y de allí extraer el costo del combustible.
Adicionalmente represente con un gif animado o un video cómo se comporta la mejor solución usando un grafico del recorrido del mapa de colombia.
Función de Rastrigin: \(f(x1,x2)= 20 + ∑_{i=1}^2 x_i^2 − 10cos(2\pi x_i) , x_i∈[−5.12,5.12]\), \(i=1,2\). Alcanza su valor minimo en \(x_1 = 0\) y \(x_2 = 0\).
# Determinamos la función de rastrigin a utilizar para graficar:
f_rastrigin2d<- function(x1,x2){
y <- 20+x1^2-10*cos(2*pi*x1)+x2^2-10*cos(2*pi*x2)
return(y)
}
n<-50
x1 <- seq(-5.12,5.12,length.out=n)
x2 <- seq(-5.12,5.12,length.out=n)
X <- expand.grid(x1,x2)
z <- f_rastrigin2d(X[,1],X[,2])
Z <- matrix(z,ncol=n,nrow=n)
Curvas de nivel de la función de Rastrigin
#Curvas de nivel:
contour(x1,x2,Z,
main = "Función de Rastrigin",
sub = "Curvas de nivel de la función")
filled.contour(x1, x2, Z,
main = "Función de Rastrigin",
color.palette = bl2gr.colors)
#persp(x1,x2,Z,theta = 50, d=2)
#persp3D(x1,x2,Z,theta = 50, phi = 20, col.palette = bl2gr.colors)
fig <- plot_ly(z = as.matrix(Z), type = "surface")
fig <- fig %>% add_surface()
fig
Definimos la funcion vectorizada
# Rastrigin vectorizada: para optimizar
f_rastrigin2d_vec <- function(x){
x1 <- x[1]
x2 <- x[2]
y <- 20+x1^2-10*cos(2*pi*x1)+x2^2-10*cos(2*pi*x2)
return(y)
}
Optimizamos la funcion con evolucion diferencial, para ello utiliamos la funcion DEoptim
# Optimizacion con evolución diferencial:
opt_ras01 <- DEoptim(fn=f_rastrigin2d_vec, lower=c(-5.12,-5.12), upper = c(5.12,5.12))
## Iteration: 1 bestvalit: 5.731015 bestmemit: -1.052497 1.966901
## Iteration: 2 bestvalit: 5.731015 bestmemit: -1.052497 1.966901
## Iteration: 3 bestvalit: 5.731015 bestmemit: -1.052497 1.966901
## Iteration: 4 bestvalit: 5.731015 bestmemit: -1.052497 1.966901
## Iteration: 5 bestvalit: 4.303786 bestmemit: -0.030076 -0.865226
## Iteration: 6 bestvalit: 4.303786 bestmemit: -0.030076 -0.865226
## Iteration: 7 bestvalit: 4.303786 bestmemit: -0.030076 -0.865226
## Iteration: 8 bestvalit: 1.252860 bestmemit: 0.987321 -0.035310
## Iteration: 9 bestvalit: 0.520615 bestmemit: -0.030076 0.041618
## Iteration: 10 bestvalit: 0.520615 bestmemit: -0.030076 0.041618
## Iteration: 11 bestvalit: 0.520615 bestmemit: -0.030076 0.041618
## Iteration: 12 bestvalit: 0.520615 bestmemit: -0.030076 0.041618
## Iteration: 13 bestvalit: 0.520615 bestmemit: -0.030076 0.041618
## Iteration: 14 bestvalit: 0.520615 bestmemit: -0.030076 0.041618
## Iteration: 15 bestvalit: 0.520615 bestmemit: -0.030076 0.041618
## Iteration: 16 bestvalit: 0.520615 bestmemit: -0.030076 0.041618
## Iteration: 17 bestvalit: 0.520615 bestmemit: -0.030076 0.041618
## Iteration: 18 bestvalit: 0.520615 bestmemit: -0.030076 0.041618
## Iteration: 19 bestvalit: 0.520615 bestmemit: -0.030076 0.041618
## Iteration: 20 bestvalit: 0.520615 bestmemit: -0.030076 0.041618
## Iteration: 21 bestvalit: 0.520615 bestmemit: -0.030076 0.041618
## Iteration: 22 bestvalit: 0.520615 bestmemit: -0.030076 0.041618
## Iteration: 23 bestvalit: 0.272920 bestmemit: 0.008153 0.036261
## Iteration: 24 bestvalit: 0.272920 bestmemit: 0.008153 0.036261
## Iteration: 25 bestvalit: 0.272920 bestmemit: 0.008153 0.036261
## Iteration: 26 bestvalit: 0.272920 bestmemit: 0.008153 0.036261
## Iteration: 27 bestvalit: 0.272920 bestmemit: 0.008153 0.036261
## Iteration: 28 bestvalit: 0.272920 bestmemit: 0.008153 0.036261
## Iteration: 29 bestvalit: 0.272920 bestmemit: 0.008153 0.036261
## Iteration: 30 bestvalit: 0.272920 bestmemit: 0.008153 0.036261
## Iteration: 31 bestvalit: 0.272920 bestmemit: 0.008153 0.036261
## Iteration: 32 bestvalit: 0.272920 bestmemit: 0.008153 0.036261
## Iteration: 33 bestvalit: 0.272920 bestmemit: 0.008153 0.036261
## Iteration: 34 bestvalit: 0.272920 bestmemit: 0.008153 0.036261
## Iteration: 35 bestvalit: 0.272920 bestmemit: 0.008153 0.036261
## Iteration: 36 bestvalit: 0.272920 bestmemit: 0.008153 0.036261
## Iteration: 37 bestvalit: 0.180107 bestmemit: -0.030170 0.000547
## Iteration: 38 bestvalit: 0.180107 bestmemit: -0.030170 0.000547
## Iteration: 39 bestvalit: 0.180107 bestmemit: -0.030170 0.000547
## Iteration: 40 bestvalit: 0.180107 bestmemit: -0.030170 0.000547
## Iteration: 41 bestvalit: 0.026855 bestmemit: -0.011624 0.000547
## Iteration: 42 bestvalit: 0.026855 bestmemit: -0.011624 0.000547
## Iteration: 43 bestvalit: 0.026855 bestmemit: -0.011624 0.000547
## Iteration: 44 bestvalit: 0.026855 bestmemit: -0.011624 0.000547
## Iteration: 45 bestvalit: 0.026855 bestmemit: -0.011624 0.000547
## Iteration: 46 bestvalit: 0.026855 bestmemit: -0.011624 0.000547
## Iteration: 47 bestvalit: 0.015868 bestmemit: 0.002638 -0.008546
## Iteration: 48 bestvalit: 0.015868 bestmemit: 0.002638 -0.008546
## Iteration: 49 bestvalit: 0.015868 bestmemit: 0.002638 -0.008546
## Iteration: 50 bestvalit: 0.015868 bestmemit: 0.002638 -0.008546
## Iteration: 51 bestvalit: 0.015868 bestmemit: 0.002638 -0.008546
## Iteration: 52 bestvalit: 0.015868 bestmemit: 0.002638 -0.008546
## Iteration: 53 bestvalit: 0.015868 bestmemit: 0.002638 -0.008546
## Iteration: 54 bestvalit: 0.015868 bestmemit: 0.002638 -0.008546
## Iteration: 55 bestvalit: 0.015868 bestmemit: 0.002638 -0.008546
## Iteration: 56 bestvalit: 0.015868 bestmemit: 0.002638 -0.008546
## Iteration: 57 bestvalit: 0.015868 bestmemit: 0.002638 -0.008546
## Iteration: 58 bestvalit: 0.015868 bestmemit: 0.002638 -0.008546
## Iteration: 59 bestvalit: 0.015868 bestmemit: 0.002638 -0.008546
## Iteration: 60 bestvalit: 0.005290 bestmemit: -0.004806 0.001888
## Iteration: 61 bestvalit: 0.005290 bestmemit: -0.004806 0.001888
## Iteration: 62 bestvalit: 0.005290 bestmemit: -0.004806 0.001888
## Iteration: 63 bestvalit: 0.005290 bestmemit: -0.004806 0.001888
## Iteration: 64 bestvalit: 0.005290 bestmemit: -0.004806 0.001888
## Iteration: 65 bestvalit: 0.005290 bestmemit: -0.004806 0.001888
## Iteration: 66 bestvalit: 0.005290 bestmemit: -0.004806 0.001888
## Iteration: 67 bestvalit: 0.005290 bestmemit: -0.004806 0.001888
## Iteration: 68 bestvalit: 0.001820 bestmemit: 0.002352 0.001908
## Iteration: 69 bestvalit: 0.001820 bestmemit: 0.002352 0.001908
## Iteration: 70 bestvalit: 0.001820 bestmemit: 0.002352 0.001908
## Iteration: 71 bestvalit: 0.001820 bestmemit: 0.002352 0.001908
## Iteration: 72 bestvalit: 0.001820 bestmemit: 0.002352 0.001908
## Iteration: 73 bestvalit: 0.001820 bestmemit: 0.002352 0.001908
## Iteration: 74 bestvalit: 0.001820 bestmemit: 0.002352 0.001908
## Iteration: 75 bestvalit: 0.001820 bestmemit: 0.002352 0.001908
## Iteration: 76 bestvalit: 0.001540 bestmemit: -0.001802 0.002126
## Iteration: 77 bestvalit: 0.000158 bestmemit: -0.000017 -0.000893
## Iteration: 78 bestvalit: 0.000158 bestmemit: -0.000017 -0.000893
## Iteration: 79 bestvalit: 0.000158 bestmemit: -0.000017 -0.000893
## Iteration: 80 bestvalit: 0.000158 bestmemit: -0.000017 -0.000893
## Iteration: 81 bestvalit: 0.000158 bestmemit: -0.000017 -0.000893
## Iteration: 82 bestvalit: 0.000158 bestmemit: -0.000017 -0.000893
## Iteration: 83 bestvalit: 0.000158 bestmemit: -0.000017 -0.000893
## Iteration: 84 bestvalit: 0.000047 bestmemit: -0.000307 -0.000381
## Iteration: 85 bestvalit: 0.000047 bestmemit: -0.000307 -0.000381
## Iteration: 86 bestvalit: 0.000047 bestmemit: -0.000307 -0.000381
## Iteration: 87 bestvalit: 0.000047 bestmemit: -0.000307 -0.000381
## Iteration: 88 bestvalit: 0.000047 bestmemit: -0.000307 -0.000381
## Iteration: 89 bestvalit: 0.000047 bestmemit: -0.000307 -0.000381
## Iteration: 90 bestvalit: 0.000047 bestmemit: -0.000307 -0.000381
## Iteration: 91 bestvalit: 0.000047 bestmemit: -0.000307 -0.000381
## Iteration: 92 bestvalit: 0.000047 bestmemit: -0.000307 -0.000381
## Iteration: 93 bestvalit: 0.000047 bestmemit: -0.000307 -0.000381
## Iteration: 94 bestvalit: 0.000047 bestmemit: -0.000307 -0.000381
## Iteration: 95 bestvalit: 0.000047 bestmemit: -0.000307 -0.000381
## Iteration: 96 bestvalit: 0.000047 bestmemit: -0.000307 -0.000381
## Iteration: 97 bestvalit: 0.000047 bestmemit: -0.000307 -0.000381
## Iteration: 98 bestvalit: 0.000047 bestmemit: -0.000307 -0.000381
## Iteration: 99 bestvalit: 0.000047 bestmemit: -0.000307 -0.000381
## Iteration: 100 bestvalit: 0.000047 bestmemit: -0.000307 -0.000381
## Iteration: 101 bestvalit: 0.000047 bestmemit: -0.000307 -0.000381
## Iteration: 102 bestvalit: 0.000047 bestmemit: -0.000307 -0.000381
## Iteration: 103 bestvalit: 0.000047 bestmemit: -0.000307 -0.000381
## Iteration: 104 bestvalit: 0.000047 bestmemit: -0.000307 -0.000381
## Iteration: 105 bestvalit: 0.000047 bestmemit: -0.000307 -0.000381
## Iteration: 106 bestvalit: 0.000047 bestmemit: -0.000307 -0.000381
## Iteration: 107 bestvalit: 0.000047 bestmemit: -0.000307 -0.000381
## Iteration: 108 bestvalit: 0.000047 bestmemit: -0.000303 -0.000381
## Iteration: 109 bestvalit: 0.000047 bestmemit: -0.000303 -0.000381
## Iteration: 110 bestvalit: 0.000047 bestmemit: -0.000303 -0.000381
## Iteration: 111 bestvalit: 0.000047 bestmemit: -0.000303 -0.000381
## Iteration: 112 bestvalit: 0.000047 bestmemit: -0.000303 -0.000381
## Iteration: 113 bestvalit: 0.000047 bestmemit: -0.000303 -0.000381
## Iteration: 114 bestvalit: 0.000047 bestmemit: -0.000303 -0.000381
## Iteration: 115 bestvalit: 0.000047 bestmemit: -0.000303 -0.000381
## Iteration: 116 bestvalit: 0.000047 bestmemit: -0.000303 -0.000381
## Iteration: 117 bestvalit: 0.000047 bestmemit: -0.000303 -0.000381
## Iteration: 118 bestvalit: 0.000047 bestmemit: -0.000303 -0.000381
## Iteration: 119 bestvalit: 0.000047 bestmemit: -0.000303 -0.000381
## Iteration: 120 bestvalit: 0.000047 bestmemit: -0.000303 -0.000381
## Iteration: 121 bestvalit: 0.000047 bestmemit: -0.000303 -0.000381
## Iteration: 122 bestvalit: 0.000036 bestmemit: -0.000189 -0.000381
## Iteration: 123 bestvalit: 0.000036 bestmemit: -0.000189 -0.000381
## Iteration: 124 bestvalit: 0.000036 bestmemit: -0.000189 -0.000381
## Iteration: 125 bestvalit: 0.000036 bestmemit: -0.000189 -0.000381
## Iteration: 126 bestvalit: 0.000014 bestmemit: -0.000242 -0.000112
## Iteration: 127 bestvalit: 0.000014 bestmemit: -0.000242 -0.000112
## Iteration: 128 bestvalit: 0.000014 bestmemit: -0.000242 -0.000112
## Iteration: 129 bestvalit: 0.000014 bestmemit: -0.000242 -0.000112
## Iteration: 130 bestvalit: 0.000014 bestmemit: -0.000242 -0.000112
## Iteration: 131 bestvalit: 0.000014 bestmemit: -0.000242 -0.000112
## Iteration: 132 bestvalit: 0.000014 bestmemit: -0.000242 -0.000112
## Iteration: 133 bestvalit: 0.000014 bestmemit: -0.000242 -0.000112
## Iteration: 134 bestvalit: 0.000014 bestmemit: -0.000242 -0.000112
## Iteration: 135 bestvalit: 0.000014 bestmemit: -0.000242 -0.000112
## Iteration: 136 bestvalit: 0.000014 bestmemit: -0.000242 -0.000112
## Iteration: 137 bestvalit: 0.000014 bestmemit: -0.000242 -0.000112
## Iteration: 138 bestvalit: 0.000014 bestmemit: -0.000242 -0.000112
## Iteration: 139 bestvalit: 0.000014 bestmemit: -0.000242 -0.000112
## Iteration: 140 bestvalit: 0.000014 bestmemit: -0.000242 -0.000112
## Iteration: 141 bestvalit: 0.000014 bestmemit: -0.000242 -0.000112
## Iteration: 142 bestvalit: 0.000014 bestmemit: -0.000242 -0.000112
## Iteration: 143 bestvalit: 0.000014 bestmemit: -0.000242 -0.000112
## Iteration: 144 bestvalit: 0.000004 bestmemit: 0.000010 -0.000142
## Iteration: 145 bestvalit: 0.000004 bestmemit: 0.000010 -0.000142
## Iteration: 146 bestvalit: 0.000004 bestmemit: 0.000010 -0.000142
## Iteration: 147 bestvalit: 0.000004 bestmemit: 0.000010 -0.000142
## Iteration: 148 bestvalit: 0.000004 bestmemit: 0.000010 -0.000142
## Iteration: 149 bestvalit: 0.000004 bestmemit: 0.000010 -0.000142
## Iteration: 150 bestvalit: 0.000003 bestmemit: -0.000086 -0.000096
## Iteration: 151 bestvalit: 0.000003 bestmemit: -0.000086 -0.000096
## Iteration: 152 bestvalit: 0.000003 bestmemit: -0.000116 0.000010
## Iteration: 153 bestvalit: 0.000003 bestmemit: -0.000116 0.000010
## Iteration: 154 bestvalit: 0.000001 bestmemit: 0.000052 0.000010
## Iteration: 155 bestvalit: 0.000001 bestmemit: 0.000052 0.000010
## Iteration: 156 bestvalit: 0.000001 bestmemit: 0.000052 0.000010
## Iteration: 157 bestvalit: 0.000001 bestmemit: 0.000052 0.000010
## Iteration: 158 bestvalit: 0.000001 bestmemit: 0.000052 0.000010
## Iteration: 159 bestvalit: 0.000001 bestmemit: 0.000052 0.000010
## Iteration: 160 bestvalit: 0.000001 bestmemit: 0.000052 0.000010
## Iteration: 161 bestvalit: 0.000001 bestmemit: 0.000052 0.000010
## Iteration: 162 bestvalit: 0.000001 bestmemit: 0.000052 0.000010
## Iteration: 163 bestvalit: 0.000001 bestmemit: 0.000052 0.000010
## Iteration: 164 bestvalit: 0.000001 bestmemit: 0.000052 0.000010
## Iteration: 165 bestvalit: 0.000001 bestmemit: 0.000052 0.000010
## Iteration: 166 bestvalit: 0.000001 bestmemit: 0.000052 0.000010
## Iteration: 167 bestvalit: 0.000001 bestmemit: 0.000052 0.000010
## Iteration: 168 bestvalit: 0.000001 bestmemit: 0.000052 0.000010
## Iteration: 169 bestvalit: 0.000001 bestmemit: 0.000052 0.000010
## Iteration: 170 bestvalit: 0.000001 bestmemit: 0.000052 0.000010
## Iteration: 171 bestvalit: 0.000001 bestmemit: 0.000052 0.000010
## Iteration: 172 bestvalit: 0.000001 bestmemit: 0.000052 0.000010
## Iteration: 173 bestvalit: 0.000001 bestmemit: 0.000052 0.000010
## Iteration: 174 bestvalit: 0.000001 bestmemit: 0.000052 0.000010
## Iteration: 175 bestvalit: 0.000001 bestmemit: 0.000052 0.000010
## Iteration: 176 bestvalit: 0.000001 bestmemit: 0.000052 0.000010
## Iteration: 177 bestvalit: 0.000000 bestmemit: 0.000009 0.000010
## Iteration: 178 bestvalit: 0.000000 bestmemit: 0.000009 0.000010
## Iteration: 179 bestvalit: 0.000000 bestmemit: 0.000009 0.000010
## Iteration: 180 bestvalit: 0.000000 bestmemit: 0.000009 0.000010
## Iteration: 181 bestvalit: 0.000000 bestmemit: 0.000009 0.000010
## Iteration: 182 bestvalit: 0.000000 bestmemit: 0.000009 0.000010
## Iteration: 183 bestvalit: 0.000000 bestmemit: 0.000009 0.000010
## Iteration: 184 bestvalit: 0.000000 bestmemit: 0.000009 0.000010
## Iteration: 185 bestvalit: 0.000000 bestmemit: 0.000009 0.000010
## Iteration: 186 bestvalit: 0.000000 bestmemit: 0.000009 0.000010
## Iteration: 187 bestvalit: 0.000000 bestmemit: 0.000009 0.000010
## Iteration: 188 bestvalit: 0.000000 bestmemit: 0.000009 0.000010
## Iteration: 189 bestvalit: 0.000000 bestmemit: 0.000009 0.000010
## Iteration: 190 bestvalit: 0.000000 bestmemit: 0.000009 0.000010
## Iteration: 191 bestvalit: 0.000000 bestmemit: 0.000009 0.000010
## Iteration: 192 bestvalit: 0.000000 bestmemit: 0.000009 0.000010
## Iteration: 193 bestvalit: 0.000000 bestmemit: 0.000009 0.000010
## Iteration: 194 bestvalit: 0.000000 bestmemit: 0.000009 0.000010
## Iteration: 195 bestvalit: 0.000000 bestmemit: 0.000009 0.000010
## Iteration: 196 bestvalit: 0.000000 bestmemit: 0.000009 0.000010
## Iteration: 197 bestvalit: 0.000000 bestmemit: 0.000009 0.000010
## Iteration: 198 bestvalit: 0.000000 bestmemit: 0.000009 0.000010
## Iteration: 199 bestvalit: 0.000000 bestmemit: -0.000003 0.000010
## Iteration: 200 bestvalit: 0.000000 bestmemit: -0.000003 0.000010
Curvas de nivel de la funcion optimizada
contour(x1,x2,Z,
main = "Función de Rastrigin",
sub = "Curvas de nivel de la función")
lines(opt_ras01$member$pop,type="p",pch=2,col="red",lwd=3)
Optimizamos con algoritmos geneticos utilizando la funcion ga
# Modifiquemos la función de Rastrigin para minimizarla usando un método de maximización:
f_rastrigin2d_vec_inv <- function(x){
x1 <- x[1]
x2 <- x[2]
y <- 20+x1^2-10*cos(2*pi*x1)+x2^2-10*cos(2*pi*x2)
return(-y)
}
opt_ras03 <- ga(type="real-valued", fitness = f_rastrigin2d_vec_inv, lower=c(-5.12,-5.12), upper = c(5.12,5.12), seed=5)
Resultados de la optimizacion
## -- Genetic Algorithm -------------------
##
## GA settings:
## Type = real-valued
## Population size = 50
## Number of generations = 100
## Elitism = 2
## Crossover probability = 0.8
## Mutation probability = 0.1
## Search domain =
## x1 x2
## lower -5.12 -5.12
## upper 5.12 5.12
##
## GA results:
## Iterations = 100
## Fitness function value = -6.90978e-06
## Solution =
## x1 x2
## [1,] 0.0001823157 -3.989041e-05
Curvas de nivel
En la siguiente grafica vemos cómo el promedio, la mediana y el mejor valor de la función objetivo (el fitness) evoluciona en cada iteración repecto a la población vigente en la iteración
Optimizamos por particulas utilizando la funcion psoptim
opt_ras_pso <- psoptim(par=c(NA,NA), fn=f_rastrigin2d_vec, lower=c(-5.12,-5.12),
upper = c(5.12,5.12), control = list(trace.stats=TRUE,trace=1))
## S=12, K=3, p=0.2297, w0=0.7213, w1=0.7213, c.p=1.193, c.g=1.193
## v.max=NA, d=14.48, vectorize=FALSE, hybrid=off
## It 10: fitness=0.3372
## It 20: fitness=0.1666
## It 30: fitness=0.07882
## It 40: fitness=0.001879
## It 50: fitness=0.0002508
## It 60: fitness=3.737e-05
## It 70: fitness=6.386e-07
## It 80: fitness=1.302e-07
## It 90: fitness=2.267e-09
## It 100: fitness=1.17e-09
## It 110: fitness=2.172e-10
## It 120: fitness=4.245e-12
## It 130: fitness=2.894e-12
## It 140: fitness=2.565e-12
## It 150: fitness=1.776e-15
## It 160: fitness=1.776e-15
## It 170: fitness=0
## It 180: fitness=0
## It 190: fitness=0
## It 200: fitness=0
## It 210: fitness=0
## It 220: fitness=0
## It 230: fitness=0
## It 240: fitness=0
## It 250: fitness=0
## It 260: fitness=0
## It 270: fitness=0
## It 280: fitness=0
## It 290: fitness=0
## It 300: fitness=0
## It 310: fitness=0
## It 320: fitness=0
## It 330: fitness=0
## It 340: fitness=0
## It 350: fitness=0
## It 360: fitness=0
## It 370: fitness=0
## It 380: fitness=0
## It 390: fitness=0
## It 400: fitness=0
## It 410: fitness=0
## It 420: fitness=0
## It 430: fitness=0
## It 440: fitness=0
## It 450: fitness=0
## It 460: fitness=0
## It 470: fitness=0
## It 480: fitness=0
## It 490: fitness=0
## It 500: fitness=0
## It 510: fitness=0
## It 520: fitness=0
## It 530: fitness=0
## It 540: fitness=0
## It 550: fitness=0
## It 560: fitness=0
## It 570: fitness=0
## It 580: fitness=0
## It 590: fitness=0
## It 600: fitness=0
## It 610: fitness=0
## It 620: fitness=0
## It 630: fitness=0
## It 640: fitness=0
## It 650: fitness=0
## It 660: fitness=0
## It 670: fitness=0
## It 680: fitness=0
## It 690: fitness=0
## It 700: fitness=0
## It 710: fitness=0
## It 720: fitness=0
## It 730: fitness=0
## It 740: fitness=0
## It 750: fitness=0
## It 760: fitness=0
## It 770: fitness=0
## It 780: fitness=0
## It 790: fitness=0
## It 800: fitness=0
## It 810: fitness=0
## It 820: fitness=0
## It 830: fitness=0
## It 840: fitness=0
## It 850: fitness=0
## It 860: fitness=0
## It 870: fitness=0
## It 880: fitness=0
## It 890: fitness=0
## It 900: fitness=0
## It 910: fitness=0
## It 920: fitness=0
## It 930: fitness=0
## It 940: fitness=0
## It 950: fitness=0
## It 960: fitness=0
## It 970: fitness=0
## It 980: fitness=0
## It 990: fitness=0
## It 1000: fitness=0
## Maximal number of iterations reached
Curvas de nivel
Optimizamos por gradiente multivariado
# Calculamos la derivada parcial
partial_dev <- function(x,i,fun,h=0.01){
e <- x*0 # crea un vector de ceros de la misma longitud de x
e[i] <- h
y <- (fun(x+e)-fun(x-e))/(2*h)
return(y)
}
# Obtenemos cada una de las derivadas parciales de f en x:
num_grad <- function(x,fun,h=0.01){
# x: punto del espacio donde se debe evaluar el gradiente
# fun: función para la que se desea calcular el gradiente en x
# h: es el tamaño de ventana para el cálculo de la derivada numérica
d <- length(x)
y <- mapply(FUN=partial_dev,i=1:d,MoreArgs=list(x=x,h=h,fun=fun))
return(y)
}
Sin precondicinamiento:
# SIN PRECONDICIONAMIENTO:
#determinamos la función para evaluar el gradiente de la función Rastrigin:
deriv_grad <- function(x,fun,i=1,h=0.01){
# x: punto en el que se evalúa el gradiente
# fun: función para la cual se calcula la derivada del gradiente respecto a la íesima componente
# i: i-ésima componente del vector x con respecto a la que se deriva
e <- x*0 # crea un vector de ceros de la misma longitud de x
e[i] <- h
y <- (num_grad(x+e,fun=fun,h=h)-num_grad(x-e,fun=fun,h=h))/(2*h)
return(y)
}
# Calculamos la matriz hessiana:
matriz_hessiana <- function(x,fun,h=0.01){
# x: punto en el que se evalúa la matriz hessiana
# fun: función a la que se le calcula la matriz hessiana en x
# h: es el tamaño de ventana para el cálculo de la derivada numérica
d <- length(x)
y <- mapply(FUN=deriv_grad,i=1:d,MoreArgs=list(x=x,h=h,fun=fun),SIMPLIFY = TRUE)
return(y)
}
# Determinamos la función de optimizador multivariado
optimizador_mult_numdev <- function(x0,fun,max_eval=100,h=0.01,eta=0.01){
x <- matrix(NA,ncol =length(x0), nrow = max_eval)
x[1,] <- x0
for (i in 2:max_eval){
num_grad_fun <- num_grad(x[i-1,],fun,h)
H <- matriz_hessiana(x[i-1,],fun,h)
cambio <- - eta*solve(H)%*%num_grad_fun
x[i,] <- x[i-1,] + cambio
cambio_opt <- sqrt(sum((x[i-1,]-x[i,])^2))
if (cambio_opt<0.00001){
break
}
}
return(x[1:i,])
}
#pasamos rastrigin al optimizador iniciando desde (0.8,4.8)
sol_ras <- optimizador_mult_numdev(f_rastrigin2d_vec,x0=c(0.8,4.8),eta=1)
Curvas de nivel
contour(x1, x2, Z, las=1,
xlab = expression(x[1]), ylab = expression(x[2]),
main = "Función de Rastrigin",
sub = "Curvas de nivel de la función")
lines(sol_ras, type="b",cex=1.5,col="red")
Con preacondicionamiento:
#CON PRECONDICIONAMIENTO
#hacemos el precondicionamiento para la cantidad de dimensiones
deriv_segunda <- function(x,fun,i=1,h=0.01){
e <- x*0 # crea un vector de ceros de la misma longitud de x
e[i] <- h
y <- (fun(x+e)-2*fun(x)+fun(x-e))/(h^2)
return(y)
}
# Determinamos la función de optimizador multivariado
optimizador_mult_precond <- function(x0,fun,max_eval=100,h=0.01,eta=0.01){
x <- matrix(NA,ncol =length(x0), nrow = max_eval)
d <- length(x0)
x[1,] <- x0
for (i in 2:max_eval){
num_grad_fun <- num_grad(x[i-1,],fun,h)
diag_H <- mapply(FUN=deriv_segunda,i=1:d,MoreArgs=list(x=x[i-1,],h=h,fun=fun))
# print(diag_H)
# H <- matriz_hessiana(x[i-1,],fun,h)
# print(H)
H_precond <- diag(1/diag_H)
cambio <- - eta*H_precond%*%num_grad_fun
x[i,] <- x[i-1,] + cambio
cambio_opt <- sqrt(sum((x[i-1,]-x[i,])^2))
if (cambio_opt<0.0000001){
break
}
}
return(x[1:i,])
}
#pasamos rastrigin al optimizador iniciando desde (0.8,4.8)
sol_ras_precon <- optimizador_mult_precond(f_rastrigin2d_vec,x0=c(0.8,4.8),eta=1)
Curvas de nivel
contour(x1, x2, Z, las=1,
xlab = expression(x[1]), ylab = expression(x[2]),
main = "Función de Rastrigin",
sub = "Curvas de nivel de la función")
lines(sol_ras_precon, type="b",cex=1.5,col="red")
lines(sol_ras, type="b",cex=1.5,col="blue")
legend("topleft",col=c("red","blue"),legend = c("Con precondicionamiento","Sin precondicionamiento"),lty=1)
Función de Schwefel: \(f(x1,x2) = -∑_{i=1}^2 x_i sin(\sqrt{|xi|}), xi∈[−500,500]\), \(i=1,2\). Alcanza su valor mínimo en \(x1=420.9687\) y \(x2=420.9687\).
#determinamos la función de schwefel a utilizar para graficar:
f_schwefel2d<- function(x1,x2){
y <- (-((x1*sin(sqrt(abs(x1)))) + (x2*sin(sqrt(abs(x2)))) ))
return(y)
}
n<-50
x1 <- seq(-500,500,length.out=n)
x2 <- seq(-500,500,length.out=n)
X <- expand.grid(x1,x2)
z <- f_schwefel2d(X[,1],X[,2])
Z <- matrix(z,ncol=n,nrow=n)
Curvas de nivel de la función de Schwefel
#Curvas de nivel:
contour(x1,x2,Z)
filled.contour(x1, x2, Z, color.palette = bl2gr.colors)
#persp(x1,x2,Z,theta = 50, d=2)
#la persp3d Esta poniendo problema para graficar con colores
#persp3d(x1,x2,Z,theta = 50, phi = 20, col.palette = bl2gr.colors)
fig <- plot_ly(z = as.matrix(Z), type = "surface")
fig <- fig %>% add_surface()
fig
Definimos la funcion vectorizada
#schwefel vectorizada: para optimizar
f_schwefel2d_vec <- function(x){
x1 <- x[1]
x2 <- x[2]
y <- (-((x1*sin(sqrt(abs(x1)))) + (x2*sin(sqrt(abs(x2))))))
return(y)
}
Optimizamos la funcion con evolucion diferencial, para ello utiliamos la funcion DEoptim
# Optimizacion con evolución diferencial:
opt_schwefel_DE <- DEoptim(fn=f_schwefel2d_vec, lower=c(-500,-500), upper = c(500,500))
## Iteration: 1 bestvalit: -540.236444 bestmemit: -122.732363 423.862569
## Iteration: 2 bestvalit: -540.236444 bestmemit: -122.732363 423.862569
## Iteration: 3 bestvalit: -540.236444 bestmemit: -122.732363 423.862569
## Iteration: 4 bestvalit: -547.838472 bestmemit: -265.952057 407.877862
## Iteration: 5 bestvalit: -547.838472 bestmemit: -265.952057 407.877862
## Iteration: 6 bestvalit: -693.740293 bestmemit: -296.574524 407.877862
## Iteration: 7 bestvalit: -693.740293 bestmemit: -296.574524 407.877862
## Iteration: 8 bestvalit: -693.740293 bestmemit: -296.574524 407.877862
## Iteration: 9 bestvalit: -693.740293 bestmemit: -296.574524 407.877862
## Iteration: 10 bestvalit: -693.740293 bestmemit: -296.574524 407.877862
## Iteration: 11 bestvalit: -693.740293 bestmemit: -296.574524 407.877862
## Iteration: 12 bestvalit: -693.740293 bestmemit: -296.574524 407.877862
## Iteration: 13 bestvalit: -693.740293 bestmemit: -296.574524 407.877862
## Iteration: 14 bestvalit: -693.740293 bestmemit: -296.574524 407.877862
## Iteration: 15 bestvalit: -693.740293 bestmemit: -296.574524 407.877862
## Iteration: 16 bestvalit: -693.740293 bestmemit: -296.574524 407.877862
## Iteration: 17 bestvalit: -693.740293 bestmemit: -296.574524 407.877862
## Iteration: 18 bestvalit: -716.508367 bestmemit: -297.976772 419.166591
## Iteration: 19 bestvalit: -716.508367 bestmemit: -297.976772 419.166591
## Iteration: 20 bestvalit: -716.508367 bestmemit: -297.976772 419.166591
## Iteration: 21 bestvalit: -716.508367 bestmemit: -297.976772 419.166591
## Iteration: 22 bestvalit: -716.508367 bestmemit: -297.976772 419.166591
## Iteration: 23 bestvalit: -716.508367 bestmemit: -297.976772 419.166591
## Iteration: 24 bestvalit: -717.483880 bestmemit: -306.115224 419.166591
## Iteration: 25 bestvalit: -717.483880 bestmemit: -306.115224 419.166591
## Iteration: 26 bestvalit: -739.071132 bestmemit: 439.898208 441.825479
## Iteration: 27 bestvalit: -739.071132 bestmemit: 439.898208 441.825479
## Iteration: 28 bestvalit: -739.071132 bestmemit: 439.898208 441.825479
## Iteration: 29 bestvalit: -834.244725 bestmemit: 416.676750 424.301526
## Iteration: 30 bestvalit: -834.244725 bestmemit: 416.676750 424.301526
## Iteration: 31 bestvalit: -834.244725 bestmemit: 416.676750 424.301526
## Iteration: 32 bestvalit: -834.701454 bestmemit: 415.928518 421.708596
## Iteration: 33 bestvalit: -834.701454 bestmemit: 415.928518 421.708596
## Iteration: 34 bestvalit: -834.701454 bestmemit: 415.928518 421.708596
## Iteration: 35 bestvalit: -834.701454 bestmemit: 415.928518 421.708596
## Iteration: 36 bestvalit: -834.701454 bestmemit: 415.928518 421.708596
## Iteration: 37 bestvalit: -837.536335 bestmemit: 419.278171 421.708596
## Iteration: 38 bestvalit: -837.536335 bestmemit: 419.278171 421.708596
## Iteration: 39 bestvalit: -837.536335 bestmemit: 419.278171 421.708596
## Iteration: 40 bestvalit: -837.536335 bestmemit: 419.278171 421.708596
## Iteration: 41 bestvalit: -837.536335 bestmemit: 419.278171 421.708596
## Iteration: 42 bestvalit: -837.536335 bestmemit: 419.278171 421.708596
## Iteration: 43 bestvalit: -837.536335 bestmemit: 419.278171 421.708596
## Iteration: 44 bestvalit: -837.536335 bestmemit: 419.278171 421.708596
## Iteration: 45 bestvalit: -837.536335 bestmemit: 419.278171 421.708596
## Iteration: 46 bestvalit: -837.810263 bestmemit: 420.141012 421.708596
## Iteration: 47 bestvalit: -837.810263 bestmemit: 420.141012 421.708596
## Iteration: 48 bestvalit: -837.810263 bestmemit: 420.141012 421.708596
## Iteration: 49 bestvalit: -837.853831 bestmemit: 421.796825 421.417308
## Iteration: 50 bestvalit: -837.853831 bestmemit: 421.796825 421.417308
## Iteration: 51 bestvalit: -837.853831 bestmemit: 421.796825 421.417308
## Iteration: 52 bestvalit: -837.853831 bestmemit: 421.796825 421.417308
## Iteration: 53 bestvalit: -837.853831 bestmemit: 421.796825 421.417308
## Iteration: 54 bestvalit: -837.947710 bestmemit: 420.600300 421.054952
## Iteration: 55 bestvalit: -837.947710 bestmemit: 420.600300 421.054952
## Iteration: 56 bestvalit: -837.947710 bestmemit: 420.600300 421.054952
## Iteration: 57 bestvalit: -837.947710 bestmemit: 420.600300 421.054952
## Iteration: 58 bestvalit: -837.947710 bestmemit: 420.600300 421.054952
## Iteration: 59 bestvalit: -837.947710 bestmemit: 420.600300 421.054952
## Iteration: 60 bestvalit: -837.959880 bestmemit: 421.026584 420.760485
## Iteration: 61 bestvalit: -837.959880 bestmemit: 421.026584 420.760485
## Iteration: 62 bestvalit: -837.959880 bestmemit: 421.026584 420.760485
## Iteration: 63 bestvalit: -837.959880 bestmemit: 421.026584 420.760485
## Iteration: 64 bestvalit: -837.959880 bestmemit: 421.026584 420.760485
## Iteration: 65 bestvalit: -837.959880 bestmemit: 421.026584 420.760485
## Iteration: 66 bestvalit: -837.963153 bestmemit: 421.026584 420.836719
## Iteration: 67 bestvalit: -837.963153 bestmemit: 421.026584 420.836719
## Iteration: 68 bestvalit: -837.963153 bestmemit: 421.026584 420.836719
## Iteration: 69 bestvalit: -837.963153 bestmemit: 421.026584 420.836719
## Iteration: 70 bestvalit: -837.964551 bestmemit: 421.026584 420.889075
## Iteration: 71 bestvalit: -837.964551 bestmemit: 421.026584 420.889075
## Iteration: 72 bestvalit: -837.964551 bestmemit: 421.026584 420.889075
## Iteration: 73 bestvalit: -837.964551 bestmemit: 421.026584 420.889075
## Iteration: 74 bestvalit: -837.964551 bestmemit: 421.026584 420.889075
## Iteration: 75 bestvalit: -837.964551 bestmemit: 421.026584 420.889075
## Iteration: 76 bestvalit: -837.964551 bestmemit: 421.026584 420.889075
## Iteration: 77 bestvalit: -837.965388 bestmemit: 420.921667 420.997831
## Iteration: 78 bestvalit: -837.965388 bestmemit: 420.921667 420.997831
## Iteration: 79 bestvalit: -837.965388 bestmemit: 420.921667 420.997831
## Iteration: 80 bestvalit: -837.965388 bestmemit: 420.921667 420.997831
## Iteration: 81 bestvalit: -837.965760 bestmemit: 420.973150 420.978348
## Iteration: 82 bestvalit: -837.965760 bestmemit: 420.973150 420.978348
## Iteration: 83 bestvalit: -837.965760 bestmemit: 420.973150 420.978348
## Iteration: 84 bestvalit: -837.965760 bestmemit: 420.973150 420.978348
## Iteration: 85 bestvalit: -837.965760 bestmemit: 420.973150 420.978348
## Iteration: 86 bestvalit: -837.965760 bestmemit: 420.973150 420.978348
## Iteration: 87 bestvalit: -837.965760 bestmemit: 420.973150 420.978348
## Iteration: 88 bestvalit: -837.965760 bestmemit: 420.973150 420.978348
## Iteration: 89 bestvalit: -837.965760 bestmemit: 420.973150 420.978348
## Iteration: 90 bestvalit: -837.965760 bestmemit: 420.973150 420.978348
## Iteration: 91 bestvalit: -837.965760 bestmemit: 420.973150 420.978348
## Iteration: 92 bestvalit: -837.965771 bestmemit: 420.973150 420.971200
## Iteration: 93 bestvalit: -837.965771 bestmemit: 420.973150 420.971200
## Iteration: 94 bestvalit: -837.965771 bestmemit: 420.973150 420.971200
## Iteration: 95 bestvalit: -837.965771 bestmemit: 420.973150 420.971200
## Iteration: 96 bestvalit: -837.965771 bestmemit: 420.973150 420.971200
## Iteration: 97 bestvalit: -837.965771 bestmemit: 420.973150 420.971200
## Iteration: 98 bestvalit: -837.965771 bestmemit: 420.973150 420.971200
## Iteration: 99 bestvalit: -837.965771 bestmemit: 420.973150 420.971200
## Iteration: 100 bestvalit: -837.965771 bestmemit: 420.973150 420.971200
## Iteration: 101 bestvalit: -837.965772 bestmemit: 420.964107 420.968859
## Iteration: 102 bestvalit: -837.965772 bestmemit: 420.964107 420.968859
## Iteration: 103 bestvalit: -837.965772 bestmemit: 420.964107 420.968859
## Iteration: 104 bestvalit: -837.965772 bestmemit: 420.964107 420.968859
## Iteration: 105 bestvalit: -837.965772 bestmemit: 420.964107 420.968859
## Iteration: 106 bestvalit: -837.965772 bestmemit: 420.964107 420.968859
## Iteration: 107 bestvalit: -837.965772 bestmemit: 420.964107 420.968859
## Iteration: 108 bestvalit: -837.965773 bestmemit: 420.966911 420.965542
## Iteration: 109 bestvalit: -837.965773 bestmemit: 420.966911 420.965542
## Iteration: 110 bestvalit: -837.965773 bestmemit: 420.966911 420.965542
## Iteration: 111 bestvalit: -837.965773 bestmemit: 420.966911 420.965542
## Iteration: 112 bestvalit: -837.965773 bestmemit: 420.966911 420.965542
## Iteration: 113 bestvalit: -837.965774 bestmemit: 420.969328 420.969116
## Iteration: 114 bestvalit: -837.965774 bestmemit: 420.969328 420.969116
## Iteration: 115 bestvalit: -837.965774 bestmemit: 420.969328 420.969116
## Iteration: 116 bestvalit: -837.965774 bestmemit: 420.969328 420.969116
## Iteration: 117 bestvalit: -837.965774 bestmemit: 420.969328 420.969116
## Iteration: 118 bestvalit: -837.965774 bestmemit: 420.969328 420.969116
## Iteration: 119 bestvalit: -837.965774 bestmemit: 420.969328 420.969116
## Iteration: 120 bestvalit: -837.965774 bestmemit: 420.969328 420.969116
## Iteration: 121 bestvalit: -837.965774 bestmemit: 420.969328 420.969116
## Iteration: 122 bestvalit: -837.965774 bestmemit: 420.969328 420.969116
## Iteration: 123 bestvalit: -837.965774 bestmemit: 420.969328 420.969116
## Iteration: 124 bestvalit: -837.965774 bestmemit: 420.969328 420.969116
## Iteration: 125 bestvalit: -837.965774 bestmemit: 420.968800 420.968145
## Iteration: 126 bestvalit: -837.965774 bestmemit: 420.968800 420.968145
## Iteration: 127 bestvalit: -837.965774 bestmemit: 420.968800 420.968145
## Iteration: 128 bestvalit: -837.965774 bestmemit: 420.968800 420.968145
## Iteration: 129 bestvalit: -837.965774 bestmemit: 420.968800 420.968145
## Iteration: 130 bestvalit: -837.965775 bestmemit: 420.968800 420.968364
## Iteration: 131 bestvalit: -837.965775 bestmemit: 420.968800 420.968364
## Iteration: 132 bestvalit: -837.965775 bestmemit: 420.968921 420.968950
## Iteration: 133 bestvalit: -837.965775 bestmemit: 420.968921 420.968950
## Iteration: 134 bestvalit: -837.965775 bestmemit: 420.968704 420.968813
## Iteration: 135 bestvalit: -837.965775 bestmemit: 420.968704 420.968813
## Iteration: 136 bestvalit: -837.965775 bestmemit: 420.968722 420.968813
## Iteration: 137 bestvalit: -837.965775 bestmemit: 420.968722 420.968813
## Iteration: 138 bestvalit: -837.965775 bestmemit: 420.968722 420.968813
## Iteration: 139 bestvalit: -837.965775 bestmemit: 420.968770 420.968680
## Iteration: 140 bestvalit: -837.965775 bestmemit: 420.968713 420.968802
## Iteration: 141 bestvalit: -837.965775 bestmemit: 420.968732 420.968686
## Iteration: 142 bestvalit: -837.965775 bestmemit: 420.968722 420.968705
## Iteration: 143 bestvalit: -837.965775 bestmemit: 420.968732 420.968752
## Iteration: 144 bestvalit: -837.965775 bestmemit: 420.968732 420.968752
## Iteration: 145 bestvalit: -837.965775 bestmemit: 420.968734 420.968748
## Iteration: 146 bestvalit: -837.965775 bestmemit: 420.968734 420.968748
## Iteration: 147 bestvalit: -837.965775 bestmemit: 420.968734 420.968748
## Iteration: 148 bestvalit: -837.965775 bestmemit: 420.968734 420.968748
## Iteration: 149 bestvalit: -837.965775 bestmemit: 420.968734 420.968748
## Iteration: 150 bestvalit: -837.965775 bestmemit: 420.968734 420.968748
## Iteration: 151 bestvalit: -837.965775 bestmemit: 420.968734 420.968748
## Iteration: 152 bestvalit: -837.965775 bestmemit: 420.968750 420.968744
## Iteration: 153 bestvalit: -837.965775 bestmemit: 420.968750 420.968744
## Iteration: 154 bestvalit: -837.965775 bestmemit: 420.968750 420.968744
## Iteration: 155 bestvalit: -837.965775 bestmemit: 420.968750 420.968744
## Iteration: 156 bestvalit: -837.965775 bestmemit: 420.968746 420.968746
## Iteration: 157 bestvalit: -837.965775 bestmemit: 420.968746 420.968746
## Iteration: 158 bestvalit: -837.965775 bestmemit: 420.968746 420.968746
## Iteration: 159 bestvalit: -837.965775 bestmemit: 420.968746 420.968746
## Iteration: 160 bestvalit: -837.965775 bestmemit: 420.968746 420.968746
## Iteration: 161 bestvalit: -837.965775 bestmemit: 420.968746 420.968746
## Iteration: 162 bestvalit: -837.965775 bestmemit: 420.968746 420.968746
## Iteration: 163 bestvalit: -837.965775 bestmemit: 420.968746 420.968746
## Iteration: 164 bestvalit: -837.965775 bestmemit: 420.968745 420.968747
## Iteration: 165 bestvalit: -837.965775 bestmemit: 420.968745 420.968747
## Iteration: 166 bestvalit: -837.965775 bestmemit: 420.968746 420.968746
## Iteration: 167 bestvalit: -837.965775 bestmemit: 420.968746 420.968746
## Iteration: 168 bestvalit: -837.965775 bestmemit: 420.968746 420.968746
## Iteration: 169 bestvalit: -837.965775 bestmemit: 420.968746 420.968746
## Iteration: 170 bestvalit: -837.965775 bestmemit: 420.968746 420.968746
## Iteration: 171 bestvalit: -837.965775 bestmemit: 420.968746 420.968746
## Iteration: 172 bestvalit: -837.965775 bestmemit: 420.968746 420.968746
## Iteration: 173 bestvalit: -837.965775 bestmemit: 420.968746 420.968746
## Iteration: 174 bestvalit: -837.965775 bestmemit: 420.968746 420.968746
## Iteration: 175 bestvalit: -837.965775 bestmemit: 420.968746 420.968746
## Iteration: 176 bestvalit: -837.965775 bestmemit: 420.968746 420.968746
## Iteration: 177 bestvalit: -837.965775 bestmemit: 420.968746 420.968746
## Iteration: 178 bestvalit: -837.965775 bestmemit: 420.968746 420.968746
## Iteration: 179 bestvalit: -837.965775 bestmemit: 420.968746 420.968746
## Iteration: 180 bestvalit: -837.965775 bestmemit: 420.968746 420.968746
## Iteration: 181 bestvalit: -837.965775 bestmemit: 420.968746 420.968746
## Iteration: 182 bestvalit: -837.965775 bestmemit: 420.968746 420.968746
## Iteration: 183 bestvalit: -837.965775 bestmemit: 420.968746 420.968746
## Iteration: 184 bestvalit: -837.965775 bestmemit: 420.968746 420.968746
## Iteration: 185 bestvalit: -837.965775 bestmemit: 420.968746 420.968746
## Iteration: 186 bestvalit: -837.965775 bestmemit: 420.968746 420.968746
## Iteration: 187 bestvalit: -837.965775 bestmemit: 420.968746 420.968746
## Iteration: 188 bestvalit: -837.965775 bestmemit: 420.968746 420.968746
## Iteration: 189 bestvalit: -837.965775 bestmemit: 420.968746 420.968746
## Iteration: 190 bestvalit: -837.965775 bestmemit: 420.968746 420.968746
## Iteration: 191 bestvalit: -837.965775 bestmemit: 420.968746 420.968746
## Iteration: 192 bestvalit: -837.965775 bestmemit: 420.968746 420.968746
## Iteration: 193 bestvalit: -837.965775 bestmemit: 420.968747 420.968746
## Iteration: 194 bestvalit: -837.965775 bestmemit: 420.968747 420.968746
## Iteration: 195 bestvalit: -837.965775 bestmemit: 420.968747 420.968746
## Iteration: 196 bestvalit: -837.965775 bestmemit: 420.968747 420.968746
## Iteration: 197 bestvalit: -837.965775 bestmemit: 420.968747 420.968746
## Iteration: 198 bestvalit: -837.965775 bestmemit: 420.968747 420.968746
## Iteration: 199 bestvalit: -837.965775 bestmemit: 420.968747 420.968746
## Iteration: 200 bestvalit: -837.965775 bestmemit: 420.968747 420.968746
Curvas de nivel de la funcion optimizada
contour(x1,x2,Z,
main = "Función de Schwefel",
sub = "Curvas de nivel de la función")
lines(opt_schwefel_DE$member$pop,type="p",pch=2,col="red",lwd=3)
Optimizamos con algoritmos geneticos utilizando la funcion ga
#Modificamos la función de Schwefel para minimizarla usando un método de maximización:
f_schwefel2d_vec_inv <- function(x){
x1 <- x[1]
x2 <- x[2]
y <- (-((x1*sin(sqrt(abs(x1)))) + (x2*sin(sqrt(abs(x2)))) ))
return(-y)
}
opt_schwefel_GA <- ga(type="real-valued", fitness = f_schwefel2d_vec_inv, lower=c(-500,-500), upper = c(500,500), seed=5)
Resultados de la optimizacion
## -- Genetic Algorithm -------------------
##
## GA settings:
## Type = real-valued
## Population size = 50
## Number of generations = 100
## Elitism = 2
## Crossover probability = 0.8
## Mutation probability = 0.1
## Search domain =
## x1 x2
## lower -500 -500
## upper 500 500
##
## GA results:
## Iterations = 100
## Fitness function value = 837.9658
## Solution =
## x1 x2
## [1,] 420.9662 420.9706
Curvas de nivel
En la siguiente grafica vemos cómo el promedio, la mediana y el mejor valor de la función objetivo (el fitness) evoluciona en cada iteración repecto a la población vigente en la iteración
Optimizamos por particulas utilizando la funcion psoptim
opt_schwefel_pso <- psoptim(par=c(NA,NA), fn=f_schwefel2d_vec, lower=c(-500,-500),
upper = c(500,500), control = list(trace.stats=TRUE,trace=1))
## S=12, K=3, p=0.2297, w0=0.7213, w1=0.7213, c.p=1.193, c.g=1.193
## v.max=NA, d=1414, vectorize=FALSE, hybrid=off
## It 10: fitness=-717.4
## It 20: fitness=-831.2
## It 30: fitness=-832.9
## It 40: fitness=-837.9
## It 50: fitness=-837.9
## It 60: fitness=-838
## It 70: fitness=-838
## It 80: fitness=-838
## It 90: fitness=-838
## It 100: fitness=-838
## It 110: fitness=-838
## It 120: fitness=-838
## It 130: fitness=-838
## It 140: fitness=-838
## It 150: fitness=-838
## It 160: fitness=-838
## It 170: fitness=-838
## It 180: fitness=-838
## It 190: fitness=-838
## It 200: fitness=-838
## It 210: fitness=-838
## It 220: fitness=-838
## It 230: fitness=-838
## It 240: fitness=-838
## It 250: fitness=-838
## It 260: fitness=-838
## It 270: fitness=-838
## It 280: fitness=-838
## It 290: fitness=-838
## It 300: fitness=-838
## It 310: fitness=-838
## It 320: fitness=-838
## It 330: fitness=-838
## It 340: fitness=-838
## It 350: fitness=-838
## It 360: fitness=-838
## It 370: fitness=-838
## It 380: fitness=-838
## It 390: fitness=-838
## It 400: fitness=-838
## It 410: fitness=-838
## It 420: fitness=-838
## It 430: fitness=-838
## It 440: fitness=-838
## It 450: fitness=-838
## It 460: fitness=-838
## It 470: fitness=-838
## It 480: fitness=-838
## It 490: fitness=-838
## It 500: fitness=-838
## It 510: fitness=-838
## It 520: fitness=-838
## It 530: fitness=-838
## It 540: fitness=-838
## It 550: fitness=-838
## It 560: fitness=-838
## It 570: fitness=-838
## It 580: fitness=-838
## It 590: fitness=-838
## It 600: fitness=-838
## It 610: fitness=-838
## It 620: fitness=-838
## It 630: fitness=-838
## It 640: fitness=-838
## It 650: fitness=-838
## It 660: fitness=-838
## It 670: fitness=-838
## It 680: fitness=-838
## It 690: fitness=-838
## It 700: fitness=-838
## It 710: fitness=-838
## It 720: fitness=-838
## It 730: fitness=-838
## It 740: fitness=-838
## It 750: fitness=-838
## It 760: fitness=-838
## It 770: fitness=-838
## It 780: fitness=-838
## It 790: fitness=-838
## It 800: fitness=-838
## It 810: fitness=-838
## It 820: fitness=-838
## It 830: fitness=-838
## It 840: fitness=-838
## It 850: fitness=-838
## It 860: fitness=-838
## It 870: fitness=-838
## It 880: fitness=-838
## It 890: fitness=-838
## It 900: fitness=-838
## It 910: fitness=-838
## It 920: fitness=-838
## It 930: fitness=-838
## It 940: fitness=-838
## It 950: fitness=-838
## It 960: fitness=-838
## It 970: fitness=-838
## It 980: fitness=-838
## It 990: fitness=-838
## It 1000: fitness=-838
## Maximal number of iterations reached
Curvas de nivel
Optimizamos por gradiente multivariado
# Calculamos la derivada parcial
partial_dev <- function(x,i,fun,h=0.01){
e <- x*0 # crea un vector de ceros de la misma longitud de x
e[i] <- h
y <- (fun(x+e)-fun(x-e))/(2*h)
return(y)
}
# Obtenemos cada una de las derivadas parciales de f en x:
num_grad <- function(x,fun,h=0.01){
# x: punto del espacio donde se debe evaluar el gradiente
# fun: función para la que se desea calcular el gradiente en x
# h: es el tamaño de ventana para el cálculo de la derivada numérica
d <- length(x)
y <- mapply(FUN=partial_dev,i=1:d,MoreArgs=list(x=x,h=h,fun=fun))
return(y)
}
Sin precondicinamiento:
#pasamos schwefel al optimizador SIN precondicionamiento iniciando desde (380,390)
sol_schwefel <- optimizador_mult_numdev(f_schwefel2d_vec,x0=c(380,390),eta=1)
Curvas de nivel
contour(x1, x2, Z, las=1,
xlab = expression(x[1]), ylab = expression(x[2]),
main = "Función de Schwefel",
sub = "Curvas de nivel de la función")
lines(sol_schwefel, type="b",cex=1.5,col="red")
Con preacondicionamiento:
#pasamos schwefel al optimizador CON precondicionamiento iniciando desde (380,390)
sol_schwefel_precon <- optimizador_mult_precond(f_schwefel2d_vec,x0=c(380,390),eta=1)
Curvas de nivel
contour(x1, x2, Z, las=1,
xlab = expression(x[1]), ylab = expression(x[2]),
main = "Función de Schwefel",
sub = "Curvas de nivel de la función")
lines(sol_schwefel_precon, type="b",cex=1.5,col="red")
lines(sol_schwefel, type="b",cex=1.5,col="blue")
legend("topleft",col=c("red","blue"),legend = c("Con precondicionamiento","Sin precondicionamiento"),lty=1)
Para llevar acabo el desarrollo del problema del vendedor viajero primero tuvimos que crear la matriz de costos a partir de otras matrices. Obtuvimos la matriz “costos entre trayectos-peajes”, “kilometros entre ciudades” y “tiempo estimado entre ciudades en minutos”, como dos de estas matrices no estaban expresadas en terminos de costos, se multiplicaron por constantes como el sueldo por hora del vendedor, el precio de la gasolina por galon y el rendimiento de vehiculo, en este caso un Renault Sandero .
Dando como resultado la siguiente matriz de costos:
## Palmira Pasto Tulua Bogota Pereira Armenia Manizales
## Palmira 0.000 196.499 44.473 258.408 106.416 94.910 149.840
## Pasto 196.499 0.000 233.708 414.567 293.912 282.930 336.818
## Tulua 44.473 233.708 0.000 245.483 64.197 52.137 106.927
## Bogota 258.408 414.567 245.483 0.000 195.466 167.024 168.387
## Pereira 106.416 293.912 64.197 195.466 0.000 33.090 44.289
## Armenia 94.910 282.930 52.137 167.024 33.090 0.000 79.480
## Manizales 149.840 336.818 106.927 168.387 44.289 79.480 0.000
## Valledupar 518.590 682.718 489.496 385.731 415.293 509.128 371.515
## Monteria 469.152 637.597 425.718 445.872 365.858 408.135 360.014
## Soledad 574.551 737.117 542.333 465.389 503.189 550.466 460.435
## Cartagena 580.668 731.259 491.298 483.495 512.687 544.064 482.770
## Barranquilla 588.808 747.033 556.069 485.501 515.069 520.210 463.024
## Medellin 243.888 434.859 201.495 223.823 152.024 183.404 135.454
## Bucaramanga 365.393 519.523 315.651 203.123 266.435 295.972 234.164
## Cucuta 469.132 624.127 427.434 308.838 381.352 410.210 338.092
## Valledupar Monteria Soledad Cartagena Barranquilla Medellin
## Palmira 518.590 469.152 574.551 580.668 588.808 243.888
## Pasto 682.718 637.597 737.117 731.259 747.033 434.859
## Tulua 489.496 425.718 542.333 491.298 556.069 201.495
## Bogota 385.731 445.872 465.389 483.495 485.501 223.823
## Pereira 415.293 365.858 503.189 512.687 515.069 152.024
## Armenia 509.128 408.135 550.466 544.064 520.210 183.404
## Manizales 371.515 360.014 460.435 482.770 463.024 135.454
## Valledupar 0.000 187.064 147.764 168.130 158.049 336.842
## Monteria 187.064 0.000 179.849 132.809 197.873 232.714
## Soledad 147.764 179.849 0.000 63.256 7.589 371.428
## Cartagena 168.130 132.809 63.256 0.000 72.780 350.760
## Barranquilla 158.049 197.873 7.589 72.780 0.000 387.881
## Medellin 336.842 232.714 371.428 350.760 387.881 0.000
## Bucaramanga 198.263 296.811 279.477 299.325 288.032 196.201
## Cucuta 220.555 312.853 300.563 327.173 315.707 303.415
## Bucaramanga Cucuta
## Palmira 365.393 469.132
## Pasto 519.523 624.127
## Tulua 315.651 427.434
## Bogota 203.123 308.838
## Pereira 266.435 381.352
## Armenia 295.972 410.210
## Manizales 234.164 338.092
## Valledupar 198.263 220.555
## Monteria 296.811 312.853
## Soledad 279.477 300.563
## Cartagena 299.325 327.173
## Barranquilla 288.032 315.707
## Medellin 196.201 303.415
## Bucaramanga 0.000 106.675
## Cucuta 106.675 0.000
Luego de obtener esta matriz procedemos a resolver el problema utilizando los dos metodos solicitados.
A continuacion presentamos el codigo utilizado para resolver el problema del vendedor viajero utilizando algoritmos geneticos, ademas incluye directamente el guardado de la grafica de cada resultado y genera un gif utilizando todas las graficas.
## Importamos las librerias que vamos a usar
library(GA)
library(tidyverse)
library(animation)
library(ggrepel)
# Creamos la matrix de coordenadas para las graficas
ciudades <- c("Palmira", "Pasto", "Tuluá", "Bogota", "Pereira", "Armenia", "Manizales", "Valledupar", "Montería", "Soledad",
"Cartagena", "Barranquilla", "Medellín", "Bucaramanga", "Cúcuta")
coordenadas <- data.frame( long = c(-76.30361, -77.28111, -76.19536, -74.08175, -75.69611, -75.68111, -75.51738, -73.25322, -75.88143, -74.76459,
-75.51444, -74.78132, -75.56359, -73.1198, -72.50782),
lat= c(3.53944, 1.21361, 4.08466, 4.60971, 4.81333, 4.53389, 5.06889, 10.46314, 8.74798, 10.91843,
10.39972, 10.96854, 6.25184, 7.12539, 7.89391),
stringsAsFactors = F)
# Leemos la matrix de costos
D <- read.csv("costos_ciudades2.csv", sep = ";", row.name = 1)
#Funcion para calcular la longitud del tour
tourLength <- function(tour, distMatrix) {
tour <- c(tour, tour[1])
route <- embed(tour, 2)[,2:1]
sum(distMatrix[route])
}
#Fitness function to be maximized
tspFitness <- function(tour, ...) 1/tourLength(tour, ...)
# Iteracciones maximas
Maxter <- c(25, 50, 75, 100, 200, 400, 600, 800, 1000, 1200)
# Ciudades
x <- coordenadas[,1]
y <- coordenadas[,2]
# Utilizamos la funcion saveGIF para crear el gif durante la iteraccion de la funcion de
# GA, es decir, durante cada entranamiento guardamos cada resultado en forma de grafica
# y por ultimos entregamos el GIF.
saveGIF(
# For para cambiar el numero maximo de iteraciones en la funcion GA
for (i in 1:length(Maxter)) {
set.seed(124)
GAiter <- ga(type = "permutation", fitness = tspFitness, distMatrix = D,
lower = 1, upper = 15, popSize = 50, maxiter = Maxter[i],
run = 500, pmutation = 0.2)
tour <- GAiter@solution[1, ]
tour <- c(tour, tour[1])
n <- length(tour)
## Grafica
map <- ggplot() +
borders("world", "colombia") +
geom_point(data = coordenadas,
aes(x = long,
y = lat), colour = c(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15))
map_vectors <- map +
ggtitle(paste( paste("Max. numero de iteraciones:", Maxter[i]), paste(" - Iteracciones realizadas: ", GAiter@iter))) +
theme(plot.title = element_text(hjust = 0.5)) +
geom_segment(aes(x = x[tour[-n]], y = y[tour[-n]], xend = x[tour[-1]], yend = y[tour[-1]]),
arrow = arrow(length = unit(0.25, "cm")), col = "steelblue", lwd= 0.6) +
geom_text_repel(aes(x, y, label = ciudades),
size = 3.5)
plot(map_vectors)
# Guardamos las imagenes para el GIF
ggsave(map_vectors, filename = gsub(" ", "", paste("Ga_", i,".png")), width = 5.78 , height = 4.66)
}
, movie.name = "TSP_GA.gif")
A continuacion podremos obervar la primer grafica obtenida con el algoritmo genetico.
En esta grafica observamos que la ruta que siguio el algoritmo fue la siguiente:
## PGA PCitys
## 1 11 Cartagena
## 2 10 Soledad
## 3 9 Montería
## 4 5 Pereira
## 5 6 Armenia
## 6 3 Tuluá
## 7 1 Palmira
## 8 2 Pasto
## 9 7 Manizales
## 10 4 Bogota
## 11 13 Medellín
## 12 14 Bucaramanga
## 13 8 Valledupar
## 14 15 Cúcuta
## 15 12 Barranquilla
Dando como resultado un costo de:
## [1] 2667694
La siguiente es la ultima grafica donde podremos detallar que a pesar de tener un maximo de 1200 iteracion el algoritmo encontro la mejor ruta en tan solo 1044 iteraciones.
En esta grafica observamos que la ruta que siguio el algoritmo fue la siguiente:
## BGA Citys
## 1 11 Cartagena
## 2 9 Montería
## 3 13 Medellín
## 4 7 Manizales
## 5 5 Pereira
## 6 6 Armenia
## 7 3 Tuluá
## 8 1 Palmira
## 9 2 Pasto
## 10 4 Bogota
## 11 14 Bucaramanga
## 12 15 Cúcuta
## 13 8 Valledupar
## 14 10 Soledad
## 15 12 Barranquilla
Dando como resultado un costo de:
## [1] 2044516
Por ultimo, presentamos el gif en el cual observaremos las variaciones que el algoritmo presenta cuando varian el numero maximo de iteracciones posibles.
Para este punto se llevo a acabo el desarrollo de la solucion en Python dado que para este lenguaje se presentaban una mayor cantidad de librerias disponibles, haciendo mas simple la implementacion del algoritmo y solucion del problema.
#Repo: https://github.com/johnberroa/Ant-Colony-Optimization
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import time
import warnings
from pandas.core.frame import DataFrame
warnings.filterwarnings("ignore")
class AntColonyOptimizer:
def __init__(self, ants, evaporation_rate, intensification, alpha=1.0, beta=0.0, beta_evaporation_rate=0,
choose_best=.1):
"""
Ant colony optimizer. Traverses a graph and finds either the max or min distance between nodes.
:param ants: number of ants to traverse the graph
:param evaporation_rate: rate at which pheromone evaporates
:param intensification: constant added to the best path
:param alpha: weighting of pheromone
:param beta: weighting of heuristic (1/distance)
:param beta_evaporation_rate: rate at which beta decays (optional)
:param choose_best: probability to choose the best route
"""
# Parameters
self.ants = ants
self.evaporation_rate = evaporation_rate
self.pheromone_intensification = intensification
self.heuristic_alpha = alpha
self.heuristic_beta = beta
self.beta_evaporation_rate = beta_evaporation_rate
self.choose_best = choose_best
# Internal representations
self.pheromone_matrix = None
self.heuristic_matrix = None
self.probability_matrix = None
self.map = None
self.set_of_available_nodes = None
# Internal stats
self.best_series = []
self.best = None
self.fitted = False
self.best_path = None
self.fit_time = None
# Plotting values
self.stopped_early = False
def __str__(self):
string = "Ant Colony Optimizer"
string += "\n--------------------"
string += "\nDesigned to optimize either the minimum or maximum distance between nodes in a square matrix that behaves like a distance matrix."
string += "\n--------------------"
string += "\nNumber of ants:\t\t\t\t{}".format(self.ants)
string += "\nEvaporation rate:\t\t\t{}".format(self.evaporation_rate)
string += "\nIntensification factor:\t\t{}".format(self.pheromone_intensification)
string += "\nAlpha Heuristic:\t\t\t{}".format(self.heuristic_alpha)
string += "\nBeta Heuristic:\t\t\t\t{}".format(self.heuristic_beta)
string += "\nBeta Evaporation Rate:\t\t{}".format(self.beta_evaporation_rate)
string += "\nChoose Best Percentage:\t\t{}".format(self.choose_best)
string += "\n--------------------"
string += "\nUSAGE:"
string += "\nNumber of ants influences how many paths are explored each iteration."
string += "\nThe alpha and beta heuristics affect how much influence the pheromones or the distance heuristic weigh an ants' decisions."
string += "\nBeta evaporation reduces the influence of the heuristic over time."
string += "\nChoose best is a percentage of how often an ant will choose the best route over probabilistically choosing a route based on pheromones."
string += "\n--------------------"
if self.fitted:
string += "\n\nThis optimizer has been fitted."
else:
string += "\n\nThis optimizer has NOT been fitted."
return string
def _initialize(self):
"""
Initializes the model by creating the various matrices and generating the list of available nodes
"""
assert self.map.shape[0] == self.map.shape[1], "Map is not a distance matrix!"
num_nodes = self.map.shape[0]
self.pheromone_matrix = np.ones((num_nodes, num_nodes))
# Remove the diagonal since there is no pheromone from node i to itself
self.pheromone_matrix[np.eye(num_nodes) == 1] = 0
self.heuristic_matrix = 1 / self.map
self.probability_matrix = (self.pheromone_matrix ** self.heuristic_alpha) * (
self.heuristic_matrix ** self.heuristic_beta) # element by element multiplcation
self.set_of_available_nodes = list(range(num_nodes))
def _reinstate_nodes(self):
"""
Resets available nodes to all nodes for the next iteration
"""
self.set_of_available_nodes = list(range(self.map.shape[0]))
def _update_probabilities(self):
"""
After evaporation and intensification, the probability matrix needs to be updated. This function
does that.
"""
self.probability_matrix = (self.pheromone_matrix ** self.heuristic_alpha) * (
self.heuristic_matrix ** self.heuristic_beta)
def _choose_next_node(self, from_node):
"""
Chooses the next node based on probabilities. If p < p_choose_best, then the best path is chosen, otherwise
it is selected from a probability distribution weighted by the pheromone.
:param from_node: the node the ant is coming from
:return: index of the node the ant is going to
"""
numerator = self.probability_matrix[from_node, self.set_of_available_nodes]
if np.random.random() < self.choose_best:
next_node = np.argmax(numerator)
else:
denominator = np.sum(numerator)
probabilities = numerator / denominator
next_node = np.random.choice(range(len(probabilities)), p=probabilities)
return next_node
def _remove_node(self, node):
self.set_of_available_nodes.remove(node)
def _evaluate(self, paths, mode):
"""
Evaluates the solutions of the ants by adding up the distances between nodes.
:param paths: solutions from the ants
:param mode: max or min
:return: x and y coordinates of the best path as a tuple, the best path, and the best score
"""
scores = np.zeros(len(paths))
coordinates_i = []
coordinates_j = []
for index, path in enumerate(paths):
score = 0
coords_i = []
coords_j = []
for i in range(len(path) - 1):
coords_i.append(path[i])
coords_j.append(path[i + 1])
score += self.map[path[i], path[i + 1]]
scores[index] = score
coordinates_i.append(coords_i)
coordinates_j.append(coords_j)
if mode == 'min':
best = np.argmin(scores)
elif mode == 'max':
best = np.argmax(scores)
return (coordinates_i[best], coordinates_j[best]), paths[best], scores[best]
def _evaporation(self):
"""
Evaporate some pheromone as the inverse of the evaporation rate. Also evaporates beta if desired.
"""
self.pheromone_matrix *= (1 - self.evaporation_rate)
self.heuristic_beta *= (1 - self.beta_evaporation_rate)
def _intensify(self, best_coords):
"""
Increases the pheromone by some scalar for the best route.
:param best_coords: x and y (i and j) coordinates of the best route
"""
i = best_coords[0]
j = best_coords[1]
self.pheromone_matrix[i, j] += self.pheromone_intensification
def fit(self, map_matrix, iterations=100, mode='min', early_stopping_count=20, verbose=True):
"""
Fits the ACO to a specific map. This was designed with the Traveling Salesman problem in mind.
:param map_matrix: Distance matrix or some other matrix with similar properties
:param iterations: number of iterations
:param mode: whether to get the minimum path or maximum path
:param early_stopping_count: how many iterations of the same score to make the algorithm stop early
:return: the best score
"""
if verbose: print("Beginning ACO Optimization with {} iterations...".format(iterations))
self.map = map_matrix
start = time.time()
self._initialize()
num_equal = 0
for i in range(iterations):
start_iter = time.time()
paths = []
path = []
for ant in range(self.ants):
current_node = self.set_of_available_nodes[np.random.randint(0, len(self.set_of_available_nodes))]
start_node = current_node
while True:
path.append(current_node)
self._remove_node(current_node)
if len(self.set_of_available_nodes) != 0:
current_node_index = self._choose_next_node(current_node)
current_node = self.set_of_available_nodes[current_node_index]
else:
break
path.append(start_node) # go back to start
self._reinstate_nodes()
paths.append(path)
path = []
best_path_coords, best_path, best_score = self._evaluate(paths, mode)
if i == 0:
best_score_so_far = best_score
else:
if mode == 'min':
if best_score < best_score_so_far:
best_score_so_far = best_score
self.best_path = best_path
elif mode == 'max':
if best_score > best_score_so_far:
best_score_so_far = best_score
self.best_path = best_path
if best_score == best_score_so_far:
num_equal += 1
else:
num_equal = 0
self.best_series.append(best_score)
self._evaporation()
self._intensify(best_path_coords)
self._update_probabilities()
if verbose: print("Best score at iteration {}: {}; overall: {} ({}s)"
"".format(i, round(best_score, 2), round(best_score_so_far, 2),
round(time.time() - start_iter)))
if best_score == best_score_so_far and num_equal == early_stopping_count:
self.stopped_early = True
print("Stopping early due to {} iterations of the same score.".format(early_stopping_count))
break
self.fit_time = round(time.time() - start)
self.fitted = True
if mode == 'min':
self.best = self.best_series[np.argmin(self.best_series)]
if verbose: print(
"ACO fitted. Runtime: {} minutes. Best score: {}".format(self.fit_time // 60, self.best))
return self.best
elif mode == 'max':
self.best = self.best_series[np.argmax(self.best_series)]
if verbose: print(
"ACO fitted. Runtime: {} minutes. Best score: {}".format(self.fit_time // 60, self.best))
return self.best
else:
raise ValueError("Invalid mode! Choose 'min' or 'max'.")
def plot(self):
"""
Plots the score over time after the model has been fitted.
:return: None if the model isn't fitted yet
"""
if not self.fitted:
print("Ant Colony Optimizer not fitted! There exists nothing to plot.")
return None
else:
fig, ax = plt.subplots(figsize=(20, 15))
ax.plot(self.best_series, label="Best Run")
ax.set_xlabel("Iteration")
ax.set_ylabel("Performance")
ax.text(.8, .6,
'Ants: {}\nEvap Rate: {}\nIntensify: {}\nAlpha: {}\nBeta: {}\nBeta Evap: {}\nChoose Best: {}\n\nFit Time: {}m{}'.format(
self.ants, self.evaporation_rate, self.pheromone_intensification, self.heuristic_alpha,
self.heuristic_beta, self.beta_evaporation_rate, self.choose_best, self.fit_time // 60,
["\nStopped Early!" if self.stopped_early else ""][0]),
bbox={'facecolor': 'gray', 'alpha': 0.8, 'pad': 10}, transform=ax.transAxes)
ax.legend()
plt.title("Ant Colony Optimization Results (best: {})".format(np.round(self.best, 2)))
plt.show()
#-------------------------------------------------------------------------------------------------------------
# Read the cost matrix
data = pd.read_csv('/home/joan/Escritorio/Ant_Colony_TSP/costos_ciudades.csv', sep=";", index_col=0)
# Change the dataframe to an array
data_matrix = data.to_numpy()
## CHANGE ANTS
# Create a dataframe to save iterations results
#best_pa = DataFrame(columns = ['Ants1','Ants15', 'Ants30', 'Ants45', 'Ants60', 'Ants75', 'Ants90','Ants105', 'Ants120', 'Ants135'])
# # Ants array
# Ants = [1, 15, 30, 45, 60, 75, 90, 105, 120, 135]
# for n in range(10):
# # Create the Antiptimizer using differents parameteres
# optimizer = AntColonyOptimizer(ants=Ants[n], evaporation_rate=.1, intensification=2, alpha=1, beta=1,
# beta_evaporation_rate=0, choose_best=.1)
# # Traing the model and save tha best result
# optimizer.fit(data_matrix, 100, early_stopping_count = 20)
# # Save the values in a dataframe
# best_pa[best_pa.columns[n]] = optimizer.best_path
## CHANGE ITERATIONS
# Create a dataframe to save iterations results
#best_pa = DataFrame(columns = ['iter5','iter10', 'iter15', 'iter20', 'iter25', 'iter30', 'iter35', 'iter40', 'iter45', 'iter50'])
best_pa = DataFrame(columns = ['iter4','iter6', 'iter8', 'iter10', 'iter12', 'iter14', 'iter16', 'iter18', 'iter20', 'iter22'])
# Ants array
#Iter = [5, 10, 15, 20, 25, 30, 35, 40, 45, 50]
Iter = [4, 6, 8, 10, 12, 14, 16, 18, 20, 22]
for n in range(10):
# Create the Antiptimizer using differents parameteres
optimizer = AntColonyOptimizer(ants=100, evaporation_rate=.1, intensification=2, alpha=1, beta=1,
beta_evaporation_rate=0, choose_best=.1)
# Traing the model and save tha best result
optimizer.fit(data_matrix, Iter[n])
# Save the values in a dataframe
best_pa[best_pa.columns[n]] = optimizer.best_path
## SAVE RESULTS
# Show the best tour in terminal
print("\nTours table results: \n")
print(best_pa)
# saving the dataframe in a csv
print("\n Saving results in tours_results.csv")
best_pa.to_csv('/home/joan/Escritorio/Ant_Colony_TSP/tours_results.csv')
Para graficar y obtener el gif utilizamos el mismo codigo implementado con en algoritmos geneticos, solo que esta vez iteramos sobre el archivo de salida que genera el codigo en python.
## Usango colonia de hormigas
## Importamos las librerias que vamos a usar
#library(GA)
#library(tidyverse)
#library(animation)
#library(ggrepel)
# Creamos la matrix de coordenadas
#ciudades <- c("Palmira", "Pasto", "Tuluá", "Bogota", "Pereira", "Armenia", "Manizales", "Valledupar", "Montería", "Soledad",
# "Cartagena", "Barranquilla", "Medellín", "Bucaramanga", "Cúcuta")
#coordenadas <- data.frame( long = c(-76.30361, -77.28111, -76.19536, -74.08175, -75.69611, -75.68111, -75.51738, -73.25322, -75.88143, -74.76459,
# -75.51444, -74.78132, -75.56359, -73.1198, -72.50782),
# lat= c(3.53944, 1.21361, 4.08466, 4.60971, 4.81333, 4.53389, 5.06889, 10.46314, 8.74798, 10.91843,
# 10.39972, 10.96854, 6.25184, 7.12539, 7.89391),
# stringsAsFactors = F)
# Leemos el archivo resultante luego de ejecutar el metodo de colonia de
# hormigas en python
Resultado_Ant <- read.csv("tours_results.csv", sep = ",", row.name = 1)
iter <- c(4,6,8,10,12,14,16,18,20,22)
# Ciudades
#x <- coordenadas[,1]
#y <- coordenadas[,2]
saveGIF(
# For para cambiar los datos que vamos a graficar
for (i in c(1,2,3,4,5,6,7,8,9,10)) {
tour <- as.matrix(Resultado_Ant[i])
tour <- tour + 1
n <- length(tour)
## Grafica
map <- ggplot() +
borders("world", "colombia") +
geom_point(data = coordenadas,
aes(x = long,
y = lat), colour = c(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15))
map_vectors <- map +
ggtitle(paste( paste("Numero de iteraciones:", iter[i]), "Hormigas: 100")) +
theme(plot.title = element_text(hjust = 0.5)) +
geom_segment(aes(x = x[tour[-n]], y = y[tour[-n]], xend = x[tour[-1]], yend = y[tour[-1]]),
arrow = arrow(length = unit(0.25, "cm")), col = "steelblue", lwd= 0.6) +
geom_text_repel(aes(x, y, label = ciudades),
size = 3.5)
plot(map_vectors)
# Guardamos las imagenes para el GIF
ggsave(map_vectors, filename = gsub(" ", "", paste("Ants_", i,".png")), width = 5.78 , height = 4.66)
}
, movie.name = "TSP_ANTS.gif")
A continuacion podremos obervar la primer grafica obtenida con el algoritmo de colonia de hormigas
En esta grafica observamos que la ruta que siguio el algoritmo fue la siguiente:
## PAN PCitys
## 1 1 Palmira
## 2 3 Tuluá
## 3 6 Armenia
## 4 5 Pereira
## 5 7 Manizales
## 6 13 Medellín
## 7 4 Bogota
## 8 14 Bucaramanga
## 9 15 Cúcuta
## 10 10 Soledad
## 11 12 Barranquilla
## 12 11 Cartagena
## 13 8 Valledupar
## 14 9 Montería
## 15 2 Pasto
Dando como resultado un costo de:
## [1] 2413283
La siguiente es la ultima grafica donde podremos observar un parecido con la ultima grafica del algoritmo genetico.
En esta grafica observamos que la ruta que siguio el algoritmo fue la siguiente:
## BAN Citys
## 1 12 Barranquilla
## 2 10 Soledad
## 3 8 Valledupar
## 4 15 Cúcuta
## 5 14 Bucaramanga
## 6 4 Bogota
## 7 2 Pasto
## 8 1 Palmira
## 9 3 Tuluá
## 10 6 Armenia
## 11 5 Pereira
## 12 7 Manizales
## 13 13 Medellín
## 14 9 Montería
## 15 11 Cartagena
Dando como resultado un costo de:
## [1] 2044516
Por ultimo, presentamos el gif en el cual observaremos las variaciones que el algoritmo presenta cuando varian el numero maximo de iteracciones posibles.
Para concluir se puede observar que tanto en Algoritmos Geneticos como en Colonia de Hormigas el mejor costo obtenido para el problema del viajero vendedor fue de $2’044.516 pesos ademas que el recorrido de las ciudades es el mismo , lo que demuestra que ambos algoritmos convergen en la misma solucion y que son muy efectivos para la resolucion de este tipo de problemas.