@@ -219,6 +219,111 @@ module LinearAlgebra =
219
219
// else LinearAlgebraManaged.QR a
220
220
LinearAlgebraManaged.QR a
221
221
222
+ /// <summary>
223
+ /// Performs QR decomposition using an alternative algorithm.
224
+ /// QR decomposition is a method to decompose a matrix A into two components:
225
+ /// Q (an orthogonal matrix) and R (an upper triangular matrix),
226
+ /// such that A = Q * R. It is commonly used in solving linear systems,
227
+ /// least squares fitting, and eigenvalue problems.
228
+ /// </summary>
229
+ /// <returns>
230
+ /// A tuple containing:
231
+ /// <list type="bullet">
232
+ /// <item><description>Q: The orthogonal matrix obtained from the decomposition.</description></item>
233
+ /// <item><description>R: The upper triangular matrix obtained from the decomposition.</description></item>
234
+ /// </list>
235
+ /// </returns>
236
+ let qrAlternative ( A : Matrix < float >) =
237
+ let m : int = A.NumRows
238
+ let n : int = A.NumCols
239
+
240
+ let q : Matrix < float > = Matrix.zero m n
241
+ let r : Matrix < float > = Matrix.zero n n
242
+ let qLengths : Vector < float > = Vector.zeroCreate n
243
+
244
+ let getVectorLength ( v : Vector < float >) = Vector.fold ( fun folder i -> folder+( i* i)) 0. v
245
+
246
+ let setqOfA ( n : int ) =
247
+ let aN : Vector < float > = Matrix.getCol A n
248
+ let qN =
249
+ if n = 0 then
250
+ aN
251
+ else
252
+ Array.init ( n) ( fun i ->
253
+ let denominator = qLengths[ i]
254
+ let forNominator : Vector < float > = Matrix.getCol q i
255
+ let nominator : float = Vector.dot aN forNominator
256
+ r.[ i, n] <- nominator
257
+ ( nominator/ denominator) * forNominator
258
+ )
259
+ |> Array.fold ( fun folder e -> folder- e ) aN
260
+ Matrix.setCol q n qN
261
+ qN
262
+
263
+ for i= 0 to n-1 do
264
+ let qN = setqOfA i
265
+ let qLength = getVectorLength qN
266
+ let rValue = sqrt( qLength)
267
+ r[ i, i] <- rValue
268
+ qLengths[ i] <- qLength
269
+
270
+ for i= 0 to n-1 do
271
+ let qN : Vector < float > = Matrix.getCol q i
272
+ let updateQ = ( 1. / sqrt( qLengths[ i] )) * qN
273
+ Matrix.setCol q i updateQ
274
+ for j= i+ 1 to n-1 do
275
+ let denominator = r[ i, i]
276
+ let nominator = r[ i, j]
277
+ r[ i, j] <- ( nominator/ denominator)
278
+
279
+ q, r
280
+
281
+ /// <summary>
282
+ /// Solves a linear system of equations using QR decomposition.
283
+ /// </summary>
284
+ /// <param name="A">The coefficient matrix of the linear system.</param>
285
+ /// <param name="t">The target vector of the linear system.</param>
286
+ /// <returns>
287
+ /// A tuple containing:
288
+ /// <list type="bullet">
289
+ /// <item><description>mX: The solution vector of the linear system.</description></item>
290
+ /// <item><description>r: The upper triangular matrix obtained from QR decomposition.</description></item>
291
+ /// </list>
292
+ /// </returns>
293
+ let solveLinearQR ( A : Matrix < float >) ( t : Vector < float >) =
294
+ let m = A.NumRows
295
+ let n = A.NumCols
296
+
297
+ System.Diagnostics.Debug.Assert( m >= n)
298
+
299
+ let q , r = qrAlternative A
300
+
301
+ let QT = q.Transpose
302
+
303
+ let mX = Vector.zeroCreate n
304
+
305
+ let c : Vector < float > = QT * t
306
+
307
+ let rec build_mX_inner cross_prod i j =
308
+ if j= n then
309
+ cross_ prod
310
+ else
311
+ let newCrossprod = cross_ prod + ( r[ i, j] * mX[ j])
312
+ build_ mX_ inner newCrossprod i ( j+ 1 )
313
+
314
+ let rec build_mX_outer i =
315
+ if i< 0 then
316
+ ()
317
+ else
318
+ let crossProd = build_ mX_ inner 0. i ( i+ 1 )
319
+ mX[ i] <- ( c[ i] - crossProd) / r[ i, i]
320
+ build_ mX_ outer ( i-1 )
321
+
322
+ build_ mX_ outer ( n-1 )
323
+
324
+ mX, r
325
+
326
+
222
327
///Returns the full Singular Value Decomposition of the input MxN matrix
223
328
///
224
329
///A : A = U * SIGMA * V**T in the tuple (S, U, V**T),
0 commit comments