Retriveing the intersection of matrices - matlab

whos.exit whos condition1 result
650 452 1 0
654 456 0 0
254 650 1 1
785 412 1 0
756 654 1 1
744 0 0
125 1 0
985 1 0
... ... ...
I wish obtain the result matrix.
Result matrix contains all "whos" which satify the condition1 and are present whos.exit but in no particular order. Note: all elements in whos.exit are unique and the result of whos(condition1) will give unique whos.

You can use ismember -
result = ismember(whos,whos.exit).*condition1
Or bsxfun -
result = any(bsxfun(#eq,whos,whos.exit.'),2).*condition1
Since whos is an in-built command in MATLAB, I would suggest using some other variable name there as a matter of good practice.

You could use intersect
intersect(whos.exit,whos.*condition1)
ans =
650
654
Or if you want a binary array (not as elegant asismember though)
A=zeros(size(whos.exit,1),1);
[~,~,iwe]=intersect(whos,whos.exit);
A(iwe) = 1;
A.*c1
ans =
0
0
1
0
1
0
0
0
or
[~,~,iwe]=intersect(whos,whos.exit);
sum((((c1.*whos.exit)./whos.exit(iwe)')==1)')'
ans =
0
0
1
0
1
0
0
0
Details
Find the indices in whose.exit whose values are in both arrays.
[~,~,iwe]=intersect(whos,whos.exit)
iwe =
3
5
Find where those values are. I just use a division because a value divided by itself will show a 1 and that tells us where the values are. Each row represents the value(s) we are looking for and the column the location of this value. The first value (whos.exit(iwe(1))) is location at position 3 and the second (whos.exit(iwe(2))) is location at position 5.
(((c1.*whos.exit)./whos.exit(iwe)')==1)'
ans =
0 0 1 0 0 0 0 0
0 0 0 0 1 0 0 0
The we just sum and transpose that to get the binary array
sum((((c1.*whos.exit)./whos.exit(iwe)')==1)')'
ans =
0
0
1
0
1
0
0
0

Related

permutation/combination with specific condition

Let us we have binary number to fill out 9 spots with specific condition: 0 always comes before 1. the possible conditions is 10:
1 1 1 1 1 1 1 1 1
0 1 1 1 1 1 1 1 1
0 0 1 1 1 1 1 1 1
0 0 0 1 1 1 1 1 1
0 0 0 0 1 1 1 1 1
0 0 0 0 0 1 1 1 1
0 0 0 0 0 0 1 1 1
0 0 0 0 0 0 0 1 1
0 0 0 0 0 0 0 0 1
0 0 0 0 0 0 0 0 0
Now lest us extent it to 0, 1, 2 with same rule. 0 should be always before 1 and/or 2. 1 should be before 1. Again, 9 spots are available to fill out.
I know that this yields to 55 combinations.
Question:
(1) what is the mathematical formulation to generalize this?
(2) How can I store all those 55 combinations? [any matlab code?]
Thanks
As the commenter said, the answer comes down to stars and bars. You can also think of this as counting the number of non-decreasing sequences i_1 <= i_2 <= ... <= i_k, where k is the number of symbols available and each i_j is a number between 0 and 9.
That said, here's a matlab script that generates all possibilities. Each row of the output matrix is one possible string of digits.
function M = bin_combs(L,k)
% L: length
% k: number of symbols
if k == 1
M = zeros(1,L);
else
M = zeros(0,L);
N = bin_combs(L,k-1);
for i = 1:size(N,1)
row = N(i,:);
for j=find(row==k-2)
new_row = row;
new_row(j:end) = new_row(j:end) + 1;
M = [M;new_row];
end
M = [M;row];
end
end
Some sample output:
>> size(bin_combs(9,3))
ans =
55 9
>> size(bin_combs(9,4))
ans =
220 9

How to perform inverse in GF(2) and multiply in GF(256) in Matlab?

I have a binary matrix A (only 1 and 0), and a vector D in Galois field (256). The vector C is calculated as:
C = (A^^-1)*D
where A^^-1 denotes the inverse matrix of matrix A in GF(2), * is multiply operation. The result vector C must be in GF(256). I tried to do it in Matlab.
A= [ 1 0 0 1 1 0 0 0 0 0 0 0 0 0;
1 1 0 0 0 1 0 0 0 0 0 0 0 0;
1 1 1 0 0 0 1 0 0 0 0 0 0 0;
0 1 1 1 0 0 0 1 0 0 0 0 0 0;
0 0 1 1 0 0 0 0 1 0 0 0 0 0;
1 1 0 1 1 0 0 1 0 1 0 0 0 0;
1 0 1 1 0 1 0 0 1 0 1 0 0 0;
1 1 1 0 0 0 1 1 1 0 0 1 0 0;
0 1 1 1 1 1 1 0 0 0 0 0 1 0;
0 0 0 0 1 1 1 1 1 0 0 0 0 1;
0 1 1 1 1 0 1 1 1 0 1 1 1 0;
0 0 0 1 0 0 0 1 0 0 0 0 0 0;
0 0 1 0 0 0 0 1 0 0 0 0 0 0;
1 1 1 1 0 0 0 0 0 0 0 0 0 0]
D=[0;0;0;0;0;0;0;0;0;0;103;198;105;115]
A=gf(A,1);
D=gf(D,8); %%2^8=256
C=inv(A)*D
%% The corrected result must be
%%C=[103;187;125;210;181;220;161;20;175;175;187;187;220;115]
However, for above code, I cannot achieved as my expected result
C=[103;187;125;210;181;220;161;20;175;175;187;187;220;115]
It produces an error as
Error using * (line 14)
Orders must match.
Could you help me achieve my expected result?
The error
Error using * (line 14)
Orders must match.
arises because Matlab does not support applying standard mathematical operations (+, *, .*, .^, \, etc.) to Galois Fields of different order, GF(2) and GF(256). The inverse operation, inv(A) is a valid operation and if you perform it on its own as shown by #Ander Biguri it will succeed and generate the inverse of A in GF(2). Your calculation breaks down when you attempt to multiply inv(A) and D as the orders of these Galois Fields do not match.
In this example it is unnecessary to explicitly define A as a Galois Field of order 2, GF(2) as multiplication in GF(256) takes place in GF(2). That is 1 + 1 = 0.
If we thus modify the code that creates the Galois Field for A to
A = gf(A, 8);
we can then perform
C = inv(A)*D
which produces
C = GF(2^8) array. Primitive polynomial = D^8+D^4+D^3+D^2+1 (285 decimal)
Array elements =
103
187
125
210
181
220
161
20
175
175
187
187
220
115
C is thus in GF(256) and produces the expected result.
It seems there is either
A) a theoretical fault in your computation or
B) something that MATLAB doesn't support.
As per the documentation in Galois field arithmetic (emphasis mine):
Section Overview. You can perform arithmetic operations on Galois
arrays by using familiar MATLAB operators, listed in the table below.
Whenever you operate on a pair of Galois arrays, both arrays must be
in the same Galois field.
And your matrices aren't.
I cant know which one is it as I have no idea how Galois fields work

Ismember, multiple times

I have an array of letters
mystring = 'abcdefghijklmnopqrstuvwxyz';
and I have the word Elephant. I want to know how many times the letters appear in Elephant. I have tried ismember and it gives me if they appear but not how many times. How can I get the number of times a letter occurs in a word?
You could use histcounts:
mystring = 'bcdfgijkmoqrsuvwxyzelphant';
myword = 'elephant';
[sortstring, idx] = sort(mystring); % Bin edges for histcounts need to be increasing
N = histcounts(double(myword), [double(sortstring) 257]); % Add 257 to the array so we capture the last character in a bin
N(idx) = N; % Undo the sort
Which returns:
N =
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 1 1 1 1 1 1
Note that due to the conversion to ASCII this method is case sensitive. You can adjust for this using lower or upper, if necessary.
mystring = char(['A':'Z','a':'z']);
Alphabet = zeros(numel(mystring),1);
for ii = 1:numel(mystring)
Alphabet(ii,1) = sum(ismember('Elephant',mystring(ii)));
end
ismember checks whether the current letter of the alphabet as dictated by the loop exists in the word. If it does, it sums all occurrences to obtain the total occurrence times of each letter, stored in Alphabet, where each entry corresponds to the letter at that position in the alphabet.
I used the method of creating the alphabet as per #Daniel's comment; capitals do now work.
Example, test for William Shakespeare:
Alphabet.'
ans =
Columns 1 through 15
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
Columns 16 through 30
0 0 0 1 0 0 0 1 0 0 0 3 0 0 0
Columns 31 through 45
3 0 0 1 2 0 1 2 1 0 0 1 0 1 1
Columns 46 through 52
0 0 0 0 0 0 0

Find Maximum Coordinate Point where Pixel value is 1 on x-axis, in 2-D image (Binary) (Matlab)

I'm using Matlab and I have a 2-D Array (image), like this
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 1 0 0
0 0 1 1 1 1 1 1 1 1 0
0 0 0 1 1 1 1 1 1 1 1
0 0 0 0 1 1 1 1 1 1 0
0 0 0 0 0 0 0 1 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
in the following array, I want to get very first position (with respect to X-axis) where X and Y have value "1" and very last position (with respect to X-axis) where X and Y have value "1".
Does anyone know the simplest way to do this?
A simple way using any and find. I assume that your image is called image
minimumX = find(any(image,1),1,'first')
maximumX = find(any(image,1),1,'last')
An alternative way is to use BoundingBox from regionprops:
stats = regionprops(image,'BoundingBox');
minimumX = stats.BoundingBox(1);
maximumX = sum(stats.BoundingBox([1 3]));
You can achieve it with max, exploting the facts that
[Y,I] = MAX(X,[],DIM) operates along the dimension DIM.
and that
If the values [...] contain more than one maximal element, the index of the first one is returned.
Let img denote your 2D array. I'm assuming your x-axis is the row index. Otherwise change ,2 to ,1 (three times) and fliplr to flipud (once).
[valid, first] = max(img,[],2);
first(~valid) = NaN;
[~, last] = max(fliplr(img),[],2);
last = size(img,2)-last+1;
last(~valid) = NaN;
In your example:
first =
NaN
NaN
5
3
4
5
8
NaN
NaN
last =
NaN
NaN
9
10
11
10
8
NaN
NaN

Matlab: descending binary to ascending binary like [0 0 1 0] to [0 1 0 0] or 1011 to 1101?

I have arrays that stores only binary numbers like the below, binaries are of the size 1x31. Now I want to make the last bit the first and the first bit the last and so on. The choice of data structure is probably very poor here -- when I learn to play with binaries I probably get rid of the array. The binaries make the ordering of the arrays far easier with a simple sort. Anyway this is puzzle now:
Is there some ready command in Matlab for changing desceding binary to asceding binary?
Input
>> C(21,:)
ans =
(1,11) 1
(1,16) 1
(1,17) 1
>> full(C(21,:))
ans =
Columns 1 through 11
0 0 0 0 0 0 0 0 0 0 1
Columns 12 through 22
0 0 0 0 1 1 0 0 0 0 0
Columns 23 through 31
0 0 0 0 0 0 0 0 0
Goal for the output with some command such as invertDec2Asc
>> invertDec2Asc(C(21,:))
ans =
(1,21) 1
(1,16) 1
(1,15) 1
Try using num2str followed by fliplr
revnum = fliplr( num2str(num) )
Test
num = ['101010';'010101']
revnum = fliplr( num2str(num) )
num =
101010
010101
revnum =
010101
101010
flipud or fliplr is what you're looking for.
Matlab documentation
fliplr([1 0 1 0]) = [0 1 0 1]
fliplr('1010') = '0101'
format of binaries in matlab: '1010', e.g. created with dec2bin(10)