I want to fill a 10x15 matrix in MATLAB using the formula z(i, j) = 2 * x(i) + 3 * y(j)^2, so that each entry at (i, j) = z(i, j). I have arrays for x and y, which are of size 10 and 15, respectively.
I've accomplished the task using the code below, but I want to do it in one line, since I'm told it's possible. Any thoughts?
x = linspace(0,1,10);
y = linspace(-0.5,0.5,15);
z = zeros(10,15);
m_1 = 2;
m_2 = 3;
for i = 1:length(x)
for j = 1:length(y)
z(i, j) = m_1*x(i) + m_2*y(i)^2;
end
end
It looks like you have a bug in your original loop:
You are using i index twice: m_1*x(i) + m_2*y(i)^2.
The result is that all the columns of z matrix are the same.
For applying the formula z(i, j) = 2*x(i) + 3*y(j)^2 use the following loop:
x = linspace(0,1,10);
y = linspace(-0.5,0.5,15);
z = zeros(10,15);
m_1 = 2;
m_2 = 3;
for i = 1:length(x)
for j = 1:length(y)
z(i, j) = m_1*x(i) + m_2*y(j)^2;
end
end
For implementing the above loop using one line, we may use meshgrid first.
Replace the loop with:
[Y, X] = meshgrid(y, x);
Z = m_1*X + m_2*Y.^2;
For expansions, read the documentation of meshgrid, it is much better than any of the expansions I can write...
The following command gives the same output as your original loop (but it's probably irrelevant):
Z = repmat((m_1*x + m_2*y(1:length(x)).^2)', [1, length(y)]);
Testing:
max(max(abs(Z - z)))
ans =
0
I'm trying to apply the Karhunen Loeve procedure to a translation-invariant data set. I understand the KL procedure, and how to create a mask to smooth out missing data. However, I'm having a hard time creating a program to model my Translation invariant data set.
The data set that I need to plot in matlab is:
Translation-Invariant Data Set
And here's the matlab code that I tried to use to model it:
function [fmu] = kLProcedure(N, P, M)
for k = 1:N;
for m = 1:M;
for n = 1:P;
x(m) = ((m-1)*2.*(pi))/M;
t(n) = ((n - 1)*2.*(pi))/P;
k = 1:3;
fmu(x(m),t(n)) = (1/N).*symsum((1/k).*sin(k(x(m)-t(n))),k);
end
end
end
With N=3, P=64, M=64;
I'm trying to use a nested for-loop to calculate each iteration of m, n, and t. and keep getting the error:
Error using /
Matrix dimensions must agree.
Error in kLProcedure (line 28)
fmu(x(m),t(n)) = (1/N).*symsum((1/k).*sin(k(x(m)-t(n))),k);
And advice would be greatly appreciated. Thank you.
Honestly, I don't have an in-depth knowledge of the algorithms you are using, but looking at the formulation of the one you are trying to reproduce, I think the following code is what you are looking for:
fmu = kLProcedure(3,64,64);
plot(fmu);
function [fmu] = kLProcedure(N,M,P)
k = 1:N;
ki = 1 ./ k;
Ni = 1 / N;
m = 1:M;
x = ((m - 1) .* 2 .* pi()) ./ M;
n = 1:P;
t = ((n - 1) .* 2 .* pi()) ./ P;
fmu = zeros(M,P);
for i = m
for j = n
fmu(i,j) = Ni .* sum(ki .* sin(ki .* (x(i) - t(j))));
end
end
end
Output:
Translational-Invariant Data
function [fmu] = kLProcedure(N,M,P)
m = 1:M;
x = ((m - 1) .* 2 .* pi()) ./ M;
n = 1:P;
t = ((n - 1) .* 2 .* pi()) ./ P;
fmu = zeros(M,P);
for i = m
for j = n
fmu(i,j) = 0;
for k = 1:3
fmu(i,j) = fmu(i,j) + (1/3).*sum((1/k).*(sin((k) .* (x(i) - t(j)))));
end
end
end
I have a non-uniform rectangular grid along D dimensions, a matrix of logical values V on the grid, and a matrix of query data points X. The number of grid points differs across dimensions.
I run the interpolation multiple times for the same grid G and query X, but for different values V.
The goal is to precompute the indexes and weights for the interpolation and to reuse them, because they are always the same.
Here is an example in 2 dimensions, in which I have to compute indexes and values every time within the loop, but I want to compute them only once before the loop. I keep the data types from my application (mostly single and logical gpuArrays).
% Define grid
G{1} = single([0; 1; 3; 5; 10]);
G{2} = single([15; 17; 18; 20]);
% Steps and edges are reduntant but help make interpolation a bit faster
S{1} = G{1}(2:end)-G{1}(1:end-1);
S{2} = G{2}(2:end)-G{2}(1:end-1);
gpuInf = 1e10;
% It's my workaround for a bug in GPU version of discretize in Matlab R2017a.
% It throws an error if edges contain Inf, realmin, or realmax. Seems fixed in R2017b prerelease.
E{1} = [-gpuInf; G{1}(2:end-1); gpuInf];
E{2} = [-gpuInf; G{2}(2:end-1); gpuInf];
% Generate query points
n = 50; X = gpuArray(single([rand(n,1)*14-2, 14+rand(n,1)*7]));
[G1, G2] = ndgrid(G{1},G{2});
for i = 1 : 4
% Generate values on grid
foo = #(x1,x2) (sin(x1+rand) + cos(x2*rand))>0;
V = gpuArray(foo(G1,G2));
% Interpolate
V_interp = interpV(X, V, G, E, S);
% Plot results
subplot(2,2,i);
contourf(G1, G2, V); hold on;
scatter(X(:,1), X(:,2),50,[ones(n,1), 1-V_interp, 1-V_interp],'filled', 'MarkerEdgeColor','black'); hold off;
end
function y = interpV(X, V, G, E, S)
y = min(1, max(0, interpV_helper(X, 1, 1, 0, [], V, G, E, S) ));
end
function y = interpV_helper(X, dim, weight, curr_y, index, V, G, E, S)
if dim == ndims(V)+1
M = [1,cumprod(size(V),2)];
idx = 1 + (index-1)*M(1:end-1)';
y = curr_y + weight .* single(V(idx));
else
x = X(:,dim); grid = G{dim}; edges = E{dim}; steps = S{dim};
iL = single(discretize(x, edges));
weightL = weight .* (grid(iL+1) - x) ./ steps(iL);
weightH = weight .* (x - grid(iL)) ./ steps(iL);
y = interpV_helper(X, dim+1, weightL, curr_y, [index, iL ], V, G, E, S) +...
interpV_helper(X, dim+1, weightH, curr_y, [index, iL+1], V, G, E, S);
end
end
I found a way to do this and posting it here because (as of now) two more people are interested. It takes only a slight modification to my original code (see below).
% Define grid
G{1} = single([0; 1; 3; 5; 10]);
G{2} = single([15; 17; 18; 20]);
% Steps and edges are reduntant but help make interpolation a bit faster
S{1} = G{1}(2:end)-G{1}(1:end-1);
S{2} = G{2}(2:end)-G{2}(1:end-1);
gpuInf = 1e10;
% It's my workaround for a bug in GPU version of discretize in Matlab R2017a.
% It throws an error if edges contain Inf, realmin, or realmax. Seems fixed in R2017b prerelease.
E{1} = [-gpuInf; G{1}(2:end-1); gpuInf];
E{2} = [-gpuInf; G{2}(2:end-1); gpuInf];
% Generate query points
n = 50; X = gpuArray(single([rand(n,1)*14-2, 14+rand(n,1)*7]));
[G1, G2] = ndgrid(G{1},G{2});
[W, I] = interpIW(X, G, E, S); % Precompute weights W and indexes I
for i = 1 : 4
% Generate values on grid
foo = #(x1,x2) (sin(x1+rand) + cos(x2*rand))>0;
V = gpuArray(foo(G1,G2));
% Interpolate
V_interp = sum(W .* single(V(I)), 2);
% Plot results
subplot(2,2,i);
contourf(G1, G2, V); hold on;
scatter(X(:,1), X(:,2), 50,[ones(n,1), 1-V_interp, 1-V_interp],'filled', 'MarkerEdgeColor','black'); hold off;
end
function [W, I] = interpIW(X, G, E, S)
global Weights Indexes
Weights=[]; Indexes=[];
interpIW_helper(X, 1, 1, [], G, E, S, []);
W = Weights; I = Indexes;
end
function [] = interpIW_helper(X, dim, weight, index, G, E, S, sizeV)
global Weights Indexes
if dim == size(X,2)+1
M = [1,cumprod(sizeV,2)];
Weights = [Weights, weight];
Indexes = [Indexes, 1 + (index-1)*M(1:end-1)'];
else
x = X(:,dim); grid = G{dim}; edges = E{dim}; steps = S{dim};
iL = single(discretize(x, edges));
weightL = weight .* (grid(iL+1) - x) ./ steps(iL);
weightH = weight .* (x - grid(iL)) ./ steps(iL);
interpIW_helper(X, dim+1, weightL, [index, iL ], G, E, S, [sizeV, size(grid,1)]);
interpIW_helper(X, dim+1, weightH, [index, iL+1], G, E, S, [sizeV, size(grid,1)]);
end
end
To do the task the whole process of interpolation ,except computing the interpolated values, should be done. Here is a solution translated from the Octave c++ source. Format of the input is the same as the frst signature of the interpn function except that there is no need to the v array. Also Xs should be vectors and should not be of the ndgrid format. Both the outputs W (weights) and I (positions) have the size (a ,b) that a is the number of neighbors of a points on the grid and b is the number of requested points to be interpolated.
function [W , I] = lininterpnw(varargin)
% [W I] = lininterpnw(X1,X2,...,Xn,Xq1,Xq2,...,Xqn)
n = numel(varargin)/2;
x = varargin(1:n);
y = varargin(n+1:end);
sz = cellfun(#numel,x);
scale = [1 cumprod(sz(1:end-1))];
Ni = numel(y{1});
index = zeros(n,Ni);
x_before = zeros(n,Ni);
x_after = zeros(n,Ni);
for ii = 1:n
jj = interp1(x{ii},1:sz(ii),y{ii},'previous');
index(ii,:) = jj-1;
x_before(ii,:) = x{ii}(jj);
x_after(ii,:) = x{ii}(jj+1);
end
coef(2:2:2*n,1:Ni) = (vertcat(y{:}) - x_before) ./ (x_after - x_before);
coef(1:2:end,:) = 1 - coef(2:2:2*n,:);
bit = permute(dec2bin(0:2^n-1)=='1', [2,3,1]);
%I = reshape(1+scale*bsxfun(#plus,index,bit), Ni, []).'; %Octave
I = reshape(1+sum(bsxfun(#times,scale(:),bsxfun(#plus,index,bit))), Ni, []).';
W = squeeze(prod(reshape(coef(bsxfun(#plus,(1:2:2*n).',bit),:).',Ni,n,[]),2)).';
end
Testing:
x={[1 3 8 9],[2 12 13 17 25]};
v = rand(4,5);
y={[1.5 1.6 1.3 3.5,8.1,8.3],[8.4,13.5,14.4,23,23.9,24.2]};
[W I]=lininterpnw(x{:},y{:});
sum(W.*v(I))
interpn(x{:},v,y{:})
Thanks to #SardarUsama for testing and his useful comments.
Can you help me please translate this equation into a code?
I tried this code but its only the first part
theSum = sum(M(:, y) .* S(:, y) ./ (1 + K(:, y)))
EDIT: sorry, I was having a brainfart. The answer below makes no assumptions on the nature of M, K, etc, which is why I recommended functions like that. But they're clearly matrices. I'll make another answer, I'll leave this here for reference though in case it's useful
I would start by making the M, K, X, L, and O expressions into simple functions, so that you can easily call them as M(z,y), X(z,y) (or X(z,j) depending on the input you need ) etc.
Then you will convert each summation into a for loop and collect the result (you can think about vectorisation later, right now focus on translating the problem). The double summation is essentially a nested for loop, where the result of the inner loop is used in the outer one at each outer iteration.
So your end result should look something like:
Summation1 = 0;
for z = 1 : Z
tmp = M(z,y) / K(z,y) * (X(z,y) / (1 + L(z,y));
Summation1 = Summation1 + tmp;
end
Summation2 = 0;
for j = 1 : Y
if j ~= y
for z = 1 : Z
tmp = (M(z,j) * X(z,j) * O(j)) / (K(z,j)^2 * (1 + L(z,j)) * X(z,y);
Summation2 = Summation2 + tmp;
end
end
end
Result = Summation1 - Summation2;
(Btw, this assumes that all operations are on scalars. If M(z,y) outputs a vector, adjust for elementwise operations appropriately)
IF M, K, etc are all matrices, and all operations are expected to be element-wise, then this is a vectorised approach for this equation.
Left summation is
S1 = M(1:Z,y) ./ K(1:Z,y) .* X(1:Z,y) ./ (1 + L(1:Z,y));
S1 = sum(S1);
Right summation is (assuming (O is a horizontal vector)
S2 = M(1:Z, 1:Y) .* X(1:X, 1:Y) .* repmat(O(1:Y), [Z,1]) ./ ...
(K(1:Z, 1:Y) .^ 2 .* (1 + L(1:Z, 1:Y))) .* X(1:Z, 1:Y);
S2(:,y) = []; % remove the 'y' column from the matrix
S2 = sum(S2(:)); % add all elements
End result: S1 - S2
this is lambda version vectorized:
equation = #(y,M,K,X,L,O) ...
sum(M(:,y)./K(:,y).*X(:,y)./(1+L(:,y))) ...
-sum(sum( ...
bsxfun( ...
#times ...
,M(:,[1:y-1,y+1:end]) ...
.* X(:,[1:y-1,y+1:end]) ...
.* O(:,[1:y-1,y+1:end]) ...
./ (K(:,[1:y-1,y+1:end]) .^ 2 ...
.*(1+ L(:,[1:y-1,y+1:end]))) ...
,X(:,y) ...
) ...
));
%%% example:
y = 3;
Y = 5;
Z = 10;
M = rand(Y, Z);K = rand(Y, Z);X = rand(Y, Z);L = rand(Y, Z);O = rand(Y, Z);
equation(y,M,K,X,L,O)