```Object subclass: #Regression
instanceVariableNames: ''
classVariableNames: 'RSquared '
poolDictionaries: ''
category: 'Regression'!

"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!

Regression class
instanceVariableNames: ''!

!Regression class methodsFor: 'accessor' stamp: 'CMR 7/17/2000 17:03'!
RSquared
"return r-squared statistic"
^RSquared.! !

!Regression class methodsFor: 'accessor' stamp: 'CMR 7/17/2000 17:03'!
RSquared: aNumber
"Assign the r-squared statistic"
^RSquared := aNumber! !

!Regression class methodsFor: 'regression functions' stamp: 'CMR 7/17/2000 17:03'!
equationSolve: rawCollection equationFormat: eqForm
| n a b term ysquare xpower coef ss xaverage yaverage |

"initialize the variables"
n := (eqForm size).
a := Array new:n.
b := Array new:n.
term := Array new:n.
(1 to: n) do: [:i |
a at:i put:(Array new:n).
(1 to: n) do: [:j | (a at:i) at:j put:0].
b at:i put:0.
term at:i put:0.
].
ysquare := 0.

"step through each raw data entry"
(1 to: (rawCollection size)) do: [:i |

"sum the y values"
b at:1 put:((b at:1) + ((rawCollection at:i) at:1)).
ysquare := ysquare +
(((rawCollection at:i) at:1) * ((rawCollection at:i) at:1)).

"sum the x power values"
(1 to: n) do: [:j |
xpower := (eqForm at:j) value:(rawCollection at:i) value:j.
term at:j put:xpower.
(a at:1) at:j put:(((a at:1) at:j) + xpower).
].

" now set up the rest of the rows in the matrix"
(2 to: n) do: [:j |
b at:j put:((b at:j) + (((rawCollection at:i) at:1) * (term at:j))).
(1 to: n) do: [:k |
(a at:j) at:k put:(((a at:j) at:k) + ((term at:j) * (term at:k))).
].
].
].

"solve for the coefficients"
coef := Regression gaussAMatrix:a gaussBMatrix:b.

"calculate the r-squared statistic"
ss := 0.
yaverage := (b at:1) / (rawCollection size).
(1 to: n) do: [:i |
xaverage := ((a at:1) at:i) / (rawCollection size).
ss := ss + ((coef at:i) *
((b at:i) - ((rawCollection size) * xaverage * yaverage)))
].
Regression RSquared: ss /
(ysquare - ((rawCollection size) * yaverage * yaverage)).

^coef.! !

!Regression class methodsFor: 'regression functions' stamp: 'CMR 7/17/2000 17:03'!
equationSolve: rawCollection equationOrder: nOrder
| eqForm |
eqForm := Array new:(nOrder+1).
(1 to: (nOrder+1)) do: [:i |
eqForm at:i put:[:data :coefNum | (data at:2) raisedTo:(coefNum-1)].
].
^Regression
equationSolve: rawCollection
equationFormat: eqForm.! !

!Regression class methodsFor: 'regression functions' stamp: 'CMR 7/17/2000 17:03'!
gaussAMatrix: aMatrix gaussBMatrix: bMatrix
"matrix solution for |c| where |a| = |b| * |c|"
| a b pivot mult top n coef |

"initialize the local variables"
n := bMatrix size.
coef := Array new:n.
1 to: n do: [:i | coef at:i put:0].

"copy over the matrix values - inplace solution"
a := aMatrix deepCopy.
b := bMatrix deepCopy.

(1 to: (n-1)) do: [:j |
pivot := ((a at:j) at:j).
((j+1) to: n) do: [:i |
mult := ((a at:i) at:j) / pivot.
((j+1) to: n) do: [:k |
(a at:i) at:k put:(((a at:i) at:k) - (mult * ((a at:j) at:k))).
].
b at:i put:((b at:i) - (mult * (b at:j))).
].
].

coef at:n put:((b at:n) / ((a at:n) at:n)).
(1 to: (n-1)) reverseDo: [:i |
top := b at:i.
((i+1) to: n) do: [:k |
top := top - (((a at:i) at:k) * (coef at:k)).
].
coef at:i put:(top / ((a at:i) at:i)).
].
^coef! !

!Regression class methodsFor: 'printing' stamp: 'CMR 7/17/2000 17:03'!
printEquation: coef
(1 to: (coef size)) do: [:i |
Transcript
show:
((i = 1)
ifTrue:  ['Y = ']
ifFalse: [' + ']);
show: (coef at: i) printString;
show: '*X^';
show: (i-1) printString.
].
Transcript
show: '   [r^2 = ';
show: (Regression RSquared printString);
show: ']';
cr.! !

!Regression class methodsFor: 'testing' stamp: 'CMR 7/17/2000 17:03'!
test
"Test the regression routines:  Regression test."
| myCoefficients rawCollection temp eqForm |

"do a simple equation: Y = 1 + 2X"
myCoefficients := Regression equationSolve:#((1 0) (3 1) (5 2)) equationOrder:1.
Regression printEquation: myCoefficients.

rawCollection := Array new:100.
(1 to: (rawCollection size)) do: [:i | rawCollection at:i put:(Array new:2)].

"second order equation: Y = 1 + 2X + 3X^2"
(1 to: (rawCollection size)) do: [:i |
(rawCollection at:i) at:1 put:(1 + (2*i) + (3*i*i)).
(rawCollection at:i) at:2 put:i.
].
myCoefficients := Regression equationSolve:rawCollection equationOrder:2.
Regression printEquation: myCoefficients.

"third order equation: Y = 4 + 3X + 2X^2 + 1X^3"
(1 to: (rawCollection size)) do: [:i |
(rawCollection at:i) at:1 put:(4 + (3*i) + (2*i*i) + (1*i*i*i)).
(rawCollection at:i) at:2 put:i.
].
myCoefficients := Regression equationSolve:rawCollection equationOrder:3.
Regression printEquation: myCoefficients.

"do a multivariate regression: Y = 6 + 5X + 4X^2 + 3XZ + 2Z + 1Z^2"
(1 to: (rawCollection size)) do: [:i | rawCollection at:i put:(Array new:3)].
(1 to: (rawCollection size)) do: [:i |
temp := 100 atRandom.
(rawCollection at:i) at:1 put:(6 + (5*i) + (4*i*i) + (3*i*temp) +
(2*temp) + (1*temp*temp)).
(rawCollection at:i) at:2 put:i.
(rawCollection at:i) at:3 put:temp.
].
eqForm := Array new:6.
eqForm at:1 put:[:data :coefNum | 1].
eqForm at:2 put:[:data :coefNum | (data at:2)].
eqForm at:3 put:[:data :coefNum | (data at:2) raisedTo:2].
eqForm at:4 put:[:data :coefNum | (data at:2) * (data at:3)].
eqForm at:5 put:[:data :coefNum | (data at:3)].
eqForm at:6 put:[:data :coefNum | (data at:3) raisedTo:2].
myCoefficients := Regression equationSolve:rawCollection equationFormat:eqForm.
Transcript show: myCoefficients printString; cr.
Transcript show: 'r^2 = '.
Transcript show: (Regression RSquared) printString.! !
```