我试图在Excel中优化三个参数,以最大限度地减少实验值和理论值之间的误差。在for循环中,我对每个参数都使用"解算器",每次一个。然而,我想迭代这个循环求解器(循环中的循环),直到实验值和理论值的误差小于某个目标值。
我的实验值是$K25
我的理论值(根据我的模型方程计算)是$J$25
我需要优化的参数是$C$4
、$C$5
、$C$6
当我运行以下VBA代码时,我在$C$4
、$C$5
和$C$6
中的参数不会从初始值更改。但是,宏编译良好,没有任何错误。有人能帮我吗?
这是代码:
Sub Macro3()
Application.ScreenUpdating = False
SolverReset
Dim j As Integer
For j = 1 To 100 Step 1
If "$J$25" > "$K$25" Then
Dim i As Integer, s As String
For i = 4 To 6 Step 1
s = Format(i, "0")
SolverOk SetCell:="$J$25", MaxMinVal:=2, ValueOf:=0, ByChange:="$C$" & s, Engine:= _
1, EngineDesc:="GRG Nonlinear"
SolverOptions MaxTime:=0, Iterations:=1000000, Precision:=0.000001, Convergence _
:=0.00001, StepThru:=False, Scaling:=True, AssumeNonNeg:=True, Derivatives:=1
SolverOptions PopulationSize:=100, RandomSeed:=0, MutationRate:=0.075, Multistart _
:=False, RequireBounds:=True, MaxSubproblems:=0, MaxIntegerSols:=0, _
IntTolerance:=1, SolveWithout:=False, MaxTimeNoImp:=30
SolverOk SetCell:="$J$25", MaxMinVal:=2, ValueOf:=0, ByChange:="$C$" & s, Engine:= _
1, EngineDesc:="GRG Nonlinear"
SolverSolve (True)
SolverReset
Next i
End If
Next j
Application.ScreenUpdating = True
End Sub
我真的不确定你是否需要在VBA中执行此操作,因为你所寻找的正是解算器应该做的事情-修改一组参数,使其他内容最大化/最小化!
因此,您所需要做的就是在另一个单元格中插入公式=ABS(J25-K25)
。此单元格将显示实验值和理论值之间的差值。现在设置你的解算器,通过改变你的三个参数来最小化这个单元,你就完成了!(请注意,您可以在"通过更改可变单元格"字段中提供多个单元格!)
如果你想坚持你的方法,这里有语法正确的代码。请注意,我还没有测试过它,只是通过查看代码来纠正我可能发现的错误。希望这将是一个良好的起点。事实上,看看这种方法,我相信你最终会得到错误的结果,因为每次运行只优化一个变量,因此你永远不会研究两个或三个参数组合产生的任何影响!
不管怎样,这是你的代码:
Sub RunSolver()
Dim j As Integer, i As Integer
Application.ScreenUpdating = False
SolverReset
For j = 1 To 100
Application.Statusbar = j & "/100"
If Range("$J$25") > Range("$K$25") Then
For i = 4 To 6
SolverOk SetCell:=Range("$J$25"), MaxMinVal:=2, ValueOf:=0, ByChange:=Range("$C$" & i), Engine:= _
1, EngineDesc:="GRG Nonlinear"
SolverOptions MaxTime:=0, Iterations:=1000000, Precision:=0.000001, Convergence _
:=0.00001, StepThru:=False, Scaling:=True, AssumeNonNeg:=True, Derivatives:=1
SolverOptions PopulationSize:=100, RandomSeed:=0, MutationRate:=0.075, Multistart _
:=False, RequireBounds:=True, MaxSubproblems:=0, MaxIntegerSols:=0, _
IntTolerance:=1, SolveWithout:=False, MaxTimeNoImp:=30
SolverSolve (True)
SolverReset
Next i
End If
Next j
Application.StatusBar = False
Application.ScreenUpdating = True
End Sub
您可以仔细检查代码中写着:
Engine:= 1, EngineDesc:="GRG Nonlinear"
根据MS文件:
- 对于单纯形LP方法为1
- 2用于GRG非线性方法,或
- 3表示进化方法
可能,您的目标函数是非线性,并且您认为您正在使用GRG非线性解算器,因为您在EngineDesc参数下提到了它。这是不正确的。这只是一个描述参数。
实际使用的解算器是Simplex LP,其值为1。
更改为2以使用GRG非线性解算器。