Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Haskell scripts to solve identity matrix

Tags:

haskell

how to solve identity for a matrix using Haskell scripts? For example, if with this given type

 type Matrice a = [[a]]
 identity :: Int -> Maybe (Matrice Int)

How can it return the identity matrice for the given size? I know that identity matrice is a square matrice which has zero for all values, except the values on the top-left to bottom-right diagonal which are all one. With the condition of, if the size is less than 1, then the identity matrice isn't defined and Nothing is returned.

So say for example,

Prelude > identity 5
          Just [[1,0,0,0,0],[0,1,0,0,0],[0,0,1,0,0],[0,0,0,1,0],[0,0,0,0,1]]
Prelude > identity 2
          Just [[1,0],[0,1]]

I've tried

identity1 :: Int -> Int -> [Int]
identity1 a b
    | a == 0 []
    | b == 0 (1:identity (a-1) (-1))
    | otherwise = (0:identity' (a-1) (b-1))

identity2 :: Int -> Int -> Matrice Int
identity2 a b
    | b == 0 []
    | otherwise = (0:identity1 (a-1) (b-1) : identity2 a (b-1) 
like image 732
Anna Avatar asked Aug 17 '26 11:08

Anna


1 Answers

One short approach is to define the "infinite" identity matrix as

ii = (1 : repeat 0) : fmap (0:) ii

The first row is 1 0 0 ...; each subsequent row is the row above it with a 0 prepended to it.

It should be obvious that the first n rows of the first n columns of the infinite identity matrix is In.

1 | 0 | 0 | 0 | 0 | 0 |
--+   |   |   |   |   |
0   1 | 0 | 0 | 0 | 0 |
------+   |   |   |   |
0   0   1 | 0 | 0 | 0 |
----------+   |   |   |  ...
0   0   0   1 | 0 | 0 |
--------------+   |   |
0   0   0   0   1 | 0 |
------------------+   |
0   0   0   0   0   1 |
----------------------+
           .            .
           .              .
           .                .

Given that, we just use take to obtain the appropriate-sized sub matrix. take n applied to each row will return the first n columns, and take n applied to the result takes just the first n rows.

type Matrix a = [[a]]

identity :: Int -> Maybe (Matrix Int)
identity n | n <= 0 = Nothing
           | otherwise = let ii = (1:repeat 0) : (fmap (0:) ii)
                         in Just $ take n (take n <$> ii)

If recursively defined infinite lists tie your brain in knots, you can also just define an enlarge function that generates In+1 from In. To do so, it is convenient to assume that I0 exists and is represented as an empty list.

enlarge :: Matrix Int -> Matrix Int
enlarge [] = [[1]]
enlarge i@(r:_) = (1:(0<$r)) : fmap (0:) i

Then you can define identity :: Int -> Matrix Int by indexing an infinite list of identity matrices

identity n | n <= 0 = Nothing
identity n = Just (identities !! n)

where identities :: [Matrix Int] is built with either iterate

identities = iterate enlarge []

or Data.List.unfoldr:

identities = unfoldr (\x -> Just (x, enlarge x)) []

It's also worth noting that the infinite identity matrix is the fixed point of enlarge:

import Data.Function
ii = fix enlarge
like image 138
chepner Avatar answered Aug 20 '26 07:08

chepner



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!