@@ -55,6 +55,72 @@ let leastSquaresCholeskyTests =
5555 )
5656 ]
5757open FSharp.Stats .Fitting .Spline
58+
59+ [<Tests>]
60+ let weightedSimpleLinearRegressionTests =
61+ // Known exact case: y = 2 + 3x, equal weights → coefficients must be exact
62+ let xData = vector [| 1. ; 2. ; 3. ; 4. ; 5. |]
63+ let yExact = vector [| 5. ; 8. ; 11. ; 14. ; 17. |] // 2 + 3x
64+
65+ testList " Weighted Simple Linear Regression" [
66+
67+ testCase " Equal unit weights reproduce unweighted fit" ( fun () ->
68+ let weights = vector [| 1. ; 1. ; 1. ; 1. ; 1. |]
69+ let wCoef = LinearRegression.OLS.Linear.Univariable.fitWithWeighting weights xData yExact
70+ let uCoef = LinearRegression.OLS.Linear.Univariable.fit xData yExact
71+ Expect.floatClose Accuracy.high wCoef.Constant uCoef.Constant " Intercept should match unweighted"
72+ Expect.floatClose Accuracy.high wCoef.Linear uCoef.Linear " Slope should match unweighted"
73+ )
74+
75+ testCase " Exact line – intercept 2, slope 3" ( fun () ->
76+ let weights = vector [| 1. ; 1. ; 1. ; 1. ; 1. |]
77+ let coef = LinearRegression.OLS.Linear.Univariable.fitWithWeighting weights xData yExact
78+ Expect.floatClose Accuracy.high coef.Constant 2. " Intercept should be 2"
79+ Expect.floatClose Accuracy.high coef.Linear 3. " Slope should be 3"
80+ )
81+
82+ testCase " Down-weighting an outlier pulls fit toward true line" ( fun () ->
83+ // y = 2 + 3x except the last point is a large outlier
84+ let yOutlier = vector [| 5. ; 8. ; 11. ; 14. ; 100. |]
85+ let weightsFlat = vector [| 1. ; 1. ; 1. ; 1. ; 1. |]
86+ let weightsDownLast = vector [| 1. ; 1. ; 1. ; 1. ; 0.001 |]
87+ let coefFlat = LinearRegression.OLS.Linear.Univariable.fitWithWeighting weightsFlat xData yOutlier
88+ let coefDown = LinearRegression.OLS.Linear.Univariable.fitWithWeighting weightsDownLast xData yOutlier
89+ // The down-weighted fit should be closer to slope=3, intercept=2
90+ let errorFlat = abs ( coefFlat.Linear - 3. ) + abs ( coefFlat.Constant - 2. )
91+ let errorDown = abs ( coefDown.Linear - 3. ) + abs ( coefDown.Constant - 2. )
92+ Expect.isTrue ( errorDown < errorFlat) " Down-weighting outlier should give fit closer to true line"
93+ )
94+
95+ testCase " Doubling all weights does not change coefficients" ( fun () ->
96+ let yData = vector [| 4. ; 7. ; 9. ; 10. ; 11. |]
97+ let w1 = vector [| 1. ; 1. ; 1. ; 1. ; 1. |]
98+ let w2 = vector [| 2. ; 2. ; 2. ; 2. ; 2. |]
99+ let coef1 = LinearRegression.OLS.Linear.Univariable.fitWithWeighting w1 xData yData
100+ let coef2 = LinearRegression.OLS.Linear.Univariable.fitWithWeighting w2 xData yData
101+ Expect.floatClose Accuracy.high coef1.Constant coef2.Constant " Intercept invariant to weight scaling"
102+ Expect.floatClose Accuracy.high coef1.Linear coef2.Linear " Slope invariant to weight scaling"
103+ )
104+
105+ testCase " Agrees with Polynomial.fitWithWeighting order 1" ( fun () ->
106+ let yData = vector [| 4. ; 7. ; 9. ; 10. ; 11. |]
107+ let weights = vector [| 2. ; 1. ; 0.5 ; 1. ; 1. |]
108+ let coefUni = LinearRegression.OLS.Linear.Univariable.fitWithWeighting weights xData yData
109+ let coefPoly = LinearRegression.OLS.Polynomial.fitWithWeighting 1 weights xData yData
110+ Expect.floatClose Accuracy.high coefUni.Constant coefPoly.Constant " Intercept agrees with poly order-1"
111+ Expect.floatClose Accuracy.high coefUni.Linear coefPoly.Linear " Slope agrees with poly order-1"
112+ )
113+
114+ testCase " LinearRegressor.fit dispatches to weighted path" ( fun () ->
115+ let yData = vector [| 4. ; 7. ; 9. ; 10. ; 11. |]
116+ let weights = vector [| 2. ; 1. ; 0.5 ; 1. ; 1. |]
117+ let coefDirect = LinearRegression.OLS.Linear.Univariable.fitWithWeighting weights xData yData
118+ let coefDispatch = LinearRegression.fit( xData, yData, FittingMethod = Method.SimpleLinear, Weighting = weights)
119+ Expect.floatClose Accuracy.high coefDirect.Constant coefDispatch.Constant " Intercept matches dispatch"
120+ Expect.floatClose Accuracy.high coefDirect.Linear coefDispatch.Linear " Slope matches dispatch"
121+ )
122+ ]
123+
58124[<Tests>]
59125let splineTests =
60126 testList " Fitting.Spline" [
0 commit comments