Search code examples
jtacit-programming

J: Gauss-Jordan elimination


Task to code Gauss-Jordan method of solving linear system of algebraic equations is an exercise that I've selected to advance in learning J. System is Ax=b, where A is n-by-n matrix, b and unknown x are n-vectors. Firstly, I've started with the simplest form with control structures:

   gj0 =: dyad :0 NB. usage is same to %.
    y=.y,.b 
    for_d.i.#y do. 
     for_r.i.#y do. 
      if.r=d do.continue.end. NB. do not eliminate d'th row
      t=.%/ (<"1(r,d),:(d,d)) { y
      for_c.d}.>:i.#y do.
       y=.(((<r,c){y)-(t*(<d,c){y)) (<r,c)} y
      end.
      y=.0 (<r,d)} y NB. ensure zero
     end. 
    end. NB. now A is diagonal but not identity matrix, so:
    x=.{:"1 y NB. x = b
    for_r.i.#y do.
     x=.((r{x)%(<r,r){y) r} x NB. divide by coefficients on diagonal
    end. 
   )
   Ab =: (".;._2) 0 :0
   0.25 _0.16 _0.38  0.17
   0.19 _0.22 _0.02  0.41
   0.13  0.08 _0.08 _0.13
   0.13 _0.1  _0.32  0.65
   )
   b =: 0.37 0.01 0.01 1.51
   (,.".&.>)('A';'b';'gj0 A,.b';'b %. A')
┌────────┬──────────────────────┐
│A       │0.25 _0.16 _0.38  0.17│
│        │0.19 _0.22 _0.02  0.41│
│        │0.13  0.08 _0.08 _0.13│
│        │0.13  _0.1 _0.32  0.65│
├────────┼──────────────────────┤
│b       │0.37 0.01 0.01 1.51   │
├────────┼──────────────────────┤
│b gj0 A │_1 3 _2 2             │
├────────┼──────────────────────┤
│b %. A  │_1 3 _2 2             │
└────────┴──────────────────────┘

Correct! Next I've decided to get rid of as many control structures as possible:

   gj1 =:dyad :0
    y=.y,.b 
    for_d.i.#y do.
     for_r.d ({.,]}.~[:>:[) i.#y do. NB. for indices without d
      t=.%/ (<"1(r,d),:(d,d)) { y
      y=.((r{y)-(t*d{y)) r}y NB. no need to iterate for each column
      y=.0 (<r,d)} y
     end. 
    end.
    ({:"1 y)%(+/}:"1 y) NB. b divide by sum of each item of A (drop zeroes)
   )
   b gj1 A
_1 3 _2 2

OK, Now I can try to translate for_r.-loop into tacit form... but it seems like it will look more cumbersome and I think that I'm at a wrong way -- but what's study without mistakes? I really want to code Gauss-Jordan method tacitly to:

  • exercise in J coding
  • see if it is better in performance
  • try to understand code a few weeks later :)

Help me please write it to the end or point out a better approach.


Solution

  • Thanks to Eelvex, who advised me to look in addons/math/misc/linear.ijs, I've concluded the task with this nice code:

       gj=: monad :0
       I=. i.#y
       for_i. I do. y=. y - (col - i=I) */ (i{y) % i{col=. i{"1 y end.
       )
       gj Ab
    1 0 0 0 _1
    0 1 0 0  3
    0 0 1 0 _2
    0 0 0 1  2
    

    It has taken some time to understand verb pivot in linear.ijs - but pencil-paper method helps.