2020-04-27 15:30:03 +00:00
|
|
|
// File for testing: ABCLogLinData.laz
|
|
|
|
// Use all variables in original order
|
|
|
|
// Click the button and define Min/max values:
|
|
|
|
// variable "Row": 1 .. 2
|
|
|
|
// variable "Col": 1 .. 2
|
|
|
|
// variable "Slice": 1 .. 3
|
|
|
|
// variable "X": 1 .. 9
|
|
|
|
//
|
|
|
|
// NOTE: the calculation crashes
|
|
|
|
|
2020-03-30 18:01:44 +00:00
|
|
|
unit LogLinScreenUnit;
|
|
|
|
|
|
|
|
{$mode objfpc}{$H+}
|
|
|
|
|
|
|
|
interface
|
|
|
|
|
|
|
|
uses
|
2020-12-03 23:51:15 +00:00
|
|
|
Classes, SysUtils, Forms, Controls, Graphics, Dialogs,
|
2020-04-27 20:51:12 +00:00
|
|
|
StdCtrls, Buttons, ExtCtrls, Grids,
|
2020-12-03 23:51:15 +00:00
|
|
|
Globals, MainUnit, FunctionsLib, BasicStatsReportFormUnit;
|
2020-03-30 18:01:44 +00:00
|
|
|
|
|
|
|
type
|
|
|
|
|
2020-12-02 23:51:03 +00:00
|
|
|
{ TLogLinScreenForm }
|
2020-03-30 18:01:44 +00:00
|
|
|
|
2020-12-03 23:51:15 +00:00
|
|
|
TLogLinScreenForm = class(TBasicStatsReportForm)
|
2020-04-27 20:51:12 +00:00
|
|
|
Bevel2: TBevel;
|
2020-03-30 18:01:44 +00:00
|
|
|
InBtn: TBitBtn;
|
2020-04-27 20:51:12 +00:00
|
|
|
Label1: TLabel;
|
2020-03-30 18:01:44 +00:00
|
|
|
OutBtn: TBitBtn;
|
|
|
|
AllBtn: TBitBtn;
|
|
|
|
MarginsChk: TCheckBox;
|
|
|
|
GenlModelChk: TCheckBox;
|
2020-12-03 23:51:15 +00:00
|
|
|
OptionsGroup: TGroupBox;
|
2020-03-30 18:01:44 +00:00
|
|
|
Label2: TLabel;
|
|
|
|
Label3: TLabel;
|
|
|
|
SelectList: TListBox;
|
2020-04-27 20:51:12 +00:00
|
|
|
MinMaxGrid: TStringGrid;
|
2020-03-30 18:01:44 +00:00
|
|
|
VarList: TListBox;
|
|
|
|
CountVarChk: TCheckBox;
|
|
|
|
procedure AllBtnClick(Sender: TObject);
|
2020-04-27 20:51:12 +00:00
|
|
|
procedure CountVarChkChange(Sender: TObject);
|
2020-03-30 18:01:44 +00:00
|
|
|
procedure InBtnClick(Sender: TObject);
|
|
|
|
procedure OutBtnClick(Sender: TObject);
|
2020-10-26 18:00:52 +00:00
|
|
|
procedure SelectListSelectionChange(Sender: TObject; {%H-}User: boolean);
|
2020-12-03 23:51:15 +00:00
|
|
|
procedure VarListDblClick(Sender: TObject);
|
2020-11-06 00:04:57 +00:00
|
|
|
procedure VarListSelectionChange(Sender: TObject; {%H-}User: boolean);
|
2020-03-30 18:01:44 +00:00
|
|
|
|
|
|
|
private
|
2020-12-03 23:51:15 +00:00
|
|
|
function ArrayPosition(ANumDims: integer;
|
|
|
|
const Subscripts, DimSize: IntDyneVec): integer;
|
|
|
|
|
2020-04-27 20:51:12 +00:00
|
|
|
procedure UpdateMinMaxGrid;
|
|
|
|
|
|
|
|
procedure Screen(VAR NVAR : integer;
|
2020-03-30 18:01:44 +00:00
|
|
|
VAR MP : integer; VAR MM : integer;
|
|
|
|
VAR NTAB : integer; VAR TABLE : DblDyneVec;
|
|
|
|
VAR DIM : IntDyneVec; VAR GSQ : DblDyneVec;
|
|
|
|
VAR DGFR : IntDyneVec; VAR PART : DblDyneMat;
|
|
|
|
VAR MARG : DblDyneMat; VAR DFS : IntDyneMat;
|
|
|
|
VAR IP : IntDyneMat; VAR IM : IntDyneMat;
|
|
|
|
VAR ISET : IntDyneVec; VAR JSET : IntDyneVec;
|
|
|
|
VAR CONFIG : IntDyneMat; VAR FIT : DblDyneVec;
|
|
|
|
VAR SIZE : IntDyneVec; VAR COORD : IntDyneVec;
|
|
|
|
VAR X : DblDyneVec; VAR Y : DblDyneVec;
|
|
|
|
VAR IFAULT : integer);
|
|
|
|
|
2020-04-27 20:51:12 +00:00
|
|
|
procedure CONF(VAR N : integer; VAR M : integer;
|
2020-03-30 18:01:44 +00:00
|
|
|
VAR MP : integer;
|
|
|
|
VAR MM : integer;
|
|
|
|
VAR ISET : IntDyneVec; VAR JSET : IntDyneVec;
|
|
|
|
VAR IP : IntDyneMat; VAR IM : IntDyneMat; VAR NP : integer);
|
|
|
|
|
2020-04-27 20:51:12 +00:00
|
|
|
procedure COMBO(VAR ISET : IntDyneVec;
|
2020-03-30 18:01:44 +00:00
|
|
|
N, M : Integer;
|
|
|
|
VAR LAST : boolean);
|
|
|
|
|
2020-04-27 20:51:12 +00:00
|
|
|
procedure EVAL(VAR IAR : IntDyneMat;
|
2020-03-30 18:01:44 +00:00
|
|
|
NC, NV, IBEG, NVAR, MAX : integer;
|
|
|
|
VAR CONFIG : IntDyneMat;
|
|
|
|
VAR DIM : IntDyneVec; VAR DF : integer);
|
|
|
|
|
2020-04-27 20:51:12 +00:00
|
|
|
procedure RESET(VAR FIT : DblDyneVec; NTAB : Integer;
|
2020-12-03 23:51:15 +00:00
|
|
|
AVG : Double);
|
2020-03-30 18:01:44 +00:00
|
|
|
|
2020-12-03 23:51:15 +00:00
|
|
|
procedure LIKE(var GSQ: Double; const FIT, TABLE: DblDyneVec; NTAB: integer);
|
2020-03-30 18:01:44 +00:00
|
|
|
|
2020-04-27 20:51:12 +00:00
|
|
|
procedure LOGFIT(NVAR, NTAB, NCON : integer;
|
2020-03-30 18:01:44 +00:00
|
|
|
VAR DIM : IntDyneVec;
|
|
|
|
VAR CONFIG : IntDyneMat; VAR TABLE : DblDyneVec;
|
|
|
|
VAR FIT : DblDyneVec; VAR SIZE : IntDyneVec;
|
|
|
|
VAR COORD : IntDyneVec; VAR X : DblDyneVec;
|
|
|
|
VAR Y : DblDyneVec);
|
|
|
|
|
2020-04-27 20:51:12 +00:00
|
|
|
procedure MaxCombos(NumDims: integer; out MM, MP: integer);
|
2020-03-30 18:01:44 +00:00
|
|
|
|
2020-12-03 23:51:15 +00:00
|
|
|
procedure Marginals(NumDims, ArraySize: integer; const Indexes: IntDyneMat;
|
|
|
|
const Data: DblDyneVec; const Margins: IntDyneMat);
|
|
|
|
|
|
|
|
protected
|
|
|
|
procedure AdjustConstraints; override;
|
|
|
|
procedure Compute; override;
|
|
|
|
procedure UpdateBtnStates; override;
|
|
|
|
function Validate(out AMsg: String; out AControl: TWinControl): Boolean; override;
|
|
|
|
|
2020-03-30 18:01:44 +00:00
|
|
|
public
|
2020-12-03 23:51:15 +00:00
|
|
|
procedure Reset; override;
|
2020-03-30 18:01:44 +00:00
|
|
|
end;
|
|
|
|
|
|
|
|
var
|
2020-12-02 23:51:03 +00:00
|
|
|
LogLinScreenForm: TLogLinScreenForm;
|
2020-03-30 18:01:44 +00:00
|
|
|
|
|
|
|
implementation
|
|
|
|
|
2020-12-03 23:51:15 +00:00
|
|
|
{$R *.lfm}
|
|
|
|
|
2020-03-30 18:01:44 +00:00
|
|
|
uses
|
2020-12-03 23:51:15 +00:00
|
|
|
Math, LCLIntf, LCLType,
|
|
|
|
Utils, DataProcs, GridProcs;
|
2020-03-30 18:01:44 +00:00
|
|
|
|
|
|
|
|
2020-12-03 23:51:15 +00:00
|
|
|
{ TLogLinScreenForm }
|
2020-04-27 15:30:03 +00:00
|
|
|
|
2020-12-03 23:51:15 +00:00
|
|
|
procedure TLogLinScreenForm.AdjustConstraints;
|
2020-04-27 15:30:03 +00:00
|
|
|
begin
|
2020-12-03 23:51:15 +00:00
|
|
|
inherited;
|
|
|
|
ParamsPanel.Constraints.MinWidth := MaxValue([
|
|
|
|
4*CloseBtn.Width + 3*CloseBtn.BorderSpacing.Left,
|
|
|
|
OptionsGroup.Width,
|
|
|
|
Label2.Width * 2 + AllBtn.Width + 2*varList.BorderSpacing.Right +
|
|
|
|
MinMaxGrid.Width + MinMaxGrid.BorderSpacing.Left
|
|
|
|
]);
|
|
|
|
ParamsPanel.Constraints.MinHeight := AllBtn.Top + AllBtn.Height +
|
|
|
|
CountVarChk.BorderSpacing.Top + CountVarChk.Height +
|
|
|
|
VarList.BorderSpacing.Bottom + OptionsGroup.Height + ButtonBevel.Height +
|
|
|
|
CloseBtn.BorderSpacing.Top + CloseBtn.Height;
|
2020-03-30 18:01:44 +00:00
|
|
|
end;
|
2020-12-03 23:51:15 +00:00
|
|
|
|
2020-03-30 18:01:44 +00:00
|
|
|
|
2020-12-03 23:51:15 +00:00
|
|
|
procedure TLogLinScreenForm.AllBtnClick(Sender: TObject);
|
2020-04-27 15:30:03 +00:00
|
|
|
var
|
|
|
|
i: integer;
|
2020-03-30 18:01:44 +00:00
|
|
|
begin
|
2020-12-03 23:51:15 +00:00
|
|
|
for i := 0 to VarList.Items.Count-1 do
|
|
|
|
SelectList.Items.Add(VarList.Items[i]);
|
|
|
|
VarList.Clear;
|
2020-04-27 15:30:03 +00:00
|
|
|
UpdateBtnStates;
|
2020-12-03 23:51:15 +00:00
|
|
|
UpdateMinMaxGrid;
|
2020-03-30 18:01:44 +00:00
|
|
|
end;
|
|
|
|
|
2020-12-03 23:51:15 +00:00
|
|
|
|
|
|
|
function TLogLinScreenForm.ArrayPosition(ANumDims: integer;
|
|
|
|
const Subscripts, DimSize: IntDyneVec): integer;
|
2020-03-30 18:01:44 +00:00
|
|
|
var
|
2020-12-03 23:51:15 +00:00
|
|
|
Pos : integer;
|
|
|
|
i, j : integer;
|
|
|
|
PriorSizes : IntDyneVec = nil;
|
2020-03-30 18:01:44 +00:00
|
|
|
begin
|
2020-12-03 23:51:15 +00:00
|
|
|
// allocate space for PriorSizes
|
|
|
|
SetLength(PriorSizes, ANumDims);
|
2020-03-30 18:01:44 +00:00
|
|
|
|
2020-12-03 23:51:15 +00:00
|
|
|
// calculate PriorSizes values
|
|
|
|
for i := 0 to ANumDims - 2 do
|
|
|
|
PriorSizes[i] := 1; // initialize
|
2020-04-27 20:51:12 +00:00
|
|
|
|
2020-12-03 23:51:15 +00:00
|
|
|
for i := ANumDims - 2 downto 0 do
|
|
|
|
for j := 0 to i do PriorSizes[i] := PriorSizes[i] * DimSize[j];
|
2020-04-27 20:51:12 +00:00
|
|
|
|
2020-12-03 23:51:15 +00:00
|
|
|
Pos := Subscripts[0] - 1;
|
|
|
|
for i := 0 to ANumDims - 2 do
|
|
|
|
Pos := Pos + (PriorSizes[i] * (Subscripts[i+1]-1));
|
2020-03-30 18:01:44 +00:00
|
|
|
|
2020-12-03 23:51:15 +00:00
|
|
|
Result := Pos;
|
|
|
|
PriorSizes := nil;
|
2020-03-30 18:01:44 +00:00
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
|
2020-12-03 23:51:15 +00:00
|
|
|
{ SUBROUTINE COMBO(ISET, N, M, LAST)
|
2020-03-30 18:01:44 +00:00
|
|
|
|
2020-12-03 23:51:15 +00:00
|
|
|
ALGORITHM AS 160.2 APPL. STATIST. (1981) VOL.30, NO.1
|
|
|
|
|
|
|
|
Subroutine to generate all possible combinations of M of the
|
|
|
|
integers from 1 to N in a stepwise fashion. Prior to the first
|
|
|
|
call, LAST should be set to .FALSE. Thereafter, as long as LAST
|
|
|
|
is returned .FALSE., a new valid combination has been generated.
|
|
|
|
When LAST goes .TRUE., there are no more combinations.
|
|
|
|
|
|
|
|
LOGICAL LAST
|
|
|
|
INTEGER N, M, ISET(M)
|
|
|
|
}
|
|
|
|
procedure TLogLinScreenForm.COMBO(var ISET: IntDyneVec; N, M: Integer;
|
|
|
|
var LAST: boolean);
|
|
|
|
label
|
|
|
|
100, 110, 130, 150;
|
2020-04-27 15:30:03 +00:00
|
|
|
var
|
2020-12-03 23:51:15 +00:00
|
|
|
I, K, L : integer;
|
2020-03-30 18:01:44 +00:00
|
|
|
begin
|
2020-12-03 23:51:15 +00:00
|
|
|
IF (LAST) then GOTO 110;
|
|
|
|
//
|
|
|
|
// Get next element to increment
|
|
|
|
//
|
|
|
|
K := M;
|
|
|
|
100: L := ISET[K] + 1;
|
|
|
|
IF (L + M - K <= N) then GOTO 150;
|
|
|
|
K := K - 1;
|
|
|
|
//
|
|
|
|
// See if we are done
|
|
|
|
//
|
|
|
|
IF (K <= 0) then GOTO 130;
|
|
|
|
GOTO 100;
|
|
|
|
//
|
|
|
|
// Initialize first combination
|
|
|
|
//
|
|
|
|
110: for I := 1 to M do ISET[I] := I;
|
|
|
|
130: LAST := NOT LAST;
|
|
|
|
exit;
|
|
|
|
//
|
|
|
|
// Fill in remainder of combination.
|
|
|
|
//
|
|
|
|
150: for I := K to M do //DO 160 I = K, M
|
|
|
|
begin
|
|
|
|
ISET[I] := L;
|
|
|
|
L := L + 1;
|
|
|
|
end; //160 CONTINUE
|
2020-03-30 18:01:44 +00:00
|
|
|
end;
|
|
|
|
|
2020-12-03 23:51:15 +00:00
|
|
|
|
|
|
|
procedure TLogLinScreenForm.Compute;
|
2020-03-30 18:01:44 +00:00
|
|
|
var
|
2020-12-03 23:51:15 +00:00
|
|
|
ArraySize: integer;
|
|
|
|
N: integer;
|
|
|
|
index, index2, i, j, k, l, nVars: integer;
|
|
|
|
count: integer;
|
|
|
|
Data: DblDyneVec = nil;
|
|
|
|
Subscripts: IntDyneVec = nil;
|
|
|
|
DimSize: IntDyneVec = nil;
|
|
|
|
GridPos: IntDyneVec = nil;
|
|
|
|
Labels: StrDyneVec = nil;
|
|
|
|
Margins: IntDyneMat = nil;
|
|
|
|
Expected: DblDyneVec = nil;
|
|
|
|
WorkVec: IntDyneVec = nil;
|
|
|
|
Indexes: IntDyneMat = nil;
|
|
|
|
LogM: DblDyneVec = nil;
|
|
|
|
M: DblDyneMat = nil;
|
|
|
|
astr, HeadStr : string;
|
|
|
|
MaxDim, MP, MM : integer;
|
|
|
|
U, Mu : Double;
|
|
|
|
Chi2, G2 : double;
|
|
|
|
DF : integer;
|
|
|
|
ProbChi2, ProbG2 : double;
|
|
|
|
GSQ : DblDyneVec = nil;
|
|
|
|
DGFR : IntDyneVec = nil;
|
|
|
|
PART : DblDyneMat = nil;
|
|
|
|
MARG : DblDyneMat = nil;
|
|
|
|
DFS : IntDyneMat = nil;
|
|
|
|
IP : IntDyneMat = nil;
|
|
|
|
IM : IntDyneMat = nil;
|
|
|
|
ISET : IntDyneVec = nil;
|
|
|
|
JSET : IntDyneVec = nil;
|
|
|
|
CONFIG : IntDyneMat = nil;
|
|
|
|
FIT : DblDyneVec = nil;
|
|
|
|
SIZE : IntDyneVec = nil;
|
|
|
|
COORD : IntDyneVec = nil;
|
|
|
|
X: DblDyneVec = nil;
|
|
|
|
Y : DblDyneVec = nil;
|
|
|
|
IFAULT : integer;
|
|
|
|
TABLE : DblDyneVec = nil;
|
|
|
|
DIM : IntDyneVec = nil;
|
|
|
|
nDims: Integer;
|
|
|
|
Minimums: IntDyneVec = nil;
|
|
|
|
Maximums: IntDyneVec = nil;
|
2020-04-27 20:51:12 +00:00
|
|
|
// Response: BoolDyneVec;
|
|
|
|
// Interact: BoolDyneVec;
|
2020-12-03 23:51:15 +00:00
|
|
|
lReport: TStrings;
|
2020-03-30 18:01:44 +00:00
|
|
|
begin
|
2020-04-27 15:30:03 +00:00
|
|
|
lReport := TStringList.Create;
|
|
|
|
try
|
2020-12-03 23:51:15 +00:00
|
|
|
// Allocate space for labels, DimSize and SubScripts
|
|
|
|
nDims := MinMaxGrid.RowCount - 1;
|
|
|
|
nVars := SelectList.Items.Count;
|
|
|
|
|
|
|
|
SetLength(Labels, nVars);
|
|
|
|
SetLength(GridPos, nVars);
|
|
|
|
SetLength(Minimums, nDims);
|
|
|
|
SetLength(Maximums, nDims);
|
|
|
|
SetLength(DimSize, nDims);
|
|
|
|
SetLength(Subscripts, nDims);
|
|
|
|
|
|
|
|
for i := 1 to nDims do
|
|
|
|
begin
|
|
|
|
if not TryStrToInt(MinMaxGrid.Cells[1, i], Minimums[i-1]) then
|
|
|
|
begin
|
|
|
|
ErrorMsg('Valid Integer number > 0 expected.');
|
|
|
|
exit;
|
|
|
|
end;
|
|
|
|
if not TryStrToInt(MinMaxGrid.Cells[2, i], Maximums[i-1]) then
|
|
|
|
begin
|
|
|
|
ErrorMsg('Integer number > 0 expected.');
|
|
|
|
exit;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
// get variable labels and column positions
|
|
|
|
for i := 0 to nVars-1 do
|
|
|
|
begin
|
|
|
|
Labels[i] := SelectList.Items[i];
|
|
|
|
GridPos[i] := GetVariableIndex(OS3MainFrm.DataGrid, Labels[i]);
|
|
|
|
end;
|
|
|
|
|
|
|
|
// Get no. of categories for each dimension (DimSize)
|
|
|
|
MaxDim := 0;
|
|
|
|
ArraySize := 1;
|
|
|
|
for i := 0 to nDims - 1 do
|
|
|
|
begin
|
|
|
|
DimSize[i] := Maximums[i] - Minimums[i] + 1;
|
|
|
|
if DimSize[i] > MaxDim then MaxDim := DimSize[i];
|
|
|
|
ArraySize := ArraySize * DimSize[i];
|
|
|
|
end;
|
|
|
|
|
|
|
|
// Allocate space for Data and marginals
|
|
|
|
SetLength(WorkVec, MaxDim);
|
|
|
|
SetLength(Data, ArraySize);
|
|
|
|
SetLength(Margins, nDims, MaxDim);
|
|
|
|
SetLength(Expected, ArraySize);
|
|
|
|
SetLength(Indexes, ArraySize+1, nDims);
|
|
|
|
SetLength(LogM, ArraySize);
|
|
|
|
SetLength(M, ArraySize, nDims);
|
|
|
|
|
|
|
|
// Read and store frequencies in Data
|
|
|
|
for i := 1 to NoCases do
|
|
|
|
begin
|
|
|
|
if GoodRecord(OS3MainFrm.DataGrid, i, GridPos) then // casewise check
|
|
|
|
begin
|
|
|
|
// get cell subscripts
|
|
|
|
for j := 0 to nDims-1 do
|
|
|
|
begin
|
|
|
|
index := StrToInt(OS3MainFrm.DataGrid.Cells[GridPos[j], i]);
|
|
|
|
index := index - Minimums[j] + 1;
|
|
|
|
Subscripts[j] := index;
|
|
|
|
end;
|
|
|
|
|
|
|
|
index := ArrayPosition(nDims, Subscripts, DimSize);
|
|
|
|
|
|
|
|
// save subscripts for later use
|
|
|
|
for j := 0 to nDims-1 do
|
|
|
|
Indexes[index, j] := Subscripts[j];
|
|
|
|
|
|
|
|
if CountVarChk.Checked then
|
|
|
|
begin
|
|
|
|
k := GridPos[nVars-1];
|
|
|
|
Data[index] := Data[index] + StrToInt(OS3MainFrm.DataGrid.Cells[k, i]);
|
|
|
|
end else
|
|
|
|
Data[index] := Data[index] + 1;
|
|
|
|
end;
|
|
|
|
end;
|
2020-03-30 18:01:44 +00:00
|
|
|
|
|
|
|
// get total N
|
2020-12-03 23:51:15 +00:00
|
|
|
N := 0;
|
|
|
|
for i := 0 to ArraySize-1 do
|
|
|
|
N := N + Round(Data[i]);
|
|
|
|
|
|
|
|
// Get marginal frequencies
|
|
|
|
Marginals(nDims, ArraySize, Indexes, Data, Margins);
|
|
|
|
|
|
|
|
// Print Marginal totals if requested
|
|
|
|
if MarginsChk.Checked then
|
|
|
|
begin
|
|
|
|
lReport.Add('FILE: '+ OS3MainFrm.FileNameEdit.Text);
|
|
|
|
lReport.Add('');
|
|
|
|
for i := 0 to nDims-1 do
|
|
|
|
begin
|
|
|
|
HeadStr := 'Marginal Totals for ' + Labels[i];
|
|
|
|
k := DimSize[i];
|
|
|
|
for j := 0 to k-1 do WorkVec[j] := Margins[i, j];
|
|
|
|
VecPrint(WorkVec, k, HeadStr, lReport);
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
lReport.Add('');
|
|
|
|
lReport.Add('Total Frequencies: %d', [N]);
|
|
|
|
|
|
|
|
lReport.Add('');
|
|
|
|
lReport.Add(DIVIDER);
|
|
|
|
lReport.Add('');
|
|
|
|
|
|
|
|
// Get Expected cell values
|
|
|
|
U := 0.0; // overall mean (mu) of log linear model
|
|
|
|
for i := 0 to ArraySize-1 do // indexes point to each cell
|
|
|
|
begin
|
|
|
|
Expected[i] := 1.0;
|
|
|
|
for j := 0 to nDims-1 do
|
|
|
|
begin
|
|
|
|
k := Indexes[i, j];
|
|
|
|
Expected[i] := Expected[i] * (Margins[j, k-1] / N);
|
|
|
|
end;
|
|
|
|
Expected[i] := Expected[i] * N;
|
|
|
|
LogM[i] := ln(Expected[i]);
|
|
|
|
end;
|
|
|
|
for i := 0 to ArraySize-1 do U := U + LogM[i];
|
|
|
|
U := U / ArraySize;
|
|
|
|
|
|
|
|
// print expected values
|
|
|
|
lReport.Add('FILE: '+ OS3MainFrm.FileNameEdit.Text);
|
|
|
|
lReport.Add('');
|
|
|
|
lReport.Add('EXPECTED CELL VALUES FOR MODEL OF COMPLETE INDEPENDENCE');
|
|
|
|
lReport.Add('');
|
|
|
|
|
|
|
|
astr := 'Cell';
|
|
|
|
for j := 2 to nDims do astr := astr + ' ';
|
|
|
|
lReport.Add(astr + 'Observed Expected Log Expected');
|
|
|
|
|
|
|
|
astr := '';
|
|
|
|
for j := 1 to nDims do astr := astr + '--- ';
|
|
|
|
astr := astr + '---------- ---------- ----------';
|
|
|
|
lReport.Add(astr);
|
|
|
|
|
|
|
|
for i := 1 to ArraySize do
|
|
|
|
begin
|
|
|
|
astr := '';
|
|
|
|
for j := 1 to nDims do
|
|
|
|
astr := astr + Format('%3d ', [Indexes[i-1, j-1]]);
|
|
|
|
astr := astr + Format('%10.0f %10.2f %10.3f',[Data[i-1], Expected[i-1], LogM[i-1]]);
|
|
|
|
lReport.Add(astr);
|
|
|
|
end;
|
|
|
|
|
|
|
|
// Calculate chi-squared and G squared statistics
|
|
|
|
chi2 := 0.0;
|
|
|
|
G2 := 0.0;
|
|
|
|
for i := 0 to ArraySize-1 do
|
|
|
|
begin
|
|
|
|
chi2 := chi2 + Sqr(Data[i] - Expected[i]) / Expected[i];
|
|
|
|
G2 := G2 + Data[i] * ln(Data[i] / Expected[i]);
|
|
|
|
end;
|
|
|
|
G2 := 2.0 * G2;
|
|
|
|
DF := 1;
|
|
|
|
for i := 0 to nDims-1 do
|
|
|
|
DF := DF * (DimSize[i] - 1);
|
|
|
|
ProbChi2 := 1.0 - ChiSquaredProb(chi2,DF);
|
|
|
|
ProbG2 := 1.0 - ChiSquaredProb(G2,DF);
|
|
|
|
lReport.Add('Chisquare: %10.3f with probability %10.3f (DF %d)', [chi2, ProbChi2, DF]);
|
|
|
|
lReport.Add('G squared: %10.3f with probability %10.3f (DF %d)', [G2, ProbG2, DF]);
|
|
|
|
lReport.Add('');
|
|
|
|
lReport.Add('U (mu) for general loglinear model: %10.2f', [U]);
|
|
|
|
|
|
|
|
lReport.Add('');
|
|
|
|
lReport.Add(DIVIDER);
|
|
|
|
lReport.Add('');
|
|
|
|
|
|
|
|
// Get log linear model values for each cell
|
|
|
|
// get M's for each cell
|
|
|
|
lReport.Add('First Order LogLinear Model Factors and N of Cells in Each');
|
|
|
|
astr := 'CELL ';
|
|
|
|
for i := 1 to nDims do
|
|
|
|
astr := astr + Format(' U%d N Cells ',[i]);
|
|
|
|
lReport.Add(astr);
|
|
|
|
lReport.Add('');
|
|
|
|
for i := 1 to ArraySize do // cell
|
|
|
|
begin
|
|
|
|
astr := '';
|
|
|
|
for j := 1 to nDims do
|
|
|
|
astr := astr + Format('%3d ', [Indexes[i-1,j-1]]);
|
|
|
|
for j := 1 to nDims do // jth mu
|
|
|
|
begin
|
|
|
|
index := Indexes[i-1,j-1]; // sum for this mu
|
|
|
|
count := 0;
|
|
|
|
Mu := 0.0;
|
|
|
|
for k := 1 to ArraySize do
|
|
|
|
begin
|
|
|
|
if index = Indexes[k-1,j-1] then
|
2020-03-30 18:01:44 +00:00
|
|
|
begin
|
2020-12-03 23:51:15 +00:00
|
|
|
count := count + 1;
|
|
|
|
Mu := Mu + LogM[k-1];
|
2020-03-30 18:01:44 +00:00
|
|
|
end;
|
2020-12-03 23:51:15 +00:00
|
|
|
end;
|
|
|
|
Mu := Mu / count - U;
|
|
|
|
astr := astr + format('%10.3f %3d ',[Mu,count]);
|
|
|
|
end;
|
|
|
|
lReport.Add(astr);
|
|
|
|
end;
|
|
|
|
|
|
|
|
lReport.Add('');
|
|
|
|
lReport.Add(DIVIDER);
|
|
|
|
lReport.Add('');
|
|
|
|
|
|
|
|
// get second order interactions
|
|
|
|
lReport.Add('Second Order Loglinear Model Terms and N of Cells in Each');
|
|
|
|
astr := 'CELL ';
|
|
|
|
for i := 1 to nDims-1 do
|
|
|
|
for j := i + 1 to nDims do
|
|
|
|
astr := astr + format('U%d%d N Cells ',[i,j]);
|
|
|
|
lReport.Add(astr);
|
|
|
|
lReport.Add('');
|
|
|
|
for i := 1 to ArraySize do // cell
|
|
|
|
begin
|
|
|
|
astr := '';
|
|
|
|
for j := 0 to nDims-1 do
|
|
|
|
astr := astr + Format('%3d ', [Indexes[i, j]]);
|
|
|
|
for j := 1 to nDims-1 do // jth
|
|
|
|
begin
|
|
|
|
index := Indexes[i-1,j-1]; // sum for this mu using j and k
|
|
|
|
for k := j+1 to nDims do // with kth
|
|
|
|
begin
|
|
|
|
index2 := Indexes[i-1,k-1];
|
|
|
|
Mu := 0.0;
|
|
|
|
count := 0;
|
|
|
|
for l := 1 to ArraySize do
|
2020-03-30 18:01:44 +00:00
|
|
|
begin
|
2020-12-03 23:51:15 +00:00
|
|
|
if ((index = Indexes[l-1,j-1]) and (index2 = Indexes[l-1,k-1])) then
|
|
|
|
begin
|
|
|
|
Mu := Mu + LogM[l-1];
|
|
|
|
count := count + 1;
|
|
|
|
end;
|
|
|
|
end; // next l
|
|
|
|
Mu := Mu / count - U;
|
|
|
|
astr := astr + Format('%10.3f %3d', [Mu, count]);
|
|
|
|
end; // next k (second term subscript)
|
|
|
|
end; // next j (first term subscript)
|
|
|
|
lReport.Add(astr);
|
|
|
|
end; // next i
|
|
|
|
|
|
|
|
lReport.Add('');
|
|
|
|
lReport.Add(DIVIDER);
|
|
|
|
lReport.Add('');
|
|
|
|
|
|
|
|
// get maximum no. of interactions in saturated model
|
|
|
|
MaxCombos(nDims, MM, MP);
|
|
|
|
|
|
|
|
SetLength(GSQ, nDims+1);
|
|
|
|
SetLength(DGFR, nDims+1);
|
|
|
|
SetLength(PART, nDims+1, MP+1);
|
|
|
|
SetLength(MARG, nDims+1, MP+1);
|
|
|
|
SetLength(DFS, nDims+1, MP+1);
|
|
|
|
SetLength(IP, nDims+1, MP+1);
|
|
|
|
SetLength(IM, nDims+1, MM+1);
|
|
|
|
SetLength(ISET, nDims+1);
|
|
|
|
SetLength(JSET, nDims+1);
|
|
|
|
SetLength(CONFIG, nDims+1, MP+1);
|
|
|
|
SetLength(FIT, ArraySize+1);
|
|
|
|
SetLength(SIZE, nDims+1);
|
|
|
|
SetLength(COORD, nDims+1);
|
|
|
|
SetLength(X, ArraySize+1);
|
|
|
|
SetLength(Y, ArraySize+1);
|
|
|
|
SetLength(TABLE, ArraySize+1);
|
|
|
|
SetLength(DIM, nDims+1);
|
2020-03-30 18:01:44 +00:00
|
|
|
|
|
|
|
// Load TABLE and DIM one up from Data
|
|
|
|
for i := 1 to ArraySize do Table[i] := Data[i-1];
|
2020-12-03 23:51:15 +00:00
|
|
|
for i := 1 to nDims do DIM[i] := DimSize[i-1];
|
|
|
|
|
|
|
|
Screen(
|
|
|
|
nDims, MP, MM, ArraySize, TABLE, DIM,
|
|
|
|
GSQ, DGFR, PART, MARG, DFS, IP, IM, ISET, JSET, CONFIG, FIT, SIZE,
|
|
|
|
COORD, X, Y, IFAULT
|
|
|
|
);
|
|
|
|
|
|
|
|
// show results
|
|
|
|
lReport.Add('SCREEN FOR INTERACTIONS AMONG THE VARIABLES');
|
|
|
|
lReport.Add('Adapted from the Fortran program by Lustbader and Stodola printed in');
|
|
|
|
lReport.Add('Applied Statistics, Volume 30, Issue 1, 1981, pages 97-105 as Algorithm');
|
|
|
|
lReport.Add('AS 160 Partial and Marginal Association in Multidimensional Contingency Tables');
|
|
|
|
lReport.Add('');
|
|
|
|
lReport.Add('Statistics for tests that the interactions of a given order are zero');
|
|
|
|
lReport.Add('ORDER STATISTIC D.F. PROB.');
|
|
|
|
lReport.Add('----- ---------- ---- ----------');
|
|
|
|
for i := 1 to nDims do
|
|
|
|
begin
|
|
|
|
ProbChi2 := 1.0 - ChiSquaredProb(GSQ[i], DGFR[i]);
|
|
|
|
lReport.Add('%5d %10.3f %4d %10.3f',[i,GSQ[i], DGFR[i], ProbChi2]);
|
|
|
|
end;
|
|
|
|
lReport.Add('');
|
|
|
|
lReport.Add('Statistics for Marginal Association Tests');
|
|
|
|
lReport.Add('VARIABLE ASSOC. PART ASSOC. MARGINAL ASSOC. D.F. PROB');
|
|
|
|
lReport.Add('-------- ------ ----------- --------------- ---- ----------');
|
|
|
|
for i := 1 to nDims-1 do
|
|
|
|
begin
|
|
|
|
for j := 1 to MP do
|
|
|
|
begin
|
|
|
|
ProbChi2 := 1.0 - ChiSquaredProb(MARG[i,j],DFS[i,j]);
|
|
|
|
lReport.Add('%6d %5d %10.3f %12.3f %3d %10.3f',
|
|
|
|
[i, j, PART[i,j], MARG[i,j], DFS[i,j], ProbChi2]);
|
|
|
|
end;
|
|
|
|
end;
|
2020-03-30 18:01:44 +00:00
|
|
|
|
2020-12-03 23:51:15 +00:00
|
|
|
FReportFrame.DisplayReport(lReport);
|
2020-04-27 15:30:03 +00:00
|
|
|
|
|
|
|
finally
|
2020-12-03 23:51:15 +00:00
|
|
|
lReport.Free;
|
2020-04-27 15:30:03 +00:00
|
|
|
end;
|
2020-03-30 18:01:44 +00:00
|
|
|
end;
|
|
|
|
|
|
|
|
|
2020-12-03 23:51:15 +00:00
|
|
|
{ SUBROUTINE CONF(N, M, MP, MM, ISET, JSET, IP, IM, NP)
|
2020-03-30 18:01:44 +00:00
|
|
|
|
2020-12-03 23:51:15 +00:00
|
|
|
ALGORITHM AS 160.1 APPL. STATIST. (1981) VOL.30, NO.1
|
2020-03-30 18:01:44 +00:00
|
|
|
|
2020-12-03 23:51:15 +00:00
|
|
|
Set up the arrays IP and IM for a given N and M. Essentially
|
|
|
|
IP contains all possible combinations of (N choose M). For each
|
|
|
|
combination found IM contains all combinations of degree M-1.
|
|
|
|
|
|
|
|
INTEGER ISET(N), JSET(N), IP(N,MP), IM(N,MM)
|
|
|
|
LOGICAL ILAST, JLAST
|
|
|
|
}
|
2020-12-02 23:51:03 +00:00
|
|
|
procedure TLogLinScreenForm.CONF(var N: integer; var M: integer;
|
2020-03-30 18:01:44 +00:00
|
|
|
var MP: integer; var MM: integer; var ISET: IntDyneVec; var JSET: IntDyneVec;
|
|
|
|
var IP: IntDyneMat; var IM: IntDyneMat; var NP: integer);
|
2020-12-03 23:51:15 +00:00
|
|
|
label
|
|
|
|
100, 120;
|
|
|
|
var
|
|
|
|
ILAST, JLAST: boolean;
|
|
|
|
I, L, NM, JS: integer;
|
2020-03-30 18:01:44 +00:00
|
|
|
begin
|
|
|
|
ILAST := TRUE;
|
|
|
|
NP := 0;
|
|
|
|
NM := 0;
|
|
|
|
//
|
|
|
|
// Get IP
|
|
|
|
//
|
|
|
|
100:
|
|
|
|
COMBO(ISET, N, M, ILAST);
|
|
|
|
IF (ILAST) then exit;
|
|
|
|
NP := NP + 1;
|
|
|
|
for I := 1 to M do IP[I,NP] := ISET[I];
|
|
|
|
IF (M = 1) then GOTO 100;
|
|
|
|
//
|
|
|
|
// Get IM
|
|
|
|
//
|
|
|
|
JLAST := TRUE;
|
|
|
|
L := M - 1;
|
|
|
|
120:
|
|
|
|
COMBO(JSET, M, L, JLAST);
|
|
|
|
IF (JLAST) then GOTO 100;
|
|
|
|
NM := NM + 1;
|
|
|
|
for I := 1 to L do // DO 130 I = 1, L
|
|
|
|
begin
|
|
|
|
JS := JSET[I];
|
|
|
|
IM[I,NM] := ISET[JS];
|
|
|
|
end; // 130 CONTINUE
|
|
|
|
GOTO 120;
|
|
|
|
end;
|
|
|
|
|
2020-12-03 23:51:15 +00:00
|
|
|
|
2020-12-02 23:51:03 +00:00
|
|
|
procedure TLogLinScreenForm.CountVarChkChange(Sender: TObject);
|
2020-04-27 20:51:12 +00:00
|
|
|
begin
|
|
|
|
UpdateMinMaxGrid;
|
|
|
|
end;
|
|
|
|
|
2020-03-30 18:01:44 +00:00
|
|
|
|
2020-12-02 23:51:03 +00:00
|
|
|
procedure TLogLinScreenForm.EVAL(var IAR: IntDyneMat; NC, NV, IBEG, NVAR,
|
2020-03-30 18:01:44 +00:00
|
|
|
MAX: integer; var CONFIG: IntDyneMat; var DIM: IntDyneVec; var DF: integer);
|
|
|
|
VAR I, J, K, KK, L : integer;
|
|
|
|
// SUBROUTINE EVAL(IAR, NC, NV, IBEG, NVAR, MAX, CONFIG, DIM, DF)
|
|
|
|
//
|
|
|
|
// ALGORITHM AS 160.3 APPL. STATIST. (1981) VOL.30, NO.1
|
|
|
|
//
|
|
|
|
// IAR = array containing the effects to be fitted
|
|
|
|
// NC = number of columns of IAR to be used
|
|
|
|
// NV = number of variables in each effect
|
|
|
|
// IBEG = gebinning column
|
|
|
|
// DF = degrees of freedom
|
|
|
|
//
|
|
|
|
// CONFIG is in a format compatible with algorithm AS 51
|
|
|
|
//
|
|
|
|
// INTEGER IAR(NVAR,MAX), CONFIG(NVAR,NC), DIM(NVAR), DF
|
|
|
|
//
|
|
|
|
begin
|
|
|
|
DF := 0;
|
|
|
|
for J := 1 to NC do //DO 110 J = 1, NC
|
|
|
|
begin
|
|
|
|
KK := 1;
|
|
|
|
for I := 1 to NV do //DO 100 I = 1, NV
|
|
|
|
begin
|
|
|
|
L := IBEG + J - 1;
|
|
|
|
K := IAR[I,L];
|
|
|
|
KK := KK * (DIM[K] - 1);
|
|
|
|
CONFIG[I,J] := K;
|
|
|
|
end; // 100 CONTINUE
|
|
|
|
CONFIG[NV+1,J] := 0;
|
|
|
|
DF := DF + KK;
|
|
|
|
end; // 110 CONTINUE
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
2020-12-03 23:51:15 +00:00
|
|
|
procedure TLogLinScreenForm.InBtnClick(Sender: TObject);
|
|
|
|
var
|
|
|
|
i: integer;
|
|
|
|
begin
|
|
|
|
i := 0;
|
|
|
|
while i < VarList.Items.Count do
|
|
|
|
begin
|
|
|
|
if VarList.Selected[i] then
|
|
|
|
begin
|
|
|
|
SelectList.Items.Add(VarList.Items[i]);
|
|
|
|
VarList.Items.Delete(i);
|
|
|
|
i := 0;
|
|
|
|
end else
|
|
|
|
i := i + 1;
|
|
|
|
end;
|
|
|
|
UpdateMinMaxGrid;
|
|
|
|
UpdateBtnStates;
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
{ SUBROUTINE LIKE(GSQ, FIT, TABLE, NTAB)
|
|
|
|
ALGORITHM AS 160.5 APPL. STATIST. (1981) VOL.30, NO.1
|
2020-03-30 18:01:44 +00:00
|
|
|
|
2020-12-03 23:51:15 +00:00
|
|
|
Compute the likelihood-ration chi-square
|
2020-03-30 18:01:44 +00:00
|
|
|
|
2020-12-03 23:51:15 +00:00
|
|
|
REAL FIT(NTAB), TABLE(NTAB), ZERO, TWO
|
|
|
|
DATA ZERO /0.0/, TWO /2.0/
|
|
|
|
}
|
|
|
|
procedure TLogLinScreenForm.LIKE(var GSQ: Double; const FIT, TABLE: DblDyneVec;
|
|
|
|
NTAB: integer);
|
|
|
|
const
|
|
|
|
ZERO = 0.0;
|
|
|
|
TWO = 2.0;
|
|
|
|
var
|
|
|
|
I: integer;
|
2020-03-30 18:01:44 +00:00
|
|
|
begin
|
2020-12-03 23:51:15 +00:00
|
|
|
GSQ := ZERO;
|
|
|
|
for I := 1 to NTAB do //DO 100 I = 1, NTAB
|
|
|
|
begin
|
|
|
|
if (FIT[I] = ZERO) or (TABLE[I] = ZERO) then continue; // GO TO 100
|
|
|
|
GSQ := GSQ + TABLE[I] * Ln(TABLE[I] / FIT[I]);
|
|
|
|
end; // 100 CONTINUE
|
|
|
|
GSQ := TWO * GSQ;
|
2020-03-30 18:01:44 +00:00
|
|
|
end;
|
|
|
|
|
2020-12-03 23:51:15 +00:00
|
|
|
|
|
|
|
{
|
|
|
|
SUBROUTINE LOGFIT(NVAR, NTAB, NCON, DIM, CONFIG, TABLE, FIT, SIZE, COORD, X, Y)
|
|
|
|
|
|
|
|
ALGORITHM AS 160.6 APPL. STATIST. (1981) VOL.30, NO.1
|
|
|
|
|
|
|
|
Iterative proportional fitting of the marginals of a contingency table.
|
|
|
|
Relevant code from AS 51 is used.
|
|
|
|
|
|
|
|
REAL TABLE(NTAB), FIT(NTAB), MAXDEV, X(NTAB), Y(NTAB), ZERO
|
|
|
|
INTEGER CONFIG(NVAR,NCON), DIM(NVAR), SIZE(NVAR), COORD(NVAR)
|
|
|
|
LOGICAL OPTION
|
|
|
|
DATA MAXDEV /0.25/, MAXIT /25/, ZERO /0.0/
|
|
|
|
}
|
2020-12-02 23:51:03 +00:00
|
|
|
procedure TLogLinScreenForm.LOGFIT(NVAR, NTAB, NCON: integer;
|
2020-03-30 18:01:44 +00:00
|
|
|
var DIM: IntDyneVec; var CONFIG: IntDyneMat; var TABLE: DblDyneVec;
|
|
|
|
var FIT: DblDyneVec; var SIZE: IntDyneVec; var COORD: IntDyneVec;
|
|
|
|
var X: DblDyneVec; var Y: DblDyneVec);
|
2020-12-03 23:51:15 +00:00
|
|
|
label
|
|
|
|
110, 130, 150, 170, 180, 200;
|
|
|
|
const
|
|
|
|
ZERO = 0.0;
|
|
|
|
MAXDEV = 0.25;
|
|
|
|
MAXIT = 25;
|
|
|
|
var
|
|
|
|
II, K, KK, L, N, J, I: integer;
|
|
|
|
OPTION: boolean;
|
|
|
|
XMAX, E: double;
|
|
|
|
NV1, ISZ: integer;
|
2020-03-30 18:01:44 +00:00
|
|
|
begin
|
|
|
|
for KK := 1 to MAXIT do //DO 230 KK = 1, MAXIT
|
|
|
|
begin
|
|
|
|
//
|
|
|
|
// XMAX is the maximum deviation between fitted and true marginal
|
|
|
|
//
|
|
|
|
XMAX := ZERO;
|
|
|
|
for II := 1 to NCON do //DO 220 II = 1, NCON
|
|
|
|
begin
|
|
|
|
OPTION := TRUE;
|
|
|
|
//
|
|
|
|
// Initialize arrays
|
|
|
|
//
|
|
|
|
SIZE[1] := 1;
|
|
|
|
NV1 := NVAR - 1;
|
|
|
|
for K := 1 to NV1 do //DO 100 K = 1, NV1
|
|
|
|
begin
|
|
|
|
L := CONFIG[K,II];
|
|
|
|
IF (L = 0) then GOTO 110;
|
|
|
|
SIZE[K+1] := SIZE[K] * DIM[L];
|
|
|
|
end; // 100 CONTINUE
|
|
|
|
K := NVAR;
|
|
|
|
110: N := K - 1;
|
|
|
|
ISZ := SIZE[K];
|
|
|
|
for J := 1 to ISZ do //DO 120 J = 1, ISZ
|
|
|
|
begin
|
|
|
|
X[J] := ZERO;
|
|
|
|
Y[J] := ZERO;
|
|
|
|
end; // 120 CONTINUE
|
|
|
|
//
|
|
|
|
// Initialize co-ordinates
|
|
|
|
//
|
|
|
|
130: for K := 1 to NVAR do COORD[K] := 0;
|
|
|
|
//
|
|
|
|
// Find locations in tables
|
|
|
|
//
|
|
|
|
I := 1;
|
|
|
|
150: J := 1;
|
|
|
|
for K := 1 to N do //DO 160 K = 1, N
|
|
|
|
begin
|
|
|
|
L := CONFIG[K,II];
|
|
|
|
J := J + COORD[L] * SIZE[K];
|
|
|
|
end; //160 CONTINUE
|
|
|
|
IF (NOT OPTION) then GOTO 170;
|
|
|
|
//
|
|
|
|
// Compute marginals
|
|
|
|
//
|
|
|
|
X[J] := X[J] + TABLE[I];
|
|
|
|
Y[J] := Y[J] + FIT[I];
|
|
|
|
GOTO 180;
|
|
|
|
//
|
|
|
|
// Make adjustments
|
|
|
|
//
|
|
|
|
170: IF (Y[J] <= ZERO) then FIT[I] := ZERO;
|
|
|
|
IF (Y[J] > ZERO) then FIT[I] := FIT[I] * X[J] / Y[J];
|
|
|
|
//
|
|
|
|
// Update co-ordinates
|
|
|
|
//
|
|
|
|
180: I := I + 1;
|
|
|
|
for K := 1 to NVAR do //DO 190 K = 1, NVAR
|
|
|
|
begin
|
|
|
|
COORD[K] := COORD[K] + 1;
|
|
|
|
IF (COORD[K] < DIM[K]) then GOTO 150;
|
|
|
|
COORD[K] := 0;
|
|
|
|
end; //190 CONTINUE
|
|
|
|
IF (NOT OPTION) then GOTO 200;
|
|
|
|
OPTION := FALSE;
|
|
|
|
GOTO 130;
|
|
|
|
//
|
|
|
|
// Find the largest deviation
|
|
|
|
//
|
|
|
|
200: for I := 1 to ISZ do //DO 210 I = 1, ISZ
|
|
|
|
begin
|
|
|
|
E := ABS(X[I] - Y[I]);
|
|
|
|
IF (E > XMAX) then XMAX := E;
|
|
|
|
end; // 210 CONTINUE
|
|
|
|
end; // 220 CONTINUE
|
|
|
|
//
|
|
|
|
// Test convergence
|
|
|
|
//
|
|
|
|
IF (XMAX < MAXDEV) then exit;
|
|
|
|
end; // 230 CONTINUE
|
|
|
|
end;
|
|
|
|
|
2020-12-03 23:51:15 +00:00
|
|
|
|
|
|
|
procedure TLogLinScreenForm.Marginals(NumDims, ArraySize: integer;
|
|
|
|
const Indexes: IntDyneMat; const Data: DblDyneVec; const Margins: IntDyneMat);
|
|
|
|
var
|
|
|
|
i, j, category: integer;
|
|
|
|
begin
|
|
|
|
for i := 1 to ArraySize do
|
|
|
|
begin
|
|
|
|
for j := 1 to NumDims do
|
|
|
|
begin
|
|
|
|
category := Indexes[i-1,j-1];
|
|
|
|
Margins[j-1,category-1] := Margins[j-1,category-1] + Round(Data[i-1]);
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
2020-12-02 23:51:03 +00:00
|
|
|
procedure TLogLinScreenForm.MaxCombos(NumDims: integer; out MM, MP: integer);
|
2020-03-30 18:01:44 +00:00
|
|
|
var
|
2020-04-27 20:51:12 +00:00
|
|
|
combos: integer;
|
|
|
|
i,j: integer;
|
2020-03-30 18:01:44 +00:00
|
|
|
begin
|
2020-04-27 20:51:12 +00:00
|
|
|
MM := 0;
|
|
|
|
MP := 0;
|
|
|
|
for i := 1 to NumDims do
|
|
|
|
begin
|
|
|
|
combos := 1;
|
2020-03-30 18:01:44 +00:00
|
|
|
|
2020-04-27 20:51:12 +00:00
|
|
|
// get numerator factorial products down to i
|
|
|
|
for j := NumDims downto i + 1 do
|
|
|
|
combos := combos * j;
|
2020-03-30 18:01:44 +00:00
|
|
|
|
2020-04-27 20:51:12 +00:00
|
|
|
// divide by factorial of NumDims - i;
|
|
|
|
for j := (NumDims - i) downto 2 do
|
|
|
|
combos := combos div j;
|
2020-03-30 18:01:44 +00:00
|
|
|
|
2020-04-27 20:51:12 +00:00
|
|
|
if combos > MP then
|
|
|
|
MP := combos;
|
|
|
|
if i * combos > MM then
|
|
|
|
MM := i * combos;
|
|
|
|
end;
|
2020-03-30 18:01:44 +00:00
|
|
|
end;
|
|
|
|
|
2020-12-03 23:51:15 +00:00
|
|
|
|
|
|
|
procedure TLogLinScreenForm.OutBtnClick(Sender: TObject);
|
2020-04-27 20:51:12 +00:00
|
|
|
var
|
2020-12-03 23:51:15 +00:00
|
|
|
i: integer;
|
2020-04-27 20:51:12 +00:00
|
|
|
begin
|
2020-12-03 23:51:15 +00:00
|
|
|
i := 0;
|
|
|
|
while i < SelectList.Items.Count do
|
|
|
|
begin
|
|
|
|
if SelectList.Selected[i] then
|
|
|
|
begin
|
|
|
|
VarList.Items.Add(SelectList.Items[i]);
|
|
|
|
SelectList.Items.Delete(i);
|
|
|
|
i := 0;
|
|
|
|
end else
|
|
|
|
i := i + 1;
|
|
|
|
end;
|
|
|
|
UpdateBtnStates;
|
|
|
|
UpdateMinMaxGrid;
|
|
|
|
end;
|
2020-04-27 20:51:12 +00:00
|
|
|
|
|
|
|
|
2020-12-03 23:51:15 +00:00
|
|
|
{ SUBROUTINE RESET(FIT, NTAB, AVG)
|
2020-04-27 20:51:12 +00:00
|
|
|
|
2020-12-03 23:51:15 +00:00
|
|
|
ALGORITHM AS 160.4 APPL. STATIST. (1981) VOL.30, NO.1
|
2020-04-27 20:51:12 +00:00
|
|
|
|
2020-12-03 23:51:15 +00:00
|
|
|
Initialize the fitted values to the average entry
|
2020-03-30 18:01:44 +00:00
|
|
|
|
2020-12-03 23:51:15 +00:00
|
|
|
REAL FIT(NTAB)
|
|
|
|
}
|
|
|
|
procedure TLogLinScreenForm.RESET(var FIT: DblDyneVec; NTAB: Integer; AVG: Double);
|
2020-04-27 20:51:12 +00:00
|
|
|
var
|
2020-12-03 23:51:15 +00:00
|
|
|
I: integer;
|
2020-03-30 18:01:44 +00:00
|
|
|
begin
|
2020-12-03 23:51:15 +00:00
|
|
|
for I := 1 to NTAB do //DO 100 I = 1, NTAB
|
2020-04-27 20:51:12 +00:00
|
|
|
begin
|
2020-12-03 23:51:15 +00:00
|
|
|
FIT[I] := AVG;
|
|
|
|
end; // 100 CONTINUE
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
procedure TLogLinScreenForm.Reset;
|
|
|
|
begin
|
|
|
|
inherited;
|
|
|
|
CollectVariableNames(OS3MainFrm.DataGrid, VarList.Items);
|
|
|
|
SelectList.Clear;
|
|
|
|
UpdateBtnStates;
|
|
|
|
UpdateMinMaxGrid;
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
{ SUBROUTINE SCREEN(NVAR, MP, MM, NTAB, TABLE, DIM, GSQ, DGFR,
|
|
|
|
* PART, MARG, DFS, IP, IM, ISET, JSET, CONFIG, FIT, SIZE,
|
|
|
|
* COORD, X, Y, IFAULT)
|
|
|
|
|
|
|
|
ALGORITHM AS 160 APPL. STATIST. (1981) VOL.30, NO.1
|
|
|
|
|
|
|
|
Screen all efects for partial and marginal association.
|
|
|
|
|
|
|
|
INTEGER NVAR, MP, MM, NTAB, IP(NVAR,MP), IM(NVAR,MM), DGFR(NVAR),
|
|
|
|
* DFS(NVAR,MP), ISET(NVAR), JSET(NVAR), CONFIG(NVAR,MP),
|
|
|
|
* DIM(NVAR), DF, SIZE(NVAR), COORD(NVAR)
|
|
|
|
REAL GSQ(NVAR), PART(NVAR,MP), MARG(NVAR,MP), TABLE(NTAB),
|
|
|
|
* FIT(NTAB), X(NTAB), Y(NTAB), ZERO
|
|
|
|
DATA ZERO /0.0/
|
|
|
|
}
|
|
|
|
procedure TLogLinScreenForm.Screen(var NVAR: integer; var MP: integer;
|
|
|
|
var MM: integer; var NTAB: integer; var TABLE: DblDyneVec;
|
|
|
|
var DIM: IntDyneVec; var GSQ: DblDyneVec; var DGFR: IntDyneVec;
|
|
|
|
var PART: DblDyneMat; var MARG: DblDyneMat; var DFS: IntDyneMat;
|
|
|
|
var IP: IntDyneMat; var IM: IntDyneMat; var ISET: IntDyneVec;
|
|
|
|
var JSET: IntDyneVec; var CONFIG: IntDyneMat; var FIT: DblDyneVec;
|
|
|
|
var SIZE: IntDyneVec; var COORD: IntDyneVec; var X: DblDyneVec;
|
|
|
|
var Y: DblDyneVec; var IFAULT: integer);
|
|
|
|
Label
|
|
|
|
160, 170;
|
|
|
|
const
|
|
|
|
ZERO = 0.0;
|
|
|
|
var
|
|
|
|
ISZ, MAX, LIM, I, J, NV1, M, M1, ITP, NP, NP1, L3, DF: integer;
|
|
|
|
G21, G22, G23, AVG: double;
|
|
|
|
|
|
|
|
begin
|
|
|
|
//
|
|
|
|
// Check for input errors
|
|
|
|
//
|
|
|
|
IFAULT := 1;
|
|
|
|
IF (NVAR <= 1) then exit;
|
|
|
|
ISZ := 1;
|
|
|
|
for I := 1 to NVAR do
|
|
|
|
begin
|
|
|
|
if (DIM[I] <= 1) then IFAULT := 2;
|
|
|
|
ISZ := ISZ * DIM[i];
|
|
|
|
end;
|
|
|
|
IF (ISZ <> NTAB) then IFAULT := 2;
|
|
|
|
MAX := 1;
|
|
|
|
LIM := NVAR div 2;
|
|
|
|
for I := 1 to LIM do MAX := MAX * (NVAR - I + 1) div I;
|
|
|
|
IF (MP < MAX) then IFAULT := 3;
|
|
|
|
MAX := 1;
|
|
|
|
LIM := (NVAR - 1) div 2;
|
|
|
|
for I := 1 to LIM do MAX := MAX * (NVAR - I) div I;
|
|
|
|
MAX := MAX * NVAR;
|
|
|
|
IF (MM < MAX) then IFAULT := 4;
|
|
|
|
IF (IFAULT > 1) then exit;
|
|
|
|
//
|
|
|
|
// Fit the no effect model
|
|
|
|
//
|
|
|
|
DGFR[NVAR] := NTAB - 1;
|
|
|
|
AVG := ZERO;
|
|
|
|
IFAULT := 5;
|
|
|
|
for I := 1 to NTAB do
|
|
|
|
begin
|
|
|
|
IF (TABLE[I] < ZERO) then exit; //RETURN
|
|
|
|
AVG := AVG + TABLE[I];
|
|
|
|
end;
|
|
|
|
IFAULT := 0;
|
|
|
|
AVG := AVG / NTAB;
|
|
|
|
RESET(FIT, NTAB, AVG);
|
|
|
|
LIKE(GSQ[1], FIT, TABLE, NTAB);
|
|
|
|
//
|
|
|
|
// Begin fitting effects
|
|
|
|
//
|
|
|
|
NV1 := NVAR - 1;
|
|
|
|
for M := 1 to NV1 do
|
|
|
|
begin
|
|
|
|
// DO 200 M = 1, NV1
|
|
|
|
//
|
|
|
|
// Set up the arrays IP and IM
|
|
|
|
//
|
|
|
|
M1 := M;
|
|
|
|
CONF(NVAR, M1, MP, MM, ISET, JSET, IP, IM, NP);
|
|
|
|
//
|
|
|
|
// Fit the saturated model
|
|
|
|
//
|
|
|
|
RESET(FIT, NTAB, AVG);
|
|
|
|
EVAL(IP, NP, M, 1, NVAR, MP, CONFIG, DIM, DGFR[M]);
|
|
|
|
LOGFIT(NVAR, NTAB, NP, DIM, CONFIG, TABLE, FIT, SIZE, COORD, X, Y);
|
|
|
|
LIKE(GSQ[M+1], FIT, TABLE, NTAB);
|
|
|
|
//
|
|
|
|
// Move the first column of IP to the last
|
|
|
|
//
|
|
|
|
for I := 1 to M do
|
|
|
|
begin
|
|
|
|
// DO 150 I = 1, M
|
|
|
|
ITP := IP[I,1];
|
|
|
|
NP1 := NP - 1;
|
|
|
|
for J := 1 to NP1 do IP[I,J] := IP[I,J+1];
|
|
|
|
IP[I,NP] := ITP;
|
|
|
|
end; // 150 CONTINUE
|
|
|
|
L3 := -M + 1;
|
|
|
|
for J := 1 to NP do
|
|
|
|
begin
|
|
|
|
// DO 190 J = 1, NP
|
|
|
|
//
|
|
|
|
// Fit the effects in IP ignoring the last column
|
|
|
|
//
|
|
|
|
RESET(FIT, NTAB, AVG);
|
|
|
|
EVAL(IP, NP-1, M, 1, NVAR, MP, CONFIG, DIM, DF);
|
|
|
|
LOGFIT(NVAR, NTAB, NP-1, DIM, CONFIG, TABLE, FIT, SIZE, COORD, X, Y);
|
|
|
|
LIKE(G21, FIT, TABLE, NTAB);
|
|
|
|
DFS[M,J] := DGFR[M] - DF;
|
|
|
|
PART[M,J] := G21 - GSQ[M+1];
|
|
|
|
//
|
|
|
|
// For M = 1, partials and marginals are equal
|
|
|
|
//
|
|
|
|
IF (M > 1) then GOTO 160;
|
|
|
|
MARG[1,J] := PART[1,J];
|
|
|
|
GOTO 170;
|
|
|
|
//
|
|
|
|
// Fit the last column alone
|
|
|
|
//
|
|
|
|
160: RESET(FIT, NTAB, AVG);
|
|
|
|
EVAL(IP, 1, M, NP, NVAR, MP, CONFIG, DIM, DF);
|
|
|
|
LOGFIT(NVAR, NTAB, 1, DIM, CONFIG, TABLE, FIT, SIZE,
|
|
|
|
COORD, X, Y);
|
|
|
|
LIKE(G22, FIT, TABLE, NTAB);
|
|
|
|
//
|
|
|
|
// Locate the appropriate columns of IM and fit them
|
|
|
|
//
|
|
|
|
L3 := L3 + M;
|
|
|
|
RESET(FIT, NTAB, AVG);
|
|
|
|
EVAL(IM, M, M-1, L3, NVAR, MM, CONFIG, DIM, DF);
|
|
|
|
LOGFIT(NVAR, NTAB, M, DIM, CONFIG, TABLE, FIT, SIZE,
|
|
|
|
COORD, X, Y);
|
|
|
|
LIKE(G23, FIT, TABLE, NTAB);
|
|
|
|
MARG[M,J] := G23 - G22;
|
|
|
|
//
|
|
|
|
// Move the next effect to be ignored to the last in IP
|
|
|
|
//
|
|
|
|
170: for I := 1 to M do // DO 180 I = 1, M
|
|
|
|
begin
|
|
|
|
ITP := IP[I,NP];
|
|
|
|
IP[I,NP] := IP[I,J];
|
|
|
|
IP[I,J] := ITP;
|
|
|
|
end;
|
|
|
|
// 180 CONTINUE
|
|
|
|
end; // 190 CONTINUE
|
|
|
|
//
|
|
|
|
DGFR[NVAR] := DGFR[NVAR] - DGFR[M];
|
|
|
|
GSQ[M] := GSQ[M] - GSQ[M+1];
|
|
|
|
end; // 200 CONTINUE
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
procedure TLogLinScreenForm.SelectListSelectionChange(Sender: TObject;
|
|
|
|
User: boolean);
|
|
|
|
begin
|
|
|
|
UpdateBtnStates;
|
2020-03-30 18:01:44 +00:00
|
|
|
end;
|
|
|
|
|
2020-12-03 23:51:15 +00:00
|
|
|
|
2020-12-02 23:51:03 +00:00
|
|
|
procedure TLogLinScreenForm.UpdateBtnStates;
|
2020-04-27 15:30:03 +00:00
|
|
|
begin
|
2020-12-03 23:51:15 +00:00
|
|
|
inherited;
|
|
|
|
|
2020-04-27 15:30:03 +00:00
|
|
|
InBtn.Enabled := AnySelected(VarList);
|
|
|
|
OutBtn.Enabled := AnySelected(SelectList);
|
|
|
|
AllBtn.Enabled := VarList.Items.Count > 0;
|
|
|
|
end;
|
|
|
|
|
2020-12-03 23:51:15 +00:00
|
|
|
|
2020-12-02 23:51:03 +00:00
|
|
|
procedure TLogLinScreenForm.UpdateMinMaxGrid;
|
2020-04-27 20:51:12 +00:00
|
|
|
var
|
|
|
|
NumDims, j: Integer;
|
|
|
|
begin
|
|
|
|
if CountVarChk.Checked then
|
|
|
|
NumDims := SelectList.Count - 1
|
|
|
|
else
|
|
|
|
NumDims := SelectList.Count;
|
|
|
|
if NumDims < 0 then NumDims := 0;
|
|
|
|
MinMaxGrid.RowCount := NumDims + 1;
|
|
|
|
for j := 1 to MinMaxGrid.RowCount-1 do
|
|
|
|
begin
|
|
|
|
MinMaxGrid.Cells[0, j] := SelectList.Items[j-1];
|
|
|
|
MinMaxGrid.Cells[1, j] := '';
|
|
|
|
MinMaxGrid.Cells[2, j] := '';
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
2020-12-03 23:51:15 +00:00
|
|
|
|
|
|
|
function TLogLinScreenForm.Validate(out AMsg: String;
|
|
|
|
out AControl: TWinControl): Boolean;
|
|
|
|
begin
|
|
|
|
Result := false;
|
|
|
|
|
|
|
|
if SelectList.Count = 0 then
|
|
|
|
begin
|
|
|
|
AMsg := 'No variables selected.';
|
|
|
|
AControl := VarList;
|
|
|
|
exit;
|
|
|
|
end;
|
|
|
|
|
|
|
|
Result := true;
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
|
|
|
procedure TLogLinScreenForm.VarListDblClick(Sender: TObject);
|
|
|
|
var
|
|
|
|
index: Integer;
|
|
|
|
begin
|
|
|
|
index := VarList.ItemIndex;
|
|
|
|
if index > -1 then begin
|
|
|
|
SelectList.Items.Add(VarList.Items[index]);
|
|
|
|
VarList.Items.Delete(index);
|
|
|
|
UpdateBtnStates;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
|
2020-12-02 23:51:03 +00:00
|
|
|
procedure TLogLinScreenForm.VarListSelectionChange(Sender: TObject; User: boolean);
|
2020-04-27 15:30:03 +00:00
|
|
|
begin
|
|
|
|
UpdateBtnStates;
|
|
|
|
end;
|
|
|
|
|
2020-03-30 18:01:44 +00:00
|
|
|
|
|
|
|
end.
|
|
|
|
|