Добавление ограничений в алгоритм имитации отжига в R - PullRequest
0 голосов
/ 09 июня 2019

У меня есть скрипт для алгоритма имитации отжига, и я хочу ограничить поиск, в данном случае гиперкубом.

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], но я не знаю, с чего начать.Я пытался использовать время, но это остановило функцию.

Пожалуйста и спасибо

1 Ответ

0 голосов
/ 09 июня 2019

Мне удалось найти решение, хотя и не крутое. Готовый скрипт выглядит следующим образом:

      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))
}
...