@@ -5,37 +5,72 @@ Class {
55}
66
77{ #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.
1828]
1929
2030{ #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+ ]
2242
23- | a |
43+ { #category : #tests }
44+ PMQRTest >> testMoorePenroseInverseOfNonRandomMatrix [
45+ | a inverse |
2446 a := PMMatrix new initializeRows:
2547 #( #( 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 |
2955 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)
3974]
4075
4176{ #category : #tests }
0 commit comments