可变行长求解器优化

时间:2014-09-07 18:53:48

标签: excel vba excel-vba optimization solver

假设我有四列(U,W,X,Y)。最后的关系应该是W(i)= X(i),Y(i)= 0因为Y = X-Y而U(i)是可变的。您可以更改列" U"中的值。并且使W = X并且所有值必须是正W,X,Y,U。这是我的代码而且无效。

lRo = Sheets(" Rohr-Bogen")。细胞(Rows.Count,2).End(xlUp).Row

SolverReset
solverprecision = 0.0001
SolverOk SetCell:="$Y$12:$Y$" & lRo, MaxMinVal:=3, ValueOf:="0", ByChange:="$U12$:$U$" & lRo
SolverAdd cellRef:="$W$12:$W$" & lRo, relation:=2, formulaText:="$X$12:$X$" & lRo
SolverAdd cellRef:="$X$12:$X$" & lRo, relation:=3, formulaText:=0
SolverOptions AssumeNonNeg:=True
SolverSolve UserFinish:=True
SolverFinish KeepFinal:=1

    If Range("W10").Value > 0.0001 Then
    Call solve
    End If

由于

1 个答案:

答案 0 :(得分:0)

您可以改用SolverAdd功能。这个函数的形式是

SolverAdd(CellRef, Relation, FormulaText)

其中

  • CellRef是公式单元格的范围(在您的情况下是Y单元格)。
  • Relation可以是与<=>==integerbinaryalldifferent对应的数字
  • FormulaText具有所需(目标)值CellRef
  • 的范围

根据您的代码,这是一个演示。这是未经测试的,因为不清楚电子表格中的哪些单元格是公式,哪些是值,但它应该让你开始:

'First I define an enumeration to make clear what 1, 2, 3 etc mean:
'For details check http://msdn.microsoft.com/en-us/library/office/ff838657(v=office.15).aspx
Enum tRelationship
  Const tRelationship_leq = 1  ' Stands for <=
  Const tRelationship_eq = 2   ' Stands for =
  Const tRelationship_geq = 3  ' ...
  Const tRelationship_int = 4
  Const tRelationship_bin = 5
  Const tRelationship_alldiff = 6
End Enum

 Sub solve()

lRo = Sheets(1).Cells(Rows.Count, 2).End(xlUp).Row

    SolverReset
    ' Change K7 with the range that solves all variables
    SolverOk SetCell:="$W$10", MaxMinVal:=3, ValueOf:="0", ByChange:="$K$7" 'solves first W10 = 0
    SolverOptions AssumeNonNeg:=True
    SolverSolve UserFinish:=True
    SolverFinish KeepFinal:=1

    ' Here I assume that last row is row 16. You can change that dynamically as you do
    ' in your code. No loop is necessary. I assume that Y12 = X12 - W12, Y13 = ..., etc.
    SolverAdd cellRef:=Range("Y12:Y16"), relation:=tRelationship_eq, formulaText:=0
    SolverOptions AssumeNonNeg:=True
    SolverSolve UserFinish:=True
    SolverFinish KeepFinal:=1

End Sub

您只解决一个模型,将W10设置为零,这样可以保证如果存在可行的解决方案(使用X = W),则会找到它。

我希望这有帮助!

<强>更新

解算器如何工作的快速摘要:

  • 更改给定单元格的范围(称为决策变量单元格 - 在SolverOK-->ByChange)中指定,以便

  • 给定的单元格(只有一个单元格,称为目标单元格目标 函数单元 - 在SolverOK-->SetCell)中指定,其值取决于Decision Variable单元格, 被最小化或最大化,或达到给定值SolverOK-->MaxMinValValueOf如果MaxMinVal=3

  • 依赖于决策变量单元的一系列其他单元格满足某些约束(如上所述SolverAdd部分)。

在您发布的代码的更新版本中:

  • SolverOK-->SetCell会获得一系列单元格,但会失败(请参阅here the documentation for SetCell)。
  • SolverAdd部分过于复杂(且不正确)。 假设X(i)Y(i)包含引用U单元格的公式,那么如果Y(i) = X(i) - W(i)我们只需要这一行:

SolverAdd cellRef:="$Y$12:$Y$" & lRo, relation:=2, formulaText:=0

Y单元格设置为零可确保X(i)=W(i)因为Y(i) = X(i) - W(i)

  • 代码的最后一部分有些令人困惑。您检查W10的值,但W10在模型中无处可寻。 W10是否与U(i)单元格相关联?如果您希望W10等于零,则可以将其放在目标函数中,并再次使用MaxMinVal := 3ValueOf := 0,假设它已链接到U细胞

总之,求解器仅更改Decision变量单元格(U(i))。我们需要最小化/最大化/等于值的单元格,以及应该>=<==到数值的单元格都应该链接到U(i)个细胞。

我希望这会让它变得更清楚?