You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在R语言模拟退火算法中添加超立方体搜索空间约束?

解决模拟退火算法搜索空间限制的问题

首先得先指出你原函数里的一个致命错误:你的return语句放在了for循环的内部,这会导致函数在第一次迭代后就直接返回结果,后面的99次迭代根本不会执行!这是必须先修正的问题。

接下来回到你要限制搜索空间在超立方体x_i ∈ [-5.12, 5.12]的需求,你之前用while循环导致停滞,大概率是因为没有设置退出条件——如果一直生成超出范围的邻居点,while会无限循环下去。下面给你两种可靠的解决方案:

方案1:截断法(简单高效,无停滞风险)

这种方法是生成邻居后,直接把每个维度的值截断到指定范围内,超出上界的设为上界,低于下界的设为下界。优点是不会有循环停滞的问题,计算效率也很高。

修正后的完整函数代码:

simulated_annealing <- function(func, s0, niter = 1, epsilon = 0.01) { 
  # s=state, f=function, 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) 
    # 截断到[-5.12, 5.12]范围
    s_n <- pmax(pmin(s_n, 5.12), -5.12)
    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移到循环外面!
  return(list(iteraciones = niter, Mejor_valor = f_b, Mejor_estado = s_b)) 
}

方案2:带兜底的拒绝采样法(严格生成范围内点)

如果你希望邻居点严格在搜索空间内,不想用截断,可以用拒绝采样,但必须设置最大尝试次数,避免无限循环。当尝试次数超过阈值时,用截断法兜底:

simulated_annealing <- function(func, s0, niter = 1, epsilon = 0.01) { 
  s_b <- s_c <- s_n <- s0 
  f_b <- f_c <- f_n <- func(s_n) 
  max_tries <- 100 # 设置最大尝试次数
  
  for (k in 1:niter) { 
    Temperatura <- (1 - epsilon)^k 
    try_count <- 0
    # 生成符合范围的邻居
    repeat {
      s_n <- rnorm(2, s_c, 1) 
      # 检查是否在范围内
      if (all(s_n >= -5.12) && all(s_n <= 5.12)) {
        break
      }
      try_count <- try_count + 1
      # 超过尝试次数,用截断法兜底
      if (try_count >= max_tries) {
        s_n <- pmax(pmin(s_n, 5.12), -5.12)
        break
      }
    }
    
    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)) 
}

测试调用

假设你的rastr是Rastrigin函数(常用的测试函数),可以这样测试:

# 定义Rastrigin函数
rastr <- function(x) {
  20 + x[1]^2 + x[2]^2 - 10*(cos(2*pi*x[1]) + cos(2*pi*x[2]))
}

# 调用函数
sol <- simulated_annealing(rastr, niter = 100, epsilon = 0.91, s0 = c(0, 2))
print(sol)

这样修改后,既解决了原函数迭代不完整的问题,又完美限制了搜索空间,不会出现停滞的情况。

内容的提问来源于stack exchange,提问作者user9264168

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 08:03:23