-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathrandic.m
60 lines (53 loc) · 1.91 KB
/
randic.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
% r = randic(imax,m)
%
% generate pseudorandom vector of integers in which all integers occur a
% given number of times and no two consecutive integers are equal
%
% in:
% imax - maximum integer defining the admissible interval 1:imax
% m - number of times each integer should occur in r, may be a
% scalar (each integer occurs equally frequently), or a
% vector (each integer occurs with the given number of
% times), then:
% [1,imax] = size
% out:
% r - vector of pseudorandom integers
% [sum(m), 1] = size
% author:
% Sebastian Bitzer
function r = randic(imax,m)
unsuccessfull = true;
while unsuccessfull
try
if numel(m) == 1
counts = m * ones(1,imax);
else
counts = m;
end
N = sum(counts);
% initial random integer (unconstrained)
r = [randi(imax,1); nan(N-1,1)];
counts(r(1)) = counts(r(1)) - 1;
for i = 2:N
% candidate integers
candid = 1:imax;
% remove those excluded by constraints
consti = [r(i-1), find(counts<=0)];
candid = setdiff(candid,consti);
% choose random integer
r(i) = candid(randi(length(candid),1));
% update counts
counts(r(i)) = counts(r(i)) - 1;
end
unsuccessfull = false;
catch err
if strcmp(err.identifier,'MATLAB:RandStream:randi:invalidLimits')
% this happens when the constraints have removed all integers
% from the pool (e.g., the only integer left according to
% counts is "2", but "2" was already chosen in previous step)
warning('helpers:restart','Ran in a gridlock when generating pseudorandom integers, restart.')
else
rethrow(err)
end
end
end