use 2Xn matrix entries as indices - matlab

Is it possible to use matrix entries as indices to other matrix ?
for example :
A=[1 2 ; 4 5 ; 6 7 ];
And I want to reach entries of other matrix using A, without using loops.
Othermat(1,2), Othermat(4,5) %...
If yes how can I do it ?!

Sure, use sub2ind:
A = [1 2; 4 5; 6 7];
ind = sub2ind(size(Othermat),A(:,1),A(:,2));
values = Othermat(ind);

The suggested sub2ind is a natural way to generate indices.
Of course it is also not very hard to find the linear index directly:
A = [1 2; 4 5; 6 7];
Othermat = magic(7);
Othermat(A(:,1)+(A(:,2)-1)*size(Othermat,1))

Related

Filter elements from a 3D matrix without loop

I have a 3d matrix H(i,j,k) with dimensions (i=1:m,j=1:n,k=1:o). I will use a simple case with m=n=o = 2:
H(:,:,1) =[1 2; 3 4];
H(:,:,2) =[5 6; 7 8];
I want to filter this matrix and project it to an (m,n) matrix by selecting for each j in 1:n a different k in 1:0.
For instance, I would like to retrieve (j,k) = {(1,2), (2,1)}, resulting in matrix G:
G = [5 2; 7 4];
This can be achieved with a for loop:
filter = [2 1]; % meaning filter (j,k) = {(1,2), (2,1)}
for i = 1:length(filter)
G(:,i) = squeeze(H(:,i,filter(i)));
end
But I'm wondering if it is possible to avoid the for loop via some smart indexing.
You can create all the linear indices to get such an output with the expansion needed for the first dimension with bsxfun. The implementation would look like this -
szH = size(H)
offset = (filter-1)*szH(1)*szH(2) + (0:numel(filter)-1)*szH(1)
out = H(bsxfun(#plus,[1:szH(1)].',offset))
How does it work
(filter-1)*szH(1)*szH(2) and (0:numel(filter)-1)*szH(1) gets the linear indices considering only the third and second dimension elements respectively. Adding these two gives us the offset linear indices.
Add the first dimenion linear indices 1:szH(1) to offset array in elementwise fashion with bsxfun to give us the actual linear indices, which when indexed into H would be the output.
Sample run -
H(:,:,1) =
1 2
3 4
H(:,:,2) =
5 6
7 8
filter =
2 1
out =
5 2
7 4

Given a cell array of vectors, delete vectors that are subsets of any other vector

I wanna delete all the subsets of cell c, suppose I have 6 cell vectors: c{1}=[1 2 3]; c{2}=[2 3 4];
c{3}=[1 2 3 4 5 6]; c{4}=[2 3 4 7]; c{5}=[2 3 7]; c{6}=[4 5 6]; then I wanna delete [1 2 3], [2 3 4] and [4 5 6]. I used two for loops to find all these subsets, but it's too slow for large datasets, is there any simple way can do this?
The following code removes a vector if it's a subset of any other vector. The approach is very similar to my answer to this other question:
n = numel(c);
[i1 i2] = meshgrid(1:n); %// generate all pairs of cells (their indices, really)
issubset = arrayfun(#(k) all(ismember(c{i1(k)},c{i2(k)})), 1:n^2); %// subset?
issubset = reshape(issubset,n,n) - eye(n); %// remove diagonal
c = c(~any(issubset)); %// remove subsets
Note that, in your example, [2 3 7] should also be removed.
You could find the cells that are exact matches for a particular input vector s1 using the following approach:
indx = find(cell2mat(cellfun(#(x)strcmp(num2str(x),num2str(s1)),c,'un', 0)));
You can then loop over matches (which should now be a much smaller set), and remove them by setting their contents to an empty set:
for ii=1:length(indx)
c{:,ii} = [];
end

How to use multidimensional constant array in for iterator block in matlab/simulink?

I have an array (300x6) and I want to use it for this block in simulink. But I have a problem. How can I use "for iterator" block to take the q(i,:), q(i+1,:) , q(i+2,:) ... elements respectively? Or is there any other way to do this idea? Thanks.
In Matlab, for iterates over matrix columns. So you can just transpose to iterate over rows:
A = [1 2 3; 4 5 6; 7 8 9]; %// example matrix
for v = A.'
v = v.'; %// v will be [1 2 3], then [4 5 6] etc
%// Do stuff with v
end
I'm not into Simulink but I guess you can adapt this to that environment.

Extract fixed amounts of data from array based on a list of indices

I have the array
a=1:20
and a series of indices which indicate where I want to start pulling data out:
i=[4,12]
For each index i, I want that index and the next four (well, x, really) elements in a column or row. I'll avoid getting to close to the end of the array, so that special case can be disregarded.
If I was hard-coding this, I could use:
a([4:8;12:16])
and this would achieve my result.
But i may have many different values.
Any thoughts on how I can transform a list of indices into a matrix of ranges, or other ways to solve this problem?
EDIT
I am using Matlab 2007; it would be preferable if the solution relied solely on Matlab's internals and toolboxes. bsxfun is not present until 2007a.
Let i be your indicesx and x the number of elements you want in addition to the elements in i, then you can use
i = [4 6 8];
x = 4;
bsxfun(#plus, 0:x, i(:))
to get a matrix of indices:
ans =
4 5 6 7 8
6 7 8 9 10
8 9 10 11 12
If you do not have access to bsxfun you can use repmat instead:
i = [4 6 8];
x = 4;
repmat(i(:), 1, x+1) + repmat(0:x, length(i), 1)
Here is a solution without bsxfun but with repmat inspired by the previous answer.
i = [4 6 8];
x = 4;
p = repmat(1:x,length(i),1);
q = repmat(i',1,x);
p+q

find max difference between elements in vector

I want to evaluate the difference (susbtraction) between all elements in a vector and have the maximum as a result.
For example with
[1 3 7]
the diffs are 2, 4 and 6, so that the result should be 6.
How can I do that with matlab in a clever way?
The maximum difference between any two elements in an array is the difference between the maximum and the minimum value of the array:
x = [1 3 7];
maxDifference = max(x) - min(x)
maxDifference =
6
You can do this.
x = [1 7 3]; % order doesn't matter
MaxDiff = range(x)
Something like this (tested in Octave):
x = [1 3 7];
max(abs(x - [x(2:end) x(1)]))