I was very excited when I found libraries of computational algorithms for programs written in Delphi. It seemed to offer exactly what I needed for my research project.
I would like to fit experimental data by two-exponential function y=a*exp(-x/b)+c*exp(-x/d)+k
I attempted using function LSFitNonlinearFG (i.e. approximation without Gaussian), but encountered the following problems. Approximation fails even in case of rather smooth data without noise. When I ran my program without limiting the number of iterations, it continued for hours without returning any result. If I limit the number of iterations, then it stops after executing indicated number of steps, but found parameters of 2-exponential approximation do not fit the results.
I used your library version 2.6.0 for Delphi, since I don’t have experience with programming languages corresponding to the later version 3.4.0. I’m slightly familiar with C++, and therefore it might be another opportunity, if my Delphi program could not be made working with any earlier libraries.
All methods on your website refer to the library v. 3.4.0, and I couldn’t find any description for v.2.6.0 Does it still exist?
I kindly ask for your advice in this regard.
Could any other function utilizing limitations of the number of iterations improve multi-exponential approximation?
Do you believe that Gaussian methodology might be of advantage for this purpose?
Could your libraries v.3.40 for C++ be used in a program written in Delphi?
Here’s my code:
Code:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, LsFit ,AP;
type
TForm1 = class(TForm)
Button1: TButton;
Label1: TLabel;
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
var
M : AlglibInteger;
N : AlglibInteger;
K : AlglibInteger;
Y : TReal1DArray;
X : TReal2DArray;
C : TReal1DArray;
Rep : LSFitReport;
State : LSFitState;
Info : AlglibInteger;
EpsF : Double;
EpsX : Double;
MaxIts : AlglibInteger;
I : AlglibInteger;
J : AlglibInteger;
A : Double;
B : Double;
begin
Label1.Caption:='Ждите';
Application.ProcessMessages;
//
// апроксимация 100exp(-x/10)+ 20exp(-x/200)+1 двумя exp:
// * without Hessian (gradient only)
// * using alpha=1 as initial value
// * using 30 uniformly distributed points to fit to
//
// Notes:
// * N - number of points
// * M - dimension of space where points reside
// * K - number of parameters being fitted
//
N := 30;
M := 1;
K := 5;
A := 0.1;
B := 500;
//
// Подготовка матрицы задачи
//
SetLength(Y, N);
SetLength(X, N, M);
SetLength(C, K);
I:=0;
while I<=N-1 do
begin
X[I,0] := A+(B-A)*I/(N-1);
Y[I] := 100*exp(-X[I,0]/30)+ 2*exp(-X[I,0]/200)+1;
Inc(I);
end;
C[0] := 2.0;
C[1] := 1.0;
C[2] := 1.0;
C[3] := 2.0;
C[4] := 1.0;
EpsF := 0;
EpsX := 0;
MaxIts := 21474;//83647;
//
// Решение
//
LSFitNonlinearFG(X, Y, C, N, M, K, True, State);
LSFitNonlinearSetCond(State, EpsF, EpsX, MaxIts);
LSFitNonlinearSetStpMax(State, 0.3);
while LSFitNonlinearIteration(State) do
begin
if State.NeedF then
begin
//
// F(x) = a*exp(-x/b)+ cexp(-x/d)+k
//
State.F := C[0]*Exp(-State.X[0]/State.C[1])+C[2]*Exp(-State.X[0]/State.C[3])+C[4];
end;
if State.NeedFG then
begin
//
// F(x) = a*exp(-x/b)+ cexp(-x/d)+k
// dF/da = exp(-x/b)
// dF/db = a*x*exp(-x/b)/b^2
// dF/dc = exp(-x/d)
// dF/dd = c*x*exp(-x/d)/d^2
// dF/dk = 1
State.F := C[0]*Exp(-State.X[0]/State.C[1])+C[2]*Exp(-State.X[0]/State.C[3])+C[4];
State.G[0] := Exp(-State.X[0]/State.C[1]);
State.G[1] := C[0]*State.X[0]*Exp(-State.X[0]/State.C[1])/(State.C[1]*State.C[1]);
State.G[2] := Exp(-State.X[0]/State.C[2]);
State.G[3] := C[2]*State.X[0]*Exp(-State.X[0]/State.C[3])/(State.C[3]*State.C[3]);
State.G[4] := 1;
end;
end;
//Вывод результатов
LSFitNonlinearResults(State, Info, C, Rep);
Label1.Caption:='a:'+FloatToStr(C[0])+#13+#10
+'b:'+FloatToStr(C[1])+#13+#10
+'c:'+FloatToStr(C[2])+#13+#10
+'d:'+FloatToStr(C[3])+#13+#10
+'k:'+FloatToStr(C[4])+#13+#10
+'rms.err:'+FloatToStr(Rep.RMSError)+#13+#10
+'max.err:'+FloatToStr(Rep.MaxError)+#13+#10
+'Termination type:'+FloatToStr(Info);
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
Label1.Caption:='Апроксимация 100exp(-x/30)+ 2exp(-x/200)+1 на отрезке [0.1,500] двумя exp';
end;
end.
and sample of my fitted data by other programs
And output: