Matlab d-dimensional multipication table? - matlab

I'm new to Matlab and I'm trying to solve a problem that involves creating a d dimensional multiplication table where each edge goes from 1 to n. The problem statement says that inputting d = 0 should return the number 1 and d = 1 should return a column vector with the elements 1 to n.
Ideally, I would just create a matrix of 1 to n along d dimensions and then iterate through for each element setting it equal to the product of the indices, but I don't know how to create the d dimensional matrix.
Can anyone help me with this problem?

You can create the table with repeated use of bsxfun. At each iteration, the vector 1,2,...,n is shifted to a new dimension and multiplied (with singleton expansion) by the previous result.
%// Data
d = 3;
n = 10;
%// Computations
vector = (1:n).'; %// first dimension: column vector
result = 1; %// initialization
for n = 1:d
result = bsxfun(#times, result, vector); %// new dimension
vector = shiftdim(vector,-1); %// shift to the next dimension
end

Related

Generalise indexing of a multi-dimensional array in Matlab

I want to generalise to any n the Matlab code below.
Let A be an n-dimensional array:
clear
rng default
n=4;
A=randn(n,n,n,n);
n=5;
A=randn(n,n,n,n,n);
Note that A is composed of n^(n-2) 2-dimensional matrices, each of size nxn.
For example, when n=4 these matrices are A(:,:,1,1),...,A(:,:,4,1),A(:,:,1,2),...,A(:,:,4,4).
Suppose I'm interested in a code which:
1) deletes the last column and row in each of the n^(n-2) 2-dimensional matrices
%when n=4
A(n,:,:,:)=[];
A(:,n,:,:)=[];
%when n=5
A(n,:,:,:,:)=[];
A(:,n,:,:,:)=[];
2) deletes the 2-dimensional matrices with the 3-th,4-th,5-th,n-th index equal to n.
%when n=4
A(:,:,n,:)=[];
A(:,:,:,n)=[];
%when n=5
A(:,:,n,:,:)=[];
A(:,:,:,n,:)=[];
A(:,:,:,:,n)=[];
Question: could you help me to generalise the code above to any n? I cannot see how to proceed.
You can index your matrix with a cell containing multiple elements. Each element will be interpreted as a new index (more information here):
%Example 1: A(:,:,1:3,1:3,1:3}
%elements per dimension
n = 4;
%number of dimension
d = 5;
%random matrix
repdim = repmat({n},d,1)
A = rand(repdim{:});
%We want A(:,:,1:3,1:3,1:3}, so we create c = {1:3,1:3,1:3}
c = repmat({1:n-1},d-2,1);
%Get the new matrix
A = A(:,:,c{:});
%Example 2: A(1:3,1:3,:,:,:}
%elements per dimension
n = 4;
%number of dimension
d = 5;
%random matrix
repdim = repmat({n},d,1)
A = rand(repdim{:});
%We want A(1:3,1:3,:,:,:}, so we create c1 = {1:3,1:3} and c2 = {':',':',':'}
c1 = repmat({1:n-1},2,1);
c2 = repmat({':'},d-2,1); %thanks to #LuisMendo for the suggestion.
%Get the new matrix
A = A(c1{:},c2{:});

Multiplying a 4D matrix by a vector, and collapsing 1 dimension

