pseudorandomize using brute force

9 vues (au cours des 30 derniers jours)
Nilgun Turkileri
Nilgun Turkileri le 7 Juin 2016
Modifié(e) : John D'Errico le 9 Juin 2016
Hi,
I have a vector consisted of 79 ones and 316 zeros. I would like to randomly order my vector so that a "1" can only occur after 3 or more zeros occur consecutively. So, my codes is as following:
A = [zeros(316,1); ones(79,1)];
%shuffle randomly
nTrials = size(A,1);
RandTrials = randperm(nTrials)';
A(:,2)=RandTrials(:,1);
A=sortrows(A,2);
for t=RandTrials %runs A vector by vector
if A(t,1)==1 & A(t-1,1)==0 & A(t-2,1)==0 & A(t-3,1)==0
; %do nothing
elseif A(t,1)==1 & A(t-1,1)==1;
RandTrials = randperm(nTrials)';
A(:,2)=RandTrials(:,1);
A=sortrows(A,2);
elseif A(t,1)==1 & A(t-1,1)==1 & A(t-1,2)==1;
RandTrials = randperm(nTrials)';
A(:,2)=RandTrials(:,1);
A=sortrows(A,2);
elseif A(t,1)==1 & A(t-1,1)==1 & A(t-1,2)==1 & A(t-1,3)==1;
RandTrials = randperm(nTrials)';
A(:,2)=RandTrials(:,1);
A=sortrows(A,2);
end
end
I was wondering what I am doing wrong in this code. Hope someone can help me on this.
Thanks in advance,
Nil
  2 commentaires
Walter Roberson
Walter Roberson le 8 Juin 2016
Please recheck the number of zeros. 315 or 316?
Nilgun Turkileri
Nilgun Turkileri le 8 Juin 2016
Hi Walter,
Thanks! I just edited that part although that was not crucial. I also realized the confusion on number of zeros and number of ones that you pointed out in your first comment and edited that.

Connectez-vous pour commenter.

Réponses (2)

Walter Roberson
Walter Roberson le 7 Juin 2016
If a 1 can only occur after 3 or more zeros, then you need at least 3 times as many 0 as you have 1. As you have 315 ones, you would need at least 945 zeros.
Note: your code accidentally reverses the number of 0's and 1's.
  2 commentaires
Walter Roberson
Walter Roberson le 7 Juin 2016
You might want to have a look at http://www.mathworks.com/matlabcentral/answers/282617-how-to-do-this-operation-on-a-random-matrix#comment_364318 and grab my partitions routine there and modify it to have a minimum number of items per partition. The idea would be that you would partition (total length minus number of ones) into (number of ones) pieces, each of minimum length 3, and then you would take [zeros(1, number_in_partition), 1] as the substructure.
Nilgun Turkileri
Nilgun Turkileri le 8 Juin 2016
Thank you very much for your reply. Actually, your codes seem a bit advanced to me as I am new to Matlab. Another suggestion I get from a colleague today was to find the derivates from the first 1 to the second 1, from the second 1 to the third 1 and so on. This will be inside a while loop that has 100000 (or so) iterations to shuffle the vector. Inside that while, run a loop that if the derivate is larger than 3, it will break the loop; if not, it will return while loop many times (i.e., 100000). The only downside of this is to take so much time to finish.
Thanks,
Nil

Connectez-vous pour commenter.


John D'Errico
John D'Errico le 8 Juin 2016
Modifié(e) : John D'Errico le 8 Juin 2016
Even after the repair, correcting the number of zeros and ones...
You have 79 ones, and 316 zeros. The requirement is that a one may ONLY appear after 3 zeros have appeared.
So at the very best, a 1 may appear at position 4, then 8, then 12, etc. You see the pattern. The indexes of the ones elements appear at locations:
(1:79)*4
Ok, that is a COMPLETELY non-random sequence. But is it the shortest possible such sequence. It would account for
3*79
ans =
237
Thus 237 zeros.
316 - 3*79
ans =
79
You wish to always have 316 zeros. So there must be 79 more zeros.
The solution is now trivial. Just start with the NON-random sequence.
S = zeros(1,316);
S(4:4:316) = 1;
Now, choose random insertion points, and add a zero at that location. You can do it using a loop if you wish, one zero at a time. This is the simplest solution.
for i = 1:79
ns = numel(S);
% New location of a zero,
% after the newind location in S
newind = randi(ns+1,1) - 1;
S = [S(1:newind),0,S((newind+1):end);
end
I'm feeling too lazy to do it more intelligently, but that would be entirely possible too. Since it is hardly worthwhile to optimize code that is not yet asking to be optimized...
  3 commentaires
Alan Weiss
Alan Weiss le 9 Juin 2016
I believe that you misunderstood John's suggestion. He says the following:
  • Create a nonrandom sequence of 0 and 1 having the property that you want, using all but 79 of your zeros
  • Insert the 79 other zeros into the nonrandom sequence in a random way.
I believe that this is a fine idea, satisfying your requirements in all respects, and is an efficient computational scheme.
Alan Weiss
MATLAB mathematical toolbox documentation
John D'Errico
John D'Errico le 9 Juin 2016
Modifié(e) : John D'Errico le 9 Juin 2016
Alan is completely correct. While it starts out as non-random, once you are done inserting randomly placed zeros, it is exactly that, and it has the property that you want to see, AND it is quite efficient.
The virtue of the scheme that I have proposed is in the end, you do have a fully random sequence that fits all of your requirements. Were you to try instead to choose how many zeros to place between the ones, then you would have a serious problem of assuring both that the total number of zeros is what was specified, and that every one has at least 3 zeros.
In fact, this is a fairly tightly constrained problem. You don't have that many spare zeros to insert there. On average, you will have 4 zeros between every one, but since you know that you MUST have at least 3 zeros, then there will be very few cases where you can have too many zeros separating a pair of ones.

Connectez-vous pour commenter.

Catégories

En savoir plus sur Surrogate Optimization dans Help Center et File Exchange

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by