Question

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]].

Was it helpful?

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.

OTHER TIPS

The library Vectorz (which provides the underlying types for vectorz-clj) includes a BlockDiagonalMatrix class:

You'll have to use Java interop to instantiate it right now, but it offers a couple of advangtages:

  • Memory efficiency - only the block diagonal components are stored
  • Optimised operations - various vector operations exploit the fact that large areas of the matrix are guaranteed to be zero in order to perform faster computations

Longer term, it probably makes sense to add a block-diagonal-matrix function to core.matrix itself. In fact, I've just created an issue to do this:

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