Skip to content

Commit 7c07cd5

Browse files
Merge pull request #284 from PolyMathOrg/fix-mp-inverse
Break Up Moore Penrose Test Into Smaller Tests For Clarity and Ease of Debugging
2 parents bb32795 + 8cdda2d commit 7c07cd5

File tree

1 file changed

+59
-24
lines changed

1 file changed

+59
-24
lines changed

src/Math-Tests-Matrix/PMQRTest.class.st

Lines changed: 59 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)