@@ -5,37 +5,72 @@ Class {
5
5
}
6
6
7
7
{ #category : #running }
8
- PMQRTest >> mpTestFunction: aMatrix [
9
-
10
- | inv mult |
11
- inv := aMatrix mpInverse.
12
- mult := inv * aMatrix.
13
- self assert: (aMatrix * mult closeTo: aMatrix).
14
- self assert: mult * inv closeTo: inv.
15
- self assert: mult transpose closeTo: mult.
16
- mult := aMatrix * inv.
17
- self assert: mult transpose closeTo: mult
8
+ PMQRTest >> assert: inverse isMoorePenroseInverseOf: aMatrix [
9
+
10
+ " https://en.wikipedia.org/wiki/Moore–Penrose_inverse#Definition"
11
+
12
+ | identityMatrix |
13
+ " These two assertions are what define a pseudoinverse. They are known as
14
+ the Moore–Penrose conditions of which there are four, but here we have two. The other two
15
+ are that (A * A+) and A+ * A are Hermitian.
16
+ "
17
+ self assert: aMatrix * inverse * aMatrix closeTo: aMatrix.
18
+ self assert: inverse * aMatrix * inverse closeTo: inverse.
19
+
20
+ identityMatrix := aMatrix * inverse.
21
+ self assert: identityMatrix transpose closeTo: identityMatrix.
22
+ self assert: identityMatrix * aMatrix closeTo: aMatrix.
23
+
24
+ " Pseudoinversion commutes with transposition, complex conjugation, and taking the conjugate transpose"
25
+ self
26
+ assert: aMatrix transpose mpInverse
27
+ closeTo: aMatrix mpInverse transpose.
18
28
]
19
29
20
30
{ #category : #tests }
21
- PMQRTest >> testMPInverse [
31
+ PMQRTest >> testMoorePenroseInverseOfLargeNonRandomMatrixAndItsTranspose [
32
+ | a inverse transposeOfA |
33
+ a := PMMatrix new initializeRows:
34
+ #( #( 5 40 1 2.5 ) #( 0 0 1 2.5 ) #( 0 0 1 2.5 ) ).
35
+ inverse := a mpInverse .
36
+ self assert: inverse isMoorePenroseInverseOf: a.
37
+
38
+ transposeOfA := a transpose.
39
+ inverse := transposeOfA mpInverse .
40
+ self assert: inverse isMoorePenroseInverseOf: transposeOfA.
41
+ ]
22
42
23
- | a |
43
+ { #category : #tests }
44
+ PMQRTest >> testMoorePenroseInverseOfNonRandomMatrix [
45
+ | a inverse |
24
46
a := PMMatrix new initializeRows:
25
47
#( #( 5 40 1 ) #( 0 0 1 ) #( 0 0 1 ) ).
26
- self mpTestFunction: a.
27
- a := a * (PMMatrix rows: 3 columns: 3 random: 5.0 ).
28
- self mpTestFunction: a.
48
+ inverse := a mpInverse .
49
+ self assert: inverse isMoorePenroseInverseOf: a.
50
+ ]
51
+
52
+ { #category : #tests }
53
+ PMQRTest >> testMoorePenroseInverseOfProductOfMatrices [
54
+ | a inverse |
29
55
a := PMMatrix new initializeRows:
30
- #( #( 5 40 1 2.5 ) #( 0 0 1 2.5 ) #( 0 0 1 2.5 ) ).
31
- self mpTestFunction: a.
32
- a := a transpose.
33
- self mpTestFunction: a.
34
- 3 timesRepeat: [
35
- a := PMMatrix rows: 3 columns: 3 random: 1.0 .
36
- self assert: (a mpInverse closeTo: a inverse).
37
- a := PMSymmetricMatrix new : 4 random: 1.0 .
38
- self assert: (a mpInverse closeTo: a inverse) ]
56
+ #( #( 5 40 1 ) #( 0 0 1 ) #( 0 0 1 ) ).
57
+
58
+ a := a * (PMMatrix rows: 3 columns: 3 random: 5.0 ).
59
+ inverse := a mpInverse .
60
+ self assert: inverse isMoorePenroseInverseOf: a.
61
+ ]
62
+
63
+ { #category : #tests }
64
+ PMQRTest >> testMoorePenroseInverseOfRandomMatrixIsAnInverse [
65
+ "
66
+ Proofs for the properties below can be found in literature:
67
+ If A has real entries, then so does A+
68
+ If A is invertible, its pseudoinverse is its inverse. That is, A+ = A**−1
69
+ "
70
+
71
+ | a |
72
+ a := PMSymmetricMatrix new : 4 random: 1.0 .
73
+ self assert: (a mpInverse closeTo: a inverse)
39
74
]
40
75
41
76
{ #category : #tests }
0 commit comments