Matching two matrices depending on diagonal elements of two matrices in matlab - arrays

Below are the two adjacency matrices.I have to find which row of matrix1 is correspond to which row in matrix2 depending on diagonal values.In below example
1st row=1st row(diagonal value=4)
2nd row=5th row(diagonal value=5)
3rd row=4th row(diagonal value=1)
4th row=2nd row(diagonal value=3)
5th row=3rd row(diagonal value=2)
4 4 1 3 2
4 5 1 3 2
1 1 1 1 1
3 3 1 3 2
2 2 1 2 2
4 3 2 1 4
3 3 2 1 3
2 2 2 1 2
1 1 1 1 1
4 3 2 1 5
How it can be done in matlab?

Use the second output of ismember:
[~, result] = ismember(diag(matrix1), diag(matrix2))
In your example, this returns
result =
1
5
4
2
3

Assuming mat1 and mat2 to be the first and second matrices respectively and that you are looking to find the first match of diagonal values, try this -
[~,ind] = max(bsxfun(#eq,diag(mat2),diag(mat1)'))
or
[~,ind] = max(bsxfun(#eq,diag(mat1),diag(mat2)'),[],2)
If you are certain that there are always unique matches, you can use find too -
[ind,~] = find(bsxfun(#eq,diag(mat2),diag(mat1)'))

Related

How to remove reverse rows in a permutation matrix?

I'm looking for a quick way in MATLAB to do the following:
Given a permutation matrix of a vector, say [1, 2, 3], I would like to remove all duplicate reverse rows.
So the matrix P = perms([1, 2, 3])
3 2 1
3 1 2
2 3 1
2 1 3
1 3 2
1 2 3
becomes
3 2 1
3 1 2
2 3 1
You can noticed that, symetrically, the first element of each rows have to be bigger than the last one:
n = 4; %row size
x = perms(1:n) %all perms
p = x(x(:,1)>x(:,n),:) %non symetrical perms
Or you can noticed that the number of rows contained by the p matrix follows this OEIS sequence for each n and correspond to size(x,1)/2 so since perms output the permutation in reverse lexicographic order:
n = 4; %row size
x = perms(1:n) %all perms
p = x(1:size(x,1)/2,:) %non symetrical perms
You can use MATLAB's fliplr method to flip your array left to right, and then use ismember to find rows of P in the flipped version. At last, iterate all locations and select already found rows.
Here's some code (tested with Octave 5.2.0 and MATLAB Online):
a = [1, 2, 3];
P = perms(a)
% Where can row x be found in the left right flipped version of row x?
[~, Locb] = ismember(P, fliplr(P), 'rows');
% Set up logical vector to store indices to take from P.
n = length(Locb);
idx = true(n, 1);
% Iterate all locations and set already found row to false.
for I = 1:n
if (idx(I))
idx(Locb(I)) = false;
end
end
% Generate result matrix.
P_star = P(idx, :)
Your example:
P =
3 2 1
3 1 2
2 3 1
2 1 3
1 3 2
1 2 3
P_star =
3 2 1
3 1 2
2 3 1
Added 4 to the example:
P =
4 3 2 1
4 3 1 2
4 2 3 1
4 2 1 3
4 1 3 2
4 1 2 3
3 4 2 1
3 4 1 2
3 2 4 1
3 2 1 4
3 1 4 2
3 1 2 4
2 4 3 1
2 4 1 3
2 3 4 1
2 3 1 4
2 1 4 3
2 1 3 4
1 4 3 2
1 4 2 3
1 3 4 2
1 3 2 4
1 2 4 3
1 2 3 4
P_star =
4 3 2 1
4 3 1 2
4 2 3 1
4 2 1 3
4 1 3 2
4 1 2 3
3 4 2 1
3 4 1 2
3 2 4 1
3 1 4 2
2 4 3 1
2 3 4 1
As demanded in your question (at least from my understanding), rows are taken from top to bottom.
Here's another approach:
result = P(all(~triu(~pdist2(P,P(:,end:-1:1)))),:);
pdist computes the distance between rows of P and rows of P(:,end:-1:1).
~ negates the result, so that true corresponds to coincident pairs.
triu keeps only the upper triangular part of the matrix, so that only one of the two rows of the coincident pair will be removed.
~ negates back, so that true corresponds to non-coincident pairs.
all gives a row vector with true for rows that should be kept (because they do not coincide with any previous row).
This is used as a logical index to select rows of P.

Creating multidimensional shifting array using a vectorize approach instead of FOR loop

I can "Vectorize" the circshift command but I'm having trouble adding dimensions to it.
See code below with working FOR loop that I'm trying to vectorize using dimensions
clear all,clf reset,tic,clc , close all
function [outMat] = vectcircshift(vectToShift,shiftVector)
%This function generates a matrix where each row is a circshift of the
%original vector from the specified interval in the shiftVector;
%
%Inputs
%vectToShift: is the original vector you want to circshift multiple times
%shiftVector: is the vector of the circshift sizes;
%
%Outputs
%outMat: is a matrix were every row is circshift by the amount in the
% shiftVector
[n,m]=size(vectToShift);
if n>m
inds=(1:n)';
i=toeplitz(flipud(inds),circshift(inds,[1 0]));
outMat=vectToShift(i(shiftVector,:));
outMat=circshift(outMat,[0,-1]); %shift to include original signal first
else
inds=1:m;
i=toeplitz(fliplr(inds),circshift(inds,[0 1]));
outMat=vectToShift(i(shiftVector,:));
outMat=circshift(outMat,[0,-1]); %shift to include original signal first
end
end
%%----Working FOR LOOP below I'm trying to vectorize.
ndim=0;
ndim_tot=[1:3] %total dimensions
for ndim=1:length(ndim_tot)
ndim=ndim+0
if ndim==1
array_sort(ndim,:)=circshift(ndim_tot,[0 ndim-1]) %start at row of sort array
else
array_sort(ndim,:)=circshift(ndim_tot,[0 mod(-ndim,length(ndim_tot))+1]) %next start of row of sort array
endif
array_sort= array_sort(ndim,:)
array_dim(:,:,ndim)=vectcircshift([1:5],array_sort)
endfor
I tired the syntax below but that logic won't work.
ndim_tot=[1:3]; %number of dimensions
array_dim2(:,:,ndim_tot)=vectcircshift([1:5],[1:3])
I get an error nonconformant arguments(op1 is 0x0x1, op2 is 3x5)
My goal is to create a multidimensional array that circshifts a signal / array and also creates and shifts it in multiple dimensions.
Example: of what the multidimensional array would look like
if I start with a signal / array a1=[1 2 3 4 5]
I'm trying to have it create.
array_dim(:,:,1)=
[
1 2 3 4 5
5 1 2 3 4
4 5 1 2 3
]
array_dim(:,:,2)=
[
5 1 2 3 4
4 5 1 2 3
1 2 3 4 5
]
array_dim(:,:,3)=
[
4 5 1 2 3
1 2 3 4 5
5 1 2 3 4
]
Please note: the the numbers won't be sequential I just used it as an example to help explain things a little easier.
PS: I'm using Octave 4.2.2
Not clear why you are shifting in mod 3, but here is a loop assignment using shift
a1=[1 2 3 4 5];
array_dim=zeros(3,5,3);
for i=0:2
array_dim(:,:,i+1)=[shift(a1,i);
shift(a1,mod(i+1,3));
shift(a1,mod(i+2,3))];
endfor
array_dim
and the output fits your example
array_dim =
ans(:,:,1) =
1 2 3 4 5
5 1 2 3 4
4 5 1 2 3
ans(:,:,2) =
5 1 2 3 4
4 5 1 2 3
1 2 3 4 5
ans(:,:,3) =
4 5 1 2 3
1 2 3 4 5
5 1 2 3 4

Convert output of ndgrid to a single array

I want to create an n-dimensional grid from vectors xi which specify the desired grid points in dimension i. The output should be a single N x n matrix, where N=b1*b2*b3*...*bn is the total number of grid points, and bi is the number of desired grid points along that dimension. (I want to do this in Matlab.)
I know that I can use the ndgrid function to create this n-dimensional grid, but ndgrid returns n cell arrays, each of dimension b1xb2xb3x...xbn. How can I transform this to a single array, as desired?
An additional complication: I do not know the dimension n in advance.
David already got the idea in his comment, just a minor error for n>=4.
function grid_array = ndgridarr(n, varargin)
assert(length(varargin) == 1 || length(varargin) == n);
grid_cells = cell(1, n);
[grid_cells{:}] = ndgrid(varargin{:});
grid_array = reshape(cat(n+1,grid_cells{:}),[],n);
end
An alternative is to use allcomb from file exchange or
combvec (Deep learning toolbox). They both already return a single matrix, no need to stich the cell array together.
Here's one possible solution. I'd be very happy to hear about simpler approaches.
function grid_array = ndgridarr(n, varargin)
assert(length(varargin) == 1 || length(varargin) == n);
grid_cells = cell(1, n);
[grid_cells{:}] = ndgrid(varargin{:});
grid_array = cell2mat(cellfun(#(c) c(:), grid_cells, 'UniformOutput', false));
end
You can call this function exactly like you would ndgrid, just with the additional input parameter n. (ngrid infers n automatically from the number of output arguments in the case when just a single vector is provided, but we cannot do this since we have only one output parameter in any case.)
Two examples illustrating that it does what's desired:
>> ndgridarr(3, [1,2,3])
ans =
1 1 1
2 1 1
3 1 1
1 2 1
2 2 1
3 2 1
1 3 1
2 3 1
3 3 1
1 1 2
2 1 2
3 1 2
1 2 2
2 2 2
3 2 2
1 3 2
2 3 2
3 3 2
1 1 3
2 1 3
3 1 3
1 2 3
2 2 3
3 2 3
1 3 3
2 3 3
3 3 3
>> ndgridarr(3, [1,2], [3,4], [5,6])
ans =
1 3 5
2 3 5
1 4 5
2 4 5
1 3 6
2 3 6
1 4 6
2 4 6

Eliminate repeated vectors but with elements on different order

I have a matrix A which is (243 x 5). I want to pick the unique row vectors of that matrix but taking into account that row vectors with the same elements but in different order shall be considered as being the same.
E.g., suppose for simplicity that the A matrix is (10 x 5) and equal to:
A=[1 2 1 2 3
1 3 1 1 1
1 3 1 1 2
1 2 1 1 3
2 3 1 2 1
1 3 1 2 2
1 3 1 2 3
1 3 1 3 2
1 3 1 3 1
1 3 2 3 1]
On the example above, rows (1, 5, 6) are to be considered equivalent they have the same elements but in different order. Also, rows (3 and 4) are equivalent, and rows (7, 8, 10) are also equivalent.
Is there any way to write a code that removes all "repeated rows", i.e. a code that delivers only the rows (1, 2, 3, 7 and 9) from A?
So far I came across with this solution:
B(:,1) = sum(A == 1,2);
B(:,2) = sum(A == 2,2);
B(:,3) = sum(A == 3,2);
[C, ia, ic] = unique(B,'rows');
Result = A(ia,:);
This delivers what I am looking for with one caveat - it is delivering the unique rows of A according to the criteria defined above, but it is not delivering the first row it finds. I.e. instead of delivering rows (1,2,3,7,9) it is delivering rows(7, 1, 9, 3, 2).
Anyway I can force him to deliver the rows in correct order? Also any better way of doing this?
You can do it as follows:
Sort A along the second dimension;
Get stable indices of unique (sorted) rows;
Use the result as row indices into the original A.
That is:
As = sort(A, 2);
[~, ind] = unique(As, 'rows', 'stable');
result = A(ind,:);
For
A = [1 2 1 2 3
1 3 1 1 1
1 3 1 1 2
1 2 1 1 3
2 3 1 2 1
1 3 1 2 2
1 3 1 2 3
1 3 1 3 2
1 3 1 3 1
1 3 2 3 1];
this gives
result =
1 2 1 2 3
1 3 1 1 1
1 3 1 1 2
1 3 1 2 3
1 3 1 3 1

All row-combinations of a matrix in a new matrix with matlab

I have got a question regarding all the combinations of matrix-rows in Matlab.
I currently have a matrix with the following structure:
1 2
1 3
1 4
2 3
2 4
3 4
Now I want to get all the possible combinations of these "pairs" without using a number twice in the same row:
1 2 3 4
1 3 2 4
1 4 2 3
And it must be possible to make it with n-"doublecolumns". Which means, when my pair-matrix goes for example until "5 6", i want to create the matrix with 3 of these doublecolumns:
1 2 3 4 5 6
1 2 3 5 4 6
1 2 3 6 4 5
1 3 2 4 5 6
1 3 2 5 4 6
....
I hope you understand what I mean :)
Any ideas how to solve this?
Thanks and best regard
Jonas
M = [1 2
1 3
1 4
2 3
2 4
3 4]; %// example data
n = floor(max(M(:))/2); %// size of tuples. Compute this way, or set manually
p = nchoosek(1:size(M,1), n).'; %'// generate all n-tuples of row indices
R = reshape(M(p,:).', n*size(M,2), []).'; %// generate result...
R = R(all(diff(sort(R.'))),:); %'//...removing combinations with repeated values

Resources