2013-02-20 53 views
2

我想在Excel中優化三個參數以最小化實驗值和理論值之間的誤差。我使用Solver爲每個參數,每次一個,在for循環中。然而,我想迭代這個求解器for循環(循環內的循環),直到實驗值中的誤差和理論值小於某個目標值。VBA在Excel中使用求解器的宏優化不返回最佳變量

我的實驗值是$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 

回答

1

我真的不知道你需要做到這一點的VBA,因爲你要找的東西正是求解器應該做的事情 - 修改一組參數,使其他東西最大化/最小化!

因此,您只需在另一個單元格中插入公式=ABS(J25-K25)。該單元格將顯示您的實驗值與理論值之間的差值。現在設置你的Solver,通過改變你的三個參數來最小化這個單元 - 你就完成了! (請注意,您可以在「通過更改可變單元格」字段中提供多個單元格!)

如果您想堅持使用您的方法,請使用語法正確的代碼。請注意,我沒有對它進行測試 - 但只是通過查看代碼來糾正我可以發現的錯誤。它有望成爲一個很好的起點。事實上,看着這種方法,我相信你最終會得到錯誤的結果,因爲每次運行只會優化一個變量 - 因此,您將永遠不會看到由兩個或三個參數組合產生的任何影響!

總之,這裏是你的代碼:

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 
+0

謝謝!你的建議是正確的。我正在計算我的理論方程與我的實驗結果的總差異的絕對值。然後我優化我的參數以最小化這種差異。 $ K $ 25是我的目標差異,$ J $ 25是我目前的差額,基於$ C $ 4,$ C $ 5,$ C $ 6中的參數。所以是的,正如你所建議的,我可以簡單地解算器一次優化所有三個參數,我就完成了。但是,我最終希望在更復雜的方程中優化10個參數而不是3個參數。多個參數的組合將會非常棘手! – user2092724 2013-02-20 20:28:27

+0

很確定Solver也可以處理10個參數,並獲得更好的結果,然後一個宏將每個參數錯誤地假設爲其他參數! – 2013-02-20 20:30:58

+0

您建議的代碼有效。我只是測試它。但是,如果將$ K $ 25(目標差異)設置爲Solver收斂Excel所保留的值以下,並且不會得到任何結果。不知道你是否知道防止這種情況發生的快速方法? – user2092724 2013-02-20 20:38:27

1

你可以仔細檢查該行代碼的,上面寫着:

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

根據MS documentation

  • 1爲單工LP方法,
  • 2對於GRG非線性方法od,或
  • 3爲進化方法。

也許,你的目標函數是非線性,你以爲你正在使用的GRG非線性求解,因爲你提到它的EngineDesc參數下。這是不正確的。這只是一個描述參數。

你實際使用的求解器是單純LP其中有值。

更改爲使用GRG非線性求解器