Search code examples
clojureclojure-contrib

Block Diagonal Matrix in Clojure


I looked through core.matrix searching for a block diagonal matrix function and searched Google, but have found no such function. Does such a function exist? If it does not could someone point me in the right direction to writing such a function.

Sample inputs would be nested vectors which would output along the diagonals of a larger nested vector.

Symbolic example: Let a,b,c,d be matrices (nested vectors). An example output would then look like

 [[a 0 0 0] [0 b 0 0] [0 0 c 0] [0 0 0 d]]

where d might be [[0 1] [1 0]].


Solution

  • First of all you need a function to generate vector of size n with element m injected into i th position.

    (defn vec-i [m i n]
      (-> (repeat n 0)
          (vec)
          (assoc-in [i] m)))
    
    (vec-i 'a 0 10) => [a 0 0 0 0 0 0 0 0 0]
    (vec-i 'b 2 7) => [0 0 b 0 0 0 0]
    

    Then just combine results for every i (assuming matrices are list of your diagonal elements)

    (defn block-diag [matrices]
      (let [n (count matrices)]
        (vec (map-indexed #(vec-i %2 %1 n) matrices))))
    
    (block-diag ['a 'b 'c 'd]) => [[a 0 0 0] [0 b 0 0] [0 0 c 0] [0 0 0 d]]
    

    Of course, symbols abcd can be replaced to matrix.