在R中的模拟退火算法中添加约束

时间:2019-06-09 15:10:51

标签: r optimization simulated-annealing

我有一个用于模拟退火算法的脚本,并且想要将搜索限制为超级立方体。

simulated_annealing <- function(func, s0, niter = 1, epsilon = 0.01) {
#   ##s=state, f=funcion, b=best, c=current, n=neighbour

  s_b <- s_c <- s_n <- s0
   f_b <- f_c <- f_n <- func(s_n)

   for (k in 1:niter) {     
     Temperatura <- (1 - epsilon)^k 
     s_n <- rnorm(2, s_c, 1)
     f_n <- func(s_n)
     if (f_n < f_c || runif(1, 0, 1) < exp(-(f_n - f_c) / Temperatura)) {
       s_c <- s_n
       f_c <- f_n
     }
     if (f_n < f_b) {
       s_b <- s_n
       f_b <- f_n         
     }
   return(list(iteraciones = niter, Mejor_valor = f_b, Mejor_estado = s_b))
 }}

您可以这样使用它:

sol <- simulated_annealing(rastr, niter = 100, epsilon = 0.91, s0 = c(0, 2))

我想在搜索空间中添加限制,以便它仅在超立方体x_i = [-5.12,5.12]中移动,但我不知道如何开始。我尝试使用while,但是它停止了该功能。

请和谢谢

1 个答案:

答案 0 :(得分:0)

我设法找到了一个解决方案,尽管有点不爽。完成的脚本如下:

      simulated_annealing <- function(func, s0, niter = 1000, epsilon = 0.1) {
x_upper = 5.12
x_lower = -5.12
  # Inicializamos
  ## s simboliza estado
  ## f simboliza valor de la funcion
  ## b simboliza el mejor obtenido hasta ahora
  ## c simboliza el presente
  ## n simboliza vecino
  s_b <- s_c <- s_n <- s0
  f_b <- f_c <- f_n <- func(s_n)
  message("Iteracion\tMejor\tActual\tVecino\tTemperatura")
  message(sprintf("%i\t%.4f\t%.4f\t%.4f\t%.4f", 0L, f_b, f_c, f_n, 1000))

  for (k in 1:niter) {
    Temperatura <- (1 - epsilon)^k #Exponencial
    # Contemplamos un vecino aleatorio
    s_n <- rnorm(2, s_c, 1)
    f_n <- func(s_n)
while (f_n > x_upper | f_n < x_lower) {
  s_c <- s_c[! s_c %in% c(s_n)] ##THIS IS THE ADDED LINE
  s_n <- rnorm(2, s_c, 1)
  f_n <- func(s_n)
}
#     # Actualizamos el estado actual
    if (f_n < f_c || runif(1, 0, 1) < exp(-(f_n - f_c) / Temperatura)) {
      s_c <- s_n
      f_c <- f_n
    }
#     # Actualizamos el estado al mejor conseguido
    if (f_n < f_b) {
      s_b <- s_n
      f_b <- f_n
    }
    if (k %% 1000==0) {
    message(sprintf("%i\t%.4f\t%.4f\t%.4f\t%.4f", k, f_b, f_c, f_n, Temperatura))}
  }
  return(list(iteraciones = niter, Mejor_valor = f_b, Mejor_estado = s_b))
}