factor/basis/math/matrices/elimination/elimination.factor

114 lines
2.9 KiB
Factor
Raw Normal View History

2010-01-14 10:10:13 -05:00
! Copyright (C) 2006, 2010 Slava Pestov.
2007-09-20 18:09:08 -04:00
! See http://factorcode.org/license.txt for BSD license.
2009-11-05 15:05:06 -05:00
USING: kernel locals math math.vectors math.matrices
namespaces sequences fry sorting ;
2007-09-20 18:09:08 -04:00
IN: math.matrices.elimination
SYMBOL: matrix
: with-matrix ( matrix quot -- )
2012-07-19 16:55:34 -04:00
matrix swap [ matrix get ] compose with-variable ; inline
2007-09-20 18:09:08 -04:00
: nth-row ( row# -- seq ) matrix get nth ;
: change-row ( ..a row# quot: ( ..a seq -- ..b seq ) -- ..b )
2007-09-20 18:09:08 -04:00
matrix get swap change-nth ; inline
: exchange-rows ( row# row# -- ) matrix get exchange ;
: rows ( -- n ) matrix get length ;
: cols ( -- n ) 0 nth-row length ;
2008-02-06 20:23:39 -05:00
: skip ( i seq quot -- n )
2008-11-07 01:24:32 -05:00
over [ find-from drop ] dip length or ; inline
2008-02-06 20:23:39 -05:00
2007-09-20 18:09:08 -04:00
: first-col ( row# -- n )
#! First non-zero column
0 swap nth-row [ zero? not ] skip ;
: clear-scale ( col# pivot-row i-row -- n )
2008-11-07 01:24:32 -05:00
[ over ] dip nth dup zero? [
2007-09-20 18:09:08 -04:00
3drop 0
] [
2008-11-07 01:24:32 -05:00
[ nth dup zero? ] dip swap [
2008-08-28 23:28:01 -04:00
2drop 0
2007-09-20 18:09:08 -04:00
] [
2008-08-28 23:28:01 -04:00
swap / neg
2007-09-20 18:09:08 -04:00
] if
] if ;
: (clear-col) ( col# pivot-row i -- )
2008-11-07 01:24:32 -05:00
[ [ clear-scale ] 2keep [ n*v ] dip v+ ] change-row ;
2007-09-20 18:09:08 -04:00
: rows-from ( row# -- slice )
2010-01-14 10:10:13 -05:00
rows dup iota <slice> ;
2007-09-20 18:09:08 -04:00
: clear-col ( col# row# rows -- )
2008-11-07 01:24:32 -05:00
[ nth-row ] dip [ [ 2dup ] dip (clear-col) ] each 2drop ;
2007-09-20 18:09:08 -04:00
: do-row ( exchange-with row# -- )
[ exchange-rows ] keep
[ first-col ] keep
dup 1 + rows-from clear-col ;
2007-09-20 18:09:08 -04:00
: find-row ( row# quot -- i elt )
[ rows-from ] dip find ; inline
2007-09-20 18:09:08 -04:00
: pivot-row ( col# row# -- n )
[ dupd nth-row nth zero? not ] find-row 2nip ;
2007-09-20 18:09:08 -04:00
: (echelon) ( col# row# -- )
over cols < over rows < and [
2dup pivot-row [ over do-row 1 + ] when*
[ 1 + ] dip (echelon)
2007-09-20 18:09:08 -04:00
] [
2drop
] if ;
: echelon ( matrix -- matrix' )
[ 0 0 (echelon) ] with-matrix ;
: nonzero-rows ( matrix -- matrix' )
[ [ zero? ] all? not ] filter ;
2007-09-20 18:09:08 -04:00
: null/rank ( matrix -- null rank )
echelon dup length swap nonzero-rows length [ - ] keep ;
: leading ( seq -- n elt ) [ zero? not ] find ;
: reduced ( matrix' -- matrix'' )
[
2010-01-14 10:10:13 -05:00
rows iota <reversed> [
2007-09-20 18:09:08 -04:00
dup nth-row leading drop
2010-01-14 10:10:13 -05:00
dup [ swap dup iota clear-col ] [ 2drop ] if
2007-09-20 18:09:08 -04:00
] each
] with-matrix ;
2009-11-05 15:05:06 -05:00
:: basis-vector ( row col# -- )
row clone :> row'
col# row' nth neg recip :> a
0 col# row' set-nth
a row n*v col# matrix get set-nth ;
2007-09-20 18:09:08 -04:00
: nullspace ( matrix -- seq )
echelon reduced dup empty? [
dup first length identity-matrix [
[
dup leading drop
dup [ basis-vector ] [ 2drop ] if
] each
] with-matrix flip nonzero-rows
] unless ;
: 1-pivots ( matrix -- matrix )
[ dup leading nip [ recip v*n ] when* ] map ;
: solution ( matrix -- matrix )
echelon nonzero-rows reduced 1-pivots ;
: inverse ( matrix -- matrix ) ! Assumes an invertible matrix
dup length
[ identity-matrix [ append ] 2map solution ] keep
[ tail ] curry map ;