Matrix inside Matrix in Julia

This is a matrix formula derived from algebra. My question is how to implement this in Julia?

For the first row : I is an identity matrix with a size 3x3 , 0 is a zero matrix with a size 3x6, AG is a 3x10 matrix, and IGR is a 3x1 matrix.
For the second row: I is an identity matrix with a size 6x6 , 0 is a zero matrix with a size 6x3, AD is a 6x10 matrix, and IDR is a 6x1 matrix.

and other rows are likewise.
Thanks

Some zero elements do not specify a dimension. Can you clarify whether those are scalars or zero matrices of size 6X3?

1 Like

If the matrix blocks are not too large, implementing this using Arrays / Matrix types of Julia would be easiest. A different representation would be to use BlockArrays:

using LinearAlgebra, FillArrays, BlockArrays

AG, AD = rand(6,10), rand(3,10)
TL = mortar((I(3), Fill(0.0,3,6), -AG),(Fill(0.0,6,3),-I(6),-AD))
M = mortar((TL,Fill(0.0,9,19)),(Fill(0.0,9,19),TL))

IGR, IDR, ILR, IG2, ID2, IL2 = 
  rand(3), rand(6), rand(10), rand(3), rand(6), rand(10)
V = mortar([mortar([IGR, IDR, ILR]), mortar([IG2, ID2, IL2])])

with these defined, the matrix product in the diagram can be calculated as:

julia> M*V
2-blocked 18-element BlockVector{Float64}:
 -2.7166482252406086
 -0.7411532464031856
 -1.4144505807049303
 -3.9973523077216147
 -4.2554463973398535
 -3.9794920828563947
 -3.6925883969453324
 -3.286901004924977 
 -1.6640267390765626
 ───────────────────
 -2.899615642942856 
 -1.873631050122329 
 -1.477001012721034 
 -3.3983276831541374
 -3.1006965784125096
 -4.0077663400711785
 -3.2353523978568464
 -3.3306260239290744
 -1.9377803558173756

It would be necessary to learn the other featuers of BlockedArrays (such as block indexing etc.) to really get the benefits.

3 Likes

all of them are matrices. do we need to specify their dimension one by one or Julia recognizes the size of zeros and identity matrices?

thanks.
IGR, IDR, ILR, IGI, IDI, ILI are variables.
Also, did you consider other zero matrices in M?

you could try the cat() function in its various forms

using LinearAlgebra

FI=I(3)*1
SI=I(6)*(-1)

FO=zeros(Int,3,6)
SO=zeros(Int,6,3)

AG=rand(0:9,3,10)
AD=rand(0:9,6,10)

FB=hcat(FI,FO,AG)
SB=hcat(SI,SO,AD)

M1=vcat(FB,SB)

cat(M1,M1,dims=(1,2))

If you only care about the result, you could rewrite the product like this (equivalent)

[M1*v1;M1*v2]
2 Likes

I’m fairly certain that you would have to specify the dimensions of your zero matrices. There might be a way to setup your solution so that zeros are used by default, and the indices of non-zero elements are specified manually.

One thing that might help is to compare the solutions offered by Dan and rocco_sprmnt21 with a simplified example. If you identify any limitations in the processes, we might be able to offer additional help.

1 Like

It’s even easier just to use the literal matrix constructor [ ... ], which implicitly calls hvcat:

using LinearAlgebra # for I
AG=rand(0:9,3,10)
AD=rand(0:9,6,10)

M = [        I  zeros(3,6)      -AG
     zeros(6,3)         -I      -AD]
A = [     M   zero(M)
     zero(M)       M]

Note that hvcat automatically figures out the sizes of square blocks involving I or multiples thereof, so I don’t even need to specify the size of the I terms (though I could use I(3) and I(6) to give these explicitly). And zero(M) is a matrix of zeros the same size as M (the additive identity for matrices of this size). (I initially used 0I here, but [M 0I; 0I M] makes square blocks of zeros, which is not what you seem to want.)

I would say that this is the most idiomatic way to build a matrix out of blocks in Julia (similar to Matlab, though Matlab doesn’t have our implicit I).

A similar construction also works with sparse arrays. It’s probably not worth it here for performance on such a small array with dense blocks, but it does give a nice visualization of the matrix:

julia> using SparseArrays

julia> sparse(A)
18×38 SparseMatrixCSC{Float64, Int64} with 180 stored entries:
⎡⠑⢄⠀⠀⢸⣿⣻⣿⣾⡃⠀⠀⠀⠀⠀⠀⠀⠀⠀⎤
⎢⠀⠀⠑⢄⢨⣟⣽⡿⣯⡇⠀⠀⠀⠀⠀⠀⠀⠀⠀⎥
⎢⠀⠀⠀⠀⠉⠉⠈⠉⠉⠑⢄⠀⠀⠀⣶⡶⣶⣦⡶⎥
⎢⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠑⢄⠀⣻⢟⣿⣿⣻⎥
⎣⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠑⠛⠋⠛⠚⠛⎦

If you are looking for the vectors v where Av = 0 as in your formula, you can use nullspace(A). Here, your A matrix is 18 \times 38 with rank 18, so it has a 20-dimensional nullspace — there are 20 independent possible vectors (and linear combinations thereof) that satisfy your equation, and the columns of nullspace(A) are an orthonormal basis for this space.

13 Likes

Thank guys, I tried both Dan and Steven code and worked. Since I’m new to this type of codes, could you also please help me with implementing the following as well?
Thanks.

These are two matrix formulas derived from algebra. My question is how to implement this in Julia?

  1. In the first matrix:
    tg(theta1) is tangent of theta1 and is a 6x1 matrix, tg(theta2) is tangent of theta2 and is a 6x1 matrix, I is an identity matrix ,
    IGR, IDR, ILR, IGI, IDI, ILI are variables. (IGR is a 3x1 matrix, IDR is a 6x1 matrix, ILR is a 10x1 matrix, IGI is a 3x1 matrix, IDI is a 6x1 matrix, ILI is a 10x1 matrix)
    uGR1, uGR2, uGI1,uGI2 are 3x1 matrices.
    other elements are zero matrices.

  2. In the second matrix:
    tg(theta1) is tangent of theta1 and is a 6x1 matrix, tg(theta2) is tangent of theta2 and is a 6x1 matrix, I is an identity matrix , m is a 6x1 matrix.
    VGR, VDR, VGI, VDI are variables. (VGR is a 3x1 matrix, VDR is a 6x1 matrix, VGI is a 3x1 matrix, VDI is a 6x1 matrix.
    other elements are zero matrices.

Thanks.

We already gave you sample code for your other example. This example looks very similar. You should try to understand how the provided sample code works, and then apply similar principles to your new problem.

If you have a specific confusion about the examples or explanations above, feel free to ask. But you should make an effort to learn Julia and write your own code, not simply ask people to write more code for you.

5 Likes