решение уравнения Чепмена-Ричардса

Мне нужно найти способ решить Чепмена-Ричардса с 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, либо гибридный локальный поисковый решатель для решения нелинейных задач. Кто-нибудь знает, можно ли решить мою конкретную проблему с помощью этих методов? И будут ли результаты такими же, как при использовании нелинейного метода GRG надстройки Excel Solver?

  1. Если нет, можно ли реализовать нелинейный метод GRG в Excel Solver?

  2. Есть ли другой способ реализовать это?

Спасибо за ваши ответы заранее. кар

Приложение: Извините, я забыл упомянуть, что t — это переменная времени. a, b и c — параметры, которые могут быть изменены решателем.


person user1860385    schedule 28.11.2012    source источник
comment
Является ли t константой, а a, b, c переменными?   -  person Anders Gustafsson    schedule 28.11.2012


Ответы (2)


Да, это можно сделать с помощью решателя Nelder-Mead в Solver Foundation. Вот пример кода на 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);
    }
person Anders Gustafsson    schedule 29.11.2012
comment
Большое спасибо за ваш ответ, @AndersGustafsson. Я попробую и сравню с результатами Солвера. Спасибо за вашу помощь! - person user1860385; 05.12.2012

Я решил это с помощью 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
person GioWanKenobi    schedule 16.01.2015