I’m just going to go through a few manipulations in script form first and perhaps this will give you some ideas. Let’s initialize a vector numbered 1 to 16 for clarity.
julia> xi = collect(1:16)
16-element Array{Int64,1}:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
I’m going to assume it is known apriori that there are two complex matrices and that they are square. Additionally the expanded matrix you need is one greater in each dimension.
In case those assumptions are incorrect, you can recode the following. Please do explain what your assumptions are when asking a question or that there are no assumptions.
julia>
n_matrices = 2
# divide by two below because we need two entries for complex numbers
n_rows = Int64(sqrt(length(xi)/n_matrices/2))
n_cols = n_rows
n_rows_expanded = n_rows+1
n_cols_expanded = n_cols+1
p = params = (nm=n_matrices,nr=n_rows,nc=n_cols,nre=n_rows_expanded,nce=n_cols_expanded)
(nm = 2, nr = 2, nc = 2, nre = 3, nce = 3)
Using the params above, we are now going to interpret xi
:
julia> xir = reshape(xi,(2,p.nr,p.nc,p.nm))
2×2×2×2 Array{Int64,4}:
[:, :, 1, 1] =
1 3
2 4
[:, :, 2, 1] =
5 7
6 8
[:, :, 1, 2] =
9 11
10 12
[:, :, 2, 2] =
13 15
14 16
julia> A = xir[1,:,:,1] + im*xir[2,:,:,1]
2×2 Array{Complex{Int64},2}:
1+2im 5+6im
3+4im 7+8im
julia> B = xir[1,:,:,2] + im*xir[2,:,:,2]
2×2 Array{Complex{Int64},2}:
9+10im 13+14im
11+12im 15+16im
Now let’s add zeros around the matrices. The term for this is called padding. There are several options for this such padarray
or PaddedView
. Let’s use the latter:
julia > using PaddedViews
julia> Ae = PaddedView(0,A,(p.nre,p.nce))
3×3 PaddedView(0 + 0im, ::Array{Complex{Int64},2}, (Base.OneTo(3), Base.OneTo(3))) with eltype Complex{Int64}:
1+2im 5+6im 0+0im
3+4im 7+8im 0+0im
0+0im 0+0im 0+0im
julia> Be = PaddedView(0,B,(p.nre,p.nce))
3×3 PaddedView(0 + 0im, ::Array{Complex{Int64},2}, (Base.OneTo(3), Base.OneTo(3))) with eltype Complex{Int64}:
9+10im 13+14im 0+0im
11+12im 15+16im 0+0im
0+0im 0+0im 0+0im
If we ever needed plain old complex arrays, we can use collect
.
julia> collect(Ae)
3×3 Array{Complex{Int64},2}:
1+2im 5+6im 0+0im
3+4im 7+8im 0+0im
0+0im 0+0im 0+0im
julia> collect(Be)
3×3 Array{Complex{Int64},2}:
9+10im 13+14im 0+0im
11+12im 15+16im 0+0im
0+0im 0+0im 0+0im
Now let’s go the other way and attempt to compact Ae
and Be
down back to a vector.
julia> X0 = cat(Ae,Be,dims=3)
3×3×2 Array{Complex{Int64},3}:
[:, :, 1] =
1+2im 5+6im 0+0im
3+4im 7+8im 0+0im
0+0im 0+0im 0+0im
[:, :, 2] =
9+10im 13+14im 0+0im
11+12im 15+16im 0+0im
0+0im 0+0im 0+0im
julia> X0 = cat(real.(X0),imag.(X0),dims=4)
3×3×2×2 Array{Int64,4}:
[:, :, 1, 1] =
1 5 0
3 7 0
0 0 0
[:, :, 2, 1] =
9 13 0
11 15 0
0 0 0
[:, :, 1, 2] =
2 6 0
4 8 0
0 0 0
[:, :, 2, 2] =
10 14 0
12 16 0
0 0 0
julia> X0 = permutedims(X0,(4,1,2,3))
2×2×3×3 Array{Int64,4}:
[:, :, 1, 1] =
1 2
9 10
[:, :, 2, 1] =
3 4
11 12
[:, :, 3, 1] =
0 0
0 0
[:, :, 1, 2] =
5 6
13 14
[:, :, 2, 2] =
7 8
15 16
[:, :, 3, 2] =
0 0
0 0
[:, :, 1, 3] =
0 0
0 0
[:, :, 2, 3] =
0 0
0 0
[:, :, 3, 3] =
0 0
0 0
julia> X0 = vec(X0)
36-element Array{Int64,1}:
1
2
3
4
0
0
5
6
7
8
⋮
16
0
0
0
0
0
0
0
0
Great now we compacted Ae
and Be
back into a vector. Now depending on how things are structured and how the optimization routines work, we may need to also encode the parameters in the vector:
julia> X0_with_params = [X0; collect(params)]
41-element Array{Int64,1}:
1
2
3
4
0
0
5
6
7
8
⋮
0
0
0
0
2
2
2
3
3
julia> param_keys = keys(p)
Recreating Ae and Be is just a matter of unpacking the parameters and repeating the earlier steps.
julia> p = (;zip(param_keys,X0_with_params[end-4:end])...)
(nm = 2, nr = 2, nc = 2, nre = 3, nce = 3)
julia> X0 = reshape(X0_with_params[1:end-5],(2,p.nre,p.nce,p.nm));
julia> Ae_recreated = X0[1,:,:,1] + im*X0[2,:,:,1]
3×3 Array{Complex{Int64},2}:
1+2im 5+6im 0+0im
3+4im 7+8im 0+0im
0+0im 0+0im 0+0im
julia> Be_recreated = X0[1,:,:,2] + im*X0[2,:,:,2]
3×3 Array{Complex{Int64},2}:
9+10im 13+14im 0+0im
11+12im 15+16im 0+0im
0+0im 0+0im 0+0im
julia> Ae == Ae_recreated
true
julia> Be == Be_recreated
true