Choose k vectors from n vectors in Matlab - matlab

Suppose there are a matrix of three row vectors
A = [1,2;
1,3;
2,3]
I would like to create a new matrix B which draws two vectors from A with repetitions, and there are 3^2 possible combinations. Some simple implementation is as follows:
For i = 1:3
c = A(i,:);
for j=1:3
d = A(j,:);
B = [c;d];
end
end
But, in general, if I need to choose k vectors from n vectors, what is the more general way to write such loop? It's difficult to continue write loop using i, j, ... I guess. Thanks!

For sampling at random, matlab has randsample:
rowIdx = randsample( size(A,1), k, true );
B = A(rowIdx,:);

You can just use randi for this to pick k uniformly distributed numbers in the range 1:n (with replacement)
k = 2;
n = size(A,1);
rowIdx = randi(n,k)
B = A(rowIdx,:)

Thanks for all previous suggestions.
In the end I figure out what I want is called permutations with repetitions. The matlab function permun from file exchange solves my problem.

Related

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

Vectorize with Matlab Meshgrid in Chebfun

I am trying to use meshgrid in Matlab together with Chebfun to get rid of double for loops. I first define a quasi-matrix of N functions,
%Define functions of type Chebfun
N = 10; %number of functions
x = chebfun('x', [0 8]); %Domain
psi = [];
for i = 1:N
psi = [psi sin(i.*pi.*x./8)];
end
A sample calculation would be to compute the double sum $\sum_{i,j=1}^10 psi(:,i).*psi(:,j)$. I can achieve this using two for loops in Matlab,
h = 0;
for i = 1:N
for j = 1:N
h = h + psi(:,i).*psi(:,j);
end
end
I then tried to use meshgrid to vectorize in the following way:
[i j] = meshgrid(1:N,1:N);
h = psi(:,i).*psi(:,j);
I get the error "Column index must be a vector of integers". How can I overcome this issue so that I can get rid of my double for loops and make my code a bit more efficient?
BTW, Chebfun is not part of native MATLAB and you have to download it in order to run your code: http://www.chebfun.org/. However, that shouldn't affect how I answer your question.
Basically, psi is a N column matrix and it is your desire to add up products of all combinations of pairs of columns in psi. You have the right idea with meshgrid, but what you should do instead is unroll the 2D matrix of coordinates for both i and j so that they're single vectors. You'd then use this and create two N^2 column matrices that is in such a way where each column corresponds to that exact column numbers specified from i and j sampled from psi. You'd then do an element-wise multiplication between these two matrices and sum across all of the columns for each row. BTW, I'm going to use ii and jj as variables from the output of meshgrid instead of i and j. Those variables are reserved for the complex number in MATLAB and I don't want to overshadow those unintentionally.
Something like this:
%// Your code
N = 10; %number of functions
x = chebfun('x', [0 8]); %Domain
psi = [];
for i = 1:N
psi = [psi sin(i.*pi.*x./8)];
end
%// New code
[ii,jj] = meshgrid(1:N, 1:N);
%// Create two matrices and sum
matrixA = psi(:, ii(:));
matrixB = psi(:, jj(:));
h = sum(matrixA.*matrixB, 2);
If you want to do away with the temporary variables, you can do it in one statement after calling meshgrid:
h = sum(psi(:, ii(:)).*psi(:, jj(:)), 2);
I don't have Chebfun installed, but we can verify that this calculates what we need with a simple example:
rng(123);
N = 10;
psi = randi(20, N, N);
Running this code with the above more efficient solution gives us:
>> h
h =
8100
17161
10816
12100
14641
9216
10000
8649
9025
11664
Also, running the above double for loop code also gives us:
>> h
h =
8100
17161
10816
12100
14641
9216
10000
8649
9025
11664
If you want to be absolutely sure, we can have both codes run with the outputs as separate variables, then check if they're equal:
%// Setup
rng(123);
N = 10;
psi = randi(20, N, N);
%// Old code
h = 0;
for i = 1:N
for j = 1:N
h = h + psi(:,i).*psi(:,j);
end
end
%// New code
[ii,jj] = meshgrid(1:N, 1:N);
hnew = sum(psi(:, ii(:)).*psi(:, jj(:)), 2);
%// Check for equality
eql = isequal(h, hnew);
eql checks if both variables are equal, and we do get them as such:
>> eql
eql =
1

