Vectorize code in MATLAB - matlab

How to vectorize this code in MATLAB?
n = 3;
x = zeros(n);
y = x;
for i = 1:n
x(:,i) = i;
y(i,:) = i;
end
I am not able to vectorize it. Please help.

You can use meshgrid :
n = 3;
[x,y] = meshgrid(1:n,1:n)
x =
1 2 3
1 2 3
1 2 3
y =
1 1 1
2 2 2
3 3 3

n=3;
[x,y]=meshgrid(1:n);
This uses meshgrid which does this automatically.
Or you can use bsxfun as Divakar suggests:
bsxfun(#plus,1:n,zeros(n,1))
Just as a note on your initial looped code: it's bad practise to use i as a variable

If I can add something to the mix, create a row vector from 1 to n, then use repmat on this vector to create x. After, transpose x to get y:
n = 3;
x = repmat(1:n, n, 1);
y = x.';
Running this code, we get:
>> x
x =
1 2 3
1 2 3
1 2 3
>> y
y =
1 1 1
2 2 2
3 3 3

Related

Function to accept a matrix as input and goes element by element using for-loops adding one to each of the elements

I have created a function to add one to an element as follows;
function xz = addOne(x)
nrow = size(x,1);
ncol = size(x,1);
for K = 1:nrow
for J = 1:ncol
xz = x(:) + 1;
end
end
Example: given 1 the function results in 2:
addOne(1) [2]
I have tried using a matrix as an argument for the function...
x = [1 2 3; 0 0 0; 4 5 6];
x =
1 2 3
0 0 0
4 5 6
addOneWithFors(x)
ans =
2
1
5
3
1
6
4
1
7
How would I update this function to accept a matrix with multiple rows and columns and output it as such instead of just 1 number or a list of elements. Any help would be greatly appreciated.
In Matlab, you don't need a special function to do this. Matlab natively supports adding a scalar to a matrix. For example:
x = [1 2 3; 0 0 0; 4 5 6];
y = x + 1
will produce:
y =
2 3 4
1 1 1
5 6 7
However, if you specifically want to write this out explicitly using for loops, then your addOne() function only needs minor modifications. For example:
function xz = addOne(x)
nrow = size(x,1);
ncol = size(x,2);
xz = zeros(nrow,ncol);
for K = 1:nrow
for J = 1:ncol
xz(K,J) = x(K,J) + 1;
end
end
Note that ncol = size(x,2); has been defined correctly.

How to generate matrix in MATLAB where values decrease with increasing coordinates

I'm trying to generate an n x n matrix like
5 4 3 2 1
4 4 3 2 1
3 3 3 2 1
2 2 2 2 1
1 1 1 1 1
where n = 5 or n 50. I'm at an impasse and can only generate a portion of the matrix. It is Problem 2.14 from Numerical Methods using MATLAB 3rd Edition by Penny and Lindfield. This is the best I have so far:
n = 5;
m = n;
A = zeros(m,n);
for i = 1:m
for j = 1:n
A(i,j) = m;
end
m = m - 1;
end
Any feedback is appreciated.
That was a nice brain-teaser, here’s my solution:
[x,y] = meshgrid(5:-1:1);
out = min(x,y)
Output:
ans =
5 4 3 2 1
4 4 3 2 1
3 3 3 2 1
2 2 2 2 1
1 1 1 1 1
Here's one loop-based approach:
n = 5;
m = n;
A = zeros(m, n);
for r = 1:m
for c = 1:n
A(r, c) = n+1-max(r, c);
end
end
And here's a vectorized approach (probably not faster, just for fun):
n = 5;
A = repmat(n:-1:1, n, 1);
A = min(A, A.');
That's one of the matrices in Matlab's gallery, except that it needs a 180-degree rotation, which you can achieve with rot90:
n = 5;
A = rot90(gallery('minij', n), 2);

Index out column vector of matrix and then multiply corresponding matrix

I have heavy computation as follows:
L = ones(100000,200000);
for i = 1:10000
temp = f(i,...);
L = L .* temp(:, index );
end
where temp is a 100,000*3 matrix (values computed from f(i,...); I omit arguments here) and index is a 1*200,000 integer vector (1 to 3).
I have to do above many times in my algorithm. I feel Matlab wastes time creating 100000*200000 from temp(:, index ) in the iteration. But, it may not necessary; that is, we can just extract corresponding column and then multiply to corresponding column of L. Yet, I cannot find a way to do it efficiently...
Hope anyone can give advice on this. Thanks!
I give a small and hypothetical example:
function test
x = rand(5,3);
t = rand(10,1); % could be very long
point = 3;
index = [1 2 1 3 2 3 1 2;...
2 3 2 1 2 3 1 1;...
1 1 1 2 2 3 1 1;...
3 3 2 3 2 2 2 1;...
2 3 2 1 2 1 3 1]; % could be very long
L = ones(10,8);
for i = 1:5
temp = myfun(x(i,:),t,point);
L = L .* temp(:, index(i,:) );
end
function prob = myfun(x,t,point)
prob = ones(size(t,1),point);
for k = 2:point
prob(:,k) = exp( ((k-1).*x(1).*(t) + x(k) ));
end
de = sum(prob,2);
for k = 1:point
prob(:,k) = prob(:,k)./de;
end
end
end
I managed to save just some minor computation during each iteration, perhaps it makes a difference on your large matrices though. What I did was to change one line into prob(:,k) = exp( ((k-1).*x(i,1).*(t) + x(i,k) ));. Notice the elements in x. This saves some unnecessary computation. It is somewhat difficult to optimize this as I have no idea what this is, but here's my code:
x = rand(5,3);
t = rand(10,1);
point = 3;
index = [1 2 1 3 2 3 1 2;...
2 3 2 1 2 3 1 1;...
1 1 1 2 2 3 1 1;...
3 3 2 3 2 2 2 1;...
2 3 2 1 2 1 3 1];
L = ones(10,8);
for i = 1:5
prob = ones(size(t,1),point);
for k = 2:point
prob(:,k) = exp( ((k-1).*x(i,1).*(t) + x(i,k) ));
end
de = sum(prob,2);
for k = 1:point
prob(:,k) = prob(:,k)./de;
end
L = L .* prob(:, index(i,:) );
end
There are some dangerous operations I noticed, e.g. de = sum(prob,2);. Note that if you would change prob(:,k) = prob(:,k)./de; to prob(:,k) = prob(:,k)./sum(prob,2); you have a different result. Perhaps you're aware of this already, but it may be worth mentioning. Let me know if there is anything more I can do to help.

Creating Matrix with a loop in Matlab

I want to create a matrix of the following form
Y = [1 x x.^2 x.^3 x.^4 x.^5 ... x.^100]
Let x be a column vector.
or even some more variants such as
Y = [1 x1 x2 x3 (x1).^2 (x2).^2 (x3).^2 (x1.x2) (x2.x3) (x3.x1)]
Let x1,x2 and x3 be column vectors
Let us consider the first one. I tried using something like
Y = [1 : x : x.^100]
But this also didn't work because it means take Y = [1 x 2.*x 3.*x ... x.^100] ?
(ie all values between 1 to x.^100 with difference x)
So, this also cannot be used to generate such a matrix.
Please consider x = [1; 2; 3; 4];
and suggest a way to generate this matrix
Y = [1 1 1 1 1;
1 2 4 8 16;
1 3 9 27 81;
1 4 16 64 256];
without manually having to write
Y = [ones(size(x,1)) x x.^2 x.^3 x.^4]
Use this bsxfun technique -
N = 5; %// Number of columns needed in output
x = [1; 2; 3; 4]; %// or [1:4]'
Y = bsxfun(#power,x,[0:N-1])
Output -
Y =
1 1 1 1 1
1 2 4 8 16
1 3 9 27 81
1 4 16 64 256
If you have x = [1 2; 3 4; 5 6] and you want Y = [1 1 1 2 4; 1 3 9 4 16; 1 5 25 6 36] i.e. Y = [ 1 x1 x1.^2 x2 x2.^2 ] for column vectors x1, x2 ..., you can use this one-liner -
[ones(size(x,1),1) reshape(bsxfun(#power,permute(x,[1 3 2]),1:2),size(x,1),[])]
Using an adapted Version of the code found in Matlabs vander()-Function (which is also to be found in the polyfit-function) one can get a significant speedup compared to Divakars nice and short solution if you use something like this:
N = 5;
x = [1:4]';
V(:,n+1) = ones(length(x),1);
for j = n:-1:1
V(:,j) = x.*V(:,j+1);
end
V = V(:,end:-1:1);
It is about twice as fast for the example given and it gets about 20 times as fast if i set N=50 and x = [1:40]'. Although I state that is not easy to compare the times, just as an option if speed is an issue, you might have a look at this solution.
in octave, broadcasting allows to write
N=5;
x = [1; 2; 3; 4];
y = x.^(0:N-1)
output -
y =
1 1 1 1 1
1 2 4 8 16
1 3 9 27 81
1 4 16 64 256

From matrix column subtract corresponding vector value

I have a matrix 'x' and a row vector 'v'; the number of elements in the row vector is the same as the number of columns in the matrix. Is there any predefined function for doing the following operation?
for c = 1 : columns(x)
for r = 1 : rows(x)
x(r, c) -= v(c);
end
end
bsxfun(#minus,x,v)
Here's an octave demonstration:
octave> x = [1 2 3;2 3 4]
x =
1 2 3
2 3 4
octave> v = [2 0 1]
v =
2 0 1
octave>
octave> z=bsxfun(#minus,x,v)
z =
-1 2 2
0 3 3
If you are using Octave 3.6.0 or later, you don't have to use bsxfun since Octave performs automatic broadcasting (note that this is the same as actually using bsxfun, just easier on the eye). For example:
octave> x = [1 2 3; 2 3 4]
x =
1 2 3
2 3 4
octave> v = [2 0 1]
v =
2 0 1
octave> z = x - v
z =
-1 2 2
0 3 3
Alternatively, you can replicate your vector and directly subtract it from the matrix
z = x-repmat(v, size(x, 1), 1);