简体   繁体   中英

Matlab Pseudo Random Integer with frequency constraints

I am relatively new to MATLAB and I need to design a 200x1 matrix, which is filled with random integers that can be either 1/2/3/4, so 4 possible numbers. However, in the matrix I want '1' to occur 70% (thus a total frequency of 140 for number 1), '2', '3' and '4', to occur 10% (thus a frequency of 20 for 2,3 and 4).

Moreover, I want the matrix to be filled so that the values of 2,3, and 4 never display a consecutive repeat, but that 1 may feature consecutive repeats (as it takes 70%)

I had a solution (without the consecutive repeat constraint), using the repelem function. However, on the target PC, an older version of matlab is installed (2013) and does not include this function. Could someone provide me with a solution?

Thanks

You can use the following approach

%represents odds map for 1,2,3,4
oddsMap = [0,0.7,0.8,0.9]; 

N = 200;
isValid = false;

while ~isValid
    %generate vector
    probVect = rand(N,1);
    randVect = ones(N,1);
    for ii=1:length(oddsMap)
        randVect(probVect>=oddsMap(ii)) = ii;
    end

    %check [2,3,4] constraint
    isValid = isempty(findstr(randVect',[2,3,4]));
end

Here is one approach:

Algorithm and code

  • Create a 60 element vector, with the values 2, 3 and 4 (randomly ordered) appearing 20 times each.

     a = repmat([2;3;4],20,1); % Create vector of [2;3;4] 20 times a = a(randperm(numel(a))); % Randomise intial vector 
  • Get the indices of all locations where there are equal consecutive values.

     d = find(diff(a)==0); 
  • Get the maximum number of ones which you could put at every one of these locations to break up consecutives.

     maxones = floor(200/numel(d)); 
  • Put between 1 and maxones number of ones at each location. This is to try and maintain some amount of "randomness", could just put one at each location to break them up!

     for ii = numel(d):-1:1; a = [ a(1:d(ii)) ; ones(randi(maxones), 1) ; a(d(ii)+1:end) ]; end 
  • Now randomly add the remaining number of ones to make the vector 200 elements long

     idx = randperm(numel(a), 200 - numel(a)); for ii = numel(idx):-1:1; a = [ a(1:idx(ii)); 1 ; a(idx(ii)+1:end) ]; end 

Verification

Output is a 200 element vector, with 20 elements each with the value 2, 3 or 4, and 140 elements have the value 1.

% Using nnz (number of non-zero elements) to count matching condition 
nnz(a == 1) % = 140
nnz(a == 2) % = 20
nnz(a == 3) % = 20
nnz(a == 4) % = 20

No consecutive 2s, 3s or 4s:

% Get number of elements where difference to next is 0, and value isn't 1
nnz([false; diff(a) == 0] & a ~= 1) % = 0

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM