2

我正在尝试优化 Excel 中的三个参数,以尽量减少实验值和理论值之间的误差。我在 for 循环中对每个参数使用 Solver,一次一个。但是,我想迭代这个求解器循环(循环内循环),直到实验值和理论值的误差小于某个目标值。

我的实验值为$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
4

2 回答 2

1

我不确定您是否需要在 VBA 中执行此操作,因为您正在寻找的正是 Solver 应该做的 - 修改一组参数,以便最大化/最小化其他东西!

因此,您需要做的就是将公式插入=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
于 2013-02-20T20:09:58.227 回答
1

您可以仔细检查代码中的那一行:

Engine:= 1, EngineDesc:="GRG Nonlinear"

根据MS 文档

  • 1 对于单纯形 LP 方法,
  • 2 对于 GRG 非线性方法,或
  • 3 进化方法。

可能,您的目标函数是非线性的,并且您认为您正在使用 GRG 非线性求解器,因为您在EngineDesc参数下提到了它。这是不正确的。这只是一个描述参数。

您实际使用的求解器是Simplex LP,其值为1

更改为2以使用GRG 非线性求解器

于 2015-09-28T10:05:35.700 回答