我的问题陈述说:
编写一个函数以对输入函数执行模拟退火,在下面的函数规范中我们描述了输入。它应该输出niter + 1行的历史记录(记录x0,并记录下一个x_k是否移动)以及最终向量。
我所做的是:
SA <- function(func,x0,S,M, niter) {
# f0 -- function of x to be minimized
# x0 -- initial guess for x
# s -- vector of standard deviations giving step sizes
# to take, should be of the same dimension as x.
# M -- Cooling temperature schedule constant.
# niter - number of steps to take
x_b <- x_c <- x_n <- x0
f_b <- f_c <- f_n <- func(x_n)
message("It\tBest\tCurrent\tNeigh\tTemp")
message(sprintf("%i\t%.4f\t%.4f\t%.4f\t%.4f", 0L, f_b, f_c, f_n, 1))
for (k in 1:niter) {
M <- (1 - S)^k
# consider a random neighbor
x_n <- rnorm(2, x_c, 1)
f_n <- func(x_n)
# update current state
if (f_n < f_c || runif(1, 0, 1) < exp(-(f_n - f_c) / M)) {
x_c <- x_n
f_c <- f_n
}
# update best state
if (f_n < f_b) {
x_b <- x_n
f_b <- f_n
}
message(sprintf("4f\niter%.4f\f_b%", f_b, niter))
}
return(list(Sol = f_b, iterhist = niter))
}
现在这应该适用于以下情况:
testfunc = function(x){ return( -cos( x[1] + x[2] + x[3] ) + sum(abs(x)) ) }
set.seed(1)
all.equal(SA(testfunc,rep(0.5,3),c(0.3,0.5,1),0.8,1)$sol,c(0.3120639,0.5918217,-0.3356286),tol=1e-7)
set.seed(2)
all( SA(testfunc,rep(0.5,3),c(0.3,0.5,1),0.8,1)$sol == 0.5 )
set.seed(2)
all.equal( SA(testfunc,rep(0.5,3),c(0.3,0.5,1),0.08,1)$sol,c(0.2309256 ,0.5924246 ,2.0878453),tol=1e-7)
Bu给出错误:
Error in if (f_n < f_c || runif(1, 0, 1) < exp(-(f_n - f_c)/M)) { :
missing value where TRUE/FALSE needed
代码有什么问题?
答案 0 :(得分:0)
您的问题是
testfunc = function(x){ return( -cos( x[1] + x[2] + x[3] ) + sum(abs(x)) ) }
当NA_real_
不(至少)没有三个元素时,将返回x
,并且在SA()
中您可以看到这些行
x_n <- rnorm(2, x_c, 1)
f_n <- func(x_n)
将x_n
创建为长度为2的向量,并将其提供给func()
。
请考虑以下内容:
set.seed(1)
testfunc = function(x){ return( -cos( x[1] + x[2] + x[3] ) + sum(abs(x)) ) }
x_c <- rep(0.5,3)
x_n <- rnorm(2, x_c, 1)
x_n
# [1] -0.1264538 0.6836433
testfunc(x_n)
# [1] NA
sum(abs(x_n))
# [1] 0.8100971
-cos( x_n[1] + x_n[2] + x_n[3] )
# [1] NA
-cos(sum(x_n))
# [1] -0.8487447