给定向量大小N,我想生成一个向量
<s1,s2, ..., sn>
,使得s1+s2+...+sn = S
。已知0<S<1
和si < S
。此外,所生成的向量应该是均匀分布的。任何用C编写的代码都可以帮助解释问题!这段代码在这里似乎可以解决问题,但它相当复杂。
我可能会选择一个更简单的基于拒绝的算法,即:从超平面的法向量开始,在n维空间中选择一个正交基。将每个点(S,0,0,0..0),(0,S,0,0..0)转换为该基础并沿着每个基向量存储最小值和最大值。在新的基础上均匀采样每个分量,除了第一个分量(法向量),它总是S,然后转换回原始空间并检查是否满足约束条件。如果不满足,则重新采样。
P.S. 我认为这更多是一个数学问题,实际上,询问http://maths.stackexchange.com或http://stats.stackexchange.com可能是一个好主意。
n-1
个维度。这样,在变换后,任何结果点都将在超平面上,但我们仍然需要检查它是否在界限内。例如,对于三维空间,我们将从超平面上的某个正方形区域进行抽样,然后拒绝不落入三角形内部的样本。 - QnanO(n)
,其中n是维度。但是随着n的增长,接受概率会下降(通常在基于拒绝的方法中都会如此)。如果选择最优的基底,接受概率将等于从超平面采样到其最小包围的n-1
维立方体的比例。我上面提到的Matlab代码对于较高的n值更有效,并且重新实现为C语言应该不会花费太长时间,因为它似乎没有使用比矩阵运算更复杂的东西。 - Qnan第一个要求是获得垂直于超平面的向量。对于N个变量的总和,这是n = (1,...,1)。第二个要求是平面上的一个点。对于您的示例,可以是p = (S,...,S)/N。
现在,平面上的任何点都满足n^T * (x - p) = 0
我们还假设x_i >= 0
有了这些条件,您可以在平面上计算正交基(向量n的零空间),然后在该基础上创建随机组合。最后,您将映射回原始空间并对生成的样本应用约束。
# Example in 3D
dim = 3;
S = 1;
n = ones(dim, 1); # perpendicular vector
p = S * ones(dim, 1) / dim;
# null-space of the perpendicular vector (transposed, i.e. row vector)
# this generates a basis in the plane
V = null (n.');
# These steps are just to reduce the amount of samples that are rejected
# we build a tight bounding box
bb = S * eye(dim); # each column is a corner of the constrained region
# project on the null-space
w_bb = V \ (bb - repmat(p, 1, dim));
wmin = min (w_bb(:));
wmax = max (w_bb(:));
# random combinations and map back
nsamples = 1e3;
w = wmin + (wmax - wmin) * rand(dim - 1, nsamples);
x = V * w + p;
# mask the points inside the polytope
msk = true(1, nsamples);
for i = 1:dim
msk &= (x(i,:) >= 0);
endfor
x_in = x(:, msk); # inside the polytope (your samples)
x_out = x(:, !msk); # outside the polytope
# plot the results
scatter3 (x(1,:), x(2,:), x(3,:), 8, double(msk), 'filled');
hold on
plot3(bb(1,:), bb(2,:), bb(3,:), 'xr')
axis image
可能的一个想法是:在某个包含体积中生成许多均匀分布的点,并将它们投射到平面的目标部分上。
为了获得均匀分布,该体积必须呈现出平面部分的形状,但沿着平面法线添加边缘。
要在这样的体积中均匀地生成点,我们可以将其包围在一个立方体中,并拒绝所有位于体积之外的点。
(0, S-sum)
内生成数字,其中sum
是迄今为止生成的所有数字的总和,然后对列表进行洗牌。不过我觉得这个方法并不够均匀。:| - amit