I have a question regarding the multiplication of a 4-dimensional object by a 1 dimensional object.
Effectively, I have a 4D object of sizes (15,15,3,5).
I want to multiply out the 4th dimension by using a 5x1 vector, collapsing the last dimension to 1. Then I want to use squeeze to get a (15,15,3) sized object, again multiplying it by a 3x1 vector, leaving me with a 15x15 matrix.
I can do this in a loop, but that is quite costly. Can anyone give me suggestions how to do this without a loop?
For now the loop:
expectationCalc = reshape(mValueFunction(age+1, :, :, :, :), nGridAssets, nGridHumanCapital, nNetInterestRate, nShockstoHumanCapital);
for i = 1:nGridAssets
for j = 1:nGridHumanCapital
expectation(i,j) = mTransitionNetInterestRate(nNetIntRate, :)*(squeeze(expectationCalc(i,j,:,:))*mTransitionShockHumanCapital(ShockHcapital, :)');
end
end
If you reshape your 4D matrix to a 2D matrix, where the 2nd dimension is the one you want to reduce by dot product, and the 1st dimension contains all other dimensions, then you can apply a regular matrix multiplication. The result can then be reshaped to the original size (minus one dimension):
% Input data
M = randn(15,15,3,5);
v1 = randn(5,1);
v2 = randn(3,1);
% 1st multiplication
sz = size(M);
M = reshape(M,[],sz(end));
M = M * v1;
sz(end) = []; % We no longer have that last dimension
M = reshape(M,sz);
% 2nd multiplication
M = reshape(M,[],sz(end));
M = M * v2;
sz(end) = []; % We no longer have that last dimension
M = reshape(M,sz);

Replacing elements in a base matrix by squared permutation submatrices

I have a sparse parity check matrix (consisting of ones and zeros) and I would need to replace each nonzero element (ones) from it by PM: a squared permutation matrix of dimension N (being N generally a large integer). In the case of the zero elements, these would be replaced by squared null matrices of the same dimension.
Let me share with you which the current state of my code is:
This is the base matrix in which I would like to replace its ones by permutation matrices:
B = zeros((L + ms) * dc, L * dv);
for i = 1 : 1 : L
for j = 1 : 1 : dv
B(dc*(i-1)+1 : dc*(ms+i), j+dv*(i-1)) = ones(dc*(ms+1), 1);
end
end
I have been told a way for doing so by using 'cell' objects, this is, initializing H as an array of empty cells that would contain the corresponding submatrices:
H=repmat({{}},size(B));
Mc = 500 % Dimension of the permutation matrix
MP=randi([1,5],Mc,Mc); % Definition of one permutation matrix
% It would be desirable that the permutation matrix is different for each replacement
[H{B==0}]=deal(zeros(Mp));
[H{B==1}]=deal(MP);
But there's one problem coming up -that I would need this matrix to be used as a parameter of a following function and it would be very much desirable that it were a simple matrix of ones and zeros (as I am not very familiar with 'cell' structures... however, as you can see, Mc is such a big integer that I don't know if that would be possible to be handled.
Do you have any other way of doing so to have a raw matrix of dimensions (L*ms)dcMc, LdvMc as output?
These are some parameters that could be used to have a try:
ms = 2;
Mc = 600; % any number (specially big ones) could serve for this purpose
dc = 3;
dv = 4;
L = 15;
Many thanks in advance for your attention, and may you have a nice day.
This is how it can be done with cells:
B = Randi([0,1], m, n); % m*n array of 1s and 0s
H = cell(size(B)); % Define cell array
Mc = 500; % Size of replacement matrices
MP = randi([1,5], Mc, Mc); % Permutation matrix
H(B==0) = {zeros(Mc, Mc)}; % Set elements of H where B==0 to matrix of zeros
H(B==1) = {MP}; % Set elements of H where B==1 to permutation matrix
% Convert to matrix
Hmat = cell2mat(H); % Hmat = Mc*m row by Mc*n column matrix
Each cell element holds a matrix of size Mc*Mc, at the end this can be converted to one large matrix. Take care which sorts of brackets you use with cells, the parentheses () are for logical indexing, whilst the curly braces {} are for assigning the sub-matrixes as cell elements.
Example:
B = [1 0; 1 1];
MP = [1 2; 3 4];
H(B==0) = {zeros(2, 2)};
H(B==1) = {MP};
Hmat = cell2mat(H);
% >> Hmat = [1 2 0 0
% 3 4 0 0
% 1 2 1 2
% 3 4 3 4];
If you want the replacement matrix MP to change, you will have to do this in a loop, changing MP on each iteration and using it to replace one element of H.

Filling in a Cell of Matrices in MATLAB

In Matlab I am trying to create a cell of size 16 x1 where each entry of this cell is a matrix. I have the following equation
$$W_g = exp^{\frac{j{2\pi m}{N}(n+\frac{g}{G}))} \,\,\,\,\,\,\, m,n=0,1,.....(N-1)$$
for this work assume $N=4$ and the index $g$ is the index that refers to the cell element i.e g=0:1:15
W=cell(16,1);
for g=1:16
for m=1:3
for n=1:3
W{g,m,n}= exp((2*pi*j*m/4)* n+(g-1)/16));
end
end
end
How can I make this work? I have two problems with this, you see g starts from 0 and MATLAB doesnt accept index of zero and how to actually define the matrices within the cell.
Thanks
So if I understand you have this equation:
And you just want the following code:
W=cell(16,1);
n = 1:3;
m = 1:3;
N = 4;
for g=1:16
W{g}= exp((2*pi*j.*m/4*N).*n+(g-1)/16);
end
%or the 1 line version:
W = cellfun(#(g) exp((2*pi*j.*m/4*N).*n+(g-1)/16),num2cell([1:16]),'UniformOutput',0);
With matlab you can use the Element-wise multiplication symbol .*
For example:
%A matrix multiplication
A = [2,3]
B = [1,3]';
result = A * B %result = 11
%An element wise multiplication
A = [2,3]
B = [1,3];
result = A .* B %result = [2,9]
First of all, i is the complex number in matlab (sqrt(-1)) not j, and you are correct, matlab is indexed in 1, so simply start counting g at 1, until 16.
Next, create a zero matrix, and calculate all indices accordingly. Something like this should work just fine :
clc
clear all
W=cell(16,1);
for g=1:16;
temp = zeros(3,3);
for m=1:3
for n=1:3
temp (m,n) = exp((2*pi*1i*m/4)* n+g/16);
end
end
W{g} = temp;
end
if you are considering doing much larger operations, consider using linspace to create your m and n indices and using matrix operations

Two for loops (nested), computing matrices Matlab

my current code is below.
What I have is two sets of data phi and theta both 18x30 and I have a for loop running from 1 to 30 which are the 30 columns of my data. Each of these individual columns will produce a matrix 'B' for me. The matrix 'B' is produced after going through the 18 rows of each column.
The problem I have is that I need to multiply all the resulting 'B' matrices for each of the 18 rows with each other in order to get a final matrix for each of the 30 columns, that is why I have set A(:,:,i) = eye(2) so that my first matrix will multiply by A. But I don't want to store A or B for each loop, instead what I want is that on the first loop of i my matrix B will multiply the identity matrix A. Then that matrix A will multiply the next matrix B...with the result of each multiplication being carried forward to the next matrix B that will be calculated, so the multiplications will get done as the program loops. That's why I have the line:
A(:,:,i) = A.*B;
but it doesn't seem to work. I get an error message saying the dimensions must match.
At the end of the program I want to be able to access each of the 30 matrices using a command like:
A(:,:,3), for example, to get my 2x2 matrix for the 3rd column.
Hope that was clear enough!
theta = dlmread('theta.dat');
phi = dlmread('phi.dat');
ne = 1.7;
no = 1.5;
d = 0.000001;
w = 0.000000555;
for i = 1:30
A(:,:,i) = eye(2);
for j = 1:18
nx =((cos(theta(j,i)).^2)/(no^2) + ((sin(theta(j,i)).^2)/(ne^2))).^(-1/2);
D = (2*pi*(nx-no)*d)/w;
x = ((cos(phi(j,i))).^2).*exp((-1i.*D)/2) + ((sin(phi(j,i))).^2).*exp((1i.*D)/2);
y = 1i*(sin(D/2)).*sin(2*phi(j,i));
z = ((cos(phi(j,i))).^2).*exp((1i.*D/2) + ((sin(phi(j,i))).^2).*exp((-1i.*D)/2));
B = [x y;y z];
A(:,:,i) = A.*B;
end
end
B is a 2x2 matrix. For A.*B to work, A must also be 2x2. But A in your program is three-dimensional.
From your problem description, I think you want
A(:,:,i) = A(:,:,i)*B; % Edited now that I see this happens 18 times on the same i
(Please note, I also replaced element-wise multiply .* with matrix multiply *, because that's what it sounds like you want.)
But I suggest
A = eye(2);
and
A = A*B;
and store it at the end like
results(:,:,i) = A;