Converting a complex vector to a sparse diagonal array in Julia - matlab

Trying to replicate a calculation from Matlab in Julia but am having trouble converting a single column complex array into a sparse diagonalized array for matrix multiplication.
Here is the Matlab code I am trying to replicate in Julia:
x*diag(sparse(y))
where x is of size 60,600000 and is of type: double, and y is size 600000,1 and is of type: complex double.

You can use Diagonal for that:
using LinearAlgebra
x=rand(6,60)
y=rand(Complex{Float64},60,1)
x*Diagonal(view(y,:))
I have used view(y,:) to convert y to a Vector - this is here a dimension drop operator you can also use shorter form vec(y) instead. Depending on what you want to do you might explicitly say that you want first column by view(y,:,1).
Note that Diagonal is just a sparse representation of a matrix.
julia> Diagonal(1:4)
4×4 Diagonal{Int64,UnitRange{Int64}}:
1 ⋅ ⋅ ⋅
⋅ 2 ⋅ ⋅
⋅ ⋅ 3 ⋅
⋅ ⋅ ⋅ 4
Another option that might cover more use case scenarios are BandedMatrices:
using BandedMatrices
x*BandedMatrix(0=>view(y,:))
Note that BandedMatrix uses set of pairs for bands, where band 0 is actually the diagonal.

I guess you don't mean it like this, but one can also interpret the question in the way that y is a sparse vector in the Julia sense, and you want to construct a sparse diagonal matrix out of it. In that case you can do the following:
julia> y = sprand(10, 0.2)
10-element SparseVector{Float64,Int64} with 2 stored entries:
[4 ] = 0.389682
[5 ] = 0.232429
julia> I, V = findnz(y)
([4, 5], [0.3896822408908356, 0.2324294021548845])
julia> sparse(I, I, V)
5×5 SparseMatrixCSC{Float64,Int64} with 2 stored entries:
[4, 4] = 0.389682
[5, 5] = 0.232429
Unfortunately, spdiagm does not preserve structural zeros for a sparse input:
julia> spdiagm(0 => y)
10×10 SparseMatrixCSC{Float64,Int64} with 10 stored entries:
[1 , 1] = 0.0
[2 , 2] = 0.0
[3 , 3] = 0.0
[4 , 4] = 0.389682
[5 , 5] = 0.232429
[6 , 6] = 0.0
[7 , 7] = 0.0
[8 , 8] = 0.0
[9 , 9] = 0.0
[10, 10] = 0.0
I don't know whether this is intentional, but I filed an issue about this behaviour.

Related

Vector to Scalar

