I have a question regarding how to use the binary bits as an index in MATLAB, For example, if I'm using 4 antennas to transmit data, in each instant, one antenna or two are active to transmit the data. how can I use the indexing of antennas to transmit that symbol, here an example as below:
%Suppose I'm using for antennas to transmit that data.
Nt = 4; % Number of antennas
Symbole = 1+j; % The symbol to transmit in binary after modulation
Ant_index = 11; % The antenna index which will be used to transmit data. (here number 3 will be used)
x_trans =zeros(Nt,1); % Initialization of antennas
x_trans(Ant_index) = Symbole; %Use the antenna to transmit the data
My question is in the last step, x_trans(Ant_index) = Symbole;I want to use the binary bits as index, which means, instead of the bits Ant_index = 11 which means 3 in decimal, I want to use the two bits as antennas for transmitting the same symbol. for example if I have bits 0101 , It means I will use the antenna number 1 and number 3 to transmit the symbol in the same above example Ant_index = 0011. it means that first and second antennas will be used to transmit the Symbol.
EDIT:
Second part of question, what's about if the generated bits for antenna indexing are generated randomly. and we want to avoid having the Ant_index = 000; in other words, we need the Ant_index to be as decimal value, and then make mapping for 000 which is in decimal 0, the antenna 1 should be activated, 001 = 1 ---> antenna 2 should be activated. 010 = 2 ---> antenna 3 active, 011 = 3 ---> antenna 4 active. 100 = 4 ---> antennas 1 and 2 are active, 101 = 5 ---> antennas 1 and 3 are active, and so on.
Depending on the desired format of your input, you can use one of the 2 decimal to binary conversion function:
de2bi => return
an array of 0 and 1, representing the binary number.
dec2bin =>
return a string representation of the binary number.
Conversion:
I recommend using de2bi since an array will be easier to convert into indices. For example:
activate antenna 1 and 2 (3 decimal == 11 in binary):
>> de2bi(3) % index antenna 1 and 2 (`3` decimal == `11` in binary):
ans =
1 1
>> de2bi(10) % index antenna 2 and 4 (`10` decimal == `1010` in binary):
ans =
0 1 0 1
Note that by default de2bi return the binary representation in small endian bit ordering (the first element in the array represents the lowest bit). This is a bit the opposite of our visual convention, there is a parameter to reverse that, but for your purpose it is already exactly what we want. It saves us from reading the array from right to left or reversing it.
Indexing:
You said you have 4 antenna, but for this example I'll enlarge that a bit. Let's say you need to control 7 antenna. It would mean I always have to have an array of indices conataining 7 elements. No problem, de2bi allows you to specifiy the number of output digits. So again, to activate antenna 2 and 4 (out of seven):
>> Nt=7;
>> Ant_index = de2bi(10,Nt)
Ant_index =
0 1 0 1 0 0 0
with that you can directly use your index to transmit data:
x_trans(Ant_index) = Symbole;
Input format:
This is all and well if you know your elementary binary table up to your number of antenna. In case you want to be able to specify active antennas with a binary representation instead of a direct decimal number, you can use the reverse conversion function, more specifically bin2dec
So a last example to show you how they all work together:
>> stringAntIndex = '1010'
stringAntIndex =
1010
decimalAntIndex = bin2dec(stringAntIndex)
decimalAntIndex =
10
>> Ant_index = de2bi(decimalAntIndex,7)
Ant_index =
0 1 0 1 0 0 0
Which of course you could simplify to:
>> stringAntIndex = '1010' ;
>> Ant_index = de2bi(bin2dec(stringAntIndex),Nt)
Ant_index =
0 1 0 1 0 0 0
Edit: Ok I place the answer to your updated question here to finish it but note that your edited question is completely different than your original question. What you are asking now has nothing to do with converting bits into indices, it is just a straight mapping which you have to define before hand (since it doesn't follow any computation logic).
Basically, store your active antenna indices in a cell array, and pick the the cell corresponding to your randomly generated index (you'll have to add 1 because MATLAB starts array indices at 1, not at 0 like many other languages.
So:
% Map the antenna to be active depending on decimal input
Antenna2Activate = {
[1] ; % antenna 1 active
[2] ; % antenna 2 active
[3] ; % ...
[4] ; % ...
[1 2] ; % antenna 1 & 2 active
[1 3] ; % antenna 1 & 3 active
[1 4] ; % ...
[2 3] % antenna 2 & 3 active
};
% Then to activate the proper antenna given a decimal input [decimalInput]:
Ant_index = Antenna2Activate{ decimalInput+1 } ;
x_trans(Ant_index) = Symbole;
To make sure it works the way you want, you can run the following code:
decinput = 0:7 ;
for k=1:numel(Antenna2Activate)
Ant_index = Antenna2Activate{ decinput(k)+1 } ;
fprintf('Decimal input= %d \t Binary= %3s \t Ant_index: ',decinput(k),dec2bin(decinput(k),3))
disp(Ant_index)
end
Which yields:
Decimal input= 0 Binary= 000 Ant_index: 1
Decimal input= 1 Binary= 001 Ant_index: 2
Decimal input= 2 Binary= 010 Ant_index: 3
Decimal input= 3 Binary= 011 Ant_index: 4
Decimal input= 4 Binary= 100 Ant_index: 1 2
Decimal input= 5 Binary= 101 Ant_index: 1 3
Decimal input= 6 Binary= 110 Ant_index: 1 4
Decimal input= 7 Binary= 111 Ant_index: 2 3
You do ant_index = [0,0,1,1] for transmitting the symbol on antenna 1 and 2. Then do x_trans(ant_index == 1) = symbol. Hope that helps.
Related
How can I randomize and generate numbers from 0-50 in matrix of 5x5 with SUM or each row printed on the right side?
+
is there any way to give weight to individual numbers before generating the numbers?
Please help
Thanks!
To generate a random matrix of integers between 0 and 50 (sampled with replacement) you could use
M = randint(5,5,[0,50])
To print the matrix with the sum of each row execute the following command
[M sum(M,2)]
To use a different distribution there are a number of techniques but one of the easiest is to use the datasample function from the Statistics and Machine Learning toolbox.
% sample from a truncated Normal distribution. No need to normalize
x = 0:50;
weights = exp(-0.5*(x-25).^2 / 5^2);
M = reshape(datasample(x,25,'Weights',weights),[5,5])
Edit:
Based on your comment you want to perform random sampling without replacement. You can perform such a random sampling without replacement if the weights are non-negative integers by simulating the classic ball-urn experiment.
First create an array containing the appropriate number of each value.
Example: If we have the values 0,1,2,3,4 with the following weights
w(0) = 2
w(1) = 3
w(2) = 5
w(3) = 4
w(4) = 1
Then we would first create the urn array
>> urn = [0 0 1 1 1 2 2 2 2 2 3 3 3 3 4];
then, we would shuffle the urn using randperm
>> urn_shuffled = urn(randperm(numel(urn)))
urn_shuffled =
2 0 4 3 0 3 2 2 3 3 1 2 1 2 1
To pick 5 elements without replacement we would simple select the first 5 elements of urn_shuffled.
Rather than typing out the entire urn array, we can construct it programatically given an array of weights for each value. For example
weight = [2 3 5 4 1];
urn = []
v = 0
for w = weight
urn = [urn repmat(v,1,w)];
v = v + 1;
end
In your case, the urn will contain many elements. Once you shuffle you would select the first 25 elements and reshape them into a matrix.
>> M = reshape(urn_shuffled(1:25),5,5)
To draw random integer uniformly distributed numbers, you can use the randi function:
>> randi(50,[5,5])
ans =
34 48 13 28 13
33 18 26 7 41
9 30 35 8 13
6 12 45 13 47
25 38 48 43 18
Printing the sum of each row can be done by using the sum function with 2 as the dimension argument:
>> sum(ans,2)
ans =
136
125
95
123
172
For weighting the various random numbers, see this question.
I have got a problem with splitting a vector by zeros.
I have a vector for example
v=[1 3 2 6 4 0 0 2 4 6 0 0 0 3 1]
I need to get vectors like
v1=[1 3 2 6 4]
v2=[2 4 6]
v3=[3 1]
Is there any way to do this by using MATLAB functions?
Of course I don't know of how many subvectors are included in main vector v and how many zeros delimits vectors.
I'm not a programmer and also I'm not a pro in MATLAB.
I know a procedural way to do this but want do it by MATLAB somehow.
I found a function A = strsplit(str,delimiter) but I don't have string I have a vector.
So I searched for conversion function. I found S = char(V) but when I executed it it crashed.
It's better to have the output as a cell array, not as separate variables. That way the output will be easier to handle.
Try this:
v = [1 3 2 6 4 0 0 2 4 6 0 0 0 3 1]; %// data
w = [false v~=0 false]; %// "close" v with zeros, and transform to logical
starts = find(w(2:end) & ~w(1:end-1)); %// find starts of runs of non-zeros
ends = find(~w(2:end) & w(1:end-1))-1; %// find ends of runs of non-zeros
result = arrayfun(#(s,e) v(s:e), starts, ends, 'uniformout', false); %// build result
Result (for your example):
>> result{:}
ans =
1 3 2 6 4
ans =
2 4 6
ans =
3 1
The strsplit() solution for a vector of whole numbers smaller than 9 (so a very specific solution, for a general solution see Luis Mendo's). Split and convert back to number:
res = strsplit(char(v), char(0));
res = cellfun(#(x) x - 0,res,'un',0);
celldisp(res)
res{1} =
1 3 2 6 4
res{2} =
2 4 6
res{3} =
3 1
In matlab I want to convert this:
12345.6788993442355456789
into a vector
[1 2 3 4 5 6 7 8 8 9 9 3 4 4 2 3 5 5 4 5 6 7 8 9]
I have found several solutions to convert a integer into a vector using commands like scanf, num2str,... but those don't fit with non-integers, and some solutions have problems with numbers with a large number of decimal places...
That kind of conversion is needed because I want to see and use all of the digits of the number.
What input source are you getting those numbers from? And are all those digits significant? Your example numbers are already beyond the relative precision of the double numeric type. The eps function will tell you how much roundoff you're getting.
>> sprintf('%.20f', 12345.6788993442355456789)
ans =
12345.67889934423500000000
>> eps(12345.6788993442355456789)
ans =
1.818989403545857e-012
>> sprintf('%.20f', 23432.23432345678911111111111100998)
ans =
23432.23432345678900000000
>> eps(23432.23432345678911111111111100998)
ans =
3.637978807091713e-012
When you type a number in to Matlab source code, it's treated as a literal of type double. So many of those digits are lost as soon as you enter them. See this question for more discussion: In MATLAB, are variables REALLY double-precision by default?.
If you really want to preserve all those digits, you need to avoid storing them in doubles in the first place. Start off with the full number in a string, and then parse it.
function out = parseLongDecimal(str)
ixDot = find(str == '.');
if isempty(ixDot)
out.whole = arrayfun(#str2double, str);
out.fraction = [];
else
out.whole = arrayfun(#str2double, str(1:ixDot-1));
out.fraction = arrayfun(#str2double, str(ixDot+1:end));
end
That will preserve all the digits.
>> xAsStr = '23432.23432345678911111111111100998'; % as a string literal, not numeric
>> parseLongDecimal(xAsStr)
ans =
whole: [2 3 4 3 2]
fraction: [2 3 4 3 2 3 4 5 6 7 8 9 1 1 1 1 1 1 1 1 1 1 1 1 0 0 9 9 8]
Depending on your use case, you could also just throw it in a Java BigDecimal object and work with it there.
>> jx = java.math.BigDecimal(xAsStr)
jx =
23432.23432345678911111111111100998
Also using num2str, you can do:
sol=arrayfun(#str2num,(sprintf('%f',23432.23432)),'UniformOutput',0)
horzcat(sol{:})
ans =
2 3 4 3 2 2 3 4 3
Do you want to keep the information about where is the comma?
Not familiar with Matlab syntax but if you
convert the number to a string
loop through each character and add the digit to the vector if the character is not the decimal point
that would work. There are probably more efficient ways to do this.
I would appreciate if someone showed me an easy way to do this. Let's say I have a vector in MATLAB like
d = [3 2 4 2 2 2 3 5 1 1 2 1 2 2 2 2 2 9 2]
I want to find the series of consecutive number "twos" and the lengths of those series.
Number twos can easily be found by x=find(d==2). But what I want is to get a vector which contains the lengths of all series of consecutive number twos, which means that my result in this case would be a vector like this:
[1 3 1 5 1].
Anyone who could help me?
This seems to work:
q = diff([0 d 0] == 2);
v = find(q == -1) - find(q == 1);
gives
v =
1 3 1 5 1
for me
This is called run length encoding. There is a good m-file available for it at http://www.mathworks.com/matlabcentral/fileexchange/4955-rle-deencoding . This method is generally faster than the previously posted diff/find way.
tic
d_rle = rle(d==2);
d_rle{2}(d_rle{1}==1);
toc
Elapsed time is 0.002632 seconds.
tic
q = [0 diff([0 d 0] == 2)];
find(q == -1) - find(q == 1);
toc
Elapsed time is 0.003061 seconds.
What if we want the indices of the original matrix where the consecutive values are located? Further, what if we want a matrix of the same size as the original matrix, where the number of consecutive values are stored in the indices of the consecutive values? For example:
original_matrix = [1 1 1;2 2 3; 1 2 3];
output_matrix = [3 3 3;2 2 0;0 0 0];
This problem has relevance for meteorological data quality control. For example, if I have a matrix of temperature data from a number of sensors, and I want to know what days had constant consecutive values, and how many days were constant, so I can then flag the data as possibly faulty.
temperature matrix is number of days x number of stations and I want an output matrix that is also number of days x number of stations, where the consecutive values are flagged as described above.
How can I determine the relative frequency of a value in a MATLAB vector?
vector = [ 2 2 2 2 1 1 1 2 2 1 1 1 2 2 2 2 1 2 ];
What function will return the number of occurrences of each unique element?
You can use unique in combination with histc to get the relative frequency.
A=[1,2,3,1,2,4,2,1]; %#an example vector
unqA=unique(A);
This gives the unique elements as unqA=[1,2,3,4]. To get the number of occurances,
countElA=histc(A,unqA); %# get the count of elements
relFreq=countElA/numel(A);
This gives countElA=[3,3,1,1] and relFreq=[0.3750, 0.3750, 0.1250, 0.1250], which is the relative frequency of the unique elements. This will work for both integers and floating points.
For the most general case where you have a vector of floating point values, you can use the functions UNIQUE and ACCUMARRAY:
[uniqueValues,~,uniqueIndex] = unique(vector);
frequency = accumarray(uniqueIndex(:),1)./numel(vector);
You can use the function tabulate. See this example with your vector.
vector = [ 2 2 2 2 1 1 1 2 2 1 1 1 2 2 2 2 1 2 ];
tabulate(vector);
Value Count Percent
1 7 38.89%
2 11 61.11%
If you need it in percent order, do:
t = tabulate(vector);
t = sortrows(t, 3)
Referring from this answer:
unqV = unique(vector);
y = zeros(size(unqV));
for i = 1:length(unqV)
y(i) = sum(unqV(i)==vector);
end
unqV = [1 2]
y = [7 11]