Skip to content

Commit 5b76a1a

Browse files
Merge pull request #289 from PolyMathOrg/refactor-qr-decomposition
Refactor QR Decomposition
2 parents 228fe62 + 04cc08a commit 5b76a1a

File tree

1 file changed

+63
-38
lines changed

1 file changed

+63
-38
lines changed

src/Math-Matrix/PMQRDecomposition.class.st

+63-38
Original file line numberDiff line numberDiff line change
@@ -29,64 +29,67 @@ that describes the mechanics:
2929
https://en.wikipedia.org/wiki/QR_decomposition#Using_Householder_reflections
3030
"
3131

32-
| identityMatrix householderVector i matrixOfMinor |
33-
identityMatrix := PMSymmetricMatrix identity: colSize.
32+
| i matrixOfMinor |
3433
1 to: self numberOfColumns do: [ :col |
35-
| columnVectorFromRMatrix householderMatrix v |
34+
| householderReflection householderMatrix householderVector columnVectorFromRMatrix |
3635
columnVectorFromRMatrix := r columnVectorAt: col size: colSize.
37-
householderVector := columnVectorFromRMatrix householder.
38-
v := (PMVector zeros: col - 1) , (householderVector at: 2).
39-
householderMatrix := identityMatrix
40-
-
41-
((householderVector at: 1) * v tensorProduct: v).
36+
householderReflection := self
37+
householderReflectionOf:
38+
columnVectorFromRMatrix
39+
atColumnNumber: col.
40+
householderVector := householderReflection at: 1.
41+
householderMatrix := householderReflection at: 2.
4242
q := q * householderMatrix.
4343
matrixOfMinor := r minor: col - 1 and: col - 1.
4444
matrixOfMinor := matrixOfMinor
4545
- ((householderVector at: 2) tensorProduct:
4646
(householderVector at: 1)
4747
* (householderVector at: 2) * matrixOfMinor).
4848
matrixOfMinor rowsWithIndexDo: [ :aRow :index |
49-
aRow withIndexDo: [ :n :c |
49+
aRow withIndexDo: [ :element :column |
50+
| rowNumber columnNumber |
51+
rowNumber := col + index - 1.
52+
columnNumber := col + column - 1.
5053
r
51-
rowAt: col + index - 1
52-
columnAt: col + c - 1
53-
put: ((n closeTo: 0)
54+
rowAt: rowNumber
55+
columnAt: columnNumber
56+
put: ((element closeTo: 0)
5457
ifTrue: [ 0 ]
55-
ifFalse: [ n ]) ] ] ].
58+
ifFalse: [ element ]) ] ] ].
5659
i := 0.
5760
[ (r rowAt: colSize) isZero ] whileTrue: [
5861
i := i + 1.
5962
colSize := colSize - 1 ].
6063
i > 0 ifTrue: [
61-
r := PMMatrix rows: (r rows copyFrom: 1 to: colSize).
64+
r := self upperTriangularPartOf: r With: colSize.
6265
i := q numberOfColumns - i.
6366
q := PMMatrix rows:
64-
(q rows collect: [ :row | row copyFrom: 1 to: i ]) ].
67+
(q rowsCollect: [ :row | row copyFrom: 1 to: i ]) ].
6568
^ Array with: q with: r
6669
]
6770

