Matlab: command to check for active bit in binary numbers? - matlab

This is how I do it with arrays where binaries are stored
>> hhh=[1 0 1 0 1 0 0; 0 0 1 0 0 0 0; 1 0 1 0 0 0 0; 0 0 0 1 1 0 1]; find(hhh(:,1)==1)
ans =
1
3
and now I am trying to understand how to do it with binary numbers
>> hhhh=[1010100; 0010000; 1010000; 0001101]; find(hhhh(:,1)==1)
ans =
Empty matrix: 0-by-1
where the hack to break up all binaries back into arrays can work (ismember('101010','1') and then prepending with zeros) but I feel there is probably some better alternative so
By which command to check whether Nth bit active in binary number?
P.s. Harder puzzle: is there a type-agnostic solution that would work with both binaries and DEC?

String Input
If you have a string input, you can get away with testing for char equality:
find(hhh(:, 1) == '1')
for string arrays (i.e char matrices), you can extract both outputs of find (rows and columns) to be able to determine which active bit corresponds to which string:
[r, c] = find(hhh == '1');
Numeric Input
For numeric inputs, you can use bitget to get the binary representation. From there, it's very similar to the solution for string inputs:
B = bsxfun(#bitget, hhh, size(hhh, 1):-1:1);
[r, c] = find(B);
Note that find searches for non-zero elements, so there's no need to write find(B == 1) explicitly.
Combined Solution
If the solution for the "harder puzzle" is what you're after, you can determine the type of the input first, and handle it accordingly:
if ischar(hhh)
%// Apply solution to string array
%//...
else if isnumeric(hhh)
%// Apply solution to numeric input
%// ...
else
%// This type is unsupported
assert('Matrix is of unsupported type')
end

Repeating my comment in form of an answer:
There's no need to work with the string/array-like representation of the bits in this case.
You can use bitget right on the output of find(mlf). Like:
filled = find(mlf);
filled_and_bit2 = filled(logical(bitget(filled,2)));

You should store your binary number as a string matrix:
hhhh=['1010100'; '0010000'; '1010000'; '0001101'];
Then you can do
find(bin2dec(hhhh) >= bin2dec('1000000'))
returns:
ans =
1
3
or you could use the less intuitive (but probably faster)
find(hhhh(:,1)-'0') %// Or find(hhhh(:,1)=='1') as EitanT points out
to get the same result.

This is not a direct answer to the question but related -- good point by Sebastian in a comment! So suppose that the binaries are indices. Now instead of playing with dec2bin something like
>> hhh=dec2bin(find(mlf));B=bsxfun(#bitget, hhh, 8:-1:1);find(B)
Error using bsxfun
Non-singleton dimensions of the two input arrays must match each other.
we can directly address the indices like
>> filled = find(mlf);
filled_and_bit2 = bitget(filled,1);
filled(logical(filled_and_bit2))
ans =
1
7
where it finds the binaries with the first active bit.
Procedure
Data
>> mlf=sparse([],[],[],2^31,1);
mlf(1)=7;
mlf(4)=10;
mlf(7)=-1;
>> mlf
mlf =
(1,1) 7
(4,1) 10
(7,1) -1
>> find(mlf)
ans =
1
4
7
Interpret the index numbers as binary
(1,1) -----> 000001
(4,1) -----> 000100
(7,1) -----> 000111
Examples
Output 1: find cases where 3th bit is active
4
7
Output: find cases where 1st bit is active
1
7
Output: find cases where 2nd bit is active
4

Related

Output a matrix size n x m, 1 when the sum of the indices is even, 0 otherwise

I'm attempting the following as a hobby, not as homework. In Computer Programming with MATLAB: J. Michael Fitpatrick and Akos Ledeczi, there is a practice problem that asks this:
Write a function called alternate that takes two positive integers, n and m, as input arguments (the function does not have to check the format of the input) and returns one matrix as an output argument. Each element of the n-by-m output matrix for which the sum of its indices is even is 1.
All other elements are zero.
A previous problem was similar, and I wrote a very simple function that does what it asks:
function A = alternate(n,m)
A(1:n,1:m)=0;
A(2:2:n,2:2:m)=1;
A(1:2:n,1:2:m)=1;
end
Now my question is, is that good enough? It outputs exactly what it asks for, but it's not checking for the sum. So far we haven't discussed nested if statements or anything of that sort, we just started going over very basic functions. I feel like giving it more functionality would allow it to be recycled better for future use.
Great to see you're learning, step 1 in learning any programming language should be to ensure you always add relevant comments! This helps you, and anyone reading your code. So the first improvement would be this:
function A = alternate(n,m)
% Function to return an n*m matrix, which is 1 when the sum of the indices is even
A(1:n,1:m)=0; % Create the n*m array of zeros
A(2:2:n,2:2:m)=1; % All elements with even row and col indices: even+even=even
A(1:2:n,1:2:m)=1; % All elements with odd row and col indicies: odd+odd=even
end
You can, however, make this more concise (discounting comments), and perhaps more clearly relate to the brief:
function A = alternate(n,m)
% Function to return an n*m matrix, which is 1 when the sum of the indices is even
% Sum of row and col indices. Uses implicit expansion (R2016b+) to form
% a matrix from a row and column array
idx = (1:n).' + (1:m);
% We want 1 when x is even, 0 when odd. mod(x,2) is the opposite, so 1-mod(x,2) works:
A = 1 - mod( idx, 2 );
end
Both functions do the same thing, and it's personal preference (and performance related for large problems) which you should use.
I'd argue that, even without comments, the alternative I've written more clearly does what it says on the tin. You don't have to know the brief to understand you're looking for the even index sums, since I've done the sum and tested if even. Your code requires interpretation.
It can also be written as a one-liner, whereas the indexing approach can't be (as you've done it).
A = 1 - mod( (1:n).' + (1:m), 2 ); % 1 when row + column index is even
Your function works fine and output the desired result, let me propose you an alternative:
function A = alternate(n,m)
A = zeros( n , m ) ; % pre-allocate result (all elements at 0)
[x,y] = meshgrid(1:m,1:n) ; % define a grid of indices
A(mod(x+y,2)==0) = 1 ; % modify elements of "A" whose indices verify the condition
end
Which returns:
>> alternate(4,5)
ans =
1 0 1 0 1
0 1 0 1 0
1 0 1 0 1
0 1 0 1 0
initialisation:
The first line is the equivalent to your first line, but it is the cannonical MATLAB way of creating a new matrix.
It uses the function zeros(n,m).
Note that MATLAB has similar functions to create and preallocate matrices for different types, for examples:
ones(n,m) Create
a matrix of double, size [n,m] with all elements set to 1
nan(n,m) Create a
matrix of double, size [n,m] with all elements set to NaN
false(n,m) Create a
matrix of boolean size [n,m] with all elements set to false
There are several other matrix construction predefined function, some more specialised (like eye), so before trying hard to generate your initial matrix, you can look in the documentation if a specialised function exist for your case.
indices
The second line generate 2 matrices x and y which will be the indices of A. It uses the function meshgrid. For example in the case shown above, x and y look like:
| x = | y = |
| 1 2 3 4 5 | 1 1 1 1 1 |
| 1 2 3 4 5 | 2 2 2 2 2 |
| 1 2 3 4 5 | 3 3 3 3 3 |
| 1 2 3 4 5 | 4 4 4 4 4 |
odd/even indices
To calculate the sum of the indices, it is now trivial in MATLAB, as easy as:
>> x+y
ans =
2 3 4 5 6
3 4 5 6 7
4 5 6 7 8
5 6 7 8 9
Now we just need to know which ones are even. For this we'll use the modulo operator (mod) on this summed matrix:
>> mod(x+y,2)==0
ans =
1 0 1 0 1
0 1 0 1 0
1 0 1 0 1
0 1 0 1 0
This result logical matrix is the same size as A and contain 1 where the sum of the indices is even, and 0 otherwise. We can use this logical matrix to modify only the elements of A which satisfied the condition:
>> A(mod(x+y,2)==0) = 1
A =
1 0 1 0 1
0 1 0 1 0
1 0 1 0 1
0 1 0 1 0
Note that in this case the logical matrix found in the previous step would have been ok since the value to assign to the special indices is 1, which is the same as the numeric representation of true for MATLAB. In case you wanted to assign a different value, but the same indices condition, simply replace the last assignment:
A(mod(x+y,2)==0) = your_target_value ;
I don't like spoiling the learning. So let me just give you some hints.
Matlab is very efficient if you do operations on vectors, not on individual elements. So, why not creating two matrices (e.g. N, M) that holds all the indices? Have a look at the meshgrid() function.
Than you might be able find all positions with an even sum of indices in one line.
Second hint is that the outputs of a logic operation, e.g. B = A==4, yields a logic matrix. You can convert this to a matrix of zeros by using B = double(B).
Have fun!

Eliminating zeros in a matrix - Matlab

Hi I have the following matrix:
A= 1 2 3;
0 4 0;
1 0 9
I want matrix A to be:
A= 1 2 3;
1 4 9
PS - semicolon represents the end of each column and new column starts.
How can I do that in Matlab 2014a? Any help?
Thanks
The problem you run into with your problem statement is the fact that you don't know the shape of the "squeezed" matrix ahead of time - and in particular, you cannot know whether the number of nonzero elements is a multiple of either the rows or columns of the original matrix.
As was pointed out, there is a simple function, nonzeros, that returns the nonzero elements of the input, ordered by columns. In your case,
A = [1 2 3;
0 4 0;
1 0 9];
B = nonzeros(A)
produces
1
1
2
4
3
9
What you wanted was
1 2 3
1 4 9
which happens to be what you get when you "squeeze out" the zeros by column. This would be obtained (when the number of zeros in each column is the same) with
reshape(B, 2, 3);
I think it would be better to assume that the number of elements may not be the same in each column - then you need to create a sparse array. That is actually very easy:
S = sparse(A);
The resulting object S is a sparse array - that is, it contains only the non-zero elements. It is very efficient (both for storage and computation) when lots of elements are zero: once more than 1/3 of the elements are nonzero it quickly becomes slower / bigger. But it has the advantage of maintaining the shape of your matrix regardless of the distribution of zeros.
A more robust solution would have to check the number of nonzero elements in each column and decide what the shape of the final matrix will be:
cc = sum(A~=0);
will count the number of nonzero elements in each column of the matrix.
nmin = min(cc);
nmax = max(cc);
finds the smallest and largest number of nonzero elements in any column
[i j s] = find(A); % the i, j coordinates and value of nonzero elements of A
nc = size(A, 2); % number of columns
B = zeros(nmax, nc);
for k = 1:nc
B(1:cc(k), k) = s(j == k);
end
Now B has all the nonzero elements: for columns with fewer nonzero elements, there will be zero padding at the end. Finally you can decide if / how much you want to trim your matrix B - if you want to have no zeros at all, you will need to trim some values from the longer columns. For example:
B = B(1:nmin, :);
Simple solution:
A = [1 2 3;0 4 0;1 0 9]
A =
1 2 3
0 4 0
1 0 9
A(A==0) = [];
A =
1 1 2 4 3 9
reshape(A,2,3)
ans =
1 2 3
1 4 9
It's very simple though and might be slow. Do you need to perform this operation on very large/many matrices?
From your question it's not clear what you want (how to arrange the non-zero values, specially if the number of zeros in each column is not the same). Maybe this:
A = reshape(nonzeros(A),[],size(A,2));
Matlab's logical indexing is extremely powerful. The best way to do this is create a logical array:
>> lZeros = A==0
then use this logical array to index into A and delete these zeros
>> A(lZeros) = []
Finally, reshape the array to your desired size using the built in reshape command
>> A = reshape(A, 2, 3)

MATLAB syntax length

I'm reading some MATLAB trying to pick it up. The line below is probably rather simple but I do not understand it.
I understand length will give me the length of a vector, in this case a vector which is part of a struct, index_struct.data_incl.
The actual value of index_stuct.data_incl at run time is simply 1. What is confusing me is what is inside the brackets i.e. (index_struct.data_incl == 1)? I can't work out what this line is trying to do as simple as it may be!
int_var = length(index_struct.data_incl(index_struct.data_incl == 1));
try this (but think of x as your index_struct.data_incl:):
x = [1 4 5 13 1 1]
length(x(x==1))
ans =
3
It's just counting the number of elements of your x vector that are equal to 1
because x==1 evaluates to [1 0 0 0 1 1] and then using logical indexing x(x==1) evaluates to [1 1 1] whose length is 3;
It could have been written more simply as sum(index_struct.data_incl == 1)
If I dont see the code I can only guess..., but I guess that index_struc.data_incl should be a vector, with length n meaning that you have the option to read until n files, and all the values of the array should be 0 at the begining, and when you read a file you change the corresponding position in the vector index_struc.data_incl from 0 to 1. After some time you can see how many of these files you have read using
int_var = length(index_struct.data_incl(index_struct.data_incl == 1));
because it will give to you the number of 1 in the vector index_struct.data_incl.

Appending "in a way" multiple matrices

Say I have matrices A and B. I want to create a third matrix C where
A = [1,0,0,1]
B = [1,0,1,0]
C = [11, 00, 01, 10]
Is there such a function in Matlab? If not how would I go about creating a function that does this?
Edit: C is not literal numbers. They are concatenated values of A,B element-wise.
Edit2: The actual problem I am dealing with is I have 10 large matrices of the size [x,y] where x,y > 1000. The elements in these matrices all have 0s and 1s. No other number. What I need to accomplish is have the element [x1,y1] in matrix 1 to be appended to the element in [x1,y1] of matrix 2. and then that value to be appended to [x1,y1] of matrix 3.
Another example:
A = [1,1,1,1;
0,0,0,0]
B = [0,0,0,0;
1,1,1,1]
C = [1,0,1,0;
0,1,0,1]
And I need a matrix D where
D = [101, 100, 101, 101; 010, 011, 010, 011]
I recommend that you avoid manipulating binary numbers as strings where possible. It seems tempting, and there are cases where matlab provides a more elegant solution if you treat a binary number as a string, but you cannot perform binary arithmetic on strings. You can always work with integers as if they were binary (they are stored as bits in your machine after all), and then just display them as binary numbers using dec2bin when necessary.
A = [1,0,0,1]
B = [1,0,1,0]
C = bitshift(A,1)+B;
display(dec2bin(C));
In the other case you show in your question you could use:
A = [1,1,1,1; 0,0,0,0];
B = [0,0,0,0; 1,1,1,1];
C = [1,0,1,0; 0,1,0,1];
D = bitshift(A,2) + bitshift(B,1) + C;
You can also convert an arbitrary length row vector of zeros and ones into its decimal equivalent by defining this simple function:
mat2dec = #(x) x*2.^(size(x,2)-1:-1:0)';
This will also work for matrices too. For example
>> M = [0 0 1; 0 1 1; 0 1 0; 1 1 0; 1 1 1; 1 1 0; 1 0 0];
>> dec2bin(mat2dec(M))
ans =
001
011
010
110
111
110
100
In my experience, treating binary numbers as strings obfuscates your code and is not very flexible. For example, try adding two binary "strings" together. You have to use bin2dec every time, so why not just leave the numbers as numbers until you want to display them? You have already run into some of the issues caused by strings of different lengths too. You will be amazed how one simple change can break everything when treating numbers as strings. The worst part is that an algorithm may work great for one set of data and not for another. If all I test with is two-bit binary numbers and a three-bit number somehow sneaks its way in, I may not see an error, but my results will be inexplicably incorrect. I realize that this is a very subjective issue, and I think that I definitely stand in the minority on StackOverflow, so take it for what it's worth.
It depends how you want the output formatted. You could apply bitshift to the numerical values and convert to binary:
>> b = dec2bin(bitshift(A,1)+B)
b =
11
00
01
10
For a general matrix Digits:
>> Digits
Digits =
1 0 0 0
0 1 0 0
1 0 1 1
1 1 0 0
1 0 0 0
1 0 1 1
1 1 0 0
1 0 1 0
0 1 1 1
0 1 1 1
>> Ddec = D*(2.^(size(D,2)-1:-1:0))'; % dot product
>> dec2bin(Ddec)
ans =
1000
0100
1011
1100
1000
1011
1100
1010
0111
0111
Another way to write that is dec2bin(sum(D .* repmat(2.^(size(D,2)-1:-1:0),size(D,1),1),2)).
For your larger problem, with 10 large matrixes (say M1, M2, ..., M10), you can build the starting Digits matrix by:
Digits = [M1(:) M2(:) M3(:) M4(:) M5(:) M6(:) M7(:) M8(:) M9(:) M10(:)];
If that is reverse the order of the digits, just do Digits = fliplr(Digits);.
If you would rather not reshape anything you can compute the matrix decimal values from the matrices of digits as follows:
M = cat(3,A,B,C);
Ddec = sum(bsxfun(#times,M,permute(2.^(size(M,3)-1:-1:0),[1 3 2])),3)
I see some quite extensive answers so perhaps this is thinking too simple, but how about just this assuming you have vectors of ones and zeros representing your binary numbers:
A = [1,0,0,1];
B = [1,0,1,0];
C = 10*A + B
This should give you the numbers you want, you may want to add leading zeros. Of course this method can easily be expanded to append multiple matrices, you just need to make sure there is a factor (base) 10 between them before adding.

haltonset: understanding skip and leap

If i read the doc of how to construct a Halton quasi-random point set and it mentions that it's possible to 'skip' the first values and then retain the 'leap' values.
Don't understand what the 'skip' and 'leap' really mean.
Have tried the following:
>> p = haltonset(1,'Skip',50,'Leap',10); d = haltonset(1,'Skip',51,'Leap',9);
>> p(2:10), d(1:9)
ans =
0.7344
0.0703
0.7891
0.4766
0.5859
0.1797
0.9922
0.3164
0.6602
ans =
0.7969
0.7344
0.8828
0.5391
0.8516
0.6484
0.9609
0.6172
0.7539
>> p(2:10) == d(1:9)
ans =
0
0
0
0
0
0
0
0
0
Thought that it might be that that this would save 10 values to p and 9 to d. Also thought that d would have the same values as p. But this was not the case.
I then tested if the 'leap' would be the same as a normal way to make a vector
- ex: (1:leap:10)
>> p = haltonset(1,'Skip',50,'Leap',1); d = haltonset(1,'Skip',50,'Leap',2);
>> p(1:2:10)==d(1:5)
ans =
1
0
0
0
0
>> p = haltonset(1,'Skip',0,'Leap',1); d = haltonset(1,'Skip',0,'Leap',2);
>> p(1:2:10)==d(1:5)
ans =
1
0
0
0
0
but this seemed not to be the case..
Can anybody give a plain English explanation of how to interpreted the 'skip' and 'leap' variables.
I find the following description to be very clear [quoting this documentation page]:
Imagine a simple 1-D sequence that produces the integers from 1 to 10.
This is the basic sequence and the first three points are [1,2,3]:
Now look at how Scramble, Leap, and Skip work together:
Scramble: Scrambling shuffles the points in one of several
different ways. In this example, assume a scramble turns the sequence
into 1,3,5,7,9,2,4,6,8,10. The first three points are now [1,3,5]:
Skip: A Skip value specifies the number of initial points to
ignore. In this example, set the Skip value to 2. The sequence is now
5,7,9,2,4,6,8,10 and the first three points are [5,7,9]:
Leap: A Leap value specifies the number of points to ignore for
each one you take. Continuing the example with the Skip set to 2, if
you set the Leap to 1, the sequence uses every other point. In this
example, the sequence is now 5,9,4,8 and the first three points are
[5,9,4]:
EDIT:
Let me show with an example:
%# create 1D sequences (x: picked, .: ignored)
p00 = haltonset(1,'Skip',0,'Leap',0); %# xxxxxxxxxxxxxxx
p50 = haltonset(1,'Skip',5,'Leap',0); %# .....xxxxxxxxxx
p02 = haltonset(1,'Skip',0,'Leap',2); %# x..x..x..x..x..
p52 = haltonset(1,'Skip',5,'Leap',2); %# .....x..x..x..x
%# each pair of these are equal
[p50(1:10) p00(6:15)] %# skip vs. noskip
[p02(1:5) p00(1:3:13)] %# leap vs. noleap
[p52(1:4) p00(6:3:15)] %# skip+leap vs. noskip+noleap
In general:
skip = 50;
leap = 10;
p00 = haltonset(1,'Skip',0,'Leap',0);
p = haltonset(1,'Skip',skip,'Leap',leap);
num = 9;
[p(1:num) p00(skip+1:leap+1:num*leap+num-leap+skip)]