Replacing duplicates in a vector of required length

2 views (last 30 days)
Hi there, I am simulating events of different durations and am stuck about how to replace duplicate values in my vector. This is what I have so far:
To create 14 events that occur for a range of 120 to 300 seconds (the total number seconds of all 14 events must add up to 2880 seconds).
du=round(randfixedsum(14,1,2880,120,300))
To generate start times for each event:
st=randperm(28800,14)
duration = du’
m = cumsum(duration);
t = m - duration + 1; s = zeros(1,m(end));
s(t) = 1;
ii = cumsum(s);
out = (1:m(end)) - t(ii) + st(ii);
sort(out)'
out=unique(out)
I end up with a list of seconds during which these events are occurring, but the total seconds now falls short of the required (2880s) as I have removed the duplicates. How do I replace these duplicates so that all the requirements are met (i.e., all the variables in this - du=round(randfixedsum(14,1,2880,120,300)).
I hope this makes sencec, any help is greatly appreciated!

Accepted Answer

Roger Stafford
Roger Stafford on 26 Aug 2013
If you are not concerned with duplicates in 'du', here is a method which only calls on 'randfixedsum' once, but adjusts an offset so as to obtain the desired sum when rounded to integers:
x = randfixedsum(14,1,2880,120,300);
tp = .5; tm = -.5;
for k = 1:53
t0 = (tp+tm)/2;
du = round(x+t0); % Round with offset
e = sum(du)-2880;
if e > 0, tp = t0;
elseif e < 0, tm = t0;
else break % Break out when sum is correct
end
end
The same would apply to the calculation I recommended for the intervals between "events" for which you might presumably call on 'randfixedsum' with:
x = randfixedsum(15,1,25920,0,25920);
(or perhaps you have some other constraint to place on these intervals between "events" tnan merely lying between 0 and 25920.)

More Answers (1)

Roger Stafford
Roger Stafford on 26 Aug 2013
I ran your computation
du=round(randfixedsum(14,1,2880,120,300));
several thousand times and found that the odds of getting a sum of exactly 2880 without any duplications are about one in four, which are not bad odds. I would suggest you use a while-loop to repeat this calculation until it succeeds, which on the average would require about four repetitions.
b = true;
while b
du=round(randfixedsum(14,1,2880,120,300));
b = sum(du)~=2880 | any(diff(sort(du))==0);
end
(Of course if those numbers: 120, 300, 14, and 2880, are altered, that would change the probability of success.)
  2 Comments
Rebecca
Rebecca on 26 Aug 2013
Thanks so much for your answer - I appreciate the help. Duplications in du are ok as these are event durations (although the loop you wrote is really useful). I am getting overlaps in the events, however. Is there a way to get st in a way that once you add each du to each st value, there are no overlaps (sorry, this is quite hard to articulate)? Any advice? Thanks so much.
Roger Stafford
Roger Stafford on 26 Aug 2013
The details of what you are trying to achieve are still unclear, but I have the impression that you want something like this. You have 14 events, each of which must last an integral number of seconds, and their total time should be 2880 seconds. These events should be placed in a larger interval of time lasting 28800 seconds with random starting times but such that the event intervals don't overlap. Is that roughly what you are after?
There is no need to randomize the ordering of the event times, since that is already done by 'randfixedsum'. What I think you need is a second application of 'randfixedsum' for the 15 intervals between events, before the first one, or after the last one, accompanied also by a 'round' operation for which the sum is exactly 28800-2880 (or something like that anyway.) From this you can generate all starting times. You are getting into trouble trying to use 'randperm' to generate those starting times.

Sign in to comment.

Categories

Find more on Creating and Concatenating Matrices in Help Center and File Exchange

Community Treasure Hunt

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

Start Hunting!