如何在JuMP循环中收集NLexpression?场景化存储k8与k9的技术求助
解决JuMP循环中收集NLexpression结果的问题
我明白你想在循环结束后保留每个场景(i=1到N)对应的k8和k9值,而不是把它们全部累加起来。当前代码里Q=Q+k8+k9只是在做数值累加,既没办法区分不同场景的结果,还因为k8/k9是JuMP的NLexpression对象,直接这样操作本身就会出问题。
下面是调整后的完整解决方案:
步骤1:初始化结果存储容器
我们可以用一个类型明确的数组来保存每个场景的(k8, k9)对,这样后续访问和处理结果会更清晰:
Q = Tuple{Float64, Float64}[] # 存储每个场景的(k8数值, k9数值)元组
步骤2:补全求解逻辑并收集结果
你当前的代码遗漏了最关键的模型求解步骤,必须调用optimize!(ALT)才能让JuMP计算出变量和表达式的具体值。之后我们用value()函数提取k8和k9的数值,再存入数组中。
调整后的完整代码:
using JuMP, CPUTime, Distributions, Ipopt, Juniper, Cplex n1=1; #the least of scenarios N=4; #number of scenarios M=20; #number of sampling landa=0.01; E=0.05 T0=0; T1=2; T2=2; gam2=1; gam1=1; a1=0.5; a2=0.1; a3=50; ap=25; c0=10; Zn=zeros(N, 4) Q = Tuple{Float64, Float64}[] # 初始化结果存储数组 for i in n1:N C1=rand(100:100:300); sig=rand(0.5:0.5:2); f(x) = cdf(Normal(0, 1), x); #--------------------------------------------------------------------------- ALT= Model(optimizer_with_attributes(Juniper.Optimizer, "nl_solver"=>optimizer_with_attributes(Ipopt.Optimizer, "print_level" => 0), "mip_solver"=>optimizer_with_attributes(Cplex.Optimizer, "logLevel" => 0), "registered_functions" =>[Juniper.register( :f, 1, f; autodiff = true)] )); # variables----------------------------------------------------------------- JuMP.register(ALT, :f, 1, f; autodiff = true); @variable(ALT, h >= 0.001); @variable(ALT, L >= 0.000001); @variable(ALT, n>=2, Int); #--------------------------------------------------------------------------- @NLexpression(ALT,k1,h/(1-f(L-sig*sqrt(n))+f(-L - sig*sqrt(n)))); # HARL1 @NLexpression(ALT,k2,(1-(1+landa*h)*exp(-landa*h))/(landa*(1-exp(-landa*h)))); #to @NLexpression(ALT,k3,E*n+T1*gam1+T2*gam2); @NLexpression(ALT,k8,(C1*(k1-k2+k3)));# depend on scenario @NLexpression(ALT,k9,(((a1+a2*n)/h)*(k1)));#depend on scenario # 关键:求解当前场景的模型 optimize!(ALT) # 检查求解状态(可选但推荐,避免异常) if termination_status(ALT) == MOI.OPTIMAL # 提取数值并添加到结果集合中 push!(Q, (value(k8), value(k9))) else @warn "场景$i 求解失败,状态:$(termination_status(ALT))" push!(Q, (NaN, NaN)) # 用NaN标记求解失败的场景 end #----------------------------------------------------------------------- end # 查看最终结果 println("每个场景的(k8,k9)集合:") for (idx, (k8_val, k9_val)) in enumerate(Q) println("场景$idx: k8=$k8_val, k9=$k9_val") end
关键细节说明
- 容器类型:
Tuple{Float64, Float64}[]明确了数组存储的是浮点型元组,比空数组更规范,后续使用时也能避免类型错误。 - 求解模型:
optimize!(ALT)是必须的,JuMP不会自动计算变量和表达式的值,只有调用求解函数后,value()才能返回有效结果。 - 数值提取:
value(k8)会把JuMP的NLexpression对象转换成具体的浮点数值,这样才能存入数组中供后续使用。 - 异常处理:添加求解状态检查,能避免因模型无解或求解出错导致程序崩溃,同时用NaN标记异常场景,方便后续排查问题。
循环结束后,Q就是一个包含所有场景(k8,k9)结果的集合,你可以通过索引访问单个场景的结果,比如Q[2]就能获取场景2的k8和k9值。
内容的提问来源于stack exchange,提问作者Soma
相关产品推荐
相关产品推荐

