为什么在GenSA中提供初始参数总是给出相同的结果而不管种子?

时间:2018-01-12 13:28:07

标签: r simulated-annealing

我似乎不明白,当提供参数par时,GenSA使用的模拟退火算法总是会到达同一解决方案:

library(GenSA)

Rastrigin <- function(x) {
  sum(x^2 - 10 * cos(2 * pi  * x)) + 10 * length(x)
}

niter <- 10
sol <- data.frame(with.par = NaN*seq(niter))
sol$without.par <- NaN
for(i in seq(niter)){
  fit1 <- GenSA(
    par = c(1,1),
    fn = Rastrigin, 
    lower = c(-5.12, -5.12), 
    upper = c(5.12, 5.12)
  )
  fit2 <- GenSA(
    fn = Rastrigin, 
    lower = c(-5.12, -5.12), 
    upper = c(5.12, 5.12)
  )
  sol$with.par[i] <- min(as.data.frame(fit1$trace.mat)$function.value)
  sol$without.par[i] <- min(as.data.frame(fit2$trace.mat)$function.value)
}
sol

导致:

       with.par  without.par
1  2.209873e-09 2.142819e-09
2  2.209873e-09 2.209873e-09
3  2.209873e-09 2.142819e-09
4  2.209873e-09 2.209873e-09
5  2.209873e-09 2.142819e-09
6  2.209873e-09 2.209873e-09
7  2.209873e-09 2.209873e-09
8  2.209873e-09 2.209873e-09
9  2.209873e-09 2.209870e-09
10 2.209873e-09 2.209873e-09

即使par = NULL,也有很高的收敛度。无论哪种方式,这不会违背SA中随机搜索的想法吗?

2 个答案:

答案 0 :(得分:1)

在挖掘source code of GenSA之后,我意识到你是对的。如果设置par,您将始终获得相同的结果。 R的种子仅用于以下行here

     else {
        if (con$verbose) {
            cat("Initializing par with random data inside bounds\n")
        }
        par <- vector()
#initialize par with random values in the bounds
            par <- lower + runif(length(lower))*(upper-lower)
    }

在将其传递给C ++引擎之前生成随机初始点(如果未指定)。因此,如果您自己设置par,GenSA将始终返回相同的结果,因为C ++引擎是从R单独播种的。

这并不意味着它不使用随机搜索,检查收敛是如何发生的:

enter image description here

随机搜索,但如果明确设置par,则会使用相同的种子,因此每次都会获得相同的结果。

library(GenSA)
library(ggplot2)
library(data.table)

Rastrigin <- function(x) {
  sum(x^2 - 10 * cos(2 * pi  * x)) + 10 * length(x)
}

fit1 <- GenSA(
    par = c(1,1),
    fn = Rastrigin, 
    lower = c(-5.12, -5.12), 
    upper = c(5.12, 5.12)
  )
fit2 <- GenSA(
    fn = Rastrigin, 
    lower = c(-5.12, -5.12), 
    upper = c(5.12, 5.12)
  )

res = data.table(fit1$trace.mat)[,.SD[1,], .(nb.steps)]
res2 = data.table(fit2$trace.mat)[,.SD[1,], .(nb.steps)]
p = ggplot() +
          geom_line(data = res[1:250,], aes( x=nb.steps, y=function.value, colour = "par")) +
          geom_line(data = res2[1:250,], aes( x=nb.steps, y=function.value, colour = "no-par")) 

print(p)  

如果多次运行此代码,蓝线每次都会完全相同,而红线会改变。

答案 1 :(得分:1)

该软件包已更新至1.1.7版,包括&#34;种子&#34; GenSA函数的控制列表参数中的选项,用于为内部随机生成器设定种子。 最好的问候,

西尔。