LINE Solver
MATLAB API documentation
Loading...
Searching...
No Matches
randfixedsum.m
1function [x,v] = randfixedsum(n,m,s,a,b)
2% Credit: https://www.mathworks.com/matlabcentral/fileexchange/9700-random-vectors-with-fixed-sum
3%
4% [x,v] = randfixedsum(n,m,s,a,b)
5%
6% This generates an n by m array x, each of whose m columns
7% contains n random values lying in the interval [a,b], but
8% subject to the condition that their sum be equal to s. The
9% scalar value s must accordingly satisfy n*a <= s <= n*b. The
10% distribution of values is uniform in the sense that it has the
11% conditional probability distribution of a uniform distribution
12% over the whole n-cube, given that the sum of the x's is s.
13%
14% The scalar v, if requested, returns with the total
15% n-1 dimensional volume (content) of the subset satisfying
16% this condition. Consequently if v, considered as a function
17% of s and divided by sqrt(n), is integrated with respect to s
18% from s = a to s = b, the result would necessarily be the
19% n-dimensional volume of the whole cube, namely (b-a)^n.
20%
21% This algorithm does no "rejecting" on the sets of x's it
22% obtains. It is designed to generate only those that satisfy all
23% the above conditions and to do so with a uniform distribution.
24% It accomplishes this by decomposing the space of all possible x
25% sets (columns) into n-1 dimensional simplexes. (Line segments,
26% triangles, and tetrahedra, are one-, two-, and three-dimensional
27% examples of simplexes, respectively.) It makes use of three
28% different sets of 'rand' variables, one to locate values
29% uniformly within each type of simplex, another to randomly
30% select representatives of each different type of simplex in
31% proportion to their volume, and a third to perform random
32% permutations to provide an even distribution of simplex choices
33% among like types. For example, with n equal to 3 and s set at,
34% say, 40% of the way from a towards b, there will be 2 different
35% types of simplex, in this case triangles, each with its own
36% area, and 6 different versions of each from permutations, for
37% a total of 12 triangles, and these all fit together to form a
38% particular planar non-regular hexagon in 3 dimensions, with v
39% returned set equal to the hexagon's area.
40%
41% Roger Stafford - Jan. 19, 2006
42
43% Check the arguments.
44if (m~=round(m))|(n~=round(n))|(m<0)|(n<1)
45 error('n must be a whole number and m a non-negative integer.')
46elseif (s<n*a)|(s>n*b)|(a>=b)
47 error('Inequalities n*a <= s <= n*b and a < b must hold.')
48end
49
50% Rescale to a unit cube: 0 <= x(i) <= 1
51s = (s-n*a)/(b-a);
52
53% Construct the transition probability table, t.
54% t(i,j) will be utilized only in the region where j <= i + 1.
55k = max(min(floor(s),n-1),0); % Must have 0 <= k <= n-1
56s = max(min(s,k+1),k); % Must have k <= s <= k+1
57s1 = s - [k:-1:k-n+1]; % s1 & s2 will never be negative
58s2 = [k+n:-1:k+1] - s;
59w = zeros(n,n+1); w(1,2) = realmax; % Scale for full 'double' range
60t = zeros(n-1,n);
61tiny = 2^(-1074); % The smallest positive matlab 'double' no.
62for i = 2:n
63 tmp1 = w(i-1,2:i+1).*s1(1:i)/i;
64 tmp2 = w(i-1,1:i).*s2(n-i+1:n)/i;
65 w(i,2:i+1) = tmp1 + tmp2;
66 tmp3 = w(i,2:i+1) + tiny; % In case tmp1 & tmp2 are both 0,
67 tmp4 = (s2(n-i+1:n) > s1(1:i)); % then t is 0 on left & 1 on right
68 t(i-1,1:i) = (tmp2./tmp3).*tmp4 + (1-tmp1./tmp3).*(~tmp4);
69end
70
71% Derive the polytope volume v from the appropriate
72% element in the bottom row of w.
73v = n^(3/2)*(w(n,k+2)/realmax)*(b-a)^(n-1);
74
75% Now compute the matrix x.
76x = zeros(n,m);
77if m == 0, return, end % If m is zero, quit with x = []
78rt = rand(n-1,m); % For random selection of simplex type
79rs = rand(n-1,m); % For random location within a simplex
80s = repmat(s,1,m);
81j = repmat(k+1,1,m); % For indexing in the t table
82sm = zeros(1,m); pr = ones(1,m); % Start with sum zero & product 1
83for i = n-1:-1:1 % Work backwards in the t table
84 e = (rt(n-i,:)<=t(i,j)); % Use rt to choose a transition
85 sx = rs(n-i,:).^(1/i); % Use rs to compute next simplex coord.
86 sm = sm + (1-sx).*pr.*s/(i+1); % Update sum
87 pr = sx.*pr; % Update product
88 x(n-i,:) = sm + pr.*e; % Calculate x using simplex coords.
89 s = s - e; j = j - e; % Transition adjustment
90end
91x(n,:) = sm + pr.*s; % Compute the last x
92
93% Randomly permute the order in the columns of x and rescale.
94rp = rand(n,m); % Use rp to carry out a matrix 'randperm'
95[ig,p] = sort(rp); % The values placed in ig are ignored
96x = (b-a)*x(p+repmat([0:n:n*(m-1)],n,1))+a; % Permute & rescale x
97
98return