reducing matrices under certain conditions - matlab

M is a matrix 4x2000000 composed of several submatrix Ai such that Ai(1:3,j) is the same vector for j = 1,...,size(Ai,2). and Ai(4,j) are values between 1 and 100.
V = [2 15 21 43]
my goal is to eliminate all sub-matrix Ai of M, if Ai(4,:) does not contain all the values of V.
The only initial data for this problem are M and V
Example:
M = [1022 3001 4451 1022 1022 3001 1022 3001 3001 1022;
112 45 10 112 112 45 11 45 99 112;
500 11 55 500 500 11 88 11 1 500;
2 6 3 5 71 2 2 71 5 88]
A1 = [1022 1022 1022 1022;
112 112 112 112;
500 500 500 500;
2 5 71 88]
A2 = [3001 3001 3001;
45 45 45;
11 11 11;
6 2 71]
A3 = [4451;
10;
55;
3]
A4 = [1022;
11;
88;
2]
A5 =[3001;
99;
1;
5]
if V = [2 71]
The expected output (order of columns is not important):
[1022 1022 1022 1022 3001 3001 3001;
112 112 112 112 45 45 45;
500 500 500 500 11 11 11;
2 5 71 88 6 2 71]

One approach -
[~,~,idx] = unique(M(1:3,:)','rows') %//'
valid = ismember(M(4,:),V)
valid_idx = accumarray(idx(valid),M(4,valid).',[],#(x) ...
numel(unique(x)))>=numel(V) %//'
out = M(:,ismember(idx,find(valid_idx)))

Related

Using regress function on two dependent variables - Matlab

I having trying to run linear regression and plot the results on the below data.
x1 = [40 45 38 50 48 55 53 55 58 40 55 48 45 55 60 60 60 65 50 58];
x2 = [25 20 30 30 28 30 34 36 32 34 38 28 30 36 34 38 42 38 34 38];
y = [1 2 1 3 2 3 3 4 4 3 5 3 3 2 4 5 5 5 4 3];
I have attempted it with this code
X = [ones(size(x1)) x1 x2 (x1.*x2)];
b = regress(y, X);
scatter3(x1,x2,y,'filled')
I am getting this error
Error using regress
Y must be a vector and must have the same number of rows as X.
Both y and X have one row each so I am unsure how to go about this regression.
Any help is appreciated.

How to perform reduced row echelon form on a non-square GF matrix (GF(2^8)) in matlab

%GF(2^8)
m=8
mat1 = gf([160 28 233 185 176],8);
result1 = gf([160 28 233 185 176],8)/gf([160],8)
% 1 77 174 32 220
[R,jb] = rref([1 77 174 32 220;189 244 80 245 190])
I use the result from result1 as 1st row and progressively add the next row vector [189 244 80 245 190]
% reduced row echelon
mat2 = [1 77 174 32 220;189 244 80 245 190]
a = gf([1 77 174 32 220;189 244 80 245 190],8);
r2 = a(2,:); r1 = gf(189,8) * a(1,:);
subt = r2 -r1; a(2,:)= subt./gf(122,8);
a(1,:) = a(1,:)- (gf(77,8) *a(2,:));
disp(a)
mat3 = [[1 0 101 105 110]; [0 1 163 128 97]; [157 233 247 64 118]];
m3 = gf(mat3,8);
m3(3,:)= m3(3,:) - (gf(157,8) * m3(1,:))
m3(3,:)= m3(3,:) - (gf(233,8) * m3(2,:))
m3(3,:)= m3(3,:)./ gf(29,8) .
rref works without GF(2^8). But I am unable to perform the reduction using GF(2^8) . Can someone help me to find a solution and how to proceed?
I will be using the result from the above and append another row-vector to the it. Is there any function we can solve it, instead of going step-by-step

reducing matrices under certain conditions - Part 2 -

This question is more complex than my previous question because here V is a cell
M is a matrix 4x2000000 composed of several submatrix Ai such that Ai(1:3,j) is the same vector for j = 1,...,size(Ai,2). and Ai(4,j) are values between 1 and 100.
V = {V1,V2,...,Vn} (V1 or V2 or ...Vn)
V1,V2,... and Vn have different sizes.
my goal is to eliminate all sub-matrix Ai of M, if Ai(4,:) does not contain all the values of V1 or V2 or ...Vn.
The only initial data for this problem are M and V
I wanted to use a for loop with the answer of the question here, but I noticed that the calculation time increases with the size of V.
Example:
M = [1022 3001 4451 1022 1022 3001 1022 3001 3001 1022 1055 1055 1055 1055 1055 1055;
112 45 10 112 112 45 11 45 99 112 11 11 11 11 11 11;
500 11 55 500 500 11 88 11 1 500 45 45 45 45 45 45;
2 6 3 5 71 2 2 71 5 88 8 15 21 94 10 33]
A1 = [1022 1022 1022 1022;
112 112 112 112;
500 500 500 500;
2 5 71 88]
A2 = [3001 3001 3001;
45 45 45;
11 11 11;
6 2 71]
A3 = [4451;
10;
55;
3]
A4 = [1055 1055 1055 1055 1055 1055;
11 11 11 11 11 11;
45 45 45 45 45 45;
8 15 21 94 10 33]
A5 =[3001;
99;
1;
5]
if V = {[2 71],[3],[15 94 33 10]}
The expected output (order of columns is not important):
[1022 1022 1022 1022 3001 3001 3001 4451 1055 1055 1055 1055 1055 1055;
112 112 112 112 45 45 45 10 11 11 11 11 11 11;
500 500 500 500 11 11 11 55 45 45 45 45 45 45;
2 5 71 88 6 2 71 3 8 15 21 94 10 33]
See if this works for you -
%// ID columns of M based on the uniquenes of the first thre rows
[~,~,idx] = unique(M(1:3,:).','rows') %//'
%// Lengths of each V cell
lens = cellfun('length',V)
%// Setup ID array for use with ACCUMARRAY later on
id = zeros(1,sum(lens))
id(cumsum(lens(1:end-1))+1) = 1
id = cumsum(id)+1
%// Collect all cells of V as a 1D numeric array
Vn = [V{:}]
%// Counts of number of elements for each cell/groups of V
counts_V = histc(id,1:numel(V))
%// Function handle to detect for if the input would satisfy the crietria
%// of all its values belong to either V1 or V2 or ...Vn
func1 = #(x) any(counts_V == histc(id(ismember(Vn,x)),1:numel(V)))
%// For each ID in "idx", see if it satisfies the above mentioned criteria
matches = accumarray(idx(:),M(4,:)',[], func1 ) %//'
%// Use the "detections" for selecting the valid columns from M
out = M(:,ismember(idx,find(matches)))

How to divide odd matrix into cell in Matlab

consider i have an odd matrix with dimension:
x = <349*385 double>
and then i do this following step:
order = [1 9 2 3 10 17 25 18 11 4 5 12 19 26 33 ...
41 34 27 20 13 6 7 14 21 28 35 42 49 57 50 ...
43 36 29 22 15 8 16 23 30 37 44 51 58 59 52 ...
45 38 31 24 32 39 46 53 60 61 54 47 40 48 55 ...
62 63 56 64];
x = double(x);
y = im2col(x, [8 8],'distinct');
xb = size(y, 2);
y = y(order, :);
y = y(:)';
I get y :
y = <64x2156 double>
xb = 2156;
y = <1x137984 double>
and I transform y into cell :
for i=1:length(x)
r{i} = y(floor((end/length(x))*(i-1)+1):ceil((end/length(x))*i));
end
finally i reverse r into matrix :
y1 = cell2mat(r);
I get y1 :
y1 = <1x138308 double>
My question is why y1 can't get the same result with y? I want y1 and y same. Maybe i wrong when dividing matrix y into cell r. Please help me.

sum over a matrix with condition in matlab

assume I have a 10x10 matrix M
M=[64 36 50 87 22 45 37 23 68 88;
33 23 87 49 54 25 35 98 78 52;
12 54 76 43 24 87 54 98 45 34;
77 87 23 45 34 65 23 76 12 76;
12 34 55 44 76 98 93 23 54 67;
22 55 78 90 88 56 34 23 12 76;
99 23 67 89 34 23 12 87 45 23;
22 54 76 89 65 23 45 12 93 12;
44 56 23 88 67 14 15 67 34 12;
11 44 77 99 34 23 78 34 12 79];
I want to first find out the local maximum in the matrix
and then according to the maximum position do a sum over a 3x3 region over M
For the first step, the code I used is local_max=imregionalmax(M). to find out the local maximum position, but how can I go further to use this coordination to sum over a 3x3 matrix over M?
Thanks for the help.
You can calculate the sum for the whole matrix and then only keep the values that you're interested in. This should work:
local_max=imregionalmax(M)
sums = imfilter(M, ones(3));
local_max_sums = sums(local_max);
And if what you want is a matrix with non-zero entries where the local maxima are located:
local_max_sums = sums .* local_max;
You seem to be looking for the matrix subset functionality of Matlab.
Basically, for
M = [ 1 2 3 4 5 6;
4 5 6 7 8 9;
7 8 9 0 1 2;
0 1 2 3 4 5;
3 4 5 6 7 8;
6 7 8 9 0 1];
If you have a max at (3,3), you can use M(2:4, 2:4) to get
N = [ 5 6 7;
8 9 0;
1 2 3];
Summing that matrix is all that remains - as simple as
total = sum(N(:));
This is kind of brute force for Matlab, but I think it works.
bw = imregionalmax(M);
[x,y] = find(bw);
s = [];
for i = 1:length(x)
startX = x(i)-2;
if(startX < 1)
startX = 1;
end
endX = x(i)+2;
if endX > 10
endX = 10;
end
startY = y(i)-2;
if startY < 1
startY = 1;
end
endY = y(i)+2;
if endY > 10
endY = 10;
end
s(i) = sum2(M(startX:endX, startY:endY));
end