Question

Suppose I have a 3x3 matrix

(def myMatrix (matrix (range 9) 3))
; A 3x3 matrix
; -------------
; 0.00e+00  1.00e+00  2.00e+00 
; 3.00e+00  4.00e+00  5.00e+00 
; 6.00e+00  7.00e+00  8.00e+00 

I can use $ to get an element, say 2nd row 1st column

($ 1 0 myMatrix) ; --> 3

Is there any API method to quickly update an element and then return a matrix? e.g.

(update-matrix-by-element 2 1 myMatrix 4)
; A 3x3 matrix
; -------------
; 0.00e+00  1.00e+00  2.00e+00 
; 4.00e+00  4.00e+00  5.00e+00 
; 6.00e+00  7.00e+00  8.00e+00 

The closest API methods I can find are bind-rows and bind-columns, and my current version of function using these two methods is

;note i j starts from 1 rather than 0 
(defn update-matrix-by-element [i j myMatrix value]  
    (if (or (> i  (count (trans myMatrix))) (> j  (count  myMatrix)) (< i 1) (< j 1)  (not (integer? i)) (not (integer? j)))
      myMatrix
      (let [n (count myMatrix)
        m (count (trans myMatrix))
        rangeFn #(if (== %1 %2)  %1 (range %1  %2 ))
        m1 (if (==    (dec i) 0) []
             ($ (rangeFn 0 (dec i)) :all myMatrix))
        m2   (if (==  i  m) []
               ($ (rangeFn  i m)  :all myMatrix))
        matrixFn  #(if (matrix? % ) % [ %])
        newRow  (if (==   (dec j) 0) 
                  (bind-columns    [value]    (matrixFn ($  (dec i) (rangeFn   j   n ) myMatrix)))
                  (if (== j n )
                    (bind-columns  (matrixFn ($  (dec i) (rangeFn 0  (dec j) ) myMatrix))  [value]   )
                    (bind-columns  (matrixFn ($  (dec i) (rangeFn 0  (dec j) ) myMatrix))  [value]    (matrixFn ($   (dec i) (rangeFn   j    n ) myMatrix))))
                  )
    ]  

   ;  (prn " m1 " m1 ) (prn  " m2 " m2 ) (prn " newrow " newRow)

    (bind-rows m1 newRow m2))))
Was it helpful?

Solution

If you mean "quickly" in the sense of performance, then you may probably to look at core.matrix which is designed to support fast mutable matrix operations.

Example using the vectorz-clj implementation for core.matrix:

(def M (matrix [[1 2] [3 4]]))
=> #<Matrix22 [[1.0,2.0][3.0,4.0]]>

(mset! M 0 0 10)
=> #<Matrix22 [[10.0,2.0][3.0,4.0]]>

(time (dotimes [i 1000000] (mset! M 0 0 i)))
"Elapsed time: 28.895842 msecs"   ;; i.e. < 30ns per mset! operation

This will be much faster than anything which requires construction of a new mutable matrix, especially as the matrices get bigger / have higher dimensionality.

I'm working on making core.matrix integrate neatly with Incanter, so you should be able to use core.matrix matrices transparently within Incanter before too long.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top