Matlab Equivalent of sortrows for columns - matlab

To sort a matrix according to all columns except the first, I used the following code. I do not want sortrows to consider the first column because that is meant to keep track of the row numbers.
B = [1 1 0 0 0 0 0 0 0 1
2 0 1 0 0 0 0 1 0 0
3 0 0 1 0 1 0 0 1 0
4 0 1 0 0 0 1 1 0 0
5 0 0 1 0 0 0 0 1 0
6 0 0 0 0 0 1 1 0 0
7 1 0 0 1 0 0 0 0 0
8 0 0 1 0 1 0 0 0 0];
D = -sortrows(-B,[2:size(B,2)])
What if you want to sort the matrix according to all rows except the first, so the first element of each column would be ignored when sorting them in descending order? Is there any similar function to sortrows?
To clarify, the desired output is
1 0 0 0 0 0 0 1 0 1
2 1 1 0 0 0 0 0 0 0
3 0 0 1 1 1 0 0 0 0
4 1 1 0 0 0 1 0 0 0
5 0 0 1 1 0 0 0 0 0
6 1 0 0 0 0 1 0 0 0
7 0 0 0 0 0 0 1 1 0
8 0 0 1 0 1 0 0 0 0

You can do this via
transposing the input and output
keeping column 1 separate
you can use negative sort indices to avoid what you've done making the input and output negative
A = [B(:,1) sortrows( B(:,2:end).', -(2:size(B,1)) ).'];
>> A
A =
1 0 0 0 0 0 0 1 0 1
2 1 1 0 0 0 0 0 0 0
3 0 0 1 1 1 0 0 0 0
4 1 1 0 0 0 1 0 0 0
5 0 0 1 1 0 0 0 0 0
6 1 0 0 0 0 1 0 0 0
7 0 0 0 0 0 0 1 1 0
8 0 0 1 0 1 0 0 0 0

Related

Simulate obstacles in logical matrix

I'm writing an optimal path planning algorithm for one of my projects, and am a bit stuck on how to generate the map. In order to test my algorithm, I want to generate random maps that the object will pass through with obstacles in the way. To generate the maps I am making a logical array with "1" for wall or obstacle and "0" when there is nothing in the way. I am having some issues placing the obstacles however.
For now, this is what I've written in MATLAB (though I think the core idea can be solved in any language):
% lenx = length in x-direction of map [m]
% leny = length in y-direction of map [m]
% numObs = number of obstacles
% obsLoc = 2D array with the central location(s) of the obstacle(s)
% [x1, y1; x2 y2; ...]
% obsSize = size of the obstacles (all same size) [m]
% assume the obstacles are square.
% res = resolution of the map [cell/m]
%
% Outputs:
% map = 2D logical array which translates into a map
%
%---------------------------------------------------------
function map = createMap(lenx, leny, numObs, obsLoc, obsSize, res)
%Making map of the given size
map = zeros(leny*res, lenx*res);
%Adding walls
map(:,1) = 1;
map(:, lenx*res) = 1;
map(1,:) = 1;
map(leny*res, :) = 1;
%Recalculating obstacle size for this grid
obsSize = obsSize - 1;
%Adding obstacles
for i = 1:1:numObs
map(obsLoc(i,1)*res-obsSize*res:obsLoc(i,1)*res+obsSize*res,...
obsLoc(i,2)*res-obsSize*res:obsLoc(i,2)*res+obsSize*res) = 1;
end
end
The obsSize parameter is representing the dimension of one of the sides of the square obstacle. Here is a sample solution I ran:
>> createMap(10,10,1,[5,5],1,1)
ans =
1 1 1 1 1 1 1 1 1 1
1 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 1
1 0 0 0 1 0 0 0 0 1
1 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 1
1 1 1 1 1 1 1 1 1 1
Looks good! But the issue begins for obstacle sizes and resolutions that are not 1 or 2...
>> createMap(10,10,1,[5,5],0.5,2)
ans =
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
>> createMap(10,10,1,[5,5],3,2)
ans =
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1
1 0 0 0 0 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1
1 0 0 0 0 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1
1 0 0 0 0 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1
1 0 0 0 0 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1
1 0 0 0 0 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1
1 0 0 0 0 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1
1 0 0 0 0 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1
1 0 0 0 0 1 1 1 1 1 1 1 1 1 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
For the first one, we would expect there to be a 1 somewhere close to the middle, but it's nowhere to be found. In the second one, we'd expect to find 6 ones in each direction (3m * 3cell/m = 6 cell), but we are getting 8 (It's also possible that this is not what my code is calculating, but this is what I'm hoping it does. Neither case is working, and I think it has to do with this line:
Recalculating obstacle size for this grid
obsSize = obsSize - 1;
I'm pretty sure I do have to recalculate the object size so it fits to the grid, but how can I do this for any grid and obstacle? Is there a way to scale that "-1" such that it acts according to the size of the grid/obstacle?
Let me know what you come up with, and if there's any other glaring issues in my code?
Thanks!

MxN matrix with ones and zeros following a specific rule

I want to create a MxN matrix as shown below:
[1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0;
0 0 0 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0;
0 0 0 0 0 0 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0;
0 0 0 0 0 0 0 0 0 1 1 1 1 1 0 0 0 0 0 0 0 0 0;
0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 0 0 0 0 0 0;
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 0 0 0;
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1]
I have window size, let's say, 5 and it moves 3 in every row. Is it possible to create such a matrix without using for loops? Or is there any optimum way to do it?
This is a one line solution:
reshape([reshape([ones(5,6);zeros(21,6)], 1,[]), ones(1,5)],[],7).'
note:
The desired matrix can be seen as concatenation of a [6, 5+21] matrix:
1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
and a [1 ,5] matrix:
1 1 1 1 1
that reshaped to a [7 , 23] matrix.
Other solution using repelem + bsxfun + accumarray:
r = repelem (1:7,5);
c= bsxfun(#plus, ((1:5)-3).',3*(1:7));
out = accumarray([r(:) c(:)] ,1)
Indices of rows and columns of 1 s can be generated and accumarray can be used to create the desired matrix.

Advanced Search and Remove in special Matrix

I have this matrix
X= [2 0 0 0 0 0 1 0 0 0 0 0 1 1 0 0 0 0 0 1 0 1 250;
3 0 0 1 0 1 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 1 250;
2 0 0 0 0 0 1 0 0 0 0 0 1 1 0 0 0 0 0 1 0 1 250;
3 0 0 1 0 1 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 1 250;
4 0 0 1 0 1 0 0 1 0 0 0 0 0 1 1 0 0 0 0 0 0 250;
3 0 0 1 0 1 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 1 250;
2 0 0 0 0 0 1 0 0 0 0 0 1 1 0 0 0 0 0 1 0 1 250;
4 0 0 1 0 0 0 0 1 0 0 0 0 0 0 1 1 1 0 0 0 0 250;
3 0 0 1 0 1 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 1 250;
3 1 1 1 0 0 1 0 0 1 0 0 1 0 0 0 0 1 0 1 0 0 400]
I need to do three different sequence things in this matrix:
1- Search in this matrix to the following sequence 1 1 0 0 0 and write those rows that have this characteristic in new matrix (like row 1).
2- Use the matrix that generate in the first step and remove from it to the rows that have the same number in the same digits (like row 1,3,7) but at the same time keep only one row of each one (in the case of row 1,3,7 keep row 1 and remove other rows) .
3- use the matrix that generate in the second step and remove from this matrix any row that have following sequence 1 1 1 (like row 8) and put the other rows in this matrix in new matrix.
%Step-1
% Converting the matrix into a string, appending a semi-colon for similarity and removing the brackets from the string
req=mat2str(X); req(end)=';' ; req=req(2:end);
% Searching the sequence: 1 1 0 0 0
sp1=strfind(req, '1 1 0 0 0');
% Storing those rows of X in req matrix which contain the sequence
req=X(unique(ceil([sp1]/(size(req,2)/size(X,1)))),:);
%Step-2
req= unique(req,'rows');
%Step-3
% Converting the matrix into a string, appending a semi-colon for similarity and removing the brackets from the string
reqtemp=mat2str(req); reqtemp(end)=';' ; reqtemp=reqtemp(2:end);
% Searching the sequence: 1 1 1
sp1=strfind(reqtemp, '1 1 1');
% Removing those rows which contain the sequence
req(unique(ceil([sp1]/(size(reqtemp,2)/size(req,1)))),:)=[];

MATLAB: how to "equally distribute" the Trues in each column of a full lower triangular logical matrix over the columns of m new matrices?

My first question on stackoverflow! The title is vague, so let me elaborate: I have a NxN lower triangular logical matrix
N = 10 % for example
L = tril(true(N),-1)
L =
0 0 0 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0 0 0
1 1 0 0 0 0 0 0 0 0
1 1 1 0 0 0 0 0 0 0
1 1 1 1 0 0 0 0 0 0
1 1 1 1 1 0 0 0 0 0
1 1 1 1 1 1 0 0 0 0
1 1 1 1 1 1 1 0 0 0
1 1 1 1 1 1 1 1 0 0
1 1 1 1 1 1 1 1 1 0
with all trues below the diagonal. For a m=2^p a power of 2, I want to end up with m NxN lower triangular logical matrices L_1, ..., L_m such that each column of L_i contains the i-th 1/m-th (rounded) number of the Trues in the corresponding column in L. One consequence is that \sum_i(L_i) == L again.
For example, for m = 2 I know that
L_2 = L(:,ceil((N:2*N-1)/2))
L_2 =
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0 0 0
1 1 1 0 0 0 0 0 0 0
1 1 1 1 1 0 0 0 0 0
1 1 1 1 1 1 1 0 0 0
1 1 1 1 1 1 1 1 1 0
L_1 = L - L_2
L_1 =
0 0 0 0 0 0 0 0 0 0
1 0 0 0 0 0 0 0 0 0
1 1 0 0 0 0 0 0 0 0
1 1 1 0 0 0 0 0 0 0
1 1 1 1 0 0 0 0 0 0
0 1 1 1 1 0 0 0 0 0
0 0 0 1 1 1 0 0 0 0
0 0 0 0 0 1 1 0 0 0
0 0 0 0 0 0 0 1 0 0
0 0 0 0 0 0 0 0 0 0
will do the trick, but this trick does not generalize to higher powers of 2 for m. Any ideas how to do this reasonably fast for general N and m = 2^p?
(Context: each column of L are logical indices for a bisection type algorithm. Every next power p of m = 2^p corresponds to a deeper level of the bisection algorithm)

Matlab: keeping non-zero matrix elements adjacent to each other and ignoring lone elements

Here is an example matrix (but the result shouldn't be constrained to only working on this):
a=zeros(7,7);
a(5,3:6)=1;
a(2,2)=1;
a(2,4)=1;
a(7,1:2)=1
a=
0 0 0 0 0 0 0
0 1 0 1 0 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 0 1 1 1 1 0
0 0 0 0 0 0 0
1 1 0 0 0 0 0
I want to get rid of all the 1's that are alone (the noise), such that I only have the line of 1's on the fifth row.
rules:
-the 1's are in 'connected lines' if there are adjacent 1's (including diagonally) e.g.:
0 0 0 1 0 0 1 0 1
1 1 1 0 1 0 0 1 0
0 0 0 0 0 1 0 0 0
(The connected lines are what I want to keep. I want to get rid of all the 1's that are not in connected lines, the connected lines can intersect each other)
the 'connected lines need to be at least 3 elements long. So in the 7x7 example, there would only be one line that matches this criteria. If a(7,3) was set to 1, then there would be a connected line at the bottom left also
I am currently looking at this through a column by column approach, and here is the first draft of my code so far:
for nnn=2:6
rowPoss=find(a(:,nnn)==1);
rowPoss2=find(a(:,nnn+1)==1);
for nn=1:length(rowPoss)
if myResult(rowPoss(nn)-1:rowPoss(nn)+1,n-1)==0 %
%then?
end
end
end
My difficulty is, during this column by column process, I'd have to enable a way to recognise the beginning of the connected line, the middle of the connected line, and when a connected line ends. The same rules for this, when applied to noise (the lone 1's), would just ignore the lone 1's.
The output I want is basically:
b=
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 0 1 1 1 1 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
If you have image processing toolbox, try bwareaopen
b = bwareaopen(a, 3);
Sample Run #1:
>> a
a =
0 0 0 0 0 0 0
0 1 0 1 0 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 0 1 1 1 1 0
0 0 0 0 0 0 0
1 1 0 0 0 0 0
>> b
b =
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 0 1 1 1 1 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
Sample Run #2:
>> a
a =
0 0 0 0 0 0 0
0 1 0 1 0 0 0
0 0 1 0 0 0 0
0 0 0 0 0 0 0
0 0 1 1 1 1 0
0 0 0 0 0 0 0
1 1 0 0 0 0 0
>> b
b =
0 0 0 0 0 0 0
0 1 0 1 0 0 0
0 0 1 0 0 0 0
0 0 0 0 0 0 0
0 0 1 1 1 1 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0