我正在寻找具有非线性约束的非线性函数的良好(不一定是最好的)解决方案。我已经搜索了最合适的方法,我认为nlopt是GN_ISRES算法的最佳选择。
函数是在以下约束条件下最小化两组点之间的距离
- 所有点必须为整数
- 点的坐标必须是偶数或奇数
- 没有一个点可以与另一个 相同
下面是我的可复制示例代码,我的主要问题是,即使从一个坏的解决方案开始,当达到maxeval时,存储的解决方案仍然是开始的解决方案,而不是迭代的最佳解决方案。
为什么会出现这种情况,是否有一种方法可以使它返回到目前为止的最佳解决方案?
library(nloptr)
coords = data.frame(
name = c(1,2,3,4,5),
lat = c(45,46,48,42,36),
lon = c(1,3,2,5,4)
)
hexbin_coords = data.frame(
name = c(1,2,3,4,5),
x = c(1,2,3,4,5),
y = c(41,42,43,44,45)
)
eval_f <- function(z, lat, lon) {
y = z[((length(z)/2)+1):length(z)]
x = z[1:(length(z)/2)]
distance = sum(sqrt((x - lat)^2 + (y - lon)^2))
return(distance)
}
## constraints
eval_g <- function(z, lat, lon) {
y = z[((length(z)/2)+1):length(z)]
x = z[1:(length(z)/2)]
sum1 = sum((x - y) %% 2)
sum2 = sum(z %% 1)
#sum2 = 0
sum3 = any(duplicated(apply(data.frame(x,rep("a",length(x)),y), 1, paste, collapse="")))
return(sum1 + sum2 + sum3)
}
opts <- list( "algorithm"= "NLOPT_GN_ISRES",
"xtol_rel"= 1.0e-7,
"maxeval"= 10,
"print_level" = 3)
sol <- nloptr(x0 = c(hexbin_coords$x, hexbin_coords$y),
eval_f = eval_f,
eval_g_eq = eval_g,
lb = rep(0,10),
ub = rep(50,10),
opts = opts,
lat = coords$lat,
lon = coords$lon
)
print(sol)
不幸的是,nloptr
不直接提供此功能,因此唯一的选择是通过print_level=3
获取值的输出:
library(stringr) # For string matching and extracting
sol.output <- capture.output(sol <- nloptr(x0 = c(hexbin_coords$x, hexbin_coords$y),
eval_f = eval_f,
eval_g_eq = eval_g,
lb = rep(0,10),
ub = rep(50,10),
opts = opts,
lat = coords$lat,
lon = coords$lon)) # capture the "print" output to a variable
sol.hist <- sol.output[grepl("tx",sol.output)] #get all lines starting with a tab and x (Those are the lines with the variables)
sol.hist <- sapply(stringr::str_extract_all(sol.hist,"[0-9]+\.[0-9]+"),as.numeric) # Extract all numbers and convert to numeric
rownames(sol.hist) <- paste0("Iteration_",seq_len(nrow(sol.hist))) #set some descriptive names
colnames(sol.hist) <- paste0("Variable_",seq_len(ncol(sol.hist)))
sol.hist
Iteration_1 Iteration_2 Iteration_3 Iteration_4 Iteration_5 Iteration_6 Iteration_7 Iteration_8
Variable_1 1 41.870830 12.911006 2.279217 2.857534 24.370609 21.847667 11.074417
Variable_2 2 28.649218 20.234235 9.663595 37.479727 7.707112 17.469032 48.587274
Variable_3 3 28.547109 48.541501 29.354267 24.670474 16.181966 4.559475 21.171942
Variable_4 4 4.529856 0.221904 15.666075 13.072797 24.905793 39.300537 29.968914
Variable_5 5 13.938569 25.595069 43.422727 15.680567 27.393603 8.527784 47.716471
Variable_6 41 17.493988 31.714159 16.504085 48.342804 34.445824 32.355841 2.347884
Variable_7 42 20.647009 42.209615 23.079238 22.102841 7.842979 27.584622 7.954957
Variable_8 43 33.884236 24.857512 4.001447 39.029162 39.050927 38.151746 19.158068
Variable_9 44 39.405297 4.173269 48.558713 48.976114 48.358011 30.155023 6.904914
Variable_10 45 20.769793 29.435024 0.124530 21.440616 24.843518 28.395304 6.854763
使用这种方法,您不仅可以获得"最好的";价值是所有价值的完整历史。因此,您还可以绘制优化图形等