I have a simple problem that I can't seem to figure out a simple solution for ...
I have a vector x
x = [1, 2, 3, 4]
I'd like to turn that vector into a scalar where the scalar is comprised of the values of x.
for example:
>> y = compressvec(x)
y =
1234
It'd be nice if the solution also worked on arrays treating each row as its own vector
for example :
x = [1, 2, 3, 4; 5, 6, 7, 8]
>> y = compressvect(x)
y =
1234
5678
>> size(y)
ans =
2 1
Here are some ways to do it:
Convert to characters, then interpret as a base-10 number:
y = base2dec(char(x+'0'), 10);
Similar, via cell array of character vectors:
y = str2double(cellstr(char(x+'0')));
Direct arithmetic approach using matrix multiplication:
y = x * 10.^(size(x,2)-1:-1:0).';
Similar, using element-wise multiplication with broadcast:
y = sum(bsxfun(#times, x, 10.^(size(x,2)-1:-1:0)), 2);

MATLAB : 3 dimensional matrix with multipication with a vector

I have A matrix which is 16x16x155460. I have a B vector which is 12955x1. I want to multiply each 1:16x1:16x1+12*n:12+12*nwith the elements of B(n). So my goal is to find the weighted sum of the A according to B. My way to do this as follows (I don't want to use for-loop and my method gives wrong answer, I could not obtain the 1:12 vectors which is consecutive) :
B = repmat(B,[1 16 16]);
B = permute(B,[2 3 1]);
B = repmat(B,[1 1 12]);
result = B.*(A);
As a small example n=2 :
A(:,:,1)=[1 2; 3 4]
A(:,:,2)=[1 2; 3 4]
A(:,:,3)=[1 2; 3 4]
A(:,:,4)=[1 2; 3 4]
B = [2,3]
Result would be:
result(:,:,1)=A(:,:,1)*B(1);
result(:,:,2)=A(:,:,2)*B(1);
result(:,:,3)=A(:,:,1)*B(2);
result(:,:,4)=A(:,:,2)*B(2);
If I understood the problem correctly, you can use the powerful trio of bsxfun, permute and reshape to solve it, like so -
[M,N,R] = size(A);
mult_out = bsxfun(#times,reshape(A,M,N,numel(B),[]),permute(B(:),[4 3 1 2]))
out = reshape(mult_out,M,N,[])

Find row-wise combinations of a 2 dimensional matrix

I have a matrix:
X = [2,6,1; 3,8,1; 4,7,1; 6,2,1; 6,4,1; 7,3,1; 8,5,1; 7,6,1];
I want to find all row-wise combinations of X. i.e.
A(1) = [2, 6, 1; 3, 8, 1; 4, 7, 1]
A(2) = [2, 6, 1; 3, 8, 1; 6, 2, 1]
:
:
:
Here's what I've tried:
X = [2,6,1; 3,8,1; 4,7,1; 6,2,1; 6,4,1; 7,3,1; 8,5,1; 7,6,1];
p = 3
[m, n] = size(X);
comb = combnk(1:m, p);
[s, t] = size(comb);
c = [X(comb(:,1), :, :) X(comb(:,2), :, :) X(comb(:,3), :, :)];
This gives me a matrix like:
c = 2 6 1 3 8 1 4 7 1
2 6 1 3 8 1 6 2 1
2 6 1 3 8 1 6 4 1
I want to apply the concatenate matrix option to obtain c to make it dynamic depending on value of p but I'm not sure how to use it. I don't want to use For loops. Please help me out.
This is fully vectorized, so it should be fast:
n = 3; %// number of rows to pick each time
ind = reshape(nchoosek(1:size(X,1), n).', [], 1); %'// indices of combinations
A = permute(reshape(X(ind,:).', size(X,2), n, []), [2 1 3]);
The result is
A(:,:,1)
ans =
2 6 1
3 8 1
4 7 1
A(:,:,2)
ans =
2 6 1
3 8 1
6 2 1
etc.
Should you need the result in the form of a cell array, you can convert A from 3D-array to cell array this way:
A = mat2cell(A, size(A,1), size(A,2), ones(1,size(A,3)));
Your thinking is pretty close. This code does the job. I put comments in code, which should be easy to read.
X = [2,6,1; 3,8,1; 4,7,1; 6,2,1; 6,4,1; 7,3,1; 8,5,1; 7,6,1];
p = 3;
%// List all combinations choosing 3 out of 1:8.
v = nchoosek(1:size(X,1), p);
%// Use each row of v to create the matrices, and put the results in an cell array.
%// This is the A matrix in your question.
A = arrayfun(#(k)X(v(k,:), :), 1:size(v,1), 'UniformOutput', false);
%// And you can concatenate A vertically to get c.
flatA = cellfun(#(x)reshape(x, 1, []), A, 'UniformOutput', false);
c = vertcat(flatA{:});
PS: From my understanding I thought the result you wanted was A, which is an easy to use cell array. But I added an extra step to get c exactly as in your question just in case.
Disclaimer: arrayfun and cellfun are pretty much equivalent to for loop in terms of performance.
You can do it using reshape and a bunch of transposes since Matlab is column-major ordered:
c = reshape(X(comb',:)',9,[])'
or if you want a 3D matrix:
A = permute(reshape(X(comb',:)',3,3,[])', [2,1,3])

Find part of vector in another vector matlab

I would like to know if there is an easy way to find the indices of a vector in another vector in matlab:
a = [1 2 3 5 7 10 2 3 6 8 7 5 2 4 7 2 3]
b = [2 3]
So how to get the indices of a when comparing it with b (index of first element is needed)
In this case:
ans = [2 7 16]
Thanks in advance
find(a(1:end-1) == b(1) & a(2:end) == b(2) == 1)
You can re-purpose strfind by converting the elements of both vectors to byte arrays (uint8) with typecast:
bytesPerEl = numel(typecast(a(1),'uint8'));
byteLocs = strfind(char(typecast(a,'uint8')),char(typecast(b,'uint8')));
locsb = (byteLocs-1)/bytesPerEl + 1
locsb =
2 7 16
Just make sure a and b are of the same type. Also note that this works for 1D vectors, not matrixes or higher dimensional arrays.
General approach with length of b arbitrary (not necessarily 2 as in the example), and avoiding the use of strings:
match1 = bsxfun(#eq, a(:), b(:).'); %'// now we just need to make the diagonals
%// horizontal (in order to apply "all" row-wise). For that we'll use indices
%// ind, ind1, ind2
ind = reshape(1:numel(match1), numel(a), numel(b));
ind1 = nonzeros(tril(ind)); %// source indices
ind2 = sort(nonzeros(tril(flipud(ind)))); %// destination indices
match2 = zeros(size(match1));
match2(ind2) = match1(ind1); %// diagonals have become horizontal
result = find(all(match2.'));

Partition a matrix into several matrices

How can I partition a matrix into several smaller matrices to find unknown variables?
For example, given:
how can solve this problem by partitioning (splitting) a matrix 3x3 into smaller matrices (1x1 or other) to find the values of x, y, z and u?
Your matrix dimensions dont agree, or am I missing something?
Edit:
The code from Jeff E will work fine on smaller matrices.
For bigger matrices you will need to use backward substitution or some other algorithm, mainly because matrix inversion is a memory intensive task.
In the new image, you isolate for the unknown matrix using some identities:
A * X = B
(inv(A)) * A * X = (inv(A)) * B
I * X = (inv(A)) * B
X = (inv(A)) * B
In Matlab:
A = [1, 2; 0, 1]
B = [4, 7; 4, 6]
X = inv(A) * B
Output:
ans =
-4 -5
4 6
To solve an equation of the form A*X=B, you should use the backslash operator, since explicitly taking the inverse should be avoided if possible
A = [1, 2; 0, 1];
B = [4, 7; 4, 6];
X = A\B
X =
-4 -5
4 6