MATLAB Vector: Prevent Sequential Values ​​from One Range

Well, this may seem like a strange question, but carry me.

So, I have a random vector in a .m file with certain limitations built into it. Here is my code:

randvecall = randsample(done, done, true); randvec = randvecall([1;diff(randvecall(:))]~=0); 

Done is just a range of values ​​from which we take a sample, so don't worry about it. As you can see, this changes the range of values ​​and then cuts out this random vector using the diff function, so that duplicate duplicate values ​​are removed. There is still potential for repeating values ​​in a vector, but they simply cannot be sequential.

It is good and good, and works great.

So let's say randvec looks like this:

 randvec = 54 47 52 26 39 2 14 51 24 6 19 56 34 46 12 7 41 18 29 7 

Actually it is much longer, with something like 60-70 values, but you get the point.

I want to add a little extra restriction on this vector. When I take a sample from this vector, the values ​​are classified according to their range. Thus, values ​​from 1-15 belong to category 1, 16-30 belong to category 2, etc. The reasons for this are not significant, but this is a rather important part of the program. Therefore, if you look at the above values, you will see a section like this:

  7 41 18 29 7 

This is really bad for my program. Since the ranges of values ​​are processed separately, 41, 18 and 29 are used in different ways than 7. So, for all purposes and tasks, 7 appears sequentially in my script. What I want to do is somehow parse / modify / regardless of the vector when it is generated so that the same number from a certain range does not appear twice "in a row", no matter how many other numbers from different ranges located between them. Does this make sense / have I described it well? So, I want MATLAB to search for a vector, and for all values ​​in certain ranges (1-15,16-30,31-45,46-60) make sure that the "consecutive" values ​​from the same range are not identical.

So here is what I want to do. This in no way may be the best way to do this, so any tips / alternatives are certainly appreciated. I know that I can do it better with multiple vectors, but for various reasons I need it to be one long vector (as my script project was designed, it just wouldn't work if I had a separate vector for each range values).

+4
source share
4 answers

What you can do is create four random vectors, one for each category, ensure that they do not contain any two consecutive equal values, and then build your final random vector by an ordered set of values ​​from random categories, i.e.

 %# make a 50-by-nCategories array of random numbers categories = [1,16,31,46;15,30,45,60]; %# category min/max nCategories = size(categories,2); randomCategories = zeros(50,nCategories); for c=1:nCategories %# draw 100 numbers for good measure tmp = randi(categories(:,c),[100 1]); tmp(diff(tmp==0)) = []; %# remove consecutive duplicates %# store randomCategories(:,c) = tmp(1:50); end %# select from which bins to pick. Use half the numbers, so that we don't force the %# numbers of entries per category to be exactly equal bins = randi(nCategories,[100,1]); %# combine the output, ie replace eg the numbers %# '3' in 'bins' with the consecutive entries %# from the third category out = zeros(100,1); for c = 1:nCategories cIdx = find(bins==c); out(cIdx) = randomCategories(1:length(cIdx),c); end 
+3
source

First, we assign each element the cell number of the range in which it is located:

 [~,bins] = histc(randvec, [1 16 31 46 61]); 

Next, we loop for each range and find elements in these categories. For example, for the first range 1-16 we get:

 >> ind = find(bins==1); %# bin#1 of 1-16 >> x = randvec(ind) ans = 2 14 6 12 7 7 

you can now apply the same process to remove consecutive duplicates:

 >> idx = ([1;diff(x)] == 0) idx = 0 0 0 0 0 1 >> problematicIndices = ind(idx) %# indices into the vector: randvec 

Do this for all ranges and collect these problematic indices. Then decide how you want to deal with them (delete them, generate other numbers in your place, etc.)

+2
source

If I understand your problem correctly, I think this is one solution. It uses a unique one, but applies it to each of the subranges of the vector. Values ​​that are duplicated within the range of indices are identified so that you can handle them.

 cat_inds = [1,16,31,46,60]; % need to include last element for i=2:numel(cat_inds) randvec_part = randvec( cat_inds(i-1):cat_inds(i) ); % Find the indices for the first unique elements in this part of the array [~,uniqInds] = unique(randvec_part,'first'); % this binary vector identifies the indices that are duplicated in % this part of randvec % % NB: they are indices into randvec_part % inds_of_duplicates = ~ismember(1:numel(randvec_part), uniqInds); % code to deal with the problem indices goes here. Modify randvec_part accordingly... % Write it back to the original vector (assumes that the length is the same) randvec( cat_inds(i-1):cat_inds(i) ) = randvec_part; end 
+1
source

Here's a different approach than what everyone else threw. The premise I'm working on right now is that you want to have a random arrangement of values ​​in a vector without reprocessing. I'm not sure what other restrictions you apply until the moment we issue the input.

My thoughts is to use the randperm function.

Here is an example of how it will work:

 %randvec is your vector of random values randvec2 = unique(randvec); % This will return the sorted list of values from randvec. randomizedvector = randvec2(randperm(length(randvec2)); % Note: if randvec is multidimensional you'll have to use numel instead of length 

At this point, randomizedvector should contain all the unique values ​​from the initial randvec , but "shuffled" or re-randomized after a unique function call. Now you can just split randvec differently to avoid having to call a unique function, since just calling randperm(n) will return a randomized vector with values ​​from 1 to n.

Just off the wall 2 cents there = P enjoy!

+1
source

All Articles