R使用ROI求解g40/g60最优解时函数参数校验报错如何解决?
问题描述
你需要求解g40和g60的最优解,满足change=0.01的约束条件,运行代码时报错:Error in .check_function_for_sanity(F, n) : cannot evaluate function 'F' using 'n' = 2 parameters
代码错误排查
- 包装函数定义错误:当前wrapper仅接收1个参数,但
F_objective指定参数数量n=2(对应g40、g60两个待优化变量),二者不匹配触发报错。 - 原始基尼系数未定义:FG函数中计算
change用到的Gini是原始分布的基尼系数,未提前计算赋值,运行时会出现对象未找到错误。 - 约束定义逻辑错误:约束中直接调用的
sum(L_prime)、change是FG函数内部的临时变量,不能直接作为约束参数传入,需要基于输入的待优化参数动态计算。 - 全局data被重复修改:FG函数每次运行都会给原始data新增L_prime列,多次调用后列数累加,取第3列计算分位点的逻辑会失效,应避免修改全局data,改用临时变量存储L_prime。
- 目标函数不明确:当前FG函数返回的是change值,但change已被设为约束条件,你需要明确目标函数需要最小化/最大化的指标。
修正后的代码示例
# 提前计算原始基尼系数(和Gini_prime计算逻辑一致) Lp0.2_raw = data[which(abs(data$p-0.2)==min(abs(data$p-0.2))), 2] Lp0.4_raw = data[which(abs(data$p-0.4)==min(abs(data$p-0.4))), 2] Lp0.6_raw = data[which(abs(data$p-0.6)==min(abs(data$p-0.6))), 2] Lp0.8_raw = data[which(abs(data$p-0.8)==min(abs(data$p-0.8))), 2] Gini = 2*(125/288)*(1/5)*(3*(0.2-Lp0.2_raw)+2*(0.4-Lp0.4_raw)+2*(0.6-Lp0.6_raw)+3*(0.8-Lp0.8_raw)) #weights p40=which(abs(data$p-0.4)==min(abs(data$p-0.4))) w40=data[p40,2] w60=1-w40 #Non-cumulative L L_non=data$L[1] for(i in 2:nrow(data)) L_non[i]=data$L[i]-data$L[i-1] #X x1=sum(data$p*L_non)/sum(L_non) x2=sum(data$p[1:p40]*L_non[1:p40])/sum(L_non[1:p40]) # 定义核心计算函数,返回目标值、两个约束值 calc_vals = function(g40, g60) { #Gammas and m gama=g40*w40+g60*w60 gama40=g40 m=gama40-gama #theta & delta theta=-m/(x2-x1) delta=gama+theta*x1 #L_prime 不修改全局data L_prime=(1+delta-theta*data$p)*L_non #Gini approximated from the new distribution Lp0.2 = L_prime[which(abs(data$p-0.2)==min(abs(data$p-0.2)))] Lp0.4 = L_prime[which(abs(data$p-0.4)==min(abs(data$p-0.4)))] Lp0.6 = L_prime[which(abs(data$p-0.6)==min(abs(data$p-0.6)))] Lp0.8 = L_prime[which(abs(data$p-0.8)==min(abs(data$p-0.8)))] Gini_prime=2*(125/288)*(1/5)*(3*(0.2-Lp0.2)+2*(0.4-Lp0.4)+2*(0.6-Lp0.6)+3*(0.8-Lp0.8)) #change change=(Gini_prime/Gini)-1 # 示例目标:最小化g40和g60的平方和,可替换为自身实际优化目标 obj = g40^2 + g60^2 return(list(obj=obj, cons1=sum(L_prime), cons2=change)) } # 包装函数:适配ROI参数要求,输入长度为2的向量 wrapper_obj <- function(x) { vals = calc_vals(x[1], x[2]) return(vals$obj) } # 约束函数1:sum(L_prime) = 1 wrapper_cons1 <- function(x) { vals = calc_vals(x[1], x[2]) return(vals$cons1) } # 约束函数2:change = 0.01 wrapper_cons2 <- function(x) { vals = calc_vals(x[1], x[2]) return(vals$cons2) } #OP problem library(ROI) library(ROI.plugin.nloptr) prob<-OP( objective = F_objective(F = wrapper_obj, n = 2), constraints = F_constraint(F = wrapper_cons1, dir = "==", rhs = 1) + F_constraint(F = wrapper_cons2, dir = "==", rhs = 0.01) ) solve_res = ROI_solve(prob, solver = "nloptr.cobyla", start = c(0,0)) H = solution(solve_res)
内容的提问来源于stack exchange,提问作者Jinane Jouni
相关产品推荐
相关产品推荐

