How to mutate values of matrix which by mutating its sub-matrix?

In the below, I building matrix A which consists of for sub-matrices Y,A1,A2,A3.I want the mutation on A3 be applied automatically on A as well. How can I do that please?


using BenchmarkTools, StaticArrays, LinearAlgebra, SparseArrays, .Threads

Y  = [1 2;3 4];
A1 = [5 6;7 8];
A2 = [11 22;33 44];
A3 = [0 0;0 0];

A = [Y A1; A2 A3]

A3 .= [1 1; 1 1];  # I want the change also be applied on A

A

You either want a vector of matrices, i. e.:

julia> A3 = [0 0;0 0];

julia> A = [Y,A1,A2,A3];

julia> A3 .= [1 1; 1 1];  # I want the change also be applied on A

julia> A
4-element Vector{Matrix{Int64}}:
 [1 2; 3 4]
 [5 6; 7 8]
 [11 22; 33 44]
 [1 1; 1 1]

Or you want to define the matrix and then its slices:

julia> A 
4×4 Matrix{Int64}:
  1   2  5  6
  3   4  7  8
 11  22  0  0
 33  44  0  0

julia> A3 = @view(A[3:4,3:4])
2×2 view(::Matrix{Int64}, 3:4, 3:4) with eltype Int64:
 0  0
 0  0

julia> A3 .= 1
2×2 view(::Matrix{Int64}, 3:4, 3:4) with eltype Int64:
 1  1
 1  1

julia> A
4×4 Matrix{Int64}:
  1   2  5  6
  3   4  7  8
 11  22  1  1
 33  44  1  1
3 Likes

Thank you very much!
If the first method is used, and I want to solve x=A\b I get the below error. Is there a way to solve it or just work with the second method you proposed?
where,

Y  = [1 2;3 4];
A1 = [5 6;7 8];
A2 = [11 22;33 44];
A3 = [5 5;5 5];
A = [Y,A1,A2,A3];
4-element Vector{Matrix{Int64}}:
 [1 2; 3 4]
 [5 6; 7 8]
 [11 22; 33 44]
 [5 5; 5 5]

julia> b=[1;1;1;1]
4-element Vector{Int64}:
 1
 1
 1
 1

julia> A\b
ERROR: MethodError: no method matching zero(::Type{Matrix{Int64}})

Oh, yes, in the first one A is not a regular matrix, it is a vector of matrices, so A\b won’t work. I think you need something in the lines of the second case.

1 Like

Edit- I see lmiq gave the view solution already, I missed the second half

I think what you want is a collection of views into A.

Once you combine Y, A1, A2, A3 into A, A is now an entirely new Matrix without the references to Y, A1, A2, A3.

_Y = [1 2; 3 4];
_A1 = [5 6; 7 8];
_A2 = [11 22; 33 44];
_A3 = [0 0; 0 0];

A = [_Y _A1; _A2 _A3]
# 4×4 Matrix{Int64}:
#  1   2  5  6
#  3   4  7  8
# 11  22  0  0
# 33  44  0  0

Y = view(A, 1:2, 1:2)
A1 = view(A, 1:2, 3:4)
A2 = view(A, 3:4, 1:2)
A3 = view(A, 3:4, 3:4)

A3 .= 1

A
# 4x4 Matrix{Int64}:
#  1   2  5  6
#  3   4  7  8
# 11  22  1  1
# 33  44  1  1
2 Likes

@lmiq @sbuercklin
Thank you very much!

I tried to implement your feedbacks on building a left-shifted matrix A_shiftl of A. So, when I mutate A, the A_shiftl will be mutated as well. However, I could not do that. Any help please here?
I have and I have which it elements

A = [1.0 5 0 0 0;0 1 0 0 0;0 0 1 0 0 ;0 0 0 1 0;0 0 0 0 1];
A_shiftl = [@view(A[:,2:end]) zeros(size(A,1))]
A[3,3] =5;
julia> A
5×5 Matrix{Float64}:
 1.0  5.0  0.0  0.0  0.0
 0.0  1.0  0.0  0.0  0.0
 0.0  0.0  5.0  0.0  0.0
 0.0  0.0  0.0  1.0  0.0
 0.0  0.0  0.0  0.0  1.0

julia> A_shiftl  # It did not follow the change in A
5×5 Matrix{Float64}:
 5.0  0.0  0.0  0.0  0.0
 1.0  0.0  0.0  0.0  0.0
 0.0  1.0  0.0  0.0  0.0
 0.0  0.0  1.0  0.0  0.0
 0.0  0.0  0.0  1.0  0.0

No, that won’t work like that in general. It is better of you write functions that operate on the matrices as you want, given ranges and values.

1 Like

@lmiq @sbuercklin
When I am using @view with sparsematrix, the resulting one is not sparse like Asp_r below. Any way to keep it sparse?

Asp = spzeros(5,6);
Asp[1,1] = 1.0;
Asp[1,2] = 5.0; 
Asp[2,2] = 1.0; 
Asp[3,3] = 1.0; 
Asp[4,4] = 1.0; 
Asp[5,5] = 1.0; 
julia> Asp_r =@view(Asp[:,1:end-1])
5×5 view(::SparseMatrixCSC{Float64, Int64}, :, 1:5) with eltype Float64:
 1.0  5.0  0.0  0.0  0.0
 0.0  1.0  0.0  0.0  0.0
 0.0  0.0  1.0  0.0  0.0
 0.0  0.0  0.0  1.0  0.0
 0.0  0.0  0.0  0.0  1.0

It looks sparse to me, it just prints a 0.0 instead of . for the empty entries because of how views print. You can check sparsity using issparse:

julia> issparse(Asp_r)
true

I recommend looking at the Views section of the Julia manual here

1 Like

Thanks for your feedback.