The sentence
rref =: ''rrefdef
uses explicit adverb rrefdef below to create tacit verb rref with 378 words as found by 5!:5
Linear Representation and ;: Words. rref is a verb to produce the reduced row echelon form of a
matrix. Although it doesn't test inputs to see that they are nonempty rank 2 numeric arrays
without infinities or _. , it does clean as it goes to avoid spurious pivots, and it correctly
handles "unexpected" matrices which might come to it from other programs rather than directly
from a user.
Why tacit, in fact tacit f. ? I was young, and tacit rref was a challenge. I
thought tacit f.
was more efficient than tacit with expensive name look-ups (a youthful opinion).
Why package the definition in an adverb? I think I was remembering the EXPLAIN verbs in APL
workspaces. No one could understand a 378 word one-liner, but one could type rrefdef to see a
commented definition in terms of understandable pieces. The explanation is likely to fit the
verb, because the explanation creates the verb.
A more common approach would define the pieces and the verb in a well-organized and commented
script that stores the pieces and verb in a special locale just for that verb. In contrast the
rrefdef pieces are just local definitions in the adverb.
rref a =: 1 2 3 4 , 5 6 7 8 ,: 9 10 11 12
1 0 _1 _2
0 1 2 3
0 0 0 0
rref 0 , 0 ,. a
0 1 0 _1 _2
0 0 1 2 3
0 0 0 0 0
0 0 0 0 0
rref ,. 2 1 3
1
0
0
rref ,: 0 2 1
0 1 0.5
rref ,. 5
1
rref ,. 0
0
rrefdef
1 : 0
NB. usage name =: ''rrefdef
NB. assigns to name a tacit verb that returns
NB. the reduced row echelon form of a matrix
NB.
NB. ARGUMENT TO RESULTING VERB MUST BE RANK 2 NUMERIC ARRAY
NB.
NB. Utilities
the =. [: NB. the f g is composition, "the f of g"
R0 =. (0 {:: ]) ::([: > ]) NB. return element 0 from right argument
R1 =. 1 {:: ]
R2 =. 2 {:: ]
L =. [: :[ NB. return left argument
R =. ]
NB.
NB. Verb clean below is adapted from 'load numeric' clean.
NB. Numbers near 0 are replaced by 0.
clean =. (] * (<: |@:]))`(j./"1@:([ (] * (<: |@:])) +.@:]))@.(3!:0@:] e. 16
16384"_)
shl =. 1 |."1 R NB. Shift matrix one column to left, wrapping right.
sul =. the shl 1 |. R NB. Shift matrix one row up then one column left,
wrapping.
NB.
NB. Now read the rest from bottom to top!
NB.
NB. Verb finish shifts matrix up and left to produce echelon (staircase) form.
finish =. R1 |."1 R0 |. R2
NB. Pivot was not found in the first column; shift left to search next column:
if0 =. R0 ; (the <: R1) ; the shl R2
NB. Verb pvt below subtracts multiples of the first row from other rows
NB. so as to produce 0's below the upper left corner 1.
NB. This idea belongs to Ken Iverson.
pvt =. (the {. R) (L , R - R0"1 */ L) the }. R
NB. Verb prp below divides the first row by its first element
NB. producing a 1 in the upper left corner.
prp =. (the }. R) ,~ the (% R0) the {. R
NB. Pivot was found in first column:
if1 =. (the <: R0) ; (the <: R1) ; 1r8589934592 clean the sul the pvt the prp R2
pivot =. if0`...@.(0 ~: (<0 0) { R2)
NB. Sort below arranges the first r rows in descending order of |(first
number).
sort =. (\: |)@{. , }.
repeat =. the pivot R0 ; R1 ; R0 sort R2
NB. The algorithm recurs verb "repeat" on a list r;c;matrix reducing r or c
NB. each time until r is 0 or c is 0. r,c is the shape of the upper left
NB. corner of the matrix where a (non-zero) pivot element may be found.
NB. Initially, r,c is the shape of the matrix. The matrix is cleaned each
NB. time to prevent spurious pivot elements, and shifted and sorted each time
NB. so that when a pivot element is found, it was found in the first column
NB. and is now in the upper left corner.
while =. (0 < R0) *. 0 < R1
start =. the (r...@$ ; r...@$ ; R) 1r8589934592 clean R
finish@(repeat^:while^:_)@start f. NB. the algorithm
)
Kip Murray
----------------------------------------------------------------------
For information about J forums see http://www.jsoftware.com/forums.htm