使用nloptr优化平衡不平衡矩阵时遇参数传递错误求助
问题分析与解决方案
错误原因
- 优化变量格式不匹配:
nloptr要求初始值x0、上下界lb/ub必须是一维向量,你传入了矩阵,导致参数解析错误。 - 函数参数顺序错误:
nloptr的目标函数、约束函数第一个参数必须是待优化的变量(向量),后续才是额外参数。你把额外参数(u/uu)放在了第一个位置,导致参数传递时匹配失败,触发'u' passed to (...) but not required错误。 - 初始值未定义:
x0 = u中的u从未定义,应该使用初始矩阵的向量形式。 - 约束逻辑错误:原约束函数写反了目标值与优化值的位置,无法实现行列和匹配的需求。
修正后的代码
library(nloptr) # 基准矩阵(目标行列和来源) U <- matrix(c(3,5,4,6), ncol = 2, nrow = 2) # 待优化的初始矩阵 Uu <- matrix(c(3,5,4,5), ncol = 2, nrow = 2) # 目标函数:第一个参数为优化变量(向量),后续为额外参数 obj_function <- function(x, U, Uu) { # 将向量转回矩阵 x_mat <- matrix(x, nrow = nrow(U)) # 计算KL散度(确保矩阵元素非0,若有0值需额外处理) sum(Uu * log(Uu / x_mat)) } # 等式约束函数:第一个参数为优化变量(向量),后续为额外参数 eq_constr <- function(x, U) { x_mat <- matrix(x, nrow = nrow(U)) # 约束:优化后矩阵的行/列和与U的行/列和相等 c(rowSums(x_mat) - rowSums(U), colSums(x_mat) - colSums(U)) } # 优化选项:增加迭代次数与收敛精度,适配大矩阵场景 opts <- list("algorithm" = "NLOPT_GN_ISRES", "maxeval" = 10000, "xtol_rel" = 1e-6) # 转换为一维向量:适配nloptr的输入要求 x0 <- as.vector(Uu) lb <- as.vector(matrix(0, ncol = 2, nrow = 2)) ub <- as.vector(matrix(1000, ncol = 2, nrow = 2)) # 调用nloptr:额外参数按函数定义顺序传递 res <- nloptr( x0 = x0, lb = lb, ub = ub, eval_f = obj_function, eval_g_eq = eq_constr, opts = opts, U = U, Uu = Uu ) # 输出结果 print(res) # 将优化结果转回矩阵 optimized_mat <- matrix(res$solution, nrow = nrow(U)) print("优化后的矩阵:") print(optimized_mat) print("优化后矩阵的行列和:") print("行和:") print(rowSums(optimized_mat)) print("列和:") print(colSums(optimized_mat))
关键修正点
- 参数顺序调整:目标函数与约束函数的第一个参数改为
x(优化变量向量),后续传入U/Uu等固定参数,匹配nloptr的参数传递规则。 - 向量-矩阵转换:所有输入参数(
x0、lb、ub)转成一维向量,在函数内部再转回矩阵进行行列和计算。 - 约束逻辑修正:约束函数返回优化后矩阵与目标矩阵
U的行列和差值,确保等式约束为0(即行列和完全匹配)。 - 优化参数增强:添加
maxeval(最大迭代次数)和xtol_rel(相对收敛精度),提升60x60大矩阵场景下的收敛稳定性。
内容的提问来源于stack exchange,提问作者arnyeinstein
相关产品推荐
相关产品推荐

