F# Creating a square sub-matrix from a square matrix

Viewed 85

I have a function in F# that i would like for it to create a square sub-matrix from just a square matrix. What i need to be able to do is remove a row and column from the original matrix and transform it into a sub matrix. This is what i tried so far:

/// <param name="A">An N-by-N matrix.</param>
/// <param name="i">The index of the row to remove.</param>
/// <param name="j">The index of the column to remove.</param>
/// <returns>The resulting (N - 1)-by-(N - 1) submatrix.</returns>
static member SquareSubMatrix (A : Matrix) (i : int) (j : int) : Matrix =
    let m_rows = A.M_Rows
    let n_cols = A.N_Cols


    let toarr = A.ToArray()
    let retval = toarr.[0..m_rows-1,0..n_cols-1]



    Matrix retval

The M_Rows and N_Cols is just custom function to get the number of rows and columns a matrix has, and the ToArray function is just as the name says.

So i've tried converting the matrix into an array so i can slice it, and then convert it back but im not sure how i can slice out a specific row/column from the array. The code above just returns the input matrix because it doesnt slice anything cause im not sure how to do it.

1 Answers

I guess A.ToArray() returns you a multi-dimensional array - the way you did slice it enumerates all columns and all rows again.

AFAIK you cannot use the slice notation to take out a single row - you can only take ranges. So a functional approach could be to slice up the upper/lower half, then slice those halves into left/right each and have functions to concatinate columns/rows. I think the last function are not part of the base-libraries so you'd have to write those yourself.

Anyway F# is a hybrid language and it's no real problem to mutate stuff locally in place so you can go with a more imperative solution: I'd suggest copying out the 4 parts (top-left, top-right, bottom-left, bottom-right) parts using Array2D.blit:

So this should work:


    let sourceArr = A.ToArray()
    let targetArr = Array2D.create (m_rows-1) (n_cols-1)
    // top-left
    Array2D.blit sourceArr 0 0 targetArr 0 0 i j
    // bottom-left
    Array2D.blit sourceArr (i+1) 0 targetArr i 0 (m_rows-i-1) j
    // top-right
    Array2D.blit sourceArr 0 (j+1) targetArr 0 j i (n_cols-j-1)
    // bottom-right
    Array2D.blit sourceArr (i+1) (j+1) targetArr i j (m_rows-i-1) (n_cols-j-1)

    // continue with targetArr

If I did not mess up the index-math (quite possible) this should work - I think you get the idea

Related