The following program performs a crude test of scale-invariance (Browne, 1982, page 75) by changing the scale of each observed variable, one variable at a time, and re-fitting the model after each change of scale. Changing the scale of a variable consists of pre- and post-multiplying the sample covariance matrix by a diagonal matrix. The model is reported to be "probably scale-invariant" if every change of scale has a small effect on the discrepancy function. If means/intercepts are explicit model parameters, an additional crude test of location-invariance is performed by changing the location of each observed variable (i.e., adding a constant to its sample mean) and re-fitting the model. The model is reported to be "probably location- invariant" if every change of location has a small effect on the discrepancy function.
A more thorough test of scale-invariance and location-invariance could be achieved by examining the implied moments after each change of scale and location.
Imports System
Imports System.Diagnostics
Imports AmosEngineLib
Imports AmosEngineLib.AmosEngine.TMatrixID
Imports Microsoft.VisualBasic
Module MainModule
Sub Main()
Dim Sem As New AmosEngine
Dim i As Integer, j As Integer
Sem.NeedEstimates(SampleCovariances)
Sem.NeedEstimates(SampleMeans)
SpecifyModel(Sem)
TestModelForInvariance(Sem)
Sem.Dispose()
End Sub
Sub TestModelForInvariance(ByVal Sem As AmosEngine)
'Discrepancy function values within Eps of each other are considered to be equal
Const Eps As Double = 0.0000000001
Const ScaleFactor As Double = 10
Const LocationShift As Double = 1
Dim BaselineF As Double
Dim Covariances(,) As Double, Means(,) As Double
Dim VariableNames() As String
Dim NVariables As Integer
Dim i As Integer, j As Integer
Dim IsScaleSensitive As Boolean, IsLocationSensitive As Boolean
If Sem.NumberOfGroups <> 1 Then
Throw(New exception("This routine works only for 1-group models."))
End If
BaselineF = MinimumDiscrepancy(Sem)
Sem.GetEstimates(SampleCovariances, Covariances)
Sem.RowNames(SampleCovariances, VariableNames)
NVariables = UBound(Covariances)
Dim VectorMeans() As Double
If Sem.IsModelingMeansAndIntercepts() Then
Sem.GetEstimates(SampleMeans, Means)
'Means() is now a 2-dimensional array with 1 row,
'but a 1-dimensional array of means is required.
ReDim VectorMeans(NVariables - 1)
For i = 0 To NVariables - 1
VectorMeans(i) = Means(0, i)
Next
End If
'Test for scale-invariance
For i = 0 To NVariables - 1
ScaleOneVariable(Covariances, i, ScaleFactor)
If Sem.IsModelingMeansAndIntercepts() Then
Sem.PutSampleMoments(Covariances, VectorMeans)
Else
Sem.PutSampleCovariances(Covariances)
End If
If Math.Abs(MinimumDiscrepancy(Sem) - BaselineF) > Eps Then
IsScaleSensitive = True
Debug.WriteLine( _
"The model is probably sensitive to the scale of " & VariableNames(i))
End If
ScaleOneVariable(Covariances, i, 1 / ScaleFactor)
Next
If Not IsScaleSensitive Then
Debug.WriteLine("The model is probably scale-invariant.")
End If
'Test for location-invariance
If Sem.IsModelingMeansAndIntercepts() Then
Dim DTemp As Double
For i = 0 To NVariables - 1
DTemp = VectorMeans(i)
VectorMeans(i) = VectorMeans(i) + LocationShift
Sem.PutSampleMoments(Covariances, VectorMeans)
If Math.Abs(MinimumDiscrepancy(Sem) - BaselineF) > Eps Then
IsLocationSensitive = True
Debug.WriteLine( _
"Model is probably sensitive to the location of " & VariableNames(i))
End If
VectorMeans(i) = DTemp
Next
If Not IsLocationSensitive Then
Debug.WriteLine("Model is probably location-invariant.")
End If
End If
End Sub
Sub ScaleOneVariable(ByVal ScaledCovariances(,) As Double, ByVal k As Integer, ByVal ScaleFactor As Double)
Dim i As Integer
Dim NVariables As Integer
NVariables = UBound(ScaledCovariances, 1) + 1
For i = 0 To NVariables - 1
ScaledCovariances(i, k) = ScaledCovariances(i, k) * ScaleFactor
ScaledCovariances(k, i) = ScaledCovariances(k, i) * ScaleFactor
Next
End Sub
Function MinimumDiscrepancy(ByVal Sem As AmosEngine) As Double
If Sem.FitModel() <> 0 Then
Throw(New exception("Could not fit model."))
End If
MinimumDiscrepancy = Sem.Cmin()
End Function
Sub SpecifyModel(ByVal Sem As AmosEngine)
'Example 8
Sem.BeginGroup(AmosEngine.AmosDir & "Examples\English\UserGuide.xls", "Grnt_fem")
Sem.AStructure("visperc = (1) spatial + (1) err_v")
Sem.AStructure("cubes = (a) spatial + (1) err_c")
Sem.AStructure("lozenges = (b) spatial + (1) err_l")
Sem.AStructure("paragraph = (1) verbal + (1) err_p")
Sem.AStructure("sentence = (c) verbal + (1) err_s")
Sem.AStructure("wordmean = (d) verbal + (1) err_w")
End Sub
End Module