How to do a fast matrix multiplication for each column of two matrices without for loops?

I have two matrices A and B for which I want to do a multiplication for each of their columns to produce a new matrix. The first thing cross my mind is
A = rand(4,3);
B = rand(4,3);
for J=1:SIZE(A,2)
for jj=1:size(B,2)
C(:,:,m) = A(:,j)*B(:,jj)' ;
m = m+1 ;
end
end
But I don't want to use for loops which makes it slow. Is there any way?
I am going to use the matrices of third dimension of C, the ones which are built by multiplication of columns of A and B, Is it better to first build the C and then use its 3rd dimension matrices in each loop or just do the multiplication in each loop?
One approach with bsxfun -
N1 = size(A,1);
N2 = size(B,1);
C = reshape(bsxfun(#times,permute(A,[1 4 3 2]),permute(B,[4 1 2 3])),N1,N2,[])
You could avoid going to the 4th dimension as listed next, but it's still marginally slower than the earlier 4D approach -
C = reshape(bsxfun(#times,permute(A,[1 3 2]),B(:).'),N1,N2,[])
As an alternative to Divakar's answer, you can generate all 4-fold combinations of row and column indices of the two matrices (with ndgrid) and then compute the products:
[m, p] = size(A);
[n, q] = size(B);
[mm, nn, qq, pp] = ndgrid(1:m, 1:n, 1:q, 1:p);
C = reshape(A(mm+(pp-1)*m).*B(nn+(qq-1)*n), m, n, p*q);

Recovering vector in MATLAB for loop

I am running a for loop in MATLAB. Each iteration produces a vector of length different than the vector created in the previous iteration. Is there any why to recover each individual vector? In the end I want to concatenate each of these vectors. My code is something like
for i=1:n
v = zeros(1,i)
end
so after i=n, v will be a one by n vector, but I also want to recover the vectors for any i. In my code, each vector, v, is not a zero row vector, but a vector of varying size. Thanks.
I'd already typed this when Rody's post (+1) came through so figured I might as well post it too. An alternate solution that is very slightly less efficient (I did some timed runs, the differences were marginal) than Rody's but avoids the complicated indexing is:
A = cell(1, n);
for i = 1:n
A{1, i} = zeros(1, i);
end
Soln = cat(2, A{:});
I store the varying length row vectors in a cell array through the loop then concatenate them in the final step.
The simplest way is like so:
w = [];
for i=1:n
v = zeros(1,i);
%# your stuff here
w = [w v];
end
Which produces the vector w, which is the concatenation of all generated vectors v.
Note however that this is slow, since w grows each iteration. A slightly more complicated but more efficient solution would be this:
w = zeros(1, sum(1:n) );
j = 1;
for i=1:n
v = zeros(1,i);
%# your stuff here
w(1, j:j+i-1) = v;
j = j+i;
end

Matlab/Octave one-liner for a n-vector with a 1 in the i-th position

For example, given i=5 and and n=8, I want to generate [0;0;0;0;1;0;0;0]. Specifically, I want to generate the vector v so that:
v = zeros(n,1);
v(i) = 1;
Is there a (reasonable) way to do this in one line?
Another solution:
I = eye(n);
v = I(:, i);
Actually, you can have a vector y of numbers from 1 to n and get vectors like this for each element:
v = I(:, y);
You can see my blog post for the details on this general solution.
One way is [1:8]'==5, or more generally [1:n]'==i
Here's another solution using sparse to create an n length row vector with a 1 in the ith position:
v = sparse(1,i,1,1,n)
The advantage is that for large n, this is also memory efficient and can be used as usual in matrix calculations. If you ever need the full vector, just use full.
Here is another one:
n = 8;
p = 4;
arrayfun(#str2double,dec2bin(2^(p-1),n))
And another one (Creates a row vector):
circshift( [1 zeros(1,n-1)],[0 p]);
Or a column vector:
circshift( [1 ; zeros(n-1,1)],[p 0]);
Here is another one:
subsref( eye(n), struct('type','()', 'subs',{{ p,':' }}))