Skip to content

[Repo Assist] feat: expose QR decomposition with GramSchmidt and Householder method choice#370

Draft
github-actions[bot] wants to merge 2 commits intodeveloperfrom
repo-assist/improve-qr-gramschmidt-20260406-6a12a295a9553be1
Draft

[Repo Assist] feat: expose QR decomposition with GramSchmidt and Householder method choice#370
github-actions[bot] wants to merge 2 commits intodeveloperfrom
repo-assist/improve-qr-gramschmidt-20260406-6a12a295a9553be1

Conversation

@github-actions
Copy link
Copy Markdown
Contributor

@github-actions github-actions bot commented Apr 6, 2026

🤖 This is an automated PR from Repo Assist.

Closes #317

Problem

FSharp.Stats had no user-facing API for choosing the QR decomposition method. Users who wanted the Gram-Schmidt variant had to reach down into FsMath.Algebra.LinearAlgebra.qrModifiedGramSchmidt directly, bypassing any FSharp.Stats documentation or discoverability.

Solution

New FSharp.Stats.LinearAlgebra module with:

Symbol Description
QRMethod.Householder Full QR via Householder reflections; Q is m×m, R is m×n
QRMethod.GramSchmidt Thin/economy QR via modified Gram-Schmidt; Q is m×n, R is n×n
QR.decompose method A Method-dispatching entry point
QR.householder A Named shorthand for Householder
QR.gramSchmidt A Named shorthand for Gram-Schmidt

Example

open FsMath
open FSharp.Stats.LinearAlgebra

let A = matrix [[12.;-51.;4.];[6.;167.;-68.];[-4.;24.;-41.]]

// Gram-Schmidt – thin Q (m×n)
let (qGS, rGS) = QR.decompose GramSchmidt A   // Q: 3×3, R: 3×3 (square input)

// For a 4×3 input the difference is visible:
let B = matrix [[1.;2.];[3.;4.];[5.;6.];[7.;8.]]
let (qThin, rThin) = QR.decompose GramSchmidt B   // Q: 4×2, R: 2×2
let (qFull, rFull) = QR.decompose Householder B   // Q: 4×4, R: 4×2
```

## Trade-offs

- No new algorithms introduced; both methods delegate to `FsMath.Algebra.LinearAlgebra` which is already a dependency.
- Gram-Schmidt (thin Q) uses less memory than Householder (full Q) for tall matrices, which is a common use case in regression.
- Both variants satisfy A = Q * R and Q^T Q = I; the only difference is the shape of Q and R.

## Test Status

10 new tests added:

- `A = Q * R` round-trips (both methods, square and rectangular matrix)
- `Q^T Q = I` orthonormality (both methods)
- R upper-triangular (both methods)
- Dimension checks: GramSchmidt gives thin Q (m×n), Householder gives full Q (m×m)
- `QR.decompose` dispatch test

```
Passed!  - Failed: 0, Passed: 1203, Skipped: 0, Total: 1203

Generated by 🌈 Repo Assist, see workflow run. Learn more.

To install this agentic workflow, run

gh aw add githubnext/agentics/workflows/repo-assist.md@7ee2b60744abf71b985bead4599640f165edcd93

closes #317)

Add FSharp.Stats.LinearAlgebra module with:
- QRMethod discriminated union (Householder | GramSchmidt)
- QR.decompose  – method-dispatching entry point
- QR.householder – Householder reflections (full QR, Q is m×m)
- QR.gramSchmidt – modified Gram-Schmidt (thin QR, Q is m×n)

The underlying algorithms come from FsMath.Algebra.LinearAlgebra
(qrDecompose and qrModifiedGramSchmidt). This PR simply exposes them
through a unified, discoverable FSharp.Stats API with clear doc-comments
explaining the output dimension difference between the two methods.

Added 10 tests:
- A = Q*R round-trips for both methods on a square and a rectangular matrix
- Q^T Q = I orthonormality checks
- R upper-triangular checks
- Dimension checks (thin Q for GramSchmidt, full Q for Householder)
- decompose dispatch test

1209/1209 tests pass.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature Request] QR Matrix Decomposition using Gram-Schmidt

0 participants