📄 fithill.pas
字号:
{ **********************************************************************
* Unit FITHILL.PAS *
* Version 1.2 *
* (c) J. Debord, September 2001 *
**********************************************************************
This unit fits the Hill equation :
Ymax . x^n
y = ----------
K^n + x^n
********************************************************************** }
unit fithill;
{$F+}
interface
uses
fmath, matrices, stat, regress;
function FuncName : String;
function FirstParam : Integer;
function LastParam : Integer;
function ParamName(I : Integer) : String;
function RegFunc(X : Float; B : TVector) : Float;
procedure DerivProc(X, Y : Float; B, D : TVector);
function FitModel(Method : Integer; X, Y, W : TVector;
N : Integer; B : TVector) : Integer;
implementation
function FuncName : String;
{ --------------------------------------------------------------------
Returns the name of the regression function
-------------------------------------------------------------------- }
begin
FuncName := 'y = Ymax . x^n / (K^n + x^n)';
end;
function FirstParam : Integer;
{ --------------------------------------------------------------------
Returns the index of the first parameter to be fitted
-------------------------------------------------------------------- }
begin
FirstParam := 0;
end;
function LastParam : Integer;
{ --------------------------------------------------------------------
Returns the index of the last parameter to be fitted
-------------------------------------------------------------------- }
begin
LastParam := 2;
end;
function ParamName(I : Integer) : String;
{ --------------------------------------------------------------------
Returns the name of the I-th parameter
-------------------------------------------------------------------- }
begin
case I of
0 : ParamName := 'Ymax';
1 : ParamName := 'K ';
2 : ParamName := 'n ';
end;
end;
function RegFunc(X : Float; B : TVector) : Float;
{ --------------------------------------------------------------------
Computes the regression function at point X
B is the vector of parameters, such that :
B[0] = Ymax B[1] = K B[2] = n
-------------------------------------------------------------------- }
begin
if X = 0.0 then
if B[2] > 0.0 then RegFunc := 0.0 else RegFunc := B[0]
else
{ Compute function according to y = Ymax / [1 + (K/x)^n] }
RegFunc := B[0] / (1.0 + Power(B[1] / X, B[2]));
end;
procedure DerivProc(X, Y : Float; B, D : TVector);
{ --------------------------------------------------------------------
Computes the derivatives of the regression function at point (X,Y)
with respect to the parameters B. The results are returned in D.
D[I] contains the derivative with respect to the I-th parameter
-------------------------------------------------------------------- }
var
Q, R, S : Float;
begin
if X = 0.0 then
begin
if B[2] > 0.0 then D[0] := 0.0 else D[0] := 1.0;
D[1] := 0.0;
D[2] := 0.0;
end
else
begin
Q := Power(B[1] / X, B[2]); { (K/x)^n }
R := 1.0 / (1.0 + Q); { 1 / [1 + (K/x)^n] }
S := - Y * R * Q; { -Ymax.(K/x)^n / [1 + (K/x)^n]^2 }
{ dy/dYmax = 1 / [1 + (K/x)^n] }
D[0] := R;
{ dy/dK = -Ymax.(K/x)^n.(n/K)/[1 + (K/x)^n]^2 }
D[1] := S * B[2] / B[1];
{ dy/dn = -Ymax.(K/x)^n.Ln(K/x)/[1 + (K/x)^n]^2 }
D[2] := S * Log(B[1] / X);
end;
end;
function FitModel(Method : Integer; X, Y, W : TVector;
N : Integer; B : TVector) : Integer;
{ --------------------------------------------------------------------
Approximate fit of the Hill equation by linear regression:
Ln(Ymax/y - 1) = n.Ln(K) - n.Ln(x)
--------------------------------------------------------------------
Input : Method = 0 for unweighted regression, 1 for weighted
X, Y = point coordinates
W = weights
N = number of points
Output : B = estimated regression parameters
-------------------------------------------------------------------- }
var
Ymax : Float; { Estimated value of Ymax }
X1, Y1 : TVector; { Transformed coordinates }
W1 : TVector; { Weights }
A : TVector; { Linear regression parameters }
V : TMatrix; { Variance-covariance matrix }
P : Integer; { Number of points for linear regression }
K : Integer; { Loop variable }
ErrCode : Integer; { Error code }
begin
DimVector(X1, N);
DimVector(Y1, N);
DimVector(W1, N);
DimVector(A, 1);
DimMatrix(V, 1, 1);
P := 0;
Ymax := Max(Y, 1, N);
for K := 1 to N do
if (X[K] > 0.0) and (Y[K] > 0.0) and (Y[K] < Ymax) then
begin
Inc(P);
X1[P] := Log(X[K]);
Y1[P] := Log(Ymax / Y[K] - 1.0);
W1[P] := Sqr(Y[K] * (1.0 - Y[K] / Ymax));
if Method = 1 then W1[P] := W1[P] * W[K];
end;
ErrCode := WLinFit(X1, Y1, W1, P, A, V);
if ErrCode = MAT_OK then
begin
B[0] := Ymax;
B[1] := Expo(- A[0] / A[1]);
B[2] := - A[1];
end;
FitModel := ErrCode;
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -