You've already forked lazarus-ccr
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@7790 8e941d3f-bd1b-0410-a28a-d453659cc2b4
2412 lines
74 KiB
ObjectPascal
2412 lines
74 KiB
ObjectPascal
unit MatrixLib;
|
|
|
|
{$mode objfpc}{$H+}
|
|
|
|
interface
|
|
|
|
uses
|
|
Classes, SysUtils, Dialogs,
|
|
Globals, DictionaryUnit, FunctionsLib, GridProcs, DataProcs, MainUnit;
|
|
|
|
//type
|
|
// TRegItem = (riMeanVarStdDev, riXTX);
|
|
|
|
procedure GridDotProd(col1, col2: integer; out Product: double; var Ngood: integer);
|
|
|
|
procedure GridXProd(NoSelected : integer;
|
|
{VAR} Selected : IntDyneVec;
|
|
{VAR} Product : DblDyneMat;
|
|
Augment : boolean;
|
|
VAR Ngood : integer);
|
|
|
|
procedure GridCovar(NoSelected: integer; const Selected: IntDyneVec;
|
|
const Covar: DblDyneMat; const Means, Variances, StdDevs: DblDyneVec;
|
|
var ErrorCode: boolean; var NGood: Integer);
|
|
|
|
procedure Correlations(NoSelected: integer; const Selected: IntDyneVec;
|
|
const Correlations: DblDyneMat; const Means, Variances, StdDevs: DblDyneVec;
|
|
var ErrorCode: boolean; var NGood: integer);
|
|
|
|
procedure MatAxB(const A, B, C: DblDyneMat; BRows, BCols, CRows, CCols: Integer;
|
|
out ErrorCode: boolean);
|
|
|
|
procedure MatTrn(var A: DblDyneMat; const B: DblDyneMat; BRows, BCols: Integer);
|
|
|
|
procedure nonsymroots(a : DblDyneMat; nv : integer;
|
|
var nf : integer; c : real;
|
|
var v : DblDyneMat; var e : DblDyneVec;
|
|
var px : DblDyneVec;
|
|
var t : double;
|
|
var ev : double);
|
|
|
|
procedure ludcmp(const a: DblDyneMat; n: integer; const indx: IntDyneVec; out d: double);
|
|
|
|
procedure DETERM(const a: DblDyneMat; Rows, Cols: integer;
|
|
out determ: double; out errorcode: boolean);
|
|
|
|
procedure EffectCode(GridCol, min, max : integer;
|
|
FactLetter : string;
|
|
VAR startcol : integer;
|
|
VAR endcol : integer;
|
|
VAR novectors : integer);
|
|
|
|
procedure MReg(NoIndep: integer; const IndepCols: IntDyneVec; DepCol: integer;
|
|
const RowLabels: StrDyneVec;
|
|
const Means, Variances, StdDevs, BWeights, BetaWeights, BStdErrs, Bttests, tProbs: DblDyneVec;
|
|
out R2, StdErrEst: double; NCases: integer; out ErrorCode: boolean;
|
|
PrintAll: boolean; AReport: TStrings);
|
|
|
|
procedure Dynnonsymroots(var a : DblDyneMat; nv : integer;
|
|
var nf : integer; c : real;
|
|
var v : DblDyneMat; var e : DblDyneVec;
|
|
var px : DblDyneVec;
|
|
var t : double;
|
|
var ev : double);
|
|
|
|
function DynCorrelations(novars : integer;
|
|
VAR ColSelected : IntDyneVec;
|
|
VAR DataGrid : DblDyneMat;
|
|
VAR rmatrix : DblDyneMat;
|
|
VAR means : DblDyneVec;
|
|
VAR vars : DblDyneVec;
|
|
VAR stddevs : DblDyneVec;
|
|
NCases : integer;
|
|
ReturnType : integer) : integer;
|
|
|
|
procedure Predict(VAR ColNoSelected : IntDyneVec;
|
|
NoVars : integer;
|
|
VAR IndepInverse : DblDyneMat;
|
|
VAR Means : DblDyneVec;
|
|
VAR StdDevs : DblDyneVec;
|
|
VAR BetaWeights : DblDyneVec;
|
|
StdErrEst : double;
|
|
VAR IndepIndex : IntDyneVec;
|
|
NoIndepVars : integer);
|
|
|
|
procedure MReg2(NCases : integer;
|
|
NoVars : integer;
|
|
VAR NoIndepVars : integer;
|
|
VAR IndepIndex : IntDyneVec;
|
|
VAR corrs : DblDyneMat;
|
|
VAR IndepCorrs : DblDyneMat;
|
|
VAR RowLabels : StrDyneVec;
|
|
out R2: double;
|
|
VAR BetaWeights : DblDyneVec;
|
|
VAR Means : DblDyneVec;
|
|
VAR Variances : DblDyneVec;
|
|
out errorcode : integer;
|
|
out StdErrEst: double;
|
|
out constant: double;
|
|
probout : double;
|
|
Printit : boolean;
|
|
TestOut : boolean;
|
|
PrintInv : boolean;
|
|
AReport: TStrings);
|
|
|
|
procedure MatSub(const a, b, c: DblDyneMat;
|
|
brows, bcols, crows, ccols: integer; out errorcode: boolean);
|
|
|
|
procedure IntArrayPrint(const mat: IntDyneMat; rows, cols: integer;
|
|
const YTitle: string; const RowLabels, ColLabels: StrDyneVec;
|
|
const Title: string; AReport: TStrings);
|
|
|
|
procedure eigens(VAR a: DblDyneMat; Var d : DblDyneVec; n : integer);
|
|
|
|
PROCEDURE tred2(VAR a: DblDyneMat; n: integer; VAR d,e: DblDyneVec);
|
|
|
|
PROCEDURE tqli(VAR d,e: DblDyneVec; n: integer; VAR z: DblDyneMat);
|
|
|
|
function SEVS(nv,nf : integer;
|
|
c : double;
|
|
var r : DblDyneMat;
|
|
VAR v : DblDyneMat;
|
|
VAR e : DblDyneVec;
|
|
var p : DblDyneVec;
|
|
VAR nd : integer) : integer ;
|
|
|
|
function SCPF(VAR x,y : DblDyneMat; kx,ky,n,nd : integer) : double;
|
|
|
|
procedure MatPrint(const xmat: DblDyneMat; Rows,Cols: Integer; const Title: String;
|
|
const RowLabels, ColLabels: StrDyneVec; NCases: Integer; AReport: TStrings);
|
|
|
|
procedure DynVectorPrint(const AVector: DblDyneVec; NoVars: integer;
|
|
Title: string; const Labels: StrDyneVec; NCases: integer; AReport: TStrings);
|
|
|
|
procedure ScatPlot(const x, y: DblDyneVec; NoCases: integer;
|
|
const TitleStr, x_axis, y_axis: string; x_min, x_max, y_min, y_max: double;
|
|
const VarLabels: StrDyneVec; AReport: TStrings);
|
|
|
|
procedure DynIntMatPrint(Mat: IntDyneMat; Rows, Cols: integer; YTitle: string;
|
|
RowLabels, ColLabels: StrDyneVec; Title: string; AReport: TStrings);
|
|
|
|
procedure SymMatRoots(A : DblDyneMat; M : integer; VAR E : DblDyneVec; VAR V : DblDyneMat);
|
|
procedure matinv(a, vtimesw, v, w: DblDyneMat; n: integer);
|
|
|
|
procedure AddVariable(AVarName: String; AData: DblDyneVec;
|
|
ANumFormat: String; const ABadRows: IntDyneVec);
|
|
|
|
|
|
implementation
|
|
|
|
uses
|
|
Math, StrUtils,
|
|
MatrixUnit, MathUnit;
|
|
|
|
procedure GridDotProd(col1, col2: integer; out Product: double; var Ngood: integer);
|
|
// Get the cross-product of two vectors
|
|
// col1 and col2 are grid columns of the main form's DataGrid
|
|
// Product is the vector product
|
|
// Ngood are the number of elements in the product not missing or filtered
|
|
|
|
// wp: "vector product" -- misleading name because the procedure return the "dot" product.
|
|
// ==> Renamed from "GridVecProd" to "GridDotProd"
|
|
var
|
|
i: integer;
|
|
Selected: IntDyneVec = nil;
|
|
X1, X2: double;
|
|
begin
|
|
SetLength(Selected, 2);
|
|
Product := 0.0;
|
|
Selected[0] := col1;
|
|
Selected[1] := col2;
|
|
for i := 1 to NoCases do
|
|
begin
|
|
if not GoodRecord(i,2,Selected) then continue;
|
|
Ngood := Ngood + 1;
|
|
X1 := StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[col1, i]));
|
|
X2 := StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[col2, i]));
|
|
Product := Product + X1 * X2;
|
|
end;
|
|
Selected := nil;
|
|
end;
|
|
//-------------------------------------------------------------------
|
|
|
|
procedure GridXProd(NoSelected : integer;
|
|
{VAR} Selected : IntDyneVec;
|
|
{VAR} Product : DblDyneMat;
|
|
Augment : boolean;
|
|
var Ngood : integer);
|
|
// Matrix product of a grid matrix and its transpose
|
|
// Product contains the cross-products matrix upon return
|
|
// Selected is a integer vector of grid columns of the vectors
|
|
// NoSelected is an integer of the number of grid vectors selected
|
|
// Ngood is the number of elements in a vector product not missing or filtered
|
|
// Augment is true if the augment matrix is to be obtained and is required
|
|
// to obtain means, variances, standard deviations in the correlation procedure
|
|
// and GridCovar procedure
|
|
var
|
|
i, j, k : integer;
|
|
Col1, Col2 : integer;
|
|
X1 : double;
|
|
Prod : double;
|
|
NoVars : integer;
|
|
N : double;
|
|
|
|
begin
|
|
// initialize
|
|
N := 0.0;
|
|
NoVars := 0;
|
|
for i := 1 to NoSelected do
|
|
for j := 1 to NoSelected do
|
|
Product[i-1,j-1] := 0.0;
|
|
if Augment then
|
|
begin
|
|
NoVars := NoSelected + 1;
|
|
for i := 1 to NoVars do
|
|
begin
|
|
Product[i-1,NoVars-1] := 0.0;
|
|
Product[NoVars-1,i-1] := 0.0;
|
|
end;
|
|
end;
|
|
|
|
// Do cross-products without augmentation
|
|
for i := 1 to NoSelected do // pre-matrix row (Grid transpose)
|
|
begin
|
|
for j := 1 to NoSelected do // post-matrix column (Grid)
|
|
begin
|
|
Ngood := 0;
|
|
Col1 := Selected[i-1];
|
|
Col2 := Selected[j-1];
|
|
GridDotProd(Col1,Col2,Prod, Ngood);
|
|
Product[i-1,j-1] := Prod;
|
|
end;
|
|
end;
|
|
|
|
if Augment then // do last column and row for augmented matrix
|
|
begin
|
|
for j := 1 to NoSelected do
|
|
begin
|
|
Col1 := Selected[j-1];
|
|
for k := 1 to NoCases do
|
|
begin
|
|
if not GoodRecord(k,NoSelected,Selected) then continue;
|
|
X1 := StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[Col1,k]));
|
|
Product[NoVars-1,j-1] := Product[NoVars-1,j-1] + X1;
|
|
Product[j-1,NoVars-1] := Product[j-1,NoVars-1] + X1;
|
|
end;
|
|
end;
|
|
for i := 1 to NoCases do // last cell of augmented matix
|
|
begin
|
|
if not GoodRecord(i,NoSelected,Selected) then continue;
|
|
N := N + 1.0;
|
|
end;
|
|
Product[NoVars-1,NoVars-1] := N;
|
|
Ngood := round(N);
|
|
end;
|
|
end;
|
|
//-------------------------------------------------------------------
|
|
|
|
{ Obtains the variance/covariance matrix of variables in the grid
|
|
NoSelected is the number of variables selected from the grid
|
|
Selected is a vector of integers for the grid columns of selected variables
|
|
Covar is the variance/covariance matrix returned
|
|
Means, StdDevs, Variances are double vectors obtained from the augmented matrix
|
|
errorcode is true if an error occurs due to 0 variance
|
|
Ngood is the number of records in the cross-product of vectors
|
|
This procedure calls the GridXProd procedure with augmentation true
|
|
in order to obtain the means, variances and standard deviations }
|
|
procedure GridCovar(NoSelected: integer; const Selected: IntDyneVec;
|
|
const Covar: DblDyneMat; const Means, Variances, StdDevs: DblDyneVec;
|
|
var errorcode: boolean; var NGood: integer);
|
|
var
|
|
i, j: integer;
|
|
N: double;
|
|
Augment: boolean;
|
|
begin
|
|
// initialize
|
|
ErrorCode := false;
|
|
for i := 0 to NoSelected-1 do
|
|
begin
|
|
Means[i] := 0.0;
|
|
Variances[i] := 0.0;
|
|
StdDevs[i] := 0.0;
|
|
end;
|
|
Augment := true; // augment to get intercept, means, variances, std.devs.
|
|
|
|
// get cross-products
|
|
GridXProd(NoSelected,Selected,Covar,Augment,Ngood);
|
|
|
|
// Get no. of records in cross-products
|
|
N := Ngood;
|
|
|
|
// Sums of squares are in diagonal, cross-products in off-diagonal cells
|
|
// Sums of X's are in the augmented column
|
|
// Get means and standard deviations first
|
|
for i := 0 to NoSelected-1 do
|
|
begin
|
|
Means[i] := Covar[i, NoSelected] / N;
|
|
Variances[i] := Covar[i, i] - (Sqr(Covar[i, NoSelected]) / N);
|
|
Variances[i] := Variances[i] / (N - 1.0);
|
|
if Variances[i] > 0.0 then
|
|
StdDevs[i] := sqrt(Variances[i])
|
|
else
|
|
begin
|
|
StdDevs[i] := 0.0;
|
|
ErrorCode := true;
|
|
end;
|
|
end;
|
|
|
|
// Now get covariances
|
|
for i := 0 to NoSelected-1 do
|
|
begin
|
|
for j := 0 to NoSelected-1 do
|
|
begin
|
|
Covar[i, j] := Covar[i, j] - ((Covar[i, NoSelected] * Covar[j, NoSelected]) / N);
|
|
Covar[i, j] := Covar[i, j] / (N - 1);
|
|
end;
|
|
end;
|
|
end;
|
|
//-------------------------------------------------------------------
|
|
|
|
{ Obtains the correlation matrix among grid variables
|
|
NoSelected is the no. of grid variables selected for analysis
|
|
Selected is a vector of integers of the grid variable columns selected
|
|
Correlations are returned in the Correlations matrix
|
|
Means, Variances, StdDevs are returned as double vectors
|
|
errorcode is true if a 0 variance is detected
|
|
Ngood is the number cases that do not contain missing values or are filtered
|
|
This procedure calls the GridCovar procedure }
|
|
procedure Correlations(NoSelected: integer; const Selected: IntDyneVec;
|
|
const Correlations: DblDyneMat; const Means, Variances, StdDevs: DblDyneVec;
|
|
var ErrorCode: boolean; var NGood: integer);
|
|
var
|
|
i, j: integer;
|
|
begin
|
|
// get covariance matrix, means and standard deviations
|
|
GridCovar(NoSelected, Selected, Correlations, Means, Variances, StdDevs, ErrorCode, Ngood);
|
|
for i := 0 to NoSelected-1 do
|
|
begin
|
|
for j := 0 to NoSelected-1 do
|
|
begin
|
|
if (StdDevs[i] > 0.0) and (StdDevs[j] > 0.0) then
|
|
Correlations[i, j] := Correlations[i, j] / (StdDevs[i] * StdDevs[j])
|
|
else
|
|
begin
|
|
Correlations[i, j] := 0.0;
|
|
ErrorCode := true;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
//-------------------------------------------------------------------
|
|
|
|
// Product of matrix B times C with results returned in a: A = B C
|
|
procedure MatAxB(const A, B, C: DblDyneMat; BRows, BCols, CRows, CCols: Integer;
|
|
out ErrorCode: boolean);
|
|
var
|
|
i, j, k: integer;
|
|
begin
|
|
ErrorCode := BCols <> CRows;
|
|
if not ErrorCode then
|
|
begin
|
|
for i := 0 to BRows-1 do
|
|
begin
|
|
for j := 0 to CCols-1 do
|
|
begin
|
|
A[i,j] := 0.0;
|
|
for k := 0 to CRows-1 do
|
|
A[i,j] := A[i,j] + B[i,k] * C[k,j];
|
|
end;
|
|
end;
|
|
end;
|
|
end; { of MATAxB }
|
|
|
|
//-------------------------------------------------------------------
|
|
|
|
// transpose the B matrix and return it in A
|
|
procedure MatTrn(var A: DblDyneMat; const B: DblDyneMat; BRows, BCols : integer);
|
|
var
|
|
i, j: integer;
|
|
begin
|
|
for i := 0 to BRows-1 do
|
|
for j := 0 to BCols-1 do
|
|
A[j,i] := B[i,j];
|
|
end; { of mattrn }
|
|
//-------------------------------------------------------------------
|
|
|
|
procedure nonsymroots(a : DblDyneMat; nv : integer;
|
|
var nf : integer; c : real;
|
|
var v : DblDyneMat; var e : DblDyneVec;
|
|
var px : DblDyneVec;
|
|
var t : double;
|
|
var ev : double);
|
|
{ roots and vectors of a non symetric matrix. a is square matrix entered
|
|
and is destroyed in process. nv is number of variables (rows and columns )
|
|
of a. nf is the number of factorsto be extracted - is output as the number
|
|
which exceeded c, the minimum eigenvalue to be extracted. v is the output
|
|
matrix of column vectors of loadings. e is the output vector of roots. px
|
|
is the percentages of trace for factors. t is the trace of the matrix and
|
|
ev is the percent of trace extracted }
|
|
label 40;
|
|
var
|
|
y: DblDyneVec = nil;
|
|
z: DblDyneVec = nil;
|
|
ek, e2, d : real;
|
|
i, j, k, m : integer;
|
|
begin
|
|
SetLength(y,nv);
|
|
SetLength(z,nv);
|
|
t := 0.0;
|
|
for i := 0 to nv-1 do t := t + a[i,i];
|
|
for k := 0 to nf-1 do
|
|
begin
|
|
for i := 0 to nv-1 do
|
|
begin
|
|
px[i] := 1.0;
|
|
y[i] := 1.0;
|
|
end;
|
|
e[k] := 1.0;
|
|
ek := 1.0;
|
|
for m := 1 to 25 do
|
|
begin
|
|
for i := 0 to nv-1 do
|
|
begin
|
|
v[i,k] := px[i] / e[k];
|
|
z[i] := y[i] / ek;
|
|
end;
|
|
for i := 0 to nv-1 do
|
|
begin
|
|
px[i] := 0.0;
|
|
for j := 0 to nv-1 do px[i] := px[i] + a[i,j] * v[j,k];
|
|
y[i] := 0.0;
|
|
for j := 0 to nv-1 do y[i] := y[i] + a[j,i] * z[j];
|
|
end;
|
|
e2 := 0.0;
|
|
for j := 0 to nv-1 do e2 := e2 + px[j] * v[j,k];
|
|
e[k] := sqrt(abs(e2));
|
|
ek := 0.0;
|
|
for j := 0 to nv-1 do ek := ek + y[j] * z[j];
|
|
ek := sqrt(abs(ek));
|
|
end;
|
|
if e2 >= sqr(c) then
|
|
begin
|
|
d := 0.0;
|
|
for j := 0 to nv-1 do d := d + v[j,k] * z[j];
|
|
d := e[k] / d;
|
|
for i := 0 to nv-1 do
|
|
for j := 0 to nv-1 do
|
|
a[i,j] := a[i,j] - v[i,k] * z[j] * d;
|
|
end
|
|
else begin
|
|
nf := k - 1;
|
|
goto 40;
|
|
end;
|
|
end;
|
|
40 : for i := 0 to nf-1 do px[i] := e[i] / t * 100.0;
|
|
ev := 0.0;
|
|
for i := 0 to nf-1 do ev := ev + px[i];
|
|
z := nil;
|
|
y := nil;
|
|
end; { of procedure nonsymroots }
|
|
//-------------------------------------------------------------------
|
|
|
|
PROCEDURE ludcmp(const a: DblDyneMat; n: integer; const indx: IntDyneVec; out d: double);
|
|
const
|
|
tiny = 1.0e-20;
|
|
var
|
|
k,j,imax,i: integer;
|
|
sum,dum,big: double;
|
|
vv: DblDyneVec = nil;
|
|
BEGIN
|
|
SetLength(vv,n);
|
|
d := 1.0;
|
|
imax := 0;
|
|
for i := 1 to n do begin
|
|
big := 0.0;
|
|
for j := 1 to n do
|
|
if (abs(a[i-1,j-1]) > big) then big := abs(a[i-1,j-1]);
|
|
if (big = 0.0) then
|
|
begin
|
|
MessageDlg('Singular matrix in Lower-Upper Decomposition routine', mtError, [mbOK], 0);
|
|
exit;
|
|
end;
|
|
vv[i-1] := 1.0/big;
|
|
end;
|
|
|
|
for j := 1 to n do
|
|
begin
|
|
if (j > 1) then
|
|
begin
|
|
for i := 1 to j-1 do
|
|
begin
|
|
sum := a[i-1,j-1];
|
|
if (i > 1) then
|
|
begin
|
|
for k := 1 to i-1 do
|
|
sum := sum - a[i-1,k-1] * a[k-1,j-1];
|
|
a[i-1,j-1] := sum
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
big := 0.0;
|
|
for i := j to n do
|
|
begin
|
|
sum := a[i-1,j-1];
|
|
if (j > 1) then
|
|
begin
|
|
for k := 1 to j-1 do
|
|
sum := sum - a[i-1,k-1] * a[k-1,j-1];
|
|
a[i-1,j-1] := sum
|
|
END;
|
|
dum := vv[i-1] * abs(sum);
|
|
if (dum > big) then
|
|
begin
|
|
big := dum;
|
|
imax := i
|
|
end;
|
|
end;
|
|
|
|
if (j <> imax) then
|
|
begin
|
|
for k := 1 to n do
|
|
begin
|
|
dum := a[imax-1,k-1];
|
|
a[imax-1,k-1] := a[j-1,k-1];
|
|
a[j-1,k-1] := dum;
|
|
end;
|
|
d := -d;
|
|
vv[imax-1] := vv[j-1]
|
|
end;
|
|
indx[j-1] := imax;
|
|
if (j <> n) then
|
|
begin
|
|
if (a[j-1,j-1] = 0.0) then
|
|
a[j-1,j-1] := tiny;
|
|
dum := 1.0/a[j-1,j-1];
|
|
for i := j+1 to n do
|
|
a[i-1,j-1] := a[i-1,j-1] * dum;
|
|
end;
|
|
end;
|
|
|
|
if (a[n-1,n-1] = 0.0) then
|
|
a[n-1,n-1] := tiny;
|
|
|
|
vv := nil;
|
|
end;
|
|
//-------------------------------------------------------------------
|
|
|
|
procedure Determ(const a: DblDyneMat; Rows, Cols: integer; out determ: double;
|
|
out ErrorCode: boolean);
|
|
var
|
|
indx: IntDyneVec = nil;
|
|
i: integer;
|
|
begin
|
|
SetLength(indx, rows);
|
|
ErrorCode := false;
|
|
if (rows <> cols) then
|
|
ErrorCode := true
|
|
else
|
|
begin
|
|
LUDCMP(a, rows, indx, determ);
|
|
for i := 0 to rows-1 do
|
|
determ := determ * a[i, i];
|
|
end;
|
|
end; { of determ }
|
|
//-------------------------------------------------------------------
|
|
|
|
procedure EffectCode(GridCol, min, max: integer; FactLetter: string;
|
|
var StartCol, EndCol, NoVectors: integer);
|
|
var
|
|
levels, i, j, grp, col, cval: integer;
|
|
coef: IntDyneMat = nil;
|
|
labelstr: string;
|
|
begin
|
|
Assert(OS3MainFrm <> nil);
|
|
Assert(DictionaryFrm <> nil);
|
|
|
|
// Routine for creating coded vectors representing group membership
|
|
// for purposes of multiple regression effects of group membership
|
|
levels := max - min + 1;
|
|
SetLength(coef,levels,levels);
|
|
novectors := levels - 1;
|
|
startcol := NoVariables + 1;
|
|
endcol := startcol + novectors - 1;
|
|
|
|
// setup grid for additional columns
|
|
for i := 1 to levels - 1 do
|
|
begin
|
|
labelstr := FactLetter + IntToStr(i);
|
|
col := NoVariables + 1;
|
|
DictionaryFrm.NewVar(col);
|
|
DictionaryFrm.DictGrid.Cells[1,col] := labelstr;
|
|
OS3MainFrm.DataGrid.Cells[col,0] := labelstr;
|
|
end;
|
|
|
|
// get coefficients for effect coding
|
|
for i := 1 to levels do // group code
|
|
begin
|
|
for j := 1 to levels - 1 do // vector code
|
|
begin
|
|
if i = j then coef[i-1,j-1] := 1;
|
|
if i = levels then coef[i-1,j-1] := -1;
|
|
if (i <> j) and (i <> levels) then coef[i-1,j-1] := 0;
|
|
end;
|
|
end;
|
|
|
|
// code the cases using coefficients above
|
|
col := NoVariables - (levels - 1);
|
|
for i := 1 to levels - 1 do
|
|
begin
|
|
col := col + 1;
|
|
for j := 1 to NoCases do
|
|
begin
|
|
// subject group code
|
|
grp := round(StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[GridCol,j]))) - min + 1;
|
|
// vector code
|
|
cval := coef[grp-1,i-1];
|
|
OS3MainFrm.DataGrid.Cells[col,j] := IntToStr(cval);
|
|
end;
|
|
end;
|
|
|
|
OS3MainFrm.NoVarsEdit.Text := IntToStr(NoVariables);
|
|
coef := nil;
|
|
end;
|
|
|
|
{ Calculates a multiple regression on data in the mainform's grid
|
|
|
|
NoIndep ..... Count of independent variables
|
|
IndepCols ... Grid column indices of the independent variables
|
|
DepCol ...... Grid column index of the dependent variable
|
|
RowLabels ... Names of the independent variables (they will be displayed in the
|
|
printout of matrices as rowlabels.
|
|
Means ....... Mean value for each independent variable
|
|
Variances ... Variance of each independent variable
|
|
StdDevs ..... Standard deviations of each independent variable
|
|
|
|
NCases ...... Count valid cases in the grid
|
|
ErrorCode ... if true, an error has occured during the calculations
|
|
PrintAll .... if true, intermediate matrices and vectors are written to the report
|
|
AReport ..... a string list to which the report is written.
|
|
}
|
|
procedure MReg(NoIndep: integer; const IndepCols: IntDyneVec; DepCol: integer;
|
|
const RowLabels: StrDyneVec;
|
|
const Means, Variances, StdDevs, BWeights, BetaWeights, BStdErrs, Bttests, tProbs: DblDyneVec;
|
|
out R2, StdErrEst: double; NCases: integer; out ErrorCode: boolean;
|
|
PrintAll: boolean; AReport: TStrings);
|
|
var
|
|
i, j, N: integer;
|
|
X: DblDyneMat = nil;
|
|
XT: DblDyneMat = nil;
|
|
XTX: DblDyneMat = nil;
|
|
XTY: DblDyneVec = nil;
|
|
Y: DblDyneVec = nil;
|
|
indx: IntDyneVec = nil;
|
|
ColLabels: StrDyneVec = nil;
|
|
F, Prob, VarY, SDY, MeanY: double;
|
|
value, TOL, VIF, AdjR2: double;
|
|
SSY, SSres, resvar, SSreg: double;
|
|
title: string;
|
|
deplabel: string;
|
|
begin
|
|
Assert(OS3MainFrm <> nil);
|
|
|
|
SetLength(X, NoCases+1, NoIndep+1); // augmented independent var. matrix
|
|
SetLength(XT, NoIndep+1, NoCases); // transpose of independent var's
|
|
SetLength(XTX, NoIndep+1, NoIndep+1); // product of (transpose X) times X
|
|
SetLength(Y, NCases+1); // Y variable values
|
|
SetLength(XTY, NoIndep+1); // (X transpose) times Y
|
|
SetLength(indx, NoIndep+1);
|
|
SetLength(ColLabels, NCases);
|
|
|
|
// initialize
|
|
ErrorCode := false;
|
|
for i := 0 to NCases do
|
|
begin
|
|
for j := 0 to NoIndep do X[i, j] := 0;
|
|
Y[i] := 0.0;
|
|
end;
|
|
for i := 0 to NoIndep do
|
|
begin
|
|
indx[i] := 0;
|
|
XTY[i] := 0.0;
|
|
Y[i] := 0.0;
|
|
tprobs[i] := 0.0;
|
|
Means[i] := 0.0;
|
|
Variances[i] := 0.0;
|
|
StdDevs[i] := 0.0;
|
|
BWeights[i] := 0.0;
|
|
BetaWeights[i] := 0.0;
|
|
for j := 0 to NoCases-1 do XT[i, j] := 0.0;
|
|
for j := 0 to NoIndep do XTX[i, j] := 0.0;
|
|
end;
|
|
for i := 0 to NCases-1 do
|
|
ColLabels[i] := 'Case ' + IntToStr(i+1);
|
|
|
|
SSY := 0.0;
|
|
VarY := 0.0;
|
|
SDY := 0.0;
|
|
MeanY := 0.0;
|
|
|
|
// get independent matrix and Y vector from the grid
|
|
NCases := 0;
|
|
N := NoIndep + 1;
|
|
|
|
for i := 1 to NoCases do
|
|
begin
|
|
if not GoodRecord(i, Noindep, IndepCols) then continue;
|
|
for j := 0 to NoIndep-1 do
|
|
begin
|
|
value := StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[IndepCols[j], i]));
|
|
X[NCases, j] := value;
|
|
Means[j] := Means[j] + value;
|
|
Variances[j] := Variances[j] + value * value;
|
|
end;
|
|
value := StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[DepCol, i]));
|
|
Y[NCases] := value;
|
|
MeanY := MeanY + value;
|
|
SSY := SSY + value * value;
|
|
Means[Noindep] := Means[Noindep] + value;
|
|
Variances[Noindep] := Variances[Noindep] + value * value;
|
|
NCases := NCases + 1;
|
|
end;
|
|
|
|
deplabel := OS3MainFrm.DataGrid.Cells[DepCol,0];
|
|
RowLabels[NoIndep] := 'Intercept';
|
|
VarY := SSY - sqr(MeanY) / NCases;
|
|
VarY := VarY / (NCases - 1);
|
|
SDY := sqrt(VarY);
|
|
|
|
AReport.Add('Sum of Squares Y: %20.3f', [SSY]);
|
|
AReport.Add('Variance Y: %20.3f', [VarY]);
|
|
AReport.Add('Std. Deviation Y: %20.3f', [SDY]);
|
|
AReport.Add('');
|
|
AReport.Add(DIVIDER_SMALL);
|
|
|
|
// augment the matrix
|
|
for i := 0 to NCases-1 do
|
|
X[i, NoIndep] := 1.0;
|
|
Y[NCases] := 1.0;
|
|
|
|
// get transpose of augmented X matrix
|
|
MatTrn(XT, X, NCases, NoIndep+1);
|
|
if PrintAll then
|
|
begin
|
|
AReport.Add('');
|
|
title := 'XT MATRIX';
|
|
MatPrint(XT, NoIndep+1, NCases, title, RowLabels, ColLabels, NCases, AReport);
|
|
AReport.Add(DIVIDER_SMALL);
|
|
AReport.Add('');
|
|
end;
|
|
|
|
// get product of the augmented X transpose times augmented X
|
|
MatAXB(XTX, XT, X, NoIndep+1, NCases, NCases, NoIndep+1, errorcode);
|
|
if errorCode then
|
|
exit;
|
|
|
|
if PrintAll then
|
|
begin
|
|
title := 'XTX MATRIX';
|
|
MatPrint(XTX, Noindep+1, NoIndep+1, title, RowLabels, RowLabels, NCases, AReport);
|
|
AReport.Add(DIVIDER_SMALL);
|
|
AReport.Add('');
|
|
end;
|
|
|
|
//Get means, variances and standard deviations
|
|
errorcode := false;
|
|
for i := 0 to NoIndep do
|
|
begin
|
|
Variances[i] := XTX[i,i] - sqr(XTX[i, NoIndep])/NCases;
|
|
Variances[i] := Variances[i] / (NCases - 1);
|
|
if (Variances[i] > 0.0) then
|
|
StdDevs[i] := sqrt(Variances[i])
|
|
else
|
|
errorcode := true;
|
|
Means[i] := XTX[N-1,i] / NCases;
|
|
end;
|
|
|
|
if PrintAll then
|
|
begin
|
|
DynVectorPrint(Means, NoIndep+1, 'MEANS', RowLabels, NCases, AReport);
|
|
AReport.Add(DIVIDER_SMALL);
|
|
AReport.Add('');
|
|
DynVectorPrint(Variances, NoIndep+1,'VARIANCES',RowLabels, NCases, AReport);
|
|
AReport.Add(DIVIDER_SMALL);
|
|
AReport.Add('');
|
|
DynVectorPrint(StdDevs, NoIndep+1, 'STD. DEVs', RowLabels, NCases, AReport);
|
|
AReport.Add(DIVIDER_SMALL);
|
|
AReport.Add('');
|
|
end;
|
|
|
|
// get product of the augmented X transpose matrix times the Y vector
|
|
for i := 0 to N-1 do
|
|
for j := 0 to NCases-1 do
|
|
XTY[i] := XTY[i] + (XT[i,j] * Y[j]);
|
|
if PrintAll then
|
|
begin
|
|
DynVectorPrint(XTY, NoIndep+1, 'XTY VECTOR', RowLabels, NCases, AReport);
|
|
AReport.Add(DIVIDER_SMALL);
|
|
end;
|
|
|
|
// get inverse of the augmented cross products matrix among independent variables
|
|
SVDInverse(XTX,N);
|
|
if PrintAll then
|
|
begin
|
|
AReport.Add('');
|
|
title := 'XTX MATRIX INVERSE';
|
|
MatPrint(XTX, NoIndep+1, NoIndep+1, title, RowLabels, RowLabels, NCases, AReport);
|
|
AReport.Add(DIVIDER);
|
|
end;
|
|
|
|
// multiply augmented inverse matrix times the XTY vector
|
|
// result is bweights with the intercept last
|
|
for i := 0 to N-1 do
|
|
for j := 0 to N-1 do
|
|
BWeights[i] := BWeights[i] + (XTX[i,j] * XTY[j]);
|
|
|
|
//Get Beta weightw
|
|
for i := 0 to N-2 do
|
|
BetaWeights[i] := BWeights[i] * StdDevs[i] / SDY;
|
|
|
|
// Get standard errors, squared multiple correlation, tests of significance
|
|
SSres := 0.0;
|
|
for i := 0 to NoIndep do
|
|
SSres := SSres + BWeights[i] * XTY[i];
|
|
SSres := SSY - SSres;
|
|
resvar := SSres / (NCases - N);
|
|
if resvar > 0.0 then StdErrEst := sqrt(resvar) else StdErrest := 0.0;
|
|
for i := 0 to N-1 do // Standard errors and t-tedt values for weights
|
|
begin
|
|
BStdErrs[i] := sqrt(resvar * XTX[i,i]);
|
|
Bttests[i] := BWeights[i] / BStdErrs[i];
|
|
tprobs[i] := probt(Bttests[i],NCases-N);
|
|
end;
|
|
SSY := VarY * (NCases-1);
|
|
SSreg := SSY - SSres;
|
|
R2 := SSreg / SSY;
|
|
F := (SSreg / (N - 1)) / (SSres / (NCases - N));
|
|
Prob := ProbF(F, N-1, NCases-N);
|
|
AdjR2 := 1.0 - (1.0 - R2) * (NCases - 1) / (NCases - N);
|
|
if PrintAll then
|
|
begin
|
|
AReport.Add('');
|
|
AReport.Add('Dependent variable: ' + deplabel);
|
|
AReport.Add('');
|
|
DynVectorPrint(BWeights, NoIndep+1, 'B WEIGHTS', RowLabels, NCases, AReport);
|
|
AReport.Add(DIVIDER_SMALL);
|
|
AReport.Add('');
|
|
AReport.Add('Dependent variable: ' + deplabel);
|
|
AReport.Add('');
|
|
DynVectorPrint(BetaWeights, NoIndep, 'BETA WEIGHTS', RowLabels, NCases, AReport);
|
|
AReport.Add(DIVIDER_SMALL);
|
|
AReport.Add('');
|
|
DynVectorPrint(BStdErrs, NoIndep+1, 'B STD.ERRORS', RowLabels, NCases, AReport);
|
|
AReport.Add('');
|
|
DynVectorPrint(Bttests, NoIndep+1, 'B t-test VALUES', RowLabels, NCases, AReport);
|
|
AReport.Add('');
|
|
DynVectorPrint(tprobs, NoIndep+1, 'B t VALUE PROBABILITIES', RowLabels, NCases, AReport);
|
|
AReport.Add(DIVIDER);
|
|
AReport.Add('');
|
|
AReport.Add('SSY: %10.2f', [SSY]);
|
|
AReport.Add('SSreg: %10.2f', [SSreg]);
|
|
AReport.Add('SSres: %10.2f', [SSres]);
|
|
AReport.Add('R2: %10.4f', [R2]);
|
|
AReport.Add('F: %10.2f (D.F. %d, %d)', [F, N-1, NCases-N]);
|
|
// AReport.Add('D.F. %d %d', [N-1, NCases-N]);
|
|
AReport.Add('Probability > F: %10.4f', [Prob]);
|
|
AReport.Add('Standard Error of Estimate: %10.2f', [stderrest]);
|
|
AReport.Add('');
|
|
|
|
//AReport.Add('SSY = %10.2f, SSreg = %10.2f, SSres = %10.2f', [SSY, SSreg, SSres]);
|
|
//AReport.Add('R2 = %6.4f, F = %8.2f, D.F. = %d %d, Prob>F = %6.4f', [R2, F, N-1, NCases-N, Prob]);
|
|
//AReport.Add('Standard Error of Estimate = %8.2f', [stderrest]);
|
|
end;
|
|
|
|
// Needed for calculation of VIF and TOL
|
|
Correlations(NoIndep, IndepCols, XTX, Means, Variances, StdDevs, ErrorCode, NCases);
|
|
SVDinverse(XTX, NoIndep);
|
|
|
|
AReport.Add(DIVIDER_SMALL);
|
|
AReport.Add('');
|
|
RowLabels[N-1] := 'Intercept';
|
|
AReport.Add(' Variable Beta B Std.Err. t prob VIF TOL');
|
|
AReport.Add('---------- ---------- ---------- ---------- ---------- ---------- --------- ----------');
|
|
for i := 0 to NoIndep do
|
|
begin
|
|
VIF := XTX[i,i];
|
|
if VIF > 0.0 then TOL := 1.0 / VIF else TOL := 0.0;
|
|
AReport.Add('%10s %10.3f %10.3f %10.3f %10.3f %10.3f %10.3f %10.3f', [
|
|
RowLabels[i], BetaWeights[i], BWeights[i], BStdErrs[i], Bttests[i], tprobs[i], VIF, TOL
|
|
]);
|
|
end;
|
|
AReport.Add('');
|
|
AReport.Add('SOURCE DF SS MS F Prob. > F');
|
|
AReport.Add('---------- --- -------------- -------------- -------------- ----------');
|
|
AReport.Add('Regression %3d %14.3f %14.3f %14.4f %10.4f', [N-1, SSreg, SSreg/(N-1), F, Prob]); // df1
|
|
AReport.Add('Residual %3d %14.3f %14.3f', [(NCases-N), SSres, SSres/(NCases-N)]); // df2
|
|
AReport.Add('Total %3d %14.3f', [NCases-1, SSY]);
|
|
AReport.Add('');
|
|
|
|
AReport.Add('R2: %10.4f', [R2]);
|
|
AReport.Add('F: %10.2f (D.F. %d, %d)', [F, N-1, NCases-N]);
|
|
// AReport.Add('D.F. %d and %d', [N-1, NCases-N]);
|
|
AReport.Add('Probability > F: %10.4f', [Prob]);
|
|
AReport.Add('Adjusted R2: %10.4f', [AdjR2]);
|
|
AReport.Add('Standard Error of Estimate: %10.2f', [stderrest]);
|
|
|
|
//AReport.Add('R2 = %6.4f, F = %8.2f, D.F. = %d %d Prob.>F = %6.4f', [R2, F, N-1, NCases-N, Prob]);
|
|
//AReport.Add('Adjusted R2 = %6.4f', [AdjR2]);
|
|
//AReport.Add('Standard Error of Estimate = %8.2f', [stderrest]);
|
|
|
|
// clean up the heap
|
|
ColLabels := nil;
|
|
indx := nil;
|
|
XTY := nil;
|
|
Y := nil;
|
|
XTX := nil;
|
|
XT := nil;
|
|
X := nil;
|
|
end;
|
|
//-------------------------------------------------------------------
|
|
|
|
procedure Dynnonsymroots(var a : DblDyneMat; nv : integer;
|
|
var nf : integer; c : real;
|
|
var v : DblDyneMat; var e : DblDyneVec;
|
|
var px : DblDyneVec;
|
|
var t : double;
|
|
var ev : double);
|
|
{ roots and vectors of a non symetric matrix. a is square matrix entered
|
|
and is destroyed in process. nv is number of variables (rows and columns )
|
|
of a. nf is the number of factorsto be extracted - is output as the number
|
|
which exceeded c, the minimum eigenvalue to be extracted. v is the output
|
|
matrix of column vectors of loadings. e is the output vector of roots. px
|
|
is the percentages of trace for factors. t is the trace of the matrix and
|
|
ev is the percent of trace extracted }
|
|
label 40;
|
|
var
|
|
y: DblDyneVec = nil;
|
|
z: DblDyneVec = nil;
|
|
ek, e2, d : real;
|
|
i, j, k, m : integer;
|
|
begin
|
|
SetLength(y,nv);
|
|
SetLength(z,nv);
|
|
t := 0.0;
|
|
for i := 0 to nv-1 do t := t + a[i,i];
|
|
for k := 0 to nf-1 do
|
|
begin
|
|
for i := 0 to nv-1 do
|
|
begin
|
|
px[i] := 1.0;
|
|
y[i] := 1.0;
|
|
end;
|
|
e[k] := 1.0;
|
|
ek := 1.0;
|
|
for m := 1 to 25 do
|
|
begin
|
|
for i := 0 to nv-1 do
|
|
begin
|
|
v[i,k] := px[i] / e[k];
|
|
z[i] := y[i] / ek;
|
|
end;
|
|
for i := 0 to nv - 1 do
|
|
begin
|
|
px[i] := 0.0;
|
|
for j := 0 to nv-1 do px[i] := px[i] + a[i,j] * v[j,k];
|
|
y[i] := 0.0;
|
|
for j := 0 to nv-1 do y[i] := y[i] + a[j,i] * z[j];
|
|
end;
|
|
e2 := 0.0;
|
|
for j := 0 to nv-1 do e2 := e2 + px[j] * v[j,k];
|
|
e[k] := sqrt(abs(e2));
|
|
ek := 0.0;
|
|
for j := 0 to nv-1 do ek := ek + y[j] * z[j];
|
|
ek := sqrt(abs(ek));
|
|
end;
|
|
if e2 >= sqr(c) then
|
|
begin
|
|
d := 0.0;
|
|
for j := 0 to nv - 1 do d := d + v[j,k] * z[j];
|
|
d := e[k] / d;
|
|
for i := 0 to nv - 1 do
|
|
for j := 0 to nv - 1 do
|
|
a[i,j] := a[i,j] - v[i,k] * z[j] * d;
|
|
end
|
|
else begin
|
|
nf := k - 1;
|
|
goto 40;
|
|
end;
|
|
end;
|
|
40 : for i := 0 to nf-1 do px[i] := e[i] / t * 100.0;
|
|
ev := 0.0;
|
|
for i := 0 to nf-1 do ev := ev + px[i];
|
|
z := nil;
|
|
y := nil;
|
|
end; { of procedure nonsymroots }
|
|
//-----------------------------------------------------------------------------
|
|
|
|
function DynCorrelations(novars : integer;
|
|
VAR ColSelected : IntDyneVec;
|
|
VAR DataGrid : DblDyneMat;
|
|
VAR rmatrix : DblDyneMat;
|
|
VAR means : DblDyneVec;
|
|
VAR vars : DblDyneVec;
|
|
VAR stddevs : DblDyneVec;
|
|
NCases : integer;
|
|
ReturnType : integer) : integer;
|
|
var
|
|
i, j, k, row, col, errorcode : integer;
|
|
X, Y : double;
|
|
begin
|
|
errorcode := 0;
|
|
for i := 0 to novars - 1 do
|
|
begin
|
|
means[i] := 0.0;
|
|
vars[i] := 0.0;
|
|
stdDevs[i] := 0.0;
|
|
for j := 0 to novars - 1 do
|
|
begin
|
|
rmatrix[i,j] := 0.0;
|
|
end;
|
|
end;
|
|
{ get cross products }
|
|
for i := 0 to NCases - 1 do
|
|
begin
|
|
if IsFiltered(i) then continue;
|
|
for j := 0 to novars - 1 do
|
|
begin
|
|
row := ColSelected[j];
|
|
X := DataGrid[i,row];
|
|
means[j] := means[j] + X;
|
|
vars[j] := vars[j] + (X * X);
|
|
for k := 0 to novars - 1 do
|
|
begin
|
|
col := ColSelected[k];
|
|
Y := DataGrid[i,col];
|
|
rmatrix[j,k] := rmatrix[j,k] + (X * Y);
|
|
end;
|
|
end;
|
|
end;
|
|
for j := 0 to novars - 1 do
|
|
begin
|
|
vars[j] := vars[j] - (means[j] * means[j] / NCases);
|
|
vars[j] := vars[j] / (NCases-1);
|
|
if (vars[j] > 0.0) then stddevs[j] := sqrt(vars[j])
|
|
else stddevs[j] := 0.0;
|
|
end;
|
|
if ReturnType = 1 then {return cross-products, variances, std.devs, means }
|
|
begin
|
|
for i := 0 to novars - 1 do
|
|
begin
|
|
means[i] := means[i] / NCases;
|
|
end;
|
|
DynCorrelations := errorcode;
|
|
exit;
|
|
end;
|
|
|
|
for i := 0 to novars - 1 do {get variance-covariance matrix }
|
|
begin
|
|
for j := 0 to novars - 1 do
|
|
begin
|
|
rmatrix[i,j] := rmatrix[i,j] - (means[i] * means[j] / NCases);
|
|
rmatrix[i,j] := rmatrix[i,j] / (NCases - 1);
|
|
end;
|
|
end;
|
|
if ReturnType = 2 then
|
|
begin
|
|
for i := 0 to novars - 1 do
|
|
begin
|
|
means[i] := means[i] / NCases;
|
|
end;
|
|
DynCorrelations := errorcode;
|
|
exit;
|
|
end;
|
|
|
|
for i := 0 to novars - 1 do { get product-moment correlations }
|
|
begin
|
|
for j := 0 to novars - 1 do
|
|
begin
|
|
if ((stddevs[i] > 0.0) and (stddevs[j] > 0.0)) then
|
|
rmatrix[i,j] := rmatrix[i,j] / (stddevs[i] * stddevs[j])
|
|
else
|
|
begin
|
|
rmatrix[i,j] := 9.999;
|
|
errorcode := 1;
|
|
end;
|
|
end;
|
|
end;
|
|
for i := 0 to novars - 1 do
|
|
begin
|
|
means[i] := means[i] / NCases;
|
|
end;
|
|
DynCorrelations := errorcode;
|
|
end;
|
|
//---------------------------------------------------------------------------
|
|
|
|
procedure Predict(VAR ColNoSelected : IntDyneVec;
|
|
NoVars : integer;
|
|
VAR IndepInverse : DblDyneMat;
|
|
VAR Means : DblDyneVec;
|
|
VAR StdDevs : DblDyneVec;
|
|
VAR BetaWeights : DblDyneVec;
|
|
StdErrEst : double;
|
|
VAR IndepIndex : IntDyneVec;
|
|
NoIndepVars : integer);
|
|
var
|
|
col, i, j, k, index, IndexX, IndexY : integer;
|
|
predicted, zpredicted, z1, z2, resid, Term1, Term2 : double;
|
|
StdErrPredict, t95, Hi95, Low95 : double;
|
|
|
|
begin
|
|
Assert(OS3MainFrm <> nil);
|
|
Assert(DictionaryFrm <> nil);
|
|
|
|
{ use the next available grid column to store the z predicted score }
|
|
col := NoVariables + 1;
|
|
DictionaryFrm.NewVar(col);
|
|
DictionaryFrm.DictGrid.Cells[1,col] := 'Pred.z';
|
|
OS3MainFrm.DataGrid.Cells[col,0] := 'Pred.z';
|
|
|
|
col := NoVariables + 1;
|
|
DictionaryFrm.NewVar(col);
|
|
DictionaryFrm.DictGrid.Cells[1,col] := 'z Resid.';
|
|
OS3MainFrm.DataGrid.Cells[col,0] := 'z Resid.';
|
|
|
|
for i := 1 to NoCases do
|
|
begin
|
|
zpredicted := 0.0;
|
|
for j := 1 to NoIndepVars do
|
|
begin
|
|
Index := IndepIndex[j-1];
|
|
k := ColNoSelected[Index-1];
|
|
z1 := (StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[k,i])) -
|
|
Means[Index-1]) / StdDevs[index-1];
|
|
zpredicted := zpredicted + (z1 * BetaWeights[j-1]);
|
|
OS3MainFrm.DataGrid.Cells[col-1,i] := format('%8.4f',[zpredicted]);
|
|
end;
|
|
Index := ColNoSelected[NoVars-1];
|
|
z2 := StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[Index,i]));
|
|
z2 := (z2 - Means[NoVars-1]) / StdDevs[NoVars-1];
|
|
OS3MainFrm.DataGrid.Cells[col,i] := format('%8.4f',[(z2 - zpredicted)]);
|
|
end;
|
|
|
|
col := NoVariables + 1;
|
|
DictionaryFrm.NewVar(col);
|
|
DictionaryFrm.DictGrid.Cells[1,col] := 'Pred.Raw';
|
|
OS3MainFrm.DataGrid.Cells[col,0] := 'Pred.Raw';
|
|
|
|
{ calculate raw predicted scores and store in grid at col }
|
|
for i := 1 to NoCases do
|
|
begin
|
|
predicted := StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[col-2,i])) *
|
|
StdDevs[NoVars-1] + Means[NoVars-1];
|
|
OS3MainFrm.DataGrid.Cells[col,i] := format('%8.3f',[predicted]);
|
|
end;
|
|
|
|
{ Calculate residuals of predicted raw scores }
|
|
col := NoVariables +1;
|
|
DictionaryFrm.NewVar(col);
|
|
DictionaryFrm.DictGrid.Cells[1,col] := 'Raw Resid.';
|
|
OS3MainFrm.DataGrid.Cells[col,0] := 'Raw Resid.';
|
|
|
|
for i := 1 to NoCases do
|
|
begin
|
|
Index := ColNoSelected[NoVars-1];
|
|
resid := StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[col-1,i])) -
|
|
StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[Index,i]));
|
|
OS3MainFrm.DataGrid.Cells[col,i] := Format('%8.3f',[resid]);
|
|
end;
|
|
|
|
{ Calculate Confidence Interval for raw predicted score }
|
|
col := NoVariables + 1;
|
|
DictionaryFrm.NewVar(col);
|
|
DictionaryFrm.DictGrid.Cells[1,col] := 'StdErrPred';
|
|
OS3MainFrm.DataGrid.Cells[col,0] := 'StdErrPred';
|
|
|
|
col := NoVariables + 1;
|
|
DictionaryFrm.NewVar(col);
|
|
DictionaryFrm.DictGrid.Cells[1,col] := 'Low 95%';
|
|
OS3MainFrm.DataGrid.Cells[col,0] := 'Low 95%';
|
|
|
|
col := NoVariables + 1;
|
|
DictionaryFrm.NewVar(col);
|
|
DictionaryFrm.DictGrid.Cells[1,col] := 'Top 95%';
|
|
OS3MainFrm.DataGrid.Cells[col,0] := 'Top 95%';
|
|
|
|
for i := 1 to NoCases do
|
|
begin
|
|
{ get term1 of the std. err. prediction }
|
|
Term1 := 0.0;
|
|
for j := 1 to NoIndepVars do
|
|
begin
|
|
Index := IndepIndex[j-1];
|
|
col := ColNoSelected[Index-1];
|
|
z1 := StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[col,i]));
|
|
z1 := (z1 - Means[Index-1]) / StdDevs[Index-1];
|
|
z1 := (z1 * z1) * IndepInverse[j-1,j-1];
|
|
Term1 := Term1 + z1;
|
|
end;
|
|
{ get term2 of the std err. of prediction }
|
|
term2 := 0.0;
|
|
for j := 1 to NoIndepVars - 1 do
|
|
begin
|
|
for k := j + 1 to NoIndepVars do
|
|
begin
|
|
IndexX := IndepIndex[j-1];
|
|
col := ColNoSelected[IndexX-1];
|
|
z1 := StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[col,i]));
|
|
IndexY := IndepIndex[k-1];
|
|
col := ColNoSelected[IndexY-1];
|
|
z2 := StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[col,i]));
|
|
z1 := (z1 - Means[IndexX-1]) / StdDevs[IndexX-1];
|
|
z2 := (z2 - Means[IndexY-1]) / StdDevs[IndexY-1];
|
|
Term2 := Term2 + IndepInverse[j-1,k-1] * z1 * z2;
|
|
end;
|
|
end;
|
|
term2 := 2.0 * Term2;
|
|
StdErrPredict := sqrt(NoCases + 1 + Term1 + Term2);
|
|
StdErrPredict := (StdErrEst / sqrt(NoCases)) * StdErrPredict;
|
|
t95 := Inverset(0.975,NoCases-NoIndepVars-1);
|
|
low95 := StrToFloat(Trim(OS3MainFrm.DataGrid.Cells[NoVars+4,i]));
|
|
hi95 := low95;
|
|
low95 := low95 - (t95 * StdErrPredict);
|
|
hi95 := hi95 + (t95 * StdErrPredict);
|
|
OS3MainFrm.DataGrid.Cells[NoVariables,i] := Format('%8.3f',[hi95]);
|
|
OS3MainFrm.DataGrid.Cells[NoVariables-1,i] := Format('%8.3f',[low95]);
|
|
OS3MainFrm.DataGrid.Cells[NoVariables-2,i] := Format('%8.3f',[StdErrPredict]);
|
|
end; { next case }
|
|
end;
|
|
//---------------------------------------------------------------------------
|
|
|
|
{ The following routine obtains multiple regression results for a
|
|
correlation matrix consisting of 1 to NoVars. The last variable
|
|
represents the dependent variable. The number of independent
|
|
variables is passed as NoIndepVars. The inverse matrix of independent
|
|
variables may be obtained by the calling program using the variable
|
|
IndepCorrs. The user may request printing of the inverse using the
|
|
boolean variable PrintIt. }
|
|
procedure MReg2(NCases : integer;
|
|
NoVars : integer;
|
|
VAR NoIndepVars : integer;
|
|
VAR IndepIndex : IntDyneVec;
|
|
VAR corrs : DblDyneMat;
|
|
VAR IndepCorrs : DblDyneMat;
|
|
VAR RowLabels : StrDyneVec;
|
|
out R2: double;
|
|
VAR BetaWeights : DblDyneVec;
|
|
VAR Means : DblDyneVec;
|
|
VAR Variances : DblDyneVec;
|
|
out errorcode : integer;
|
|
out StdErrEst: double;
|
|
out constant: double;
|
|
probout : double;
|
|
Printit : boolean;
|
|
TestOut : boolean;
|
|
PrintInv : boolean;
|
|
AReport: TStrings);
|
|
var
|
|
i, j, k, l : integer;
|
|
IndexX, IndexY : integer;
|
|
IndRowLabels : StrDyneVec = nil;
|
|
IndColLabels : StrDyneVec = nil;
|
|
XYCorrs : DblDyneVec = nil;
|
|
df1, df2, df3 : double;
|
|
SSt, SSres, SSreg : double;
|
|
VarEst, F : double;
|
|
FprobF : double;
|
|
outline : string;
|
|
valstring : string;
|
|
title : string;
|
|
deplabel : string;
|
|
sum, B, Beta : double;
|
|
SSx, StdErrB : double;
|
|
AdjR2 : double;
|
|
VIF, TOL : double;
|
|
outcount : integer;
|
|
varsout : IntDyneVec = nil;
|
|
begin
|
|
Assert(AReport <> nil);
|
|
|
|
SetLength(IndRowLabels,NoVars);
|
|
SetLength(IndColLabels,NoVars);
|
|
SetLength(XYCorrs,NoVars);
|
|
SetLength(varsout,NoVars);
|
|
|
|
errorcode := 0;
|
|
outcount := 0;
|
|
VIF := 0.0;
|
|
deplabel := RowLabels[NoVars-1];
|
|
for i := 0 to NoIndepVars-1 do
|
|
begin
|
|
IndexX := IndepIndex[i];
|
|
for j := 0 to NoIndepVars-1 do
|
|
begin
|
|
IndexY := IndepIndex[j];
|
|
IndepCorrs[i,j] := corrs[IndexX-1,IndexY-1];
|
|
end;
|
|
end;
|
|
for i := 0 to NoIndepVars-1 do
|
|
begin
|
|
IndRowLabels[i] := RowLabels[IndepIndex[i]-1];
|
|
IndColLabels[i] := RowLabels[IndepIndex[i]-1];
|
|
XYCorrs[i] := corrs[IndepIndex[i]-1,NoVars-1];
|
|
end;
|
|
SVDinverse(IndepCorrs, NoIndepVars);
|
|
|
|
if PrintInv then
|
|
begin
|
|
title := 'Inverse of independent variables matrix';
|
|
MatPrint(IndepCorrs, NoIndepVars, NoIndepVars, title, IndRowLabels, IndColLabels, NCases, AReport);
|
|
end;
|
|
|
|
{ Get product of inverse matrix times vector of correlations
|
|
between independent and dependent variables }
|
|
R2 := 0.0;
|
|
for i := 0 to NoIndepVars-1 do
|
|
begin
|
|
BetaWeights[i] := 0.0;
|
|
for j := 0 to NoIndepVars-1 do
|
|
BetaWeights[i] := BetaWeights[i] + IndepCorrs[i,j] * XYCorrs[j];
|
|
R2 := R2 + BetaWeights[i] * XYCorrs[i];
|
|
end;
|
|
|
|
df1 := NoIndepVars;
|
|
df2 := NCases - NoIndepVars - 1;
|
|
df3 := NCases - 1;
|
|
SSt := (NCases-1) * Variances[NoVars-1];
|
|
SSres := SSt * (1.0 - R2);
|
|
SSreg := SSt - SSres;
|
|
VarEst := SSres / df2;
|
|
if (VarEst > 0.0) then
|
|
StdErrEst := sqrt(VarEst)
|
|
else
|
|
begin
|
|
MessageDlg('Error in computing variance estimate.', mtError, [mbOK], 0);
|
|
StdErrEst := 0.0;
|
|
end;
|
|
|
|
if (R2 < 1.0) and (df2 > 0.0) and (df1 > 0.0) then
|
|
F := (R2 / df1) / ((1.0-R2)/ df2)
|
|
else
|
|
F := 0.0;
|
|
FProbF := probf(F,df1,df2);
|
|
|
|
AReport.Add('SOURCE DF SS MS F Prob. > F');
|
|
AReport.Add('---------- ---- -------------- -------------- -------------- ---------');
|
|
if df1 = 0 then
|
|
AReport.Add('Regression %4.0f %14.3f %14.3f %14.3f %9.3f', [df1, SSreg, NaN, F, FprobF])
|
|
else
|
|
AReport.Add('Regression %4.0f %14.3f %14.3f %14.3f %9.3f', [df1, SSreg, SSreg/df1, F, FprobF]);
|
|
AReport.Add('Residual %4.0f %14.3f %14.3f', [df2, SSres, SSres/df2]);
|
|
AReport.Add('Total %4.0f %14.3f', [df3, SSt]);
|
|
AReport.Add('');
|
|
|
|
AdjR2 := 1.0 - (1.0 - R2) * (NCases - 1) / df2;
|
|
if PrintIt then
|
|
begin
|
|
AReport.Add('Dependent Variable: ' + deplabel);
|
|
AReport.Add('');
|
|
AReport.Add('%8s %10s %10s %10s %5s %5s', ['R', 'R2', 'F', 'Prob.>F', 'DF1', 'DF2']);
|
|
AReport.Add('-------- ---------- ---------- ---------- ----- -----');
|
|
AReport.Add('%8.3f %10.3f %10.3f %10.3f %5.0f %5.0f', [sqrt(R2), R2, F, FProbF, df1, df2]);
|
|
AReport.Add('Adjusted R Squared: %10.3f', [AdjR2]);
|
|
AReport.Add('');
|
|
AReport.Add('Std. Error of Estimate: %10.3f', [StdErrEst]);
|
|
AReport.Add('');
|
|
AReport.Add('Variable Beta B Std.Error t Prob. > t VIF TOL');
|
|
Areport.Add('---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------');
|
|
end;
|
|
|
|
df1 := 1.0;
|
|
df2 := NCases - NoIndepVars - 1;
|
|
sum := 0.0;
|
|
for i := 0 to NoIndepVars-1 do
|
|
begin
|
|
beta := BetaWeights[i];
|
|
B := beta * sqrt(Variances[NoVars-1]) / sqrt(Variances[IndepIndex[i]-1]);
|
|
sum := sum + B * Means[IndepIndex[i]-1];
|
|
SSx := (NCases-1) * Variances[IndepIndex[i]-1];
|
|
if (IndepCorrs[i,i] > 0.0) and (VarEst > 0.0) then
|
|
begin
|
|
StdErrB := sqrt(VarEst / (SSx * (1.0 / IndepCorrs[i,i])));
|
|
F := B / StdErrB;
|
|
FProbF := probf(F*F,df1,df2);
|
|
VIF := IndepCorrs[i,i];
|
|
TOL := 1.0 / VIF;
|
|
end
|
|
else
|
|
begin
|
|
MessageDlg('Error in estimating std.err. of a B', mtError, [mbOK], 0);
|
|
StdErrB := 0.0;
|
|
F := 0.0;
|
|
FProbF := 0.0;
|
|
end;
|
|
|
|
if PrintIt then
|
|
begin
|
|
valstring := Format('%10s', [IndRowLabels[i]]);
|
|
outline := Format('%10s %10.3f %10.3f %10.3f %10.3f %10.3f %10.3f %10.3f',
|
|
[valstring, beta ,B, StdErrB, F, FProbF, VIF, TOL]);
|
|
if FprobF > ProbOut then
|
|
outline := outline + ' Exceeds limit - to be removed.';
|
|
AReport.Add(outline);
|
|
end;
|
|
|
|
if FprobF > ProbOut then
|
|
begin
|
|
outcount := outcount + 1;
|
|
varsout[outcount-1] := IndepIndex[i];
|
|
end;
|
|
end;
|
|
|
|
if PrintIt then
|
|
AReport.Add('');
|
|
|
|
{ Get constant }
|
|
constant := Means[NoVars-1] - sum;
|
|
if PrintIt then
|
|
AReport.Add('Constant: %10.3f', [constant]);
|
|
|
|
{ Now remove any variables that exceed tolerance }
|
|
if (outcount > 0) and (TestOut = true) then
|
|
begin
|
|
for i := 0 to outcount-1 do
|
|
begin
|
|
k := varsout[i]; { variable to eliminate }
|
|
for j := 0 to NoIndepVars-1 do
|
|
begin
|
|
if IndepIndex[j] = k then {eliminate this one }
|
|
begin
|
|
for l := j to NoIndepVars-2 do
|
|
IndepIndex[l] := IndepIndex[l+1];
|
|
end;
|
|
end;
|
|
end;
|
|
NoIndepVars := NoIndepVars - outcount;
|
|
errorcode := outcount;
|
|
end;
|
|
|
|
varsout := nil;
|
|
XYCorrs := nil;
|
|
IndColLabels := nil;
|
|
IndRowLabels := nil;
|
|
end;
|
|
//---------------------------------------------------------------------------
|
|
|
|
procedure MatSub(const a, b, c: DblDyneMat;
|
|
brows, bcols, crows, ccols: integer; out errorcode: boolean);
|
|
// Subtracts matrix c from b and returns the results in matrix a
|
|
var
|
|
i, j: integer;
|
|
begin
|
|
errorcode := false;
|
|
if (brows <> crows) or (bcols <> ccols) then
|
|
errorcode := true
|
|
else
|
|
begin
|
|
for i := 0 to brows-1 do
|
|
for j := 0 to bcols-1 do
|
|
a[i,j] := b[i,j] - c[i,j];
|
|
end;
|
|
end; { of matsub }
|
|
|
|
procedure IntArrayPrint(const Mat: IntDyneMat; Rows, Cols: integer;
|
|
const YTitle: string; const RowLabels, ColLabels: StrDyneVec;
|
|
const Title: string; AReport: TStrings);
|
|
var
|
|
i, j, first, last, nflds: integer;
|
|
done : boolean;
|
|
outline: string;
|
|
begin
|
|
AReport.Add('');
|
|
AReport.Add(Title);
|
|
AReport.Add('');
|
|
nflds := 4;
|
|
done := FALSE;
|
|
first := 1;
|
|
|
|
while not done do
|
|
begin
|
|
AReport.Add(' ' + ytitle);;
|
|
AReport.Add('Variables');
|
|
|
|
outline := DupeString(' ', 12+1);
|
|
last := first + nflds;
|
|
if last >= cols then
|
|
begin
|
|
done := TRUE;
|
|
last := cols
|
|
end;
|
|
for i := first to last do
|
|
outline := outline + Format('%12s ', [ColLabels[i-1]]);
|
|
AReport.Add(outline);
|
|
|
|
for i := 1 to rows do
|
|
begin
|
|
outline := Format('%12s ', [RowLabels[i-1]]);
|
|
for j := first to last do
|
|
outline := outline + Format('%12d ',[mat[i-1,j-1]]);
|
|
AReport.Add(outline);
|
|
end;
|
|
AReport.Add('');
|
|
first := last + 1;
|
|
end;
|
|
AReport.Add('');
|
|
end;
|
|
//---------------------------------------------------------------------------
|
|
|
|
procedure eigens(VAR a: DblDyneMat; Var d : DblDyneVec; n : integer);
|
|
var
|
|
e: DblDyneVec = nil;
|
|
i: integer;
|
|
begin
|
|
SetLength(e,n);
|
|
for i := 1 to n do
|
|
begin
|
|
d[i-1] := 0.0;
|
|
e[i-1] := 0.0;
|
|
end;
|
|
|
|
tred2(a, n, d ,e ); { Upon return, d contains diagonal values, e contains
|
|
off diagonal values, and a contains the orthogonal
|
|
matrix from the tridiagonalization of the a matrix }
|
|
|
|
tqli(d, e, n, a); { Upon return, d contains eigenvalues, a the column
|
|
eigenvectors of the tridiagonal matrix (in d and e). }
|
|
e := nil;
|
|
end; { Procedure eigens }
|
|
//-------------------------------------------------------------------
|
|
|
|
PROCEDURE tred2(VAR a: DblDyneMat; n: integer; VAR d,e: DblDyneVec);
|
|
(* Programs using routine TRED2 must define the types
|
|
TYPE
|
|
glnp = ARRAY [1..np] OF real;
|
|
glnpnp = ARRAY [1..np,1..np] OF real;
|
|
where 'np by np' is the physical dimension of the matrix to be analyzed. *)
|
|
|
|
VAR
|
|
l,k,j,i: integer;
|
|
scale,hh,h,g,f: double;
|
|
BEGIN
|
|
IF (n > 1) THEN BEGIN
|
|
FOR i := n DOWNTO 2 DO BEGIN
|
|
l := i-1;
|
|
h := 0.0;
|
|
scale := 0.0;
|
|
IF (l > 1) THEN BEGIN
|
|
FOR k := 1 to l DO BEGIN
|
|
scale := scale+abs(a[i-1,k-1])
|
|
END;
|
|
IF (scale = 0.0) THEN BEGIN
|
|
e[i-1] := a[i-1,l-1]
|
|
END ELSE BEGIN
|
|
FOR k := 1 to l DO BEGIN
|
|
a[i-1,k-1] := a[i-1,k-1]/scale;
|
|
h := h+sqr(a[i-1,k-1])
|
|
END;
|
|
f := a[i-1,l-1];
|
|
g := -sign(sqrt(h),f);
|
|
e[i-1] := scale*g;
|
|
h := h-f*g;
|
|
a[i-1,l-1] := f-g;
|
|
f := 0.0;
|
|
FOR j := 1 to l DO BEGIN
|
|
(* Next statement can be omitted if eigenvectors not wanted *)
|
|
a[j-1,i-1] := a[i-1,j-1]/h;
|
|
g := 0.0;
|
|
FOR k := 1 to j DO BEGIN
|
|
g := g+a[j-1,k-1]*a[i-1,k-1]
|
|
END;
|
|
IF (l > j) THEN FOR k := j+1 to l DO g := g+a[k-1,j-1]*a[i-1,k-1];
|
|
e[j-1] := g/h;
|
|
f := f+e[j-1]*a[i-1,j-1]
|
|
END;
|
|
hh := f/(h+h);
|
|
FOR j := 1 to l DO BEGIN
|
|
f := a[i-1,j-1];
|
|
g := e[j-1]-hh*f;
|
|
e[j-1] := g;
|
|
FOR k := 1 to j DO a[j-1,k-1] := a[j-1,k-1]-f*e[k-1]-g*a[i-1,k-1]
|
|
END
|
|
END
|
|
END ELSE BEGIN
|
|
e[i-1] := a[i-1,l-1]
|
|
END;
|
|
d[i-1] := h
|
|
END
|
|
END;
|
|
(* Next statement can be omitted if eigenvectors not wanted *)
|
|
d[0] := 0.0;
|
|
e[0] := 0.0;
|
|
FOR i := 1 to n DO BEGIN
|
|
(* Contents of this loop can be omitted if eigenvectors not wanted,
|
|
except for statement d[i] := a[i,i]; *)
|
|
l := i-1;
|
|
IF (d[i-1] <> 0.0) THEN BEGIN
|
|
FOR j := 1 to l DO BEGIN
|
|
g := 0.0;
|
|
FOR k := 1 to l DO BEGIN
|
|
g := g+a[i-1,k-1]*a[k-1,j-1]
|
|
END;
|
|
FOR k := 1 to l DO BEGIN
|
|
a[k-1,j-1] := a[k-1,j-1]-g*a[k-1,i-1]
|
|
END
|
|
END
|
|
END;
|
|
d[i-1] := a[i-1,i-1];
|
|
a[i-1,i-1] := 1.0;
|
|
IF (l >= 1) THEN BEGIN
|
|
FOR j := 1 to l DO BEGIN
|
|
a[i-1,j-1] := 0.0;
|
|
a[j-1,i-1] := 0.0
|
|
END
|
|
END
|
|
END
|
|
END;
|
|
//-------------------------------------------------------------------
|
|
|
|
PROCEDURE tqli(VAR d,e: DblDyneVec; n: integer; VAR z: DblDyneMat);
|
|
LABEL 1,2;
|
|
VAR
|
|
m,l,iter,i,k: integer;
|
|
s,r,p,g,f,dd,c,b: double;
|
|
BEGIN
|
|
IF (n > 1) THEN BEGIN
|
|
FOR i := 2 to n DO BEGIN
|
|
e[i-2] := e[i-1]
|
|
END;
|
|
e[n-1] := 0.0;
|
|
FOR l := 1 to n DO BEGIN
|
|
iter := 0;
|
|
1: FOR m := l to n-1 DO BEGIN
|
|
dd := abs(d[m-1])+abs(d[m]);
|
|
IF (abs(e[m-1])+ dd = dd) THEN GOTO 2
|
|
END;
|
|
m := n;
|
|
2: IF (m <> l) THEN BEGIN
|
|
IF (iter = 30) THEN BEGIN
|
|
ShowMessage('Too many iterations in routine tqli');
|
|
exit;
|
|
END;
|
|
iter := iter+1;
|
|
g := (d[l]-d[l-1])/(2.0*e[l-1]);
|
|
r := sqrt(sqr(g)+1.0);
|
|
g := d[m-1] - d[l-1] + e[l-1] / (g+sign(r,g));
|
|
s := 1.0;
|
|
c := 1.0;
|
|
p := 0.0;
|
|
FOR i := m-1 DOWNTO l DO BEGIN
|
|
f := s * e[i-1];
|
|
b := c * e[i-1];
|
|
IF (abs(f) >= abs(g)) THEN BEGIN
|
|
c := g / f;
|
|
r := sqrt(sqr(c) + 1.0);
|
|
e[i] := f * r;
|
|
s := 1.0 / r;
|
|
c := c * s
|
|
END ELSE BEGIN
|
|
s := f / g;
|
|
r := sqrt(sqr(s) + 1.0);
|
|
e[i] := g * r;
|
|
c := 1.0 / r;
|
|
s := s * c
|
|
END;
|
|
g := d[i] - p;
|
|
r := (d[i-1] - g) * s + 2.0 * c * b;
|
|
p := s * r;
|
|
d[i] := g + p;
|
|
g := c * r - b;
|
|
(* Next loop can be omitted if eigenvectors not wanted *)
|
|
FOR k := 1 to n DO BEGIN
|
|
f := z[k-1,i];
|
|
z[k-1,i] := s * z[k-1,i-1] + c * f;
|
|
z[k-1,i-1] := c * z[k-1,i-1] - s * f
|
|
END
|
|
END;
|
|
d[l-1] := d[l-1] - p;
|
|
e[l-1] := g;
|
|
e[m-1] := 0.0;
|
|
GOTO 1
|
|
END
|
|
END
|
|
END
|
|
END;
|
|
//-------------------------------------------------------------------
|
|
|
|
function SEVS(nv,nf : integer;
|
|
c : double;
|
|
var r : DblDyneMat;
|
|
VAR v : DblDyneMat;
|
|
VAR e : DblDyneVec;
|
|
var p : DblDyneVec;
|
|
VAR nd : integer) : integer ;
|
|
|
|
{ extracts roots and denormal vectors from a symetric matrix. Veldman, 1967,
|
|
page 209 }
|
|
|
|
label 1,2;
|
|
|
|
var t, ee, ev : double;
|
|
i, j, k, m : integer;
|
|
|
|
begin
|
|
t := 0.0;
|
|
for i := 1 to nv do t := t + r[i-1,i-1];
|
|
for k := 1 to nf do { compute roots in e[k] and vector in v^[.k] }
|
|
begin
|
|
for i := 1 to nv do p[i-1] := 1.0;
|
|
begin
|
|
e[k-1] := 1.0;
|
|
for m := 1 to 25 do
|
|
begin
|
|
for i := 1 to nv do v[i-1,k-1] := p[i-1] / e[k-1];
|
|
for i := 1 to nv do p[i-1] := SCPF(r,v,-i,k,nv,nd);
|
|
ee := 0.0;
|
|
for j := 1 to nv do ee := ee + p[j-1] * v[j-1,k-1];
|
|
e[k-1] := sqrt(abs(ee));
|
|
end;
|
|
end;
|
|
if ee < (c * c) then goto 1;
|
|
for i := 1 to nv do
|
|
for j := 1 to nv do
|
|
r[i-1,j-1] := r[i-1,j-1] - (v[i-1,k-1] * v[j-1,k-1]);
|
|
end;
|
|
goto 2;
|
|
1 : nf := k - 1;
|
|
2 : for i := 1 to nf do p[i-1] := e[i-1] / t * 100.0;
|
|
ev := 0.0;
|
|
for i := 1 to nf do ev := ev + p[i-1];
|
|
{
|
|
stopit;
|
|
writeln(lst);
|
|
writeln(lst,'Root % Extracted');
|
|
for i := 1 to nf do writeln(lst,i:3,' ',p^[i]:6:3);
|
|
writeln(lst,' Trace = ',t:6:3,' % Extracted = ',ev:6:3);
|
|
writeln(lst);
|
|
}
|
|
result := nf;
|
|
end; { of SEVS procedure }
|
|
//-------------------------------------------------------------------
|
|
|
|
function SCPF(VAR x,y : DblDyneMat; kx,ky,n,nd : integer) : double;
|
|
|
|
{ sum of cross products of two vectors. Veldman, 1967, pp 128-129 }
|
|
var j,k,i : integer;
|
|
scp : double;
|
|
|
|
begin
|
|
scp := 0.0;
|
|
scpf := 0.0;
|
|
j := abs(kx);
|
|
k := abs(ky);
|
|
if ((kx = 0) and (ky = 0)) then exit;
|
|
if ((kx < 0) and (ky < 0)) then
|
|
begin
|
|
for i := 1 to n do scp := scp + x[j-1,i-1] * y[k-1,i-1];
|
|
end;
|
|
if ((kx < 0) and (ky > 0)) then
|
|
begin
|
|
for i := 1 to n do scp := scp + x[j-1,i-1] * y[i-1,k-1];
|
|
end;
|
|
if ((kx > 0) and (ky < 0)) then
|
|
begin
|
|
for i := 1 to n do scp := scp + x[i-1,j-1] * y[k-1,i-1];
|
|
end;
|
|
if ((kx > 0) and (ky > 0)) then
|
|
begin
|
|
for i := 1 to n do scp := scp + x[i-1,j-1] * y[i-1,k-1];
|
|
end;
|
|
scpf := scp;
|
|
end; { of SCPF }
|
|
|
|
procedure MatPrint(const xmat: DblDyneMat; Rows, Cols: integer; const Title: string;
|
|
const RowLabels, ColLabels: StrDyneVec; NCases: integer; AReport: TStrings);
|
|
var
|
|
i, j, first, last, nflds: integer;
|
|
done: boolean;
|
|
outline: string;
|
|
valstring: string;
|
|
begin
|
|
Assert(AReport <> nil);
|
|
|
|
AReport.Add('%s with %d cases.', [Title, NCases]);
|
|
AReport.Add('');
|
|
nflds := 4;
|
|
done := FALSE;
|
|
first := 1;
|
|
while not done do
|
|
begin
|
|
AReport.Add('Variables');
|
|
outline := DupeString(' ', 12+1); //' ';
|
|
last := first + nflds;
|
|
if last >= cols then
|
|
begin
|
|
done := true;
|
|
last := cols;
|
|
end;
|
|
for i := first to last do
|
|
outline := outline + Format('%12s ',[ColLabels[i-1]]);
|
|
AReport.Add(outline);
|
|
|
|
for i := 1 to rows do
|
|
begin
|
|
outline := format('%12s ',[RowLabels[i-1]]);
|
|
for j := first to last do
|
|
begin
|
|
valstring := format('%12.3f ',[xmat[i-1,j-1]]);
|
|
outline := outline + valstring;
|
|
end;
|
|
AReport.Add(outline);
|
|
end;
|
|
if not done then AReport.Add('');
|
|
first := last + 1;
|
|
end;
|
|
AReport.Add('');
|
|
end;
|
|
|
|
procedure DynVectorPrint(const AVector: DblDyneVec; NoVars: integer;
|
|
Title: string; const Labels: StrDyneVec; NCases: integer; AReport: TStrings);
|
|
var
|
|
i, j, first, last, nflds: integer;
|
|
done: boolean;
|
|
outline: string;
|
|
valstring: string;
|
|
begin
|
|
Assert(AReport <> nil);
|
|
|
|
// AReport.Add('');
|
|
AReport.Add('%s with %d valid cases.', [Title, NCases]);
|
|
|
|
nflds := 4;
|
|
done := FALSE;
|
|
first := 0;
|
|
while not done do
|
|
begin
|
|
AReport.Add('');
|
|
last := first + nflds;
|
|
if last >= NoVars -1 then
|
|
begin
|
|
done := true;
|
|
last := NoVars-1;
|
|
end;
|
|
|
|
outline := 'Variables '; // 12+1 long
|
|
for i := first to last do
|
|
outline := outline + Format('%12s ', [Labels[i]]);
|
|
AReport.Add(outline);
|
|
|
|
outline := DupeString(' ', 12+1); //' ';
|
|
for j := first to last do
|
|
begin
|
|
valstring := Format('%12.3f ', [AVector[j]]);
|
|
outline := outline + valstring;
|
|
end;
|
|
AReport.Add(outline);
|
|
first := last + 1
|
|
end;
|
|
AReport.Add('');
|
|
end;
|
|
//--------------------------------------------------------------------------
|
|
|
|
procedure ScatPlot(const x, y: DblDyneVec; NoCases: integer;
|
|
const TitleStr, x_axis, y_axis: string; x_min, x_max, y_min, y_max: double;
|
|
const VarLabels: StrDyneVec; AReport: TStrings);
|
|
var
|
|
i, j, l, row, xslot : integer;
|
|
maxy: double;
|
|
incrementx, incrementy, rangex, rangey: double;
|
|
plotstring : array[0..51,0..61] of char;
|
|
height : integer;
|
|
overlap : boolean;
|
|
valuestring : string[2];
|
|
howlong : integer;
|
|
outline : string;
|
|
Labels : StrDyneVec = nil;
|
|
begin
|
|
SetLength(Labels, NoVariables);
|
|
for i := 1 to nocases do Labels[i-1] := VarLabels[i-1];
|
|
height := 40;
|
|
rangex := x_max - x_min ;
|
|
incrementx := rangex / 15.0;
|
|
// xdelta := rangex / 60;
|
|
// xmed := rangex / 2;
|
|
rangey := y_max - y_min;
|
|
incrementy := rangey / height;
|
|
// ymed := rangey / 2;
|
|
|
|
{ sort in descending order }
|
|
for i := 1 to (NoCases - 1) do
|
|
begin
|
|
for j := (i + 1) to NoCases do
|
|
begin
|
|
if y[i-1] < y[j-1] then
|
|
begin
|
|
Exchange(y[i-1], y[j-1]);
|
|
{
|
|
swap := y[i-1];
|
|
y[i-1] := y[j-1];
|
|
y[j-1] := swap;
|
|
}
|
|
Exchange(x[i-1], x[j-1]);
|
|
{
|
|
swap := x[i-1];
|
|
x[i-1] := x[j-1];
|
|
x[j-1] := swap;
|
|
}
|
|
Exchange(Labels[i-1], Labels[j-1]);
|
|
{
|
|
outline := Labels[i-1];
|
|
Labels[i-1] := Labels[j-1];
|
|
Labels[j-1] := outline;
|
|
}
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
AReport.Add(' SCATTERPLOT - ' + TitleStr);
|
|
AReport.Add('');
|
|
AReport.Add(y_axis);
|
|
maxy := y_max;
|
|
for i := 1 to 60 do
|
|
for j := 1 to height+1 do plotstring[j,i] := ' ';
|
|
|
|
{ Set up the plot strings with the data }
|
|
row := 0;
|
|
while maxy > y_min do
|
|
begin
|
|
row := row + 1;
|
|
plotstring[row,30] := '|';
|
|
if (row = (height / 2)) then
|
|
for i := 1 to 60 do plotstring[row,i] := '-';
|
|
for i := 1 to nocases do
|
|
begin
|
|
if ((maxy >= y[i-1]) and (y[i-1] > (maxy - incrementy))) then
|
|
begin
|
|
xslot := round(((x[i-1] - x_min) / rangex) * 60);
|
|
if xslot < 1 then xslot := 1;
|
|
if xslot > 60 then xslot := 60;
|
|
overlap := false;
|
|
str(i:2,valuestring);
|
|
howlong := 1;
|
|
if (valuestring[1] <> ' ') then howlong := 2;
|
|
for l := xslot to (xslot + howlong - 1) do
|
|
if (plotstring[row,l] = '*') then overlap := true;
|
|
if (overlap) then plotstring[row,xslot] := '*'
|
|
else
|
|
begin
|
|
if (howlong < 2) then
|
|
plotstring[row,xslot] := valuestring[2]
|
|
else for l := 1 to 2 do
|
|
plotstring[row,xslot + l - 1] := valuestring[l];
|
|
end;
|
|
end;
|
|
end;
|
|
maxy := maxy - incrementy;
|
|
end;
|
|
|
|
{ print the plot }
|
|
for i := 1 to row do
|
|
begin
|
|
outline := ' |';
|
|
for j := 1 to 60 do outline := outline + Format('%1s', [plotstring[i,j]]);
|
|
outline := outline + Format('|-%6.2f-%6.2f',
|
|
[(y_max - i * incrementy),(y_max - i * incrementy + incrementy)]);
|
|
AReport.Add(outline);
|
|
end;
|
|
|
|
outline := '';
|
|
for i := 1 to 63 do outline := outline + '-';
|
|
AReport.Add(outline);
|
|
|
|
outline := '';
|
|
for i := 1 to 16 do outline := outline + ' | ';
|
|
outline := outline + x_axis;
|
|
AReport.Add(outline);
|
|
|
|
outline := '';
|
|
for i := 1 to 16 do outline := outline + Format('%4.1f', [(x_min + i * incrementx - incrementx)]);
|
|
AReport.Add(outline);
|
|
AReport.Add('');
|
|
AReport.Add('Labels:');
|
|
for i := 1 to nocases do
|
|
AReport.Add('%2d = %s', [i, Labels[i-1]]);
|
|
|
|
Labels := nil;
|
|
end; { of scatplot procedure }
|
|
|
|
procedure DynIntMatPrint(Mat: IntDyneMat; Rows, Cols: integer; YTitle: string;
|
|
RowLabels, ColLabels: StrDyneVec; Title: string; AReport: TStrings);
|
|
var
|
|
i, j, first, last, nflds: integer;
|
|
done: boolean;
|
|
outline: string;
|
|
valstring: string;
|
|
begin
|
|
Assert(AReport <> nil);
|
|
|
|
AReport.Add(Title);
|
|
AReport.Add('');
|
|
|
|
nflds := 4;
|
|
done := false;
|
|
first := 0;
|
|
while not done do
|
|
begin
|
|
AReport.Add('');
|
|
AReport.Add(' ' + ytitle);
|
|
AReport.Add('Variables');
|
|
outline := ' ';
|
|
last := first + nflds;
|
|
if last >= Cols-1 then
|
|
begin
|
|
done := true;
|
|
last := Cols-1;
|
|
end;
|
|
for i := first to last do
|
|
outline := outline + Format('%13s', [ColLabels[i]]);
|
|
AReport.Add(outline);
|
|
|
|
for i := 0 to rows-1 do
|
|
begin
|
|
outline := Format('%10s', [RowLabels[i]]);
|
|
for j := first to last do
|
|
begin
|
|
valstring := Format('%12d ', [Mat[i,j]]);
|
|
outline := outline + valstring;
|
|
end;
|
|
AReport.Add(outline);
|
|
end;
|
|
AReport.Add('');
|
|
first := last + 1
|
|
end;
|
|
AReport.Add('');
|
|
AReport.Add('');
|
|
end;
|
|
|
|
procedure SymMatRoots(A: DblDyneMat; M: integer; var E: DblDyneVec;
|
|
var V: DblDyneMat);
|
|
Label one, three, nine, fifteen;
|
|
var
|
|
L, IT, j, k : integer;
|
|
Test, sum1, sum2 : double;
|
|
X: DblDyneVec = nil;
|
|
Y: DblDyneVec = nil;
|
|
begin
|
|
// Adapted from: "Multivariate Data Analysis" by William W. Cooley and Paul
|
|
// R. Lohnes, 1971, page 121
|
|
SetLength(X, M);
|
|
SetLength(Y, M);
|
|
sum2 := 0.0;
|
|
L := 0;
|
|
Test := 0.00000001;
|
|
one:
|
|
IT := 0;
|
|
for j := 0 to M-1 do Y[j] := 1.0;
|
|
three:
|
|
IT := IT + 1;
|
|
for j := 0 to M-1 do
|
|
begin
|
|
X[j] := 0.0;
|
|
for k := 0 to M-1 do X[j] := X[j] + (A[j,k] * Y[k]);
|
|
end;
|
|
E[L] := X[0];
|
|
Sum1 := 0.0;
|
|
for j := 0 to M-1 do
|
|
begin
|
|
V[j,L] := X[j] / X[0];
|
|
Sum1 := Sum1 + abs(Y[j] - V[j,L]);
|
|
Y[j] := V[j,L];
|
|
end;
|
|
if (IT - 10) <> 0 then goto nine;
|
|
if (Sum2 - Sum1) > 0 then goto nine
|
|
else
|
|
begin
|
|
showmessage('Root not converging. Exiting.');
|
|
exit;
|
|
end;
|
|
nine:
|
|
Sum2 := Sum1;
|
|
if (Sum1 - Test) > 0 then goto three;
|
|
Sum1 := 0.0;
|
|
for j := 0 to M-1 do Sum1 := Sum1 + (V[j,L] * V[j,L]);
|
|
Sum1 := sqrt(Sum1);
|
|
for j := 0 to M-1 do V[j,L] := V[j,L] / Sum1;
|
|
for j := 0 to M-1 do
|
|
for k := 0 to M-1 do
|
|
A[j,k] := A[j,k] - (V[j,L] * V[k,L] * E[L]);
|
|
if ((M-1)-L) <= 0 then goto fifteen;
|
|
L := L + 1;
|
|
goto one;
|
|
fifteen:
|
|
X := nil;
|
|
Y := nil;
|
|
end;
|
|
|
|
procedure matinv(a, vtimesw, v, w: DblDyneMat; n: integer);
|
|
LABEL 1,2,3;
|
|
|
|
var
|
|
ainverse: array of array of double = nil;
|
|
rv1: array of double = nil;
|
|
m,nm,l,k,j,its,i: integer;
|
|
z,y,x,scale,s,h,g,f,c,anorm: double;
|
|
|
|
begin
|
|
setlength(rv1,n);
|
|
setlength(ainverse,n,n);
|
|
m := n;
|
|
g := 0.0;
|
|
scale := 0.0;
|
|
anorm := 0.0;
|
|
FOR i := 0 to n-1 DO BEGIN
|
|
l := i+1;
|
|
rv1[i] := scale*g;
|
|
g := 0.0;
|
|
s := 0.0;
|
|
scale := 0.0;
|
|
IF (i <= m-1) THEN BEGIN
|
|
FOR k := i to m-1 DO BEGIN
|
|
scale := scale+abs(a[k,i])
|
|
END;
|
|
IF (scale <> 0.0) THEN BEGIN
|
|
FOR k := i to m-1 DO BEGIN
|
|
a[k,i] := a[k,i]/scale;
|
|
s := s+a[k,i]*a[k,i]
|
|
END;
|
|
f := a[i,i];
|
|
g := -sign(sqrt(s),f);
|
|
h := f*g-s;
|
|
a[i,i] := f-g;
|
|
IF (i <> n-1) THEN BEGIN
|
|
FOR j := l to n-1 DO BEGIN
|
|
s := 0.0;
|
|
FOR k := i to m-1 DO BEGIN
|
|
s := s+a[k,i]*a[k,j]
|
|
END;
|
|
f := s/h;
|
|
FOR k := i to m-1 DO BEGIN
|
|
a[k,j] := a[k,j]+
|
|
f*a[k,i]
|
|
END
|
|
END
|
|
END;
|
|
FOR k := i to m-1 DO BEGIN
|
|
a[k,i] := scale*a[k,i]
|
|
END
|
|
END
|
|
END;
|
|
w[i,i] := scale*g;
|
|
g := 0.0;
|
|
s := 0.0;
|
|
scale := 0.0;
|
|
IF ((i <= m-1) AND (i <> n-1)) THEN BEGIN
|
|
FOR k := l to n-1 DO BEGIN
|
|
scale := scale+abs(a[i,k])
|
|
END;
|
|
IF (scale <> 0.0) THEN BEGIN
|
|
FOR k := l to n-1 DO BEGIN
|
|
a[i,k] := a[i,k]/scale;
|
|
s := s+a[i,k]*a[i,k]
|
|
END;
|
|
f := a[i,l];
|
|
g := -sign(sqrt(s),f);
|
|
h := f*g-s;
|
|
a[i,l] := f-g;
|
|
FOR k := l to n-1 DO BEGIN
|
|
rv1[k] := a[i,k]/h
|
|
END;
|
|
IF (i <> m-1) THEN BEGIN
|
|
FOR j := l to m-1 DO BEGIN
|
|
s := 0.0;
|
|
FOR k := l to n-1 DO BEGIN
|
|
s := s+a[j,k]*a[i,k]
|
|
END;
|
|
FOR k := l to n-1 DO BEGIN
|
|
a[j,k] := a[j,k]
|
|
+s*rv1[k]
|
|
END
|
|
END
|
|
END;
|
|
FOR k := l to n-1 DO BEGIN
|
|
a[i,k] := scale*a[i,k]
|
|
END
|
|
END
|
|
END;
|
|
anorm := max(anorm,(abs(w[i,i])+abs(rv1[i])))
|
|
END;
|
|
FOR i := n-1 DOWNTO 0 DO BEGIN
|
|
IF (i < n-1) THEN BEGIN
|
|
IF (g <> 0.0) THEN BEGIN
|
|
FOR j := l to n-1 DO BEGIN
|
|
v[j,i] := (a[i,j]/a[i,l])/g
|
|
END;
|
|
FOR j := l to n-1 DO BEGIN
|
|
s := 0.0;
|
|
FOR k := l to n-1 DO BEGIN
|
|
s := s+a[i,k]*v[k,j]
|
|
END;
|
|
FOR k := l to n-1 DO BEGIN
|
|
v[k,j] := v[k,j]+s*v[k,i]
|
|
END
|
|
END
|
|
END;
|
|
FOR j := l to n-1 DO BEGIN
|
|
v[i,j] := 0.0;
|
|
v[j,i] := 0.0
|
|
END
|
|
END;
|
|
v[i,i] := 1.0;
|
|
g := rv1[i];
|
|
l := i
|
|
END;
|
|
FOR i := n-1 DOWNTO 0 DO BEGIN
|
|
l := i+1;
|
|
g := w[i,i];
|
|
IF (i < n-1) THEN BEGIN
|
|
FOR j := l to n-1 DO BEGIN
|
|
a[i,j] := 0.0
|
|
END
|
|
END;
|
|
IF (g <> 0.0) THEN BEGIN
|
|
g := 1.0/g;
|
|
IF (i <> n-1) THEN BEGIN
|
|
FOR j := l to n-1 DO BEGIN
|
|
s := 0.0;
|
|
FOR k := l to m-1 DO BEGIN
|
|
s := s+a[k,i]*a[k,j]
|
|
END;
|
|
f := (s/a[i,i])*g;
|
|
FOR k := i to m-1 DO BEGIN
|
|
a[k,j] := a[k,j]+f*a[k,i]
|
|
END
|
|
END
|
|
END;
|
|
FOR j := i to m-1 DO BEGIN
|
|
a[j,i] := a[j,i]*g
|
|
END
|
|
END ELSE BEGIN
|
|
FOR j := i to m-1 DO BEGIN
|
|
a[j,i] := 0.0
|
|
END
|
|
END;
|
|
a[i,i] := a[i,i]+1.0
|
|
END;
|
|
FOR k := n-1 DOWNTO 0 DO BEGIN
|
|
FOR its := 1 to 30 DO BEGIN
|
|
FOR l := k DOWNTO 0 DO BEGIN
|
|
nm := l-1;
|
|
IF ((abs(rv1[l])+anorm) = anorm) THEN GOTO 2;
|
|
IF ((abs(w[nm,nm])+anorm) = anorm) THEN GOTO 1
|
|
END;
|
|
1: c := 0.0;
|
|
s := 1.0;
|
|
FOR i := l to k DO BEGIN
|
|
f := s*rv1[i];
|
|
IF ((abs(f)+anorm) <> anorm) THEN BEGIN
|
|
g := w[i,i];
|
|
h := sqrt(f*f+g*g);
|
|
w[i,i] := h;
|
|
h := 1.0/h;
|
|
c := (g*h);
|
|
s := -(f*h);
|
|
FOR j := 0 to m-1 DO BEGIN
|
|
y := a[j,nm];
|
|
z := a[j,i];
|
|
a[j,nm] := (y*c)+(z*s);
|
|
a[j,i] := -(y*s)+(z*c)
|
|
END
|
|
END
|
|
END;
|
|
2: z := w[k,k];
|
|
IF (l = k) THEN BEGIN
|
|
IF (z < 0.0) THEN BEGIN
|
|
w[k,k] := -z;
|
|
FOR j := 0 to n-1 DO BEGIN
|
|
v[j,k] := -v[j,k]
|
|
END
|
|
END;
|
|
GOTO 3
|
|
END;
|
|
IF (its = 30) THEN BEGIN
|
|
showmessage('No convergence in 30 SVDCMP iterations');
|
|
exit;
|
|
END;
|
|
x := w[l,l];
|
|
nm := k-1;
|
|
y := w[nm,nm];
|
|
g := rv1[nm];
|
|
h := rv1[k];
|
|
f := ((y-z)*(y+z)+(g-h)*(g+h))/(2.0*h*y);
|
|
g := sqrt(f*f+1.0);
|
|
f := ((x-z)*(x+z)+h*((y/(f+sign(g,f)))-h))/x;
|
|
c := 1.0;
|
|
s := 1.0;
|
|
FOR j := l to nm DO BEGIN
|
|
i := j+1;
|
|
g := rv1[i];
|
|
y := w[i,i];
|
|
h := s*g;
|
|
g := c*g;
|
|
z := sqrt(f*f+h*h);
|
|
rv1[j] := z;
|
|
c := f/z;
|
|
s := h/z;
|
|
f := (x*c)+(g*s);
|
|
g := -(x*s)+(g*c);
|
|
h := y*s;
|
|
y := y*c;
|
|
FOR nm := 0 to n-1 DO BEGIN
|
|
x := v[nm,j];
|
|
z := v[nm,i];
|
|
v[nm,j] := (x*c)+(z*s);
|
|
v[nm,i] := -(x*s)+(z*c)
|
|
END;
|
|
z := sqrt(f*f+h*h);
|
|
w[j,j] := z;
|
|
IF (z <> 0.0) THEN BEGIN
|
|
z := 1.0/z;
|
|
c := f*z;
|
|
s := h*z
|
|
END;
|
|
f := (c*g)+(s*y);
|
|
x := -(s*g)+(c*y);
|
|
FOR nm := 0 to m-1 DO BEGIN
|
|
y := a[nm,j];
|
|
z := a[nm,i];
|
|
a[nm,j] := (y*c)+(z*s);
|
|
a[nm,i] := -(y*s)+(z*c)
|
|
END
|
|
END;
|
|
rv1[l] := 0.0;
|
|
rv1[k] := f;
|
|
w[k,k] := x
|
|
END;
|
|
3: END;
|
|
{ mat_print(m,a,'U matrix');
|
|
mat_print(n,v,'V matrix');
|
|
writeln(lst,'Diagonal values of W inverse matrix');
|
|
for i := 1 to n do
|
|
write(lst,1/w[i]:6:3);
|
|
writeln(lst); }
|
|
for i := 0 to n-1 do
|
|
for j := 0 to n-1 do
|
|
begin
|
|
if w[i,i] < 1.0e-6 then vtimesw[i,j] := 0
|
|
else vtimesw[i,j] := v[i,j] * (1.0 / w[j,j] );
|
|
end;
|
|
{ mat_print(n,vtimesw,'V matrix times w inverse '); }
|
|
for i := 0 to m-1 do
|
|
for j := 0 to n-1 do
|
|
begin
|
|
ainverse[i,j] := 0.0;
|
|
for k := 0 to m-1 do
|
|
begin
|
|
ainverse[i,j] := ainverse[i,j] + vtimesw[i,k] * a[j,k]
|
|
end;
|
|
end;
|
|
{ mat_print(n,ainverse,'Inverse Matrix'); }
|
|
for i := 0 to n-1 do
|
|
for j := 0 to n-1 do
|
|
a[i,j] := ainverse[i,j];
|
|
ainverse := nil;
|
|
rv1 := nil;
|
|
end;
|
|
|
|
{ Adds a new variable named AColTitle after the last grid column
|
|
and writes the specified data to it in the specified number format.
|
|
Rows mentioned in ABadRows must be omitted because they are not contained in
|
|
AData. }
|
|
procedure AddVariable(AVarName: String; AData: DblDyneVec;
|
|
ANumFormat: String; const ABadRows: IntDyneVec);
|
|
|
|
function IsBadRow(ARow: Integer): Boolean;
|
|
var
|
|
j: Integer;
|
|
begin
|
|
for j := 0 to High(ABadRows) do
|
|
if ARow = ABadRows[j] then
|
|
begin
|
|
Result := true;
|
|
exit;
|
|
end;
|
|
Result := false;
|
|
end;
|
|
|
|
var
|
|
i, j, colIndex, row: Integer;
|
|
begin
|
|
colIndex := GetVariableIndex(OS3MainFrm.DataGrid, AVarname);
|
|
if colIndex = -1 then
|
|
begin
|
|
colIndex := NoVariables + 1;
|
|
DictionaryFrm.NewVar(colIndex);
|
|
DictionaryFrm.DictGrid.Cells[1, colIndex] := AVarName;
|
|
DictionaryFrm.DictGrid.Cells[7, colIndex] := 'R';
|
|
OS3MainFrm.DataGrid.Cells[colIndex, 0] := AVarName;
|
|
OS3MainFrm.NoVarsEdit.Text := IntToStr(NoVariables);
|
|
end;
|
|
row := 1;
|
|
for i := 0 to High(AData) do
|
|
begin
|
|
while IsBadRow(row) do inc(row);
|
|
if row >= OS3MainFrm.DataGrid.RowCount then
|
|
raise Exception.Create('Bad row error.');
|
|
OS3MainFrm.DataGrid.Cells[colIndex, row] := Format(ANumFormat, [AData[i]]);
|
|
inc(row);
|
|
end;
|
|
end;
|
|
|
|
|
|
end.
|
|
|