You've already forked lazarus-ccr
1173 lines
36 KiB
ObjectPascal
1173 lines
36 KiB
ObjectPascal
![]() |
unit LogLinScreenUnit;
|
||
|
|
||
|
{$mode objfpc}{$H+}
|
||
|
|
||
|
interface
|
||
|
|
||
|
uses
|
||
|
Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics, Dialogs,
|
||
|
StdCtrls, Buttons, ExtCtrls,
|
||
|
Globals, MainUnit, FunctionsLib, OutputUnit, DataProcs, ContextHelpUnit;
|
||
|
|
||
|
type
|
||
|
|
||
|
{ TLogLinScreenFrm }
|
||
|
|
||
|
TLogLinScreenFrm = class(TForm)
|
||
|
Bevel1: TBevel;
|
||
|
HelpBtn: TButton;
|
||
|
InBtn: TBitBtn;
|
||
|
Label10: TLabel;
|
||
|
Label11: TLabel;
|
||
|
OutBtn: TBitBtn;
|
||
|
AllBtn: TBitBtn;
|
||
|
ResetBtn: TButton;
|
||
|
CancelBtn: TButton;
|
||
|
ComputeBtn: TButton;
|
||
|
ReturnBtn: TButton;
|
||
|
MarginsChk: TCheckBox;
|
||
|
GenlModelChk: TCheckBox;
|
||
|
GroupBox1: TGroupBox;
|
||
|
MaxEdit: TEdit;
|
||
|
MinEdit: TEdit;
|
||
|
Label8: TLabel;
|
||
|
Label9: TLabel;
|
||
|
VarNoEdit: TEdit;
|
||
|
Label2: TLabel;
|
||
|
Label3: TLabel;
|
||
|
Label7: TLabel;
|
||
|
Panel1: TPanel;
|
||
|
ScrollBar1: TScrollBar;
|
||
|
SelectList: TListBox;
|
||
|
VarList: TListBox;
|
||
|
Step2Btn: TButton;
|
||
|
CountVarChk: TCheckBox;
|
||
|
Label1: TLabel;
|
||
|
procedure AllBtnClick(Sender: TObject);
|
||
|
procedure CancelBtnClick(Sender: TObject);
|
||
|
procedure ComputeBtnClick(Sender: TObject);
|
||
|
procedure FormActivate(Sender: TObject);
|
||
|
procedure FormCreate(Sender: TObject);
|
||
|
procedure FormShow(Sender: TObject);
|
||
|
procedure HelpBtnClick(Sender: TObject);
|
||
|
procedure InBtnClick(Sender: TObject);
|
||
|
procedure MaxEditKeyPress(Sender: TObject; var Key: char);
|
||
|
procedure MinEditKeyPress(Sender: TObject; var Key: char);
|
||
|
procedure OutBtnClick(Sender: TObject);
|
||
|
procedure ResetBtnClick(Sender: TObject);
|
||
|
procedure ReturnBtnClick(Sender: TObject);
|
||
|
procedure ScrollBar1Change(Sender: TObject);
|
||
|
procedure Step2BtnClick(Sender: TObject);
|
||
|
function ArrayPosition(Sender: TObject; NoDims : integer;
|
||
|
VAR Data : DblDyneVec;
|
||
|
VAR Subscripts : IntDyneVec;
|
||
|
VAR DimSize : IntDyneVec) : integer;
|
||
|
procedure Marginals(Sender: TObject;
|
||
|
NoDims : integer;
|
||
|
ArraySize : integer;
|
||
|
VAR Indexes : IntDyneMat;
|
||
|
VAR Data : DblDyneVec;
|
||
|
VAR Margins : IntDyneMat);
|
||
|
|
||
|
private
|
||
|
{ private declarations }
|
||
|
FAutoSized: Boolean;
|
||
|
procedure 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);
|
||
|
|
||
|
procedure CONF(VAR N : integer; VAR M : integer;
|
||
|
VAR MP : integer;
|
||
|
VAR MM : integer;
|
||
|
VAR ISET : IntDyneVec; VAR JSET : IntDyneVec;
|
||
|
VAR IP : IntDyneMat; VAR IM : IntDyneMat; VAR NP : integer);
|
||
|
|
||
|
procedure COMBO(VAR ISET : IntDyneVec;
|
||
|
N, M : Integer;
|
||
|
VAR LAST : boolean);
|
||
|
|
||
|
procedure EVAL(VAR IAR : IntDyneMat;
|
||
|
NC, NV, IBEG, NVAR, MAX : integer;
|
||
|
VAR CONFIG : IntDyneMat;
|
||
|
VAR DIM : IntDyneVec; VAR DF : integer);
|
||
|
|
||
|
procedure RESET(VAR FIT : DblDyneVec; NTAB : Integer;
|
||
|
AVG : Double);
|
||
|
|
||
|
procedure LIKE(VAR GSQ : Double; VAR FIT : DblDyneVec;
|
||
|
VAR TABLE : DblDyneVec; NTAB : integer);
|
||
|
|
||
|
procedure LOGFIT(NVAR, NTAB, NCON : integer;
|
||
|
VAR DIM : IntDyneVec;
|
||
|
VAR CONFIG : IntDyneMat; VAR TABLE : DblDyneVec;
|
||
|
VAR FIT : DblDyneVec; VAR SIZE : IntDyneVec;
|
||
|
VAR COORD : IntDyneVec; VAR X : DblDyneVec;
|
||
|
VAR Y : DblDyneVec);
|
||
|
|
||
|
procedure MaxCombos(NoDims : integer; VAR MM : integer; VAR MP : integer);
|
||
|
|
||
|
public
|
||
|
{ public declarations }
|
||
|
end;
|
||
|
|
||
|
var
|
||
|
LogLinScreenFrm: TLogLinScreenFrm;
|
||
|
Minimums : IntDyneVec;
|
||
|
Maximums : IntDyneVec;
|
||
|
Response : BoolDyneVec;
|
||
|
Interact : BoolDyneVec;
|
||
|
NoDims : integer;
|
||
|
|
||
|
implementation
|
||
|
|
||
|
uses
|
||
|
Math;
|
||
|
|
||
|
{ TLogLinScreenFrm }
|
||
|
|
||
|
procedure TLogLinScreenFrm.ResetBtnClick(Sender: TObject);
|
||
|
VAR i : integer;
|
||
|
begin
|
||
|
Panel1.Visible := false;
|
||
|
VarList.Clear;
|
||
|
SelectList.Clear;
|
||
|
VarNoEdit.Text := '1';
|
||
|
MaxEdit.Text := '';
|
||
|
MinEdit.Text := '';
|
||
|
InBtn.Enabled := true;
|
||
|
OutBtn.Enabled := false;
|
||
|
NoDims := 0;
|
||
|
Minimums := nil;
|
||
|
Maximums := nil;
|
||
|
Response := nil;
|
||
|
Interact := nil;
|
||
|
ScrollBar1.Min := 1;
|
||
|
ScrollBar1.Max := 1;
|
||
|
ScrollBar1.Position := 1;
|
||
|
for i := 1 to NoVariables do VarList.Items.Add(OS3MainFrm.DataGrid.Cells[i,0]);
|
||
|
end;
|
||
|
|
||
|
procedure TLogLinScreenFrm.ReturnBtnClick(Sender: TObject);
|
||
|
begin
|
||
|
Maximums := nil;
|
||
|
Minimums := nil;
|
||
|
Response := nil;
|
||
|
Interact := nil;
|
||
|
Close;
|
||
|
end;
|
||
|
|
||
|
procedure TLogLinScreenFrm.ScrollBar1Change(Sender: TObject);
|
||
|
begin
|
||
|
VarNoEdit.Text := IntToStr(ScrollBar1.Position);
|
||
|
end;
|
||
|
|
||
|
procedure TLogLinScreenFrm.Step2BtnClick(Sender: TObject);
|
||
|
begin
|
||
|
if CountVarChk.Checked then
|
||
|
begin
|
||
|
NoDims := NoDims - 1;
|
||
|
ScrollBar1.Max := NoDims;
|
||
|
end;
|
||
|
Panel1.Visible := true;
|
||
|
setLength(Maximums,NoDims);
|
||
|
SetLength(Minimums,NoDims);
|
||
|
SetLength(Response,NoDims);
|
||
|
SetLength(Interact,NoDims);
|
||
|
MaxEdit.SetFocus;
|
||
|
end;
|
||
|
|
||
|
procedure TLogLinScreenFrm.InBtnClick(Sender: TObject);
|
||
|
VAR index : integer;
|
||
|
begin
|
||
|
index := VarList.ItemIndex;
|
||
|
SelectList.Items.Add(VarList.Items.Strings[index]);
|
||
|
VarList.Items.Delete(index);
|
||
|
OutBtn.Enabled := true;
|
||
|
NoDims := NoDims + 1;
|
||
|
ScrollBar1.Max := NoDims;
|
||
|
index := VarList.Items.Count;
|
||
|
if index <= 0 then InBtn.Enabled := false;
|
||
|
end;
|
||
|
|
||
|
procedure TLogLinScreenFrm.MaxEditKeyPress(Sender: TObject; var Key: char);
|
||
|
VAR DimNo : integer;
|
||
|
begin
|
||
|
if ord(Key) = 13 then // return key
|
||
|
begin
|
||
|
DimNo := StrToInt(VarNoEdit.Text);
|
||
|
Maximums[DimNo-1] := StrToInt(MaxEdit.Text);
|
||
|
ScrollBar1.SetFocus;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TLogLinScreenFrm.MinEditKeyPress(Sender: TObject; var Key: char);
|
||
|
VAR DimNo : integer;
|
||
|
begin
|
||
|
if ord(Key) = 13 then // return key
|
||
|
begin
|
||
|
DimNo := StrToInt(VarNoEdit.Text);
|
||
|
Minimums[DimNo-1] := StrToInt(MinEdit.Text);
|
||
|
MaxEdit.SetFocus;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TLogLinScreenFrm.FormActivate(Sender: TObject);
|
||
|
var
|
||
|
w: Integer;
|
||
|
begin
|
||
|
if FAutoSized then
|
||
|
exit;
|
||
|
|
||
|
w := MaxValue([HelpBtn.Width, ResetBtn.Width, CancelBtn.Width, ComputeBtn.Width, ReturnBtn.Width]);
|
||
|
HelpBtn.Constraints.MinWidth := w;
|
||
|
ResetBtn.Constraints.MinWidth := w;
|
||
|
CancelBtn.Constraints.MinWidth := w;
|
||
|
ComputeBtn.Constraints.MinWidth := w;
|
||
|
ReturnBtn.Constraints.MinWidth := w;
|
||
|
|
||
|
Constraints.MinWidth := Width;
|
||
|
Constraints.MinHeight := Height;
|
||
|
|
||
|
FAutoSized := true;
|
||
|
end;
|
||
|
|
||
|
procedure TLogLinScreenFrm.FormCreate(Sender: TObject);
|
||
|
begin
|
||
|
Assert(OS3MainFrm <> nil);
|
||
|
if OutputFrm = nil then Application.CreateForm(TOutputFrm, OutputFrm);
|
||
|
end;
|
||
|
|
||
|
procedure TLogLinScreenFrm.FormShow(Sender: TObject);
|
||
|
begin
|
||
|
ResetBtnClick(Self);
|
||
|
end;
|
||
|
|
||
|
procedure TLogLinScreenFrm.HelpBtnClick(Sender: TObject);
|
||
|
begin
|
||
|
if ContextHelpForm = nil then
|
||
|
Application.CreateForm(TContextHelpForm, ContextHelpForm);
|
||
|
ContextHelpForm.HelpMessage((Sender as TButton).Tag);
|
||
|
end;
|
||
|
|
||
|
procedure TLogLinScreenFrm.CancelBtnClick(Sender: TObject);
|
||
|
begin
|
||
|
Maximums := nil;
|
||
|
Minimums := nil;
|
||
|
Response := nil;
|
||
|
Interact := nil;
|
||
|
Close;
|
||
|
end;
|
||
|
|
||
|
procedure TLogLinScreenFrm.AllBtnClick(Sender: TObject);
|
||
|
VAR i, count : integer;
|
||
|
begin
|
||
|
count := VarList.Items.Count;
|
||
|
for i := 0 to count-1 do
|
||
|
SelectList.Items.Add(VarList.Items.Strings[i]);
|
||
|
InBtn.Enabled := false;
|
||
|
OutBtn.Enabled := true;
|
||
|
NoDims := SelectList.Items.Count;
|
||
|
ScrollBar1.Max := NoDims;
|
||
|
end;
|
||
|
|
||
|
procedure TLogLinScreenFrm.ComputeBtnClick(Sender: TObject);
|
||
|
var
|
||
|
ArraySize : integer;
|
||
|
N : integer;
|
||
|
index, index2, i, j, k, l, NoVars : integer;
|
||
|
count : integer;
|
||
|
Data : DblDyneVec;
|
||
|
Subscripts : IntDyneVec;
|
||
|
DimSize : IntDyneVec;
|
||
|
GridPos : IntDyneVec;
|
||
|
Labels : StrDyneVec;
|
||
|
Margins : IntDyneMat;
|
||
|
Expected : DblDyneVec;
|
||
|
WorkVec : IntDyneVec;
|
||
|
Indexes : IntDyneMat;
|
||
|
LogM : DblDyneVec;
|
||
|
NSize : IntDyneVec;
|
||
|
M : DblDyneMat;
|
||
|
astr, HeadStr : string;
|
||
|
MaxDim, MP, MM : integer;
|
||
|
U, Mu : Double;
|
||
|
Chi2, G2 : double;
|
||
|
DF : integer;
|
||
|
ProbChi2, ProbG2 : double;
|
||
|
GSQ : DblDyneVec;
|
||
|
DGFR : IntDyneVec;
|
||
|
PART : DblDyneMat;
|
||
|
MARG : DblDyneMat;
|
||
|
DFS : IntDyneMat;
|
||
|
IP : IntDyneMat;
|
||
|
IM : IntDyneMat;
|
||
|
ISET : IntDyneVec;
|
||
|
JSET : IntDyneVec;
|
||
|
CONFIG : IntDyneMat;
|
||
|
FIT : DblDyneVec;
|
||
|
SIZE : IntDyneVec;
|
||
|
COORD : IntDyneVec;
|
||
|
X, Y : DblDyneVec;
|
||
|
IFAULT : integer;
|
||
|
TABLE : DblDyneVec;
|
||
|
DIM : IntDyneVec;
|
||
|
begin
|
||
|
OutputFrm.RichEdit.Clear;
|
||
|
|
||
|
// Allocate space for labels, DimSize and SubScripts
|
||
|
NoVars := SelectList.Items.Count;
|
||
|
SetLength(Labels,NoVars);
|
||
|
SetLength(DimSize,NoDims);
|
||
|
SetLength(Subscripts,NoDims);
|
||
|
SetLength(GridPos,NoVars);
|
||
|
|
||
|
// get variable labels and column positions
|
||
|
for i := 1 to NoVars do
|
||
|
begin
|
||
|
astr := SelectList.Items.Strings[i-1];
|
||
|
for j := 1 to NoVariables do
|
||
|
begin
|
||
|
if OS3MainFrm.DataGrid.Cells[j,0] = astr then
|
||
|
begin
|
||
|
Labels[i-1] := astr;
|
||
|
GridPos[i-1] := j;
|
||
|
break;
|
||
|
end;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
// Get no. of categories for each dimension (DimSize)
|
||
|
MaxDim := 0;
|
||
|
ArraySize := 1;
|
||
|
for i := 0 to NoDims - 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,NoDims,MaxDim);
|
||
|
SetLength(Expected,ArraySize);
|
||
|
SetLength(Indexes,ArraySize+1,NoDims);
|
||
|
SetLength(LogM,ArraySize);
|
||
|
SetLength(M,ArraySize,NoDims);
|
||
|
SetLength(NSize,NoDims);
|
||
|
|
||
|
// Initialize data and margins arrays
|
||
|
for i := 1 to NoDims do
|
||
|
for j := 1 to MaxDim do
|
||
|
Margins[i-1,j-1] := 0;
|
||
|
for i := 1 to ArraySize do Data[i-1] := 0;
|
||
|
N := 0;
|
||
|
|
||
|
// Read and store frequencies in Data
|
||
|
for i := 1 to NoCases do
|
||
|
begin
|
||
|
if GoodRecord(i, NoVars, GridPos) then // casewise check
|
||
|
begin
|
||
|
for j := 1 to NoDims do // get cell subscripts
|
||
|
begin
|
||
|
index := StrToInt(OS3MainFrm.DataGrid.Cells[GridPos[j-1],i]);
|
||
|
index := index - Minimums[j-1] + 1;
|
||
|
Subscripts[j-1] := index;
|
||
|
end;
|
||
|
|
||
|
index := ArrayPosition(Self, NoDims, Data, Subscripts, DimSize);
|
||
|
|
||
|
for j := 1 to NoDims do // save subscripts for later use
|
||
|
Indexes[index,j-1] := Subscripts[j-1];
|
||
|
|
||
|
if CountVarChk.Checked then
|
||
|
begin
|
||
|
k := GridPos[NoVars-1];
|
||
|
Data[index] := Data[index] + StrToInt(OS3MainFrm.DataGrid.Cells[k,i]);
|
||
|
end
|
||
|
else Data[index] := Data[index] + 1;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
// get total N
|
||
|
for i := 1 to ArraySize do N := N + Round(Data[i-1]);
|
||
|
|
||
|
// Get marginal frequencies
|
||
|
Marginals(Self,NoDims,ArraySize,Indexes,Data,Margins);
|
||
|
|
||
|
// Print Marginal totals if requested
|
||
|
if MarginsChk.Checked then
|
||
|
begin
|
||
|
OutputFrm.RichEdit.Clear;
|
||
|
OutputFrm.RichEdit.Lines.Add('FILE: '+ OS3MainFrm.FileNameEdit.Text);
|
||
|
OutputFrm.RichEdit.Lines.Add('');
|
||
|
for i := 1 to NoDims do
|
||
|
begin
|
||
|
HeadStr := 'Marginal Totals for ' + Labels[i-1];
|
||
|
k := DimSize[i-1];
|
||
|
for j := 0 to k-1 do WorkVec[j] := Margins[i-1,j];
|
||
|
VecPrint(WorkVec,k,HeadStr);
|
||
|
end;
|
||
|
end;
|
||
|
OutputFrm.RichEdit.Lines.Add('');
|
||
|
astr := Format('Total Frequencies = %d',[N]);
|
||
|
OutputFrm.RichEdit.Lines.Add(astr);
|
||
|
OutputFrm.ShowModal;
|
||
|
|
||
|
// Get Expected cell values
|
||
|
U := 0.0; // overall mean (mu) of log linear model
|
||
|
for i := 1 to ArraySize do // indexes point to each cell
|
||
|
begin
|
||
|
Expected[i-1] := 1.0;
|
||
|
for j := 1 to NoDims do
|
||
|
begin
|
||
|
k := Indexes[i-1,j-1];
|
||
|
Expected[i-1] := Expected[i-1] * (Margins[j-1,k-1] / N);
|
||
|
end;
|
||
|
Expected[i-1] := Expected[i-1] * N;
|
||
|
LogM[i-1] := ln(Expected[i-1]);
|
||
|
end;
|
||
|
for i := 1 to ArraySize do U := U + LogM[i-1];
|
||
|
U := U / ArraySize;
|
||
|
|
||
|
// print expected values
|
||
|
OutputFrm.RichEdit.Clear;
|
||
|
OutputFrm.RichEdit.Lines.Add('FILE: '+ OS3MainFrm.FileNameEdit.Text);
|
||
|
OutputFrm.RichEdit.Lines.Add('');
|
||
|
OutputFrm.RichEdit.Lines.Add('EXPECTED CELL VALUES FOR MODEL OF COMPLETE INDEPENDENCE');
|
||
|
OutputFrm.RichEdit.Lines.Add('');
|
||
|
OutputFrm.RichEdit.Lines.Add('Cell Observed Expected Log Expected');
|
||
|
for i := 1 to ArraySize do
|
||
|
begin
|
||
|
astr := '';
|
||
|
for j := 1 to NoDims 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]]);
|
||
|
OutputFrm.RichEdit.Lines.Add(astr);
|
||
|
end;
|
||
|
chi2 := 0.0;
|
||
|
G2 := 0.0;
|
||
|
|
||
|
// Calculate chi-squared and G squared statistics
|
||
|
for i := 1 to ArraySize do
|
||
|
begin
|
||
|
chi2 := chi2 + Sqr(Data[i-1] - Expected[i-1]) / Expected[i-1];
|
||
|
G2 := G2 + Data[i-1] * ln(Data[i-1] / Expected[i-1]);
|
||
|
end;
|
||
|
G2 := 2.0 * G2;
|
||
|
DF := 1;
|
||
|
for i := 1 to NoDims do DF := DF * (DimSize[i-1]-1);
|
||
|
ProbChi2 := 1.0 - Chisquaredprob(chi2,DF);
|
||
|
ProbG2 := 1.0 - Chisquaredprob(G2,DF);
|
||
|
astr := format('Chisquare = %10.3f with probability = %10.3f (DF = %d)',[chi2,ProbChi2,DF]);
|
||
|
OutputFrm.RichEdit.Lines.Add(astr);
|
||
|
astr := format('G squared = %10.3f with probability = %10.3f (DF = %d)',[G2,ProbG2,DF]);
|
||
|
OutputFrm.RichEdit.Lines.Add(astr);
|
||
|
OutputFrm.RichEdit.Lines.Add('');
|
||
|
astr := format('U (mu) for general loglinear model = %10.2f',[U]);
|
||
|
OutputFrm.RichEdit.Lines.Add(astr);
|
||
|
OutputFrm.RichEdit.Lines.Add('');
|
||
|
OutputFrm.ShowModal;
|
||
|
|
||
|
// Get log linear model values for each cell
|
||
|
// get M's for each cell
|
||
|
OutputFrm.RichEdit.Clear;
|
||
|
OutputFrm.RichEdit.Lines.Add('First Order LogLinear Model Factors and N of Cells in Each');
|
||
|
astr := 'CELL ';
|
||
|
for i := 1 to NoDims do astr := astr + format(' U%d N Cells ',[i]);
|
||
|
OutputFrm.RichEdit.Lines.Add(astr);
|
||
|
OutputFrm.RichEdit.Lines.Add('');
|
||
|
for i := 1 to ArraySize do // cell
|
||
|
begin
|
||
|
astr := '';
|
||
|
for j := 1 to NoDims do
|
||
|
astr := astr + format('%3d ',[Indexes[i-1,j-1]]);
|
||
|
for j := 1 to NoDims 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
|
||
|
begin
|
||
|
count := count + 1;
|
||
|
Mu := Mu + LogM[k-1];
|
||
|
end;
|
||
|
end;
|
||
|
Mu := Mu / count - U;
|
||
|
astr := astr + format('%10.3f %3d ',[Mu,count]);
|
||
|
end;
|
||
|
OutputFrm.RichEdit.Lines.Add(astr);
|
||
|
end;
|
||
|
OutputFrm.ShowModal;
|
||
|
|
||
|
// get second order interactions
|
||
|
OutputFrm.RichEdit.Clear;
|
||
|
OutputFrm.RichEdit.Lines.Add('');
|
||
|
OutputFrm.RichEdit.Lines.Add('Second Order Loglinear Model Terms and N of Cells in Each');
|
||
|
astr := 'CELL ';
|
||
|
for i := 1 to NoDims-1 do
|
||
|
for j := i + 1 to NoDims do
|
||
|
astr := astr + format('U%d%d N Cells ',[i,j]);
|
||
|
OutputFrm.RichEdit.Lines.Add(astr);
|
||
|
OutputFrm.RichEdit.Lines.Add('');
|
||
|
for i := 1 to ArraySize do // cell
|
||
|
begin
|
||
|
astr := '';
|
||
|
for j := 1 to NoDims do
|
||
|
astr := astr + format('%3d ',[Indexes[i-1,j-1]]);
|
||
|
for j := 1 to NoDims-1 do // jth
|
||
|
begin
|
||
|
index := Indexes[i-1,j-1]; // sum for this mu using j and k
|
||
|
for k := j+1 to NoDims do // with kth
|
||
|
begin
|
||
|
index2 := Indexes[i-1,k-1];
|
||
|
Mu := 0.0;
|
||
|
count := 0;
|
||
|
for l := 1 to ArraySize do
|
||
|
begin
|
||
|
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)
|
||
|
OutputFrm.RichEdit.Lines.Add(astr);
|
||
|
end; // next i
|
||
|
|
||
|
OutputFrm.ShowModal;
|
||
|
OutputFrm.RichEdit.Clear;
|
||
|
|
||
|
// get maximum no. of interactions in saturated model
|
||
|
MaxCombos(NoDims, MM, MP);
|
||
|
|
||
|
SetLength(GSQ,NoDims+1);
|
||
|
SetLength(DGFR,NoDims+1);
|
||
|
SetLength(PART,NoDims+1,MP+1);
|
||
|
SetLength(MARG,NoDims+1,MP+1);
|
||
|
SetLength(DFS,NoDims+1,MP+1);
|
||
|
SetLength(IP,NoDims+1,MP+1);
|
||
|
SetLength(IM,NoDims+1,MM+1);
|
||
|
SetLength(ISET,NoDims+1);
|
||
|
SetLength(JSET,NoDims+1);
|
||
|
SetLength(CONFIG,NoDims+1,MP+1);
|
||
|
SetLength(FIT,ArraySize+1);
|
||
|
SetLength(SIZE,NoDims+1);
|
||
|
SetLength(COORD,NoDims+1);
|
||
|
SetLength(X,ArraySize+1);
|
||
|
SetLength(Y,ArraySize+1);
|
||
|
SetLength(TABLE,ArraySize+1);
|
||
|
SetLength(DIM,NoDims+1);
|
||
|
|
||
|
// Load TABLE and DIM one up from Data
|
||
|
for i := 1 to ArraySize do Table[i] := Data[i-1];
|
||
|
for i := 1 to NoDims do DIM[i] := DimSize[i-1];
|
||
|
|
||
|
Screen(NoDims,MP,MM,ArraySize,TABLE,DIM,
|
||
|
GSQ,DGFR,PART,MARG,DFS,IP,IM,ISET,JSET,CONFIG,FIT,SIZE,
|
||
|
COORD,X,Y,IFAULT);
|
||
|
|
||
|
// show results
|
||
|
astr := 'SCREEN FOR INTERACTIONS AMONG THE VARIABLES';
|
||
|
OutputFrm.RichEdit.Lines.Add(astr);
|
||
|
astr := 'Adapted from the Fortran program by Lustbader and Stodola printed in';
|
||
|
OutputFrm.RichEdit.Lines.Add(astr);
|
||
|
astr := 'Applied Statistics, Volume 30, Issue 1, 1981, pages 97-105 as Algorithm';
|
||
|
OutputFrm.RichEdit.Lines.Add(astr);
|
||
|
astr := 'AS 160 Partial and Marginal Association in Multidimensional Contingency Tables';
|
||
|
OutputFrm.RichEdit.Lines.Add(astr);
|
||
|
OutputFrm.RichEdit.Lines.Add('');
|
||
|
astr := 'Statistics for tests that the interactions of a given order are zero';
|
||
|
OutputFrm.RichEdit.Lines.Add(astr);
|
||
|
astr := 'ORDER STATISTIC D.F. PROB.';
|
||
|
OutputFrm.RichEdit.Lines.Add(astr);
|
||
|
for i := 1 to NoDims do
|
||
|
begin
|
||
|
ProbChi2 := 1.0 - ChiSquaredProb(GSQ[i],DGFR[i]);
|
||
|
astr := format('%5d %10.3f %3d %10.3f',[i,GSQ[i],DGFR[i],ProbChi2]);
|
||
|
OutputFrm.RichEdit.Lines.Add(astr);
|
||
|
end;
|
||
|
OutputFrm.RichEdit.Lines.Add('');
|
||
|
astr := 'Statistics for Marginal Association Tests';
|
||
|
OutputFrm.RichEdit.Lines.Add(astr);
|
||
|
astr := 'VARIABLE ASSOC. PART ASSOC. MARGINAL ASSOC. D.F. PROB';
|
||
|
OutputFrm.RichEdit.Lines.Add(astr);
|
||
|
for i := 1 to NoDims-1 do
|
||
|
begin
|
||
|
for j := 1 to MP do
|
||
|
begin
|
||
|
ProbChi2 := 1.0 - ChiSquaredProb(MARG[i,j],DFS[i,j]);
|
||
|
astr := format('%5d %5d %10.3f %10.3f %3d %10.3f',
|
||
|
[i,j,Part[i,j],MARG[i,j], DFS[i,j],ProbChi2]);
|
||
|
OutputFrm.RichEdit.Lines.Add(astr);
|
||
|
end;
|
||
|
end;
|
||
|
OutputFrm.ShowModal;
|
||
|
OutputFrm.RichEdit.Clear;
|
||
|
|
||
|
TABLE := nil;
|
||
|
DIM := nil;
|
||
|
Y := nil;
|
||
|
X := nil;
|
||
|
COORD := nil;
|
||
|
SIZE := nil;
|
||
|
FIT := nil;
|
||
|
CONFIG := nil;
|
||
|
JSET := nil;
|
||
|
ISET := nil;
|
||
|
IM := nil;
|
||
|
IP := nil;
|
||
|
DFS := nil;
|
||
|
MARG := nil;
|
||
|
PART := nil;
|
||
|
DGFR := nil;
|
||
|
GSQ := nil;
|
||
|
NSize := nil;
|
||
|
M := nil;
|
||
|
LogM := nil;
|
||
|
Indexes := nil;
|
||
|
Expected := nil;
|
||
|
Margins := nil;
|
||
|
Data := nil;
|
||
|
WorkVec := nil;
|
||
|
GridPos := nil;
|
||
|
Subscripts := nil;
|
||
|
DimSize := nil;
|
||
|
Labels := nil;
|
||
|
end;
|
||
|
|
||
|
procedure TLogLinScreenFrm.OutBtnClick(Sender: TObject);
|
||
|
VAR index : integer;
|
||
|
begin
|
||
|
index := SelectList.ItemIndex;
|
||
|
if index < 0 then exit;
|
||
|
VarList.Items.Add(SelectList.Items.Strings[index]);
|
||
|
SelectList.Items.Delete(index);
|
||
|
index := SelectList.Items.Count;
|
||
|
if index <= 0 then OutBtn.Enabled := false;
|
||
|
InBtn.Enabled := true;
|
||
|
NoDims := NoDims - 1;
|
||
|
if NoDims > 0 then ScrollBar1.Max := NoDims else ScrollBar1.Max := 1;
|
||
|
end;
|
||
|
|
||
|
procedure TLogLinScreenFrm.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;
|
||
|
VAR ISZ, MAX, LIM, I, J, NV1, M, M1, ITP, NP, NP1, L3, DF : integer;
|
||
|
ZERO, G21, G22, G23, AVG : double;
|
||
|
|
||
|
begin
|
||
|
// 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/
|
||
|
//
|
||
|
// Check for input errors
|
||
|
//
|
||
|
ZERO := 0.0;
|
||
|
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 TLogLinScreenFrm.CONF(var N: integer; var M: integer;
|
||
|
var MP: integer; var MM: integer; var ISET: IntDyneVec; var JSET: IntDyneVec;
|
||
|
var IP: IntDyneMat; var IM: IntDyneMat; var NP: integer);
|
||
|
Label 100, 120;
|
||
|
VAR
|
||
|
ILAST, JLAST : boolean;
|
||
|
I, L, NM, JS : integer;
|
||
|
// SUBROUTINE CONF(N, M, MP, MM, ISET, JSET, IP, IM, NP)
|
||
|
//C
|
||
|
//C ALGORITHM AS 160.1 APPL. STATIST. (1981) VOL.30, NO.1
|
||
|
//C
|
||
|
//C Set up the arrays IP and IM for a given N and M. Essentially
|
||
|
//C IP contains all possible combinations of (N choose M). For each
|
||
|
//C combination found IM contains all combinations of degree M-1.
|
||
|
//C
|
||
|
// INTEGER ISET(N), JSET(N), IP(N,MP), IM(N,MM)
|
||
|
// LOGICAL ILAST, JLAST
|
||
|
//C
|
||
|
|
||
|
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;
|
||
|
|
||
|
procedure TLogLinScreenFrm.COMBO(var ISET: IntDyneVec; N, M: Integer;
|
||
|
var LAST: boolean);
|
||
|
label 100, 110, 130, 150;
|
||
|
VAR
|
||
|
I, K, L : integer;
|
||
|
|
||
|
// SUBROUTINE COMBO(ISET, N, M, LAST)
|
||
|
//
|
||
|
// 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)
|
||
|
//
|
||
|
|
||
|
begin
|
||
|
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
|
||
|
end;
|
||
|
|
||
|
procedure TLogLinScreenFrm.EVAL(var IAR: IntDyneMat; NC, NV, IBEG, NVAR,
|
||
|
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;
|
||
|
|
||
|
procedure TLogLinScreenFrm.RESET(var FIT: DblDyneVec; NTAB: Integer; AVG: Double
|
||
|
);
|
||
|
VAR I : integer;
|
||
|
|
||
|
begin
|
||
|
//
|
||
|
// SUBROUTINE RESET(FIT, NTAB, AVG)
|
||
|
//
|
||
|
// ALGORITHM AS 160.4 APPL. STATIST. (1981) VOL.30, NO.1
|
||
|
//
|
||
|
// Initialize the fitted values to the average entry
|
||
|
//
|
||
|
// REAL FIT(NTAB)
|
||
|
//
|
||
|
for I := 1 to NTAB do //DO 100 I = 1, NTAB
|
||
|
begin
|
||
|
FIT[I] := AVG;
|
||
|
end; // 100 CONTINUE
|
||
|
end;
|
||
|
|
||
|
procedure TLogLinScreenFrm.LIKE(var GSQ: Double; var FIT: DblDyneVec;
|
||
|
var TABLE: DblDyneVec; NTAB: integer);
|
||
|
VAR I : integer;
|
||
|
ZERO, TWO : Double;
|
||
|
|
||
|
begin
|
||
|
ZERO := 0.0;
|
||
|
TWO := 2.0;
|
||
|
// SUBROUTINE LIKE(GSQ, FIT, TABLE, NTAB)
|
||
|
//
|
||
|
// ALGORITHM AS 160.5 APPL. STATIST. (1981) VOL.30, NO.1
|
||
|
//
|
||
|
// Compute the likelihood-ration chi-square
|
||
|
//
|
||
|
// REAL FIT(NTAB), TABLE(NTAB), ZERO, TWO
|
||
|
// DATA ZERO /0.0/, TWO /2.0/
|
||
|
//
|
||
|
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;
|
||
|
end;
|
||
|
|
||
|
procedure TLogLinScreenFrm.LOGFIT(NVAR, NTAB, NCON: integer;
|
||
|
var DIM: IntDyneVec; var CONFIG: IntDyneMat; var TABLE: DblDyneVec;
|
||
|
var FIT: DblDyneVec; var SIZE: IntDyneVec; var COORD: IntDyneVec;
|
||
|
var X: DblDyneVec; var Y: DblDyneVec);
|
||
|
LABEL 110, 130, 150, 170, 180, 200;
|
||
|
VAR
|
||
|
II, K, KK, L, N, J, I : integer;
|
||
|
OPTION : boolean;
|
||
|
MAXDEV, ZERO, XMAX, E : double;
|
||
|
MAXIT, NV1, ISZ : integer;
|
||
|
|
||
|
begin
|
||
|
// 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/
|
||
|
|
||
|
MAXDEV := 0.25;
|
||
|
ZERO := 0.0;
|
||
|
MAXIT := 25;
|
||
|
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;
|
||
|
|
||
|
procedure TLogLinScreenFrm.MaxCombos(NoDims: integer; var MM: integer;
|
||
|
var MP: integer);
|
||
|
var
|
||
|
combos : integer;
|
||
|
i,j : integer;
|
||
|
|
||
|
begin
|
||
|
MM := 0;
|
||
|
MP := 0;
|
||
|
for i := 1 to NoDims do
|
||
|
begin
|
||
|
combos := 1;
|
||
|
// get numerator factorial products down to i
|
||
|
for j := NoDims downto i + 1 do
|
||
|
combos := combos * j;
|
||
|
// divide by factorial of NoDims - i;
|
||
|
for j := (NoDims - i) downto 2 do
|
||
|
combos := combos div j;
|
||
|
if combos > MP then MP := combos;
|
||
|
if i * combos > MM then MM := i * combos;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
function TLogLinScreenFrm.ArrayPosition(Sender: TObject; NoDims : integer;
|
||
|
VAR Data : DblDyneVec;
|
||
|
VAR Subscripts : IntDyneVec;
|
||
|
VAR DimSize : IntDyneVec) : integer;
|
||
|
|
||
|
var
|
||
|
Pos : integer;
|
||
|
i, j : integer;
|
||
|
PriorSizes : IntDyneVec;
|
||
|
|
||
|
begin
|
||
|
// allocate space for PriorSizes
|
||
|
SetLength(PriorSizes,NoDims);
|
||
|
// calculate PriorSizes values
|
||
|
for i := 0 to NoDims - 2 do PriorSizes[i] := 1; // initialize
|
||
|
for i := NoDims - 2 downto 0 do
|
||
|
for j := 0 to i do PriorSizes[i] := PriorSizes[i] * DimSize[j];
|
||
|
Pos := Subscripts[0] - 1;
|
||
|
for i := 0 to NoDims - 2 do
|
||
|
Pos := Pos + (PriorSizes[i] * (Subscripts[i+1]-1));
|
||
|
Result := Pos;
|
||
|
PriorSizes := nil;
|
||
|
end;
|
||
|
|
||
|
procedure TLogLinScreenFrm.Marginals(Sender: TObject; NoDims: integer;
|
||
|
ArraySize: integer; var Indexes: IntDyneMat; var Data: DblDyneVec;
|
||
|
var Margins: IntDyneMat);
|
||
|
var i, j, category : integer;
|
||
|
|
||
|
begin
|
||
|
for i := 1 to ArraySize do
|
||
|
begin
|
||
|
for j := 1 to NoDims 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;
|
||
|
|
||
|
initialization
|
||
|
{$I loglinscreenunit.lrs}
|
||
|
|
||
|
end.
|
||
|
|