given a set of x,y points I need a procedure to give me the
a values for a polynomium fitting the points.
I think the procedure head would look like this
procedure polynomiumfit(const x : array of real;
const y : array of real;
const order : integer;
var a : array of real);
y(x) = a0 + a1* x + a2 * x*x + a3*x*x*x .....
A least-square fit is ok :
Can anyone point to a function/procedure like this?
}
PROGRAM LineFit;
Uses Crt, Graph;
CONST MaxK = 10;
{ max. number of fitting functions }
MaxN = 400;
{ max. number of xy-points }
{ MaxK*MaxN*SizeOf(Real)
must be smaller then 64K }
TYPE Real = Double; { it's faster
and more exact }
Vector = ARRAY[1..MaxN]
OF Real;
Matrix = ARRAY[1..MaxK,1..MaxK]
OF Real;
PROCEDURE Gauss(n : Integer; M: matrix; Y: Vector; VAR
X : Vector;
VAR det : Real; eps : Real);
{ Solution a Linaer-Algebraic-Equitation-Sytem (M*x=y)
}
{ with 'Gauss-Jordan-Elimination' and Pivoting
}
LABEL 10, 20 ;
VAR i, j, k, maxindex
: Integer;
change
: Integer;
maxel,
temp, wert : Real;
BEGIN
change:=0;
FOR i:=1 TO n-1 DO
BEGIN
maxindex:=i; maxel:=Abs(M[i,i]);
FOR j:=i+1 TO n DO
BEGIN IF Abs(M[j,i])
> maxel
THEN BEGIN maxel:=Abs(M[j,i]);
maxindex:=j;
END;
END;
IF maxindex <> i THEN
BEGIN FOR
j:=i TO n DO
BEGIN temp:=M[i,j];
M[i,j]:=M[maxindex,j];
M[maxindex,j]:=temp;
END;
temp:=Y[i]; Y[i]:=Y[maxindex];
Y[maxindex]:=temp;
Inc(change);
END;
IF Abs(M[i,i]) < eps THEN GOTO
10;
FOR j:=i+1 TO n DO
BEGIN wert:=M[j,i]/M[i,i];
FOR k:=i+1 TO n DO
M[j,k]:=M[j,k] - wert*M[i,k];
Y[j]:=Y[j] - wert*Y[i];
END;
END;
IF Abs(M[n,n]) < eps THEN GOTO 10;
det:=1;
FOR i:=n DOWNTO 1 DO
BEGIN wert:=0;
FOR
j:=i+1 TO n DO
wert:=wert + M[i,j]*X[j];
X[i]:=(Y[i]
- wert)/M[i,i];
det:=det*M[i,i];
END;
IF Odd(change) THEN det:=-det;
GOTO 20;
10 : det:=0; { Determinant<eps
==> System maybe singular }
20 : ;
END; {---- Gauss ----}
PROCEDURE FKT(k:Integer; xarg: Real; VAR PHI: Vector);
{ for example Polynomials }
VAR i : Integer;
BEGIN
PHI[1]:=1; { polynomials }
FOR i:=2 TO k DO PHI[i]:=PHI[i-1]*xarg;
{ Another set of 'better' (for the fitting problem) functions can
be used too }
{ These functions must be 'linearly independent' (polynomials are
sure) }
{
PHI[1]:=1;
PHI[2]:=1/(xarg+1);
PHI[3]:=xarg/(xarg*xarg+1);
PHI[4]:=sin(xarg);
PHI[5]:=exp(xarg);
....
....
}
END; {---- FKT ----}
FUNCTION CalcFitting(k : Integer; A: Vector; xwert : Real) : Real;
VAR PHI : Vector;
sum : Real;
i : Integer;
BEGIN
FKT(k,xwert,PHI);
sum:=0;
FOR i:=1 TO k DO sum:=sum + A[i]*PHI[i];
CalcFitting:=sum;
END;
PROCEDURE DoFitting(n,k : Integer; X,Y : Vector; VAR A : Vector);
TYPE FType = ARRAY[1..MaxN,1..MaxK]
OF Real;
VAR i, j, l : Integer;
PHI, B :
Vector;
F
: ^FType;
M
: ^Matrix;
det
: Real;
BEGIN
New(M); New(F);
FOR i:=1 TO n DO
{ Prepare the approximation }
BEGIN
FKT(k,X[i],PHI);
FOR j:=1 TO k DO F^[i,j]:=PHI[j];
END;
FOR j:=1 TO k DO
{ Build the matrix of the LinEqu. }
FOR i:=1 TO k DO
BEGIN M^[i,j]:=0;
FOR l:=1 TO N DO
M^[i,j]:=M^[i,j] +
F^[l,i]*F^[l,j];
M^[j,i]:=M^[i,j];
END;
FOR i:=1 TO k DO
{ Build the right side of the LinEqu.}
BEGIN B[i]:=0;
FOR l:=1 TO n DO B[i]:=B[i] + F^[l,i]*Y[l];
END;
Gauss(k, M^, B, A, det, 1.0e-15); { Solve the system }
IF det=0 THEN { Missing Errorhandling };
Dispose(F); Dispose(M);
END; {---- DoFitting ----}
VAR X, Y, A
: Vector;
n, i, k, GraphDriver, GraphMode
: Integer;
delta, Zero, xpos, ypos
: Real;
ch
: Char;
BEGIN { ---- MAIN ---- }
n:=200; { 100 Points }
GraphDriver:=Detect;
InitGraph(GraphDriver,GraphMode,'');
delta:=(GetMaxX)/(n-1); Zero:=GetMaxY/2;
FOR i:=1 TO n DO { Build an
Example }
BEGIN
x[i]:=(i-1)*delta;
y[i]:=Zero + (Sin(X[i]/150)*Zero*0.5)*(X[i]/400)
+ (Random-0.5)*25 ;
END;
delta:=GetMaxX/500; { Show 7 line-fittings
with polynomials }
FOR k:=1 TO 7 DO { k
= (degree of the polynomial)-1 }
BEGIN
ClearDevice;
SetColor(Red);
{ Show the Points }
FOR i:=1 TO n DO Circle(Round(x[i]),Round(y[i]),2);
DoFitting(n,k, X,Y, A); { Do the calculation
}
FOR i:=0 TO 500 do
{ Show the curves with 501 points }
BEGIN
xpos:=i*delta;
ypos:=CalcFitting(k,A,xpos);
PutPixel(Round(xpos),Round(ypos),((9+k)
MOD 15)+1);
END;
ch:=ReadKey;
END;
CloseGraph;
END.