6871
{ #category : #arithmetic }
6972
PMQRDecomposition >> decomposeWithPivot [
7073

71-
| identityMatrix householderVector i v vectorOfNormSquareds rank mx pivot matrixOfMinor |
74+
| i vectorOfNormSquareds rank positionOfMaximum pivot matrixOfMinor |
7275
vectorOfNormSquareds := matrixToDecompose columnsCollect: [
7376
:columnVector | columnVector * columnVector ].
74-
mx := vectorOfNormSquareds indexOf: vectorOfNormSquareds max.
77+
positionOfMaximum := vectorOfNormSquareds indexOf: vectorOfNormSquareds max.
7578
pivot := Array new: vectorOfNormSquareds size.
7679
rank := 0.
77-
identityMatrix := PMSymmetricMatrix identity: colSize.
7880
[
79-
| householderMatrix |
81+
| householderReflection householderMatrix householderVector columnVectorFromRMatrix |
8082
rank := rank + 1.
81-
pivot at: rank put: mx.
82-
r swapColumn: rank withColumn: mx.
83-
vectorOfNormSquareds swap: rank with: mx.
84-
householderVector := (r columnVectorAt: rank size: colSize)
85-
householder.
86-
v := (PMVector zeros: rank - 1) , (householderVector at: 2).
87-
householderMatrix := identityMatrix
88-
-
89-
((householderVector at: 1) * v tensorProduct: v).
83+
pivot at: rank put: positionOfMaximum.
84+
r swapColumn: rank withColumn: positionOfMaximum.
85+
vectorOfNormSquareds swap: rank with: positionOfMaximum.
86+
columnVectorFromRMatrix := r columnVectorAt: rank size: colSize.
87+
householderReflection := self
88+
householderReflectionOf:
89+
columnVectorFromRMatrix
90+
atColumnNumber: rank.
91+
householderVector := householderReflection at: 1.
92+
householderMatrix := householderReflection at: 2.
9093
q := q * householderMatrix.
9194
matrixOfMinor := r minor: rank - 1 and: rank - 1.
9295
matrixOfMinor := matrixOfMinor
@@ -95,9 +98,12 @@ PMQRDecomposition >> decomposeWithPivot [
9598
* (householderVector at: 2) * matrixOfMinor).
9699
matrixOfMinor rowsWithIndexDo: [ :aRow :index |
97100
aRow withIndexDo: [ :element :column |
101+
| rowNumber columnNumber |
102+
rowNumber := rank + index - 1.
103+
columnNumber := rank + column - 1.
98104
r
99-
rowAt: rank + index - 1
100-
columnAt: rank + column - 1
105+
rowAt: rowNumber
106+
columnAt: columnNumber
101107
put: ((element closeTo: 0)
102108
ifTrue: [ 0 ]
103109
ifFalse: [ element ]) ] ].
@@ -109,29 +115,42 @@ PMQRDecomposition >> decomposeWithPivot [
109115
- (r rowAt: rank columnAt: ind) squared ].
110116
rank < vectorOfNormSquareds size
111117
ifTrue: [
112-
mx := (vectorOfNormSquareds
118+
positionOfMaximum := (vectorOfNormSquareds
113119
copyFrom: rank + 1
114120
to: vectorOfNormSquareds size) max.
115-
(mx closeTo: 0) ifTrue: [ mx := 0 ].
116-
mx := mx > 0
121+
(positionOfMaximum closeTo: 0) ifTrue: [ positionOfMaximum := 0 ].
122+
positionOfMaximum := positionOfMaximum > 0
117123
ifTrue: [
118-
vectorOfNormSquareds indexOf: mx startingAt: rank + 1 ]
124+
vectorOfNormSquareds indexOf: positionOfMaximum startingAt: rank + 1 ]
119125
ifFalse: [ 0 ] ]
120-
ifFalse: [ mx := 0 ].
121-
mx > 0 ] whileTrue.
126+
ifFalse: [ positionOfMaximum := 0 ].
127+
positionOfMaximum > 0 ] whileTrue.
122128
i := 0.
123129
[ (r rowAt: colSize) isZero ] whileTrue: [
124130
i := i + 1.
125131
colSize := colSize - 1 ].
126132
i > 0 ifTrue: [
127-
r := PMMatrix rows: (r rows copyFrom: 1 to: colSize).
133+
r := self upperTriangularPartOf: r With: colSize.
128134
i := q numberOfColumns - i.
129135
pivot := pivot copyFrom: 1 to: i.
130136
q := PMMatrix rows:
131-
(q rows collect: [ :row | row copyFrom: 1 to: i ]) ].
137+
(q rowsCollect: [ :row | row copyFrom: 1 to: i ]) ].
132138
^ Array with: q with: r with: pivot
133139
]
134140

141+
{ #category : #private }
142+
PMQRDecomposition >> householderReflectionOf: columnVector atColumnNumber: columnNumber [
143+
144+
| householderVector v identityMatrix householderMatrix |
145+
householderVector := columnVector householder.
146+
v := (PMVector zeros: columnNumber - 1) , (householderVector at: 2).
147+
identityMatrix := PMSymmetricMatrix identity: colSize.
148+
householderMatrix := identityMatrix
149+
-
150+
((householderVector at: 1) * v tensorProduct: v).
151+
^ Array with: householderVector with: householderMatrix .
152+
]
153+
135154
{ #category : #private }
136155
PMQRDecomposition >> initialQMatrix [
137156

@@ -158,3 +177,9 @@ PMQRDecomposition >> of: matrix [
158177
r := self initialRMatrix.
159178
q := self initialQMatrix.
160179
]
180+
181+
{ #category : #private }
182+
PMQRDecomposition >> upperTriangularPartOf: matrix With: columnSize [
183+
184+
^ PMMatrix rows: (r rows copyFrom: 1 to: columnSize)
185+
]

0 commit comments

Comments
 (0)