I'm trying to write a program to check the results of all possible combinations of 5 separate 5x5 matrices, where each element in all the matrices are booleans. However, my problem is I can't figure out a way to cause the matrices to check through every combination.
Illustrating what I would like to happen for a 2x2 matrix. I want my program to produce the matrix as follow:
(1) [0 0;0 0]
(2) [1 0;0 0]
(3) [1 1;0 0]
(4) [1 1;1 0]
(5) [1 1;1 1]
(6) [1 0;0 1]
(7) [1 1;0 1]
…
and so on until every possible matrix has been done. How I may achieve this, so that I do some operation with every one of these matrix combinations?
(I realise this will probably take an impossibly long time to completely cycle through 5 5x5 matrices, however I also wish to do it for smaller matrices (3 3x3's) and I would also like to just leave it running as long as possible to check through as many possible 5 5x5's and seeing, out of the ones I've checked, which is the best result.)
So, as you can see, you have several combinations of a zero matrix you want to add a one, right?
We could say that you have the following possible combinations you want to add a one. For the 2 dimensional case:
addOnes =
Empty matrix: 1-by-0
onePossibleCombination =
0 0
0 0
addOnes =
1
onePossibleCombination =
1 0
0 0
addOnes =
2
onePossibleCombination =
0 0
1 0
addOnes =
3
onePossibleCombination =
0 1
0 0
addOnes =
4
onePossibleCombination =
0 0
0 1
addOnes =
1 2
onePossibleCombination =
1 0
1 0
addOnes =
1 3
onePossibleCombination =
1 1
0 0
addOnes =
1 4
onePossibleCombination =
1 0
0 1
addOnes =
2 3
onePossibleCombination =
0 1
1 0
addOnes =
2 4
onePossibleCombination =
0 0
1 1
addOnes =
3 4
onePossibleCombination =
0 1
0 1
addOnes =
1 2 3
onePossibleCombination =
1 1
1 0
addOnes =
1 2 4
onePossibleCombination =
1 0
1 1
addOnes =
1 3 4
onePossibleCombination =
1 1
0 1
addOnes =
2 3 4
onePossibleCombination =
0 1
1 1
addOnes =
1 2 3 4
onePossibleCombination =
1 1
1 1
How can we achieve that? All we need is to take all combinations taken by 0, 1, 2, 3 and 4. For that we use the nchoosek method as follows:
matrixSize = 2;
for k=0:matrixSize^2
combinations=nchoosek(1:matrixSize^2,k);
for m = 1:size(combinations,1)
addOnes = combinations(m,:);
onePossibleCombination = zeros(matrixSize,matrixSize);
onePossibleCombination(addOnes) = 1;
% Do your operation here with the matrix onePossibleCombination
end
end
Related
In Matlab, im looking for a way to solve the following issue in an a bit more elegant way:
In an threedimensional array, on one dimension (i.e. time in my case), from some index on all values equal zero, e.g. the following example array a is 0 for an index of 3 for the second dimension (i.e. a(:,3:end,: == 0)):
a(:,:,1) =
1 1 0
1 0 0
1 0 0
a(:,:,2) =
1 1 0
1 0 0
1 1 0
a(:,:,3) =
1 1 0
1 1 0
1 1 0
[edit, was asked for expected outcome]
expected outcome is:
o(:,:,1) =
1 1
1 0
1 0
o(:,:,2) =
1 1
1 0
1 1
o(:,:,3) =
1 1
1 1
1 1
now of course i could just check for each index in dimension 2, whether it actually is zero everywhere, which is what i'm doing right now, but i feel like there is some better way of solving this issue in matlab in some more elegant way (and possibly even for any multidimensional array). Thanks for helping!
function req = removeColwithSpecVal(a,spec_val)
req=num2cell(a,[1 2]); %Converting to cell keeping the order of rows & columns same
req=vertcat(req{:}); %Stacking multidimensional slices vertically
ind= ~all(req==spec_val,1);%Finding logical indices of the required columns
req = req(:,ind); %The matrix after removal of the not required columns
%Finding the size of the input matrix 'a'; stacking with 1 so that
%it is applicable on 1-D/2-D matrices as well
sz =[size(a) 1];
%Finding the # of columns that the required multi-dimensional matrix will have
sz(2)= numel(req)/prod([sz(1), sz(3:end)]);
%Reshaping to the desired result
req=reshape(permute(reshape(req.', sz(2),sz(1),[]),[2 1 3]),sz);
end
Sample Runs:
%1-D Example
spec_val=5;
a=[1 4 5 2 5];
req = removeColwithSpecVal(a,spec_val)
req =
1 4 2
%2-D Example
spec_val=0;
a=[1 1 0 ;
1 0 0 ;
1 0 0 ];
req = removeColwithSpecVal(a,spec_val)
req =
1 1
1 0
1 0
%Your example (3-D)
spec_val=0;
a(:,:,1) = [1 1 0;
1 0 0;
1 0 0];
a(:,:,2) = [1 1 0;
1 0 0;
1 1 0];
a(:,:,3) = [1 1 0;
1 1 0;
1 1 0];
req = removeColwithSpecVal(a,spec_val)
req(:,:,1) =
1 1
1 0
1 0
req(:,:,2) =
1 1
1 0
1 1
req(:,:,3) =
1 1
1 1
1 1
Also applicable on higher dimensional matrices.
I'm attempting to find a critical point in a matrix. The value at index (i,j) should be greater than or equal to all elements in its row, and less than or equal to all elements in its column.
Here is what I have (it's off but I'm close):
function C = critical(A)
[nrow ncol] = size(A);
C = [];
for i = 1:nrow
for j = 1:ncol
if (A(i,j) >= A(i,1:end)) && (A(i,j) <= A(1:end,j))
C = [C ; A(i,j)]
end
end
end
You can use logical indexing.
minI = min(A,[],1);
maxI = max(A,[],2);
[row,col] = find(((A.'==maxI.').' & A==minI) ==1)
Details
Remember that Matlab is column major. We therefore transpose A and maxI.
A = [
3 4 1 1 2
2 4 2 1 4
4 3 2 1 2
3 3 1 1 1
2 3 0 2 1];
A.'==maxI.'
ans =
0 0 1 1 0
1 1 0 1 1
0 0 0 0 0
0 0 0 0 0
0 1 0 0 0
Then do the minimum
A==minI
ans =
0 0 0 1 0
1 0 0 1 0
0 1 0 1 0
0 1 0 1 1
1 1 1 0 1
And then multiply the two
((A.'==maxI.').' & A==minI)
ans =
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 1 0 0 0
0 1 0 0 0
Then find the rows and cols
[row,col] = find(((A.'==maxI.').' & A==minI) ==1)
row =
4
5
col =
2
2
Try this vectorised solution using bsxfun
function [ r,c,criP ] = critical( A )
%// finding the min and max values of each col & row resptly
minI = min(A,[],1);
maxI = max(A,[],2);
%// matching all the values of min & max for each col and row resptly
%// getting the indexes of the elements satisfying both the conditions
idx = find(bsxfun(#eq,A,maxI) & bsxfun(#eq,A,minI));
%// getting the corresponding values from the indexes
criP = A(idx);
%// Also getting corresponding row and col sub
[r,c] = ind2sub(size(A),idx);
end
Sample Run:
r,c should be a vector of equal length which represents the row and column subs of each Critical point. While val is a vector of same length giving the value of the critical point itself
>> A
A =
3 4 1 1 2
2 4 2 1 4
4 3 2 1 2
3 3 1 1 1
2 3 0 2 1
>> [r,c,val] = critical(A)
r =
4
5
c =
2
2
val =
3
3
I think there is a simpler way with intersect:
>> [~, row, col] = intersect(max(A,[],2), min(A));
row =
4
col =
2
UPDATE:
With intersect, in case you have multiple critical points, it will only give you the first one. To have all the indicies, there is also another simple way:
>> B
B =
3 4 1 4 2 5
2 5 2 4 4 4
4 4 2 4 2 4
3 4 1 4 1 4
2 5 4 4 4 5
>> row = find(ismember(max(B,[],2),min(B)))
row =
3
4
>> col = find(ismember(min(B),max(B,[],2)))
col =
2 4 6
Note that the set of critical points now should be the combination of row and col, means you have total 6 critical points in this example: (3,2),(4,2),(3,4),(4,4),(3,6),(4,6).
Here you can find how to export such combination.
I want to create a matrix from all combinations of elements of one vector that fulfill a condition
For example, I have this vector
a = [1 2 3 4 5]
and want to create a matrix like
a = [1 0 0 0 0;
1 2 0 0 0;
1 2 3 0 0;
1 2 3 4 0;
1 2 3 4 5;
0 2 0 0 0;
0 2 3 0 0;
........;]
and then get the rows that fulfill the condition I can use the command:
b = sum(a')' > value
but I don't know how to generate the matrix
You can generate all possible binary combinations to determine the matrix you want:
a = [1 2 3];
n = size(a,2);
% generate bit combinations
c =(dec2bin(0:(2^n)-1)=='1');
% remove first line
c = c(2:end,:)
n_c = size(c,1);
a_rep = repmat(a,n_c,1);
result = c .* a_rep
Output:
c =
0 0 1
0 1 0
0 1 1
1 0 0
1 0 1
1 1 0
1 1 1
result =
0 0 3
0 2 0
0 2 3
1 0 0
1 0 3
1 2 0
1 2 3
I use combnk to generate a list of combinations. But, the result shape is not my required data. I want for example for combnk(1:3,2):
1 1 0
0 1 1
1 0 1
not
1 2
1 3
2 3
How can i do it? How can i change the combnk in optimal way to give results?
Don't you mean you want
1 1 0
1 0 1
0 1 1
instead of
1 2
1 3
2 3
So that each row is a logical selection vector for the original vector v?
You can get this with the following:
v = 1:3;
k = 2;
tmp = combnk(v,k);
M = size(tmp,1);
output = false(M,numel(v));
output(sub2ind(size(output),repmat((1:M)',1,k),tmp))=true;
result:
output =
1 1 0
1 0 1
0 1 1
Another solution:
c = combnk(1:3,2);
r = repmat(1:size(c,1), [1 size(c,2)]);
output = full(sparse(r,c(:),1))
result:
output =
1 1 0
1 0 1
0 1 1
How can I expand a matrix with zeroes around the edge and then crop it back to the same size, after some manipulations?
You can do this:
octave:1> x = ones(3, 4)
x =
1 1 1 1
1 1 1 1
1 1 1 1
octave:2> y = zeros(rows(x)+2, columns(x)+2);
octave:3> y(2:rows(x)+1, 2:columns(x)+1) = x
y =
0 0 0 0 0 0
0 1 1 1 1 0
0 1 1 1 1 0
0 1 1 1 1 0
0 0 0 0 0 0
octave:4> y = y.*2 (manipulation)
y =
0 0 0 0 0 0
0 2 2 2 2 0
0 2 2 2 2 0
0 2 2 2 2 0
0 0 0 0 0 0
octave:5> x = y(2:rows(x)+1, 2:columns(x)+1)
x =
2 2 2 2
2 2 2 2
2 2 2 2
To pad an array, you can use PADARRAY, if you have the image processing toolbox.
Otherwise, you can pad and shrink the following way:
smallArray = rand(10); %# make up some random data
border = [2 3]; %# add 2 rows, 3 cols on either side
smallSize = size(smallArray);
%# create big array and fill in small one
bigArray = zeros(smallSize + 2*border);
bigArray(border(1)+1:end-border(1),border(2)+1:end-border(2)) = smallArray;
%# perform calculation here
%# crop the array
newSmallArray = bigArray(border(1)+1:end-border(1),border(2)+1:end-border(2));