How to deal with indexing involving three vectors? - matlab

I have the following three vectors:
trans_now=[1 2 4]; data2send=[1 0 0 1]; datasent=[0 0 0 0];
I want to set datasent to 1 for those nodes that are members of tran_now and whose data2send status is 1. e.g 4 is a member of trans_now and data2send(4) is 1 therefore datasent(4) should be set to 1.
I can do it using for loop and if statement as shown in the code below.
for i=1:length(trans_now)
if data2send(trans_now(i))==1
datasent(trans_now(i))=1;
end
end
However I want one liner code for this. The one liner code that I tried is
req_sent(req2send(trans_now)==1)=1;
But it doesn't work.
The output should set datasent vector to [1 0 0 1].

you could solve this in 2 ways:
1.
data_sent(trans_now) = data2send(trans_now)
the output is:
data_sent =
1 0 0 1
In this solution I assumed that all the initial values of data_sent are starting as 0 and that you need to assign it once.
2.
datasent(intersect(find(data2send == 1), trans_now)) = 1
output is:
data_sent =
1 0 0 1
In this solution no assumption is used and you assign only indices where data2send == 1 and also appear in trans_now

Related

Extending ismember to cells

I have searched the forum and have not found enough info to help me solve this problem.
Consider the set (cell of vectors)
A = {[1],[1 2],[2],[1 2 3],[1 2 3 4],[1 3]}
I want to construct a matrix B that looks like
B = [1 1 0 1 1 1
0 1 0 1 1 0
0 1 1 1 1 0
0 0 0 1 1 0
0 0 0 0 1 0
0 0 0 1 1 1]
The matrix B specifies membership of vectors with respect to each other. That is, the first row looks at the first element in A, [1], and checks if it is a member of the other vectors, placing a 1 if it is a member and a 0 otherwise.
I can do this using two for loops: one over the elements of A, and another nested, for each element of A, that checks membership with respect to every other member of A.
I want to avoid using for loops. Is there a vectorized solution for obtaining B from A?
With cell arrays it's hard to avoid loops, or their cousin cellfun. This is how I would do it:
[ii, jj] = ndgrid(1:numel(A)); % indices of all possible pairs
result = cellfun(#(x,y) all(ismember(x,y)), A(ii), A(jj)); % see if all elements in the
% first are present in the second
Well you asked for it, so here's an almost* vectorized solution using bsxfun and permute -
lens = cellfun('length',A)
vals = [A{:}]
mask = bsxfun(#ge,lens,[1:max(vals)]')
a = nan(size(mask))
a(mask) = vals
matches = bsxfun(#eq,a,permute(a,[3,4,1,2]));
out = bsxfun(#eq,squeeze(sum(any(matches,3),1)),lens(:))
*: Almost because of the use of cellfun at the start with cellfun('length',A), but since its just getting the length of the cells there, so computationally would be negligible .
Also, please note that this approach would use a lot of memory resources, so might not be beneficial, but just respecting the requirements of a vectorized solution as much as possible!

Adding additional ones that surround other values of one in a vector in MATLAB

Given a vector of zeros and ones in MATLAB, where the zeros represent an event in time, I would like to add additional ones before and after the existing ones in order to capture additional variation.
Example: I would like to turn [0;0;1;0;0] into [0;1*;1;1*;0] where 1* are newly added ones.
Assuming A to be the input column vector -
%// Find all neighbouring indices with a window of [-1 1]
%// around the positions/indices of the existing ones
neigh_idx = bsxfun(#plus,find(A),[-1 1])
%// Select the valid indices and set them in A to be ones as well
A(neigh_idx(neigh_idx>=1 & neigh_idx<=numel(A))) = 1
Or use imdilate from Image Processing Toolbox with a vector kernel of ones of length 3 -
A = imdilate(A,[1;1;1])
You can do it convolving with [1 1 1], and setting to 1 all values greater than 0. This works for column or row vactors.
x = [0;0;1;0;0];
y = double(conv(x, [1 1 1],'same')>0)
Purely by logical indexing:
>> A = [0 1 1 0 0];
>> A([A(2:end) 0] == 1 | [0 A(1:end-1)] == 1) = 1;
>> disp(A);
A =
1 1 1 1 0
This probably merits an explanation. The fact that it's a 3 element local neighbourhood makes this easy. Essentially, take two portions of the input array:
Portion #1: A starting from the second element to the last element
Portion #2: A starting from the first element to the second-last element
We place the first portion into a new array and add 0 at the end of this array, and check to see which locations are equal to 1 in this new array. This essentially shifts the array A over to the left by 1. Whichever locations in this first portion are equal to 1, we set the corresponding locations in A to be 1. The same thing for the second portion where we are effectively shifting the array A over to the right by 1. To shift to the right by 1, we prepend a 0 at the beginning, then extract out the second portion of the array. Whichever locations in this second portion are equal to 1 are also set to 1.
At the end of this operation, you would essentially shift A to the left by 1 and save this as a separate array. Also, you would shift to the right by 1 and save this as another array. With these two, you simply overlap on top of the original to obtain the final result.
The benefit of this method over its predecessors in this post is that this doesn't require computations of any kind (bsxfun, conv, imdilate etc.) and purely relies on indexing into arrays and using logical operators1. This also handles boundary conditions and can work on either row or column vectors.
Some more examples with boundary cases
>> A = [0 0 1 1 0];
>> A([A(2:end) 0] == 1 | [0 A(1:end-1)] == 1) = 1
A =
0 1 1 1 1
>> A = [0 0 0 0 1];
>> A([A(2:end) 0] == 1 | [0 A(1:end-1)] == 1) = 1
A =
0 0 0 1 1
>> A = [1 0 1 0 1];
>> A([A(2:end) 0] == 1 | [0 A(1:end-1)] == 1) = 1
A =
1 1 1 1 1
1: This post is dedicated to Troy Haskin, one who believes that almost any question (including this one) can be answered by logical indexing.

Turbo Encoder inter-leaver not working

I am trying to create a turbo encoder for my project.
Till now i have created the convolution encoder of 1/2 rate. Now i am having difficulty to apply interleaver. Here is my code. I am not getting output in ilvr. Correct me where i am going incorrect. Thanks in advance
msg = [0 1 0 1 1 1 0 0 1 0 1 0 0 0 1];
t= poly2trellis(3,[6 7]);
[isok,status] = istrellis(t);
code1 = convenc(msg,t);
ilvr = randperm(msg);
code2 = convenc(ilvr,t);
Well, firstly, if your question is about ilvr then why include the rest of the code other than the definition of msg and the line in question?
Secondly, when I ran this:
msg = [0 1 0 1 1 1 0 0 1 0 1 0 0 0 1];
ilvr = randperm(msg);
I got the following error:
Error using randperm
Size inputs must be scalar.
So, this means the the input is not what randperm was expecting. Then I typed help randperm, and looked at the help for randperm, so now I understand what randperm does and what inputs it expects. The error is because you gave randperm a vector, but the first input must be an integer.
I'm not sure what you are trying to do on that line, maybe you are trying to get a random permutation of the elements in msg? Following a hint in the help page, try this:
ilvr=msg(randperm(numel(msg)));

MATLAB:how to summarize the ones in an vector?

For example:
a=[1 1 0 0 1 1 0 1 1 1 0 0];
Now i want to sum only the ones which are divides by the zeros:
ones=[2 2 3] - That means two ones,then we have 2 zeros which we do not count,then again two ones etc.
How can i do this?
Well, I would suggest finding all places where it switches from 0 to 1 and then finding all places where it switches from 1 to 0, and using those indices to find those lengths. The problem arises at the edges where if the first entry is 1, it doesn't switch to one from zero, and if the last entry is 1, we never find it because nothing switches to 0 at the end. In order to avoid this problem easily, we can add a 0 in the beginning and one at the end. This way we're guaranteed to find each one of those bursts of ones. In essence:
b = [0 a 0];
d = diff(b);
posEdge = find(d==1);
negEdge = find(d==-1);
countOnes = negEdge - posEdge

I Need help Numeric Comparison in matlab

I have one matrix called targets (1X4000); column 1 to 2000 contains double value 0 and column 2001 to 4000 contains double value 1
a)
i want to create a matrix called targets_1 where i want to check if the value is 0 then make the entry 1 so at the end of the day i must have a matrix with :column 1 to 2000 with value 1 and column 2001:4000 with value zero
b)
Same situation as above but this time i want to check if the value is 1 then make the entry 1 and if it is zero then make the entry zero; at the end; my new matrix targets_2 contains values: column 1 to 2000 with value zero and column 2001:4000 with value 1
i know how to use the strcmp function to make such checking with strings, but problem is that my original matrix is double and i dont know if there is such function like
setosaCmp = strcmp('setosa',species);
which could work with double (numbers); any help would be appreciated
Your question isn't very clear. It sounds like the following would satisfy your description:
targets_1 = 1 - targets;
targets_2 = targets;
targets1 = double(targets == 0);
targets2 = targets;
I'm basing this answer purely on the fact that you've mentioned setosaCmp = strcmp('setosa', species);. From this I'm guessing that
You have Statistics Toolbox, as setosa is a species of iris from the Fisher Iris dataset widely used in Statistics Toolbox demos, and
You have a variable containing class labels, and you'd like to construct some class indicator variables (i.e. a new variable for each class label, each of which is 1 when the item is in that class, and 0 when it's not).
Is that right? If not, please ignore me.
If I'm right, then I think the command you're looking for is dummyvar from Statistics Toolbox. Try this:
>> classLabels = [1, 2, 1, 2, 3, 1, 3];
>> dummyvar(classLabels)
ans =
1 0 0
0 1 0
1 0 0
0 1 0
0 0 1
1 0 0
0 0 1