Path: news.mathworks.com!not-for-mail
From: "Bruno Luong" <b.luong@fogale.findmycountry>
Newsgroups: comp.soft-sys.matlab
Subject: Re: Generate random numbers with fixed sum and different constraints
Date: Mon, 19 Nov 2012 06:39:13 +0000 (UTC)
Organization: FOGALE nanotech
Lines: 63
Message-ID: <k8ck6h$lhp$1@newscl01ah.mathworks.com>
References: <k80995$9eo$1@newscl01ah.mathworks.com> <k87s11$h6u$1@newscl01ah.mathworks.com> <k88l7g$7tm$1@newscl01ah.mathworks.com> <k88qag$nm1$1@newscl01ah.mathworks.com> <k89ehg$rm6$1@newscl01ah.mathworks.com> <k8b4e9$ja7$1@newscl01ah.mathworks.com> <k8badi$8rd$1@newscl01ah.mathworks.com>
Reply-To: "Bruno Luong" <b.luong@fogale.findmycountry>
NNTP-Posting-Host: www-06-blr.mathworks.com
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 8bit
X-Trace: newscl01ah.mathworks.com 1353307153 22073 172.30.248.38 (19 Nov 2012 06:39:13 GMT)
X-Complaints-To: news@mathworks.com
NNTP-Posting-Date: Mon, 19 Nov 2012 06:39:13 +0000 (UTC)
X-Newsreader: MATLAB Central Newsreader 390839
Xref: news.mathworks.com comp.soft-sys.matlab:783046

Sorry, I miss the definition of the variable 'tol' in my previous posted code; here we go again:

% lower + upper bounds
lo = [1 0 2 1 0];
up = [5 6 4 4 2];
% target sum
s = 15;
% number of samples
n = 1000;

%% Engine
m = length(lo);
slo = sum(lo);
sup = sum(up);

% A particular solution, x0
x0 = interp1([slo; sup], [lo; up], s);
if any(isnan(x0))
    error('no solution exists')
end

% feasible set: S = { x=x0+A*y : A*y <= b }
x0 = x0(:);
B = null(ones(size(lo)));
A = [-B; B];
b = [x0-lo(:); up(:)-x0];

% FEX: http://www.mathworks.com/matlabcentral/fileexchange/30892
tol = 1e-6;
[V,nr,nre] = lcon2vert(A,b,[],[],tol);

% Split S in simplex
T = delaunayn(V);
P = V(T,:);
P = reshape(P, [size(T) m-1]);
P = permute(P, [3 2 1]);
np = size(P,3);

% Compute the volume of simplexes
Q = bsxfun(@minus, P, P(:,end,:));
Q(:,end,:) = [];
vol = arrayfun(@(k) det(Q(:,:,k)), 1:np);
vol = abs(vol);

% generate n samples (i) of v with probability ~ vol
vol = vol / sum(vol);
c = cumsum(vol); c(end)=1;
[~, i] = histc(rand(1,n),[0 c]);

% Random rarycentric coordinates
% FEX: http://www.mathworks.com/matlabcentral/fileexchange/9700
w = randfixedsum(m,n,1,0,1);

% Put together
V = P(:,:,i);
y = zeros(m-1, n);
for k=1:n
    y(:,k) = V(:,:,k)*w(:,k);
end
% final result, m x n array of random vector
x = bsxfun(@plus, x0, B*y);

% Bruno