解决查普曼 - 理查兹方程

时间:2012-11-28 16:01:44

标签: ms-solver-foundation nonlinear-optimization

我需要找到一种方法来解决Chapman-Richards的3个参数。等式是

F=a(1-EXP(-bt)) power c

这是一个非线性问题。目标是最小化误差,并且约束是3个变量必须> = 0.0001。我们当前的实现使用Excel和Solver插件(GRG非线性方法)。但现在,我们需要在不使用Excel的情况下实现所有这些。

我的问题是: 1.是否可以使用MS Solver Foundation来解决这个问题? 我已经阅读了一些文档,并了解MS Solver Foundation使用Nelder Mead Solver或混合局部搜索求解器来解决非线性问题。有谁知道我的特定问题是否可以使用这些方法解决?并且,结果是否与使用Excel的Solver插件的GRG非线性方法相同?

  1. 如果没有,是否可以实现Excel Solver的GRG非线性方法?

  2. 还有其他方法可以实现吗?

  3. 感谢您提前回复。 KAR

    附录: 对不起,我忘了提到t是时间变量。 a,b和c是解算器可以更改的参数。

2 个答案:

答案 0 :(得分:0)

是的,可以使用Solver Foundation中的 Nelder-Mead 解算器完成。这是C#中的一些示例代码。只需确保引用 Microsoft.Solver.Foundation 程序集。

    private const double t = 1.0;

    public static void Main()
    {
        var solver = new NelderMeadSolver();

        // Objective function.
        int objId;
        solver.AddRow("obj", out objId);
        solver.AddGoal(objId, 0, true);

        // Define variables.
        int aId, bId, cId;
        solver.AddVariable("a", out aId);
        solver.AddVariable("b", out bId);
        solver.AddVariable("c", out cId);

        // Define bounds.
        solver.SetLowerBound(aId, 0.001);
        solver.SetLowerBound(bId, 0.001);
        solver.SetLowerBound(cId, 0.001);

        // Assign objective function delegate.
        solver.FunctionEvaluator = FunctionValue;

        // Solve.
        var param = new NelderMeadSolverParams();
        var solution = solver.Solve(param);

        Console.WriteLine("The Result is " + solution.Result + ".");
        Console.WriteLine("The minimium objective value is " + 
                          solution.GetValue(objId) + ".");
        Console.WriteLine("a = " + solution.GetValue(aId) + ".");
        Console.WriteLine("b = " + solution.GetValue(bId) + ".");
        Console.WriteLine("c = " + solution.GetValue(cId) + ".");

        Console.ReadKey();
    }

    private static double FunctionValue(INonlinearModel model, int rowVid,
         ValuesByIndex values, bool newValues)
    {
        var a = values[model.GetIndexFromKey("a")];
        var b = values[model.GetIndexFromKey("b")];
        var c = values[model.GetIndexFromKey("c")];

        return a * Math.Pow(1.0-Math.Exp(-b * t), c);
    }

答案 1 :(得分:0)

我使用Visual Studio 2013和Visual Basic解决它,有代码的翻译。

Private Sub NelderMead()
    Dim Solver As New Microsoft.SolverFoundation.Solvers.NelderMeadSolver

    Dim objId As Integer
    Solver.AddRow("obj", objId)
    Solver.AddGoal(objId, 0, True)

    Dim aId, bId, cId As Integer
    Solver.AddVariable("a", aId)
    Solver.AddVariable("b", bId)
    Solver.AddVariable("c", cId)

    Solver.SetLowerBound(aId, 0.001)
    Solver.SetLowerBound(bId, 0.001)
    Solver.SetLowerBound(cId, 0.001)

    Solver.FunctionEvaluator = AddressOf FunctionValue

    Dim Par As New Microsoft.SolverFoundation.Solvers.NelderMeadSolverParams
    Dim Solucion = Solver.Solve(Par)

    Debug.Print(Solucion.Result)
End Sub

Function FunctionValue(Model As Microsoft.SolverFoundation.Services.INonlinearModel, _
                       rowVid As Integer, _
                       Values As Microsoft.SolverFoundation.Services.ValuesByIndex, _
                       newValues As Boolean) As Object
    Dim a, b, c As Double

    a = Values(Model.GetIndexFromKey("a"))
    b = Values(Model.GetIndexFromKey("b"))
    c = Values(Model.GetIndexFromKey("c"))

    Return a * Math.Pow(1.0 - Math.Exp(-b * t), c)
End Function