问题
I need to find a way to solve the Chapman-Richards with 3 parameters. The equation is
F=a(1-EXP(-bt)) power c
It is a nonlinear problem. The goal is to minimize the error and the constraints are that the 3 variables must be >= 0.0001. Our current implementation uses Excel and the Solver plugin (GRG nonlinear method). But now, we need to implement all this without making use of Excel.
My questions are: 1. Is it possible to use MS Solver Foundation to solve this problem? I have read some docs and understand that MS Solver Foundation uses either the Nelder Mead Solver or the hybrid local search solver to solve nonlinear problems. Does anyone know if my particular problem can be solved using these methods? And, will the results be same as using GRG nonlinear method of Excel's Solver addin?
If not, is it possible to implement the GRG nonlinear method of Excel Solver?
Is there any other way to implement this?
Thanks for your replies in advance. kar
Addendum: Sorry, I forgot to mention that t is the time variable. a, b, and c are the parameters which can be changed by the solver.
回答1:
Yes, it can be done with the Nelder-Mead solver in Solver Foundation. Here is some example code in C#. Just make sure you reference the Microsoft.Solver.Foundation assembly.
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);
}
回答2:
I solved it with Visual Studio 2013 and Visual Basic, there is the traslation of the code.
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
来源:https://stackoverflow.com/questions/13609265/solving-the-chapman-richards-equation