将矢量乘以随机数,同时保持总和相同(MATLAB)

时间:2014-12-06 15:31:07

标签: matlab

我试图将(长度为N)的向量V乘以(a,b)范围内随机生成的数字,同时保持向量的总和等于总量E.我想要在MATLAB中这样做,但我不知道如何。获取某个范围之间的随机数我知道该怎么做:

minrand = 0;
maxrand = 1;
randfac = (maxrand-minrand).*rand(1,N) + minrand;

但是,除此之外,我很无能为力。我猜这些随机数不能真正生成,因为如果我们将随机数称为向量R,那么我想要那样 R_1 * V1 + R_2 * V2 .... + R_N * V_N = E.所以我猜这是一个很大的等式。有没有办法解决它,同时对R?

的最大值和最小值设置约束

4 个答案:

答案 0 :(得分:2)

您可以选择两个元素对(在所有组合中)并添加和减去相等的随机数。

% Make up a random vector
N=10;
randfac = 10*rand(1,N);

%OP Answer here:  Given randfac with sum E re-randomize it
E = sum(randfac);
minrand = 0;
maxrand = 2;

disp(randfac)
% v = [6.4685    2.9652    6.6567    1.6153    7.3581    0.0237    7.1025
% 3.2381    1.9176    1.3561]
disp(sum(randfac))
% E = 38.7019

r = minrand + (maxrand-minrand)*rand(N*N,1);

k = 1;
for i=1:N
    for j=1:N
        randfac(i) = randfac(i)-r(k);
        randfac(j) = randfac(j)+r(k);
        k = k + 1;
    end
end

disp(randfac)
% v = [5.4905    0.7051    4.7646    1.3479    9.3722   -1.4222    7.9275
% 7.5777    1.7549    1.1836]
disp(sum(randfac))
% E = 38.7019

答案 1 :(得分:1)

只需将矢量除以总和并乘以目标E

randfac = (maxrand-minrand).*rand(1,N) + minrand;
randfac = E*randfac/sum(randfac);

只要算子是线性的,结果就是保持它的随机性。以下是一些示例代码:

minrand = 0;
maxrand = 1;
N = 1000; %size
v = (maxrand-minrand).*rand(1,N) + minrand;
E = 100; %Target sum
A = sum(v);
randfac = (E/A)*v;

disp(sum(randfac))
% 100.0000

答案 2 :(得分:1)

首先,在[a b]的区间内使用随机数,您不能保证您将获得相同的求和(相同E)。例如,如果[a b]=[1 2]当然E会增加。

这是一个想法,我不知道这有多随意!

对于even N我随机化V然后将其分成两行,并将其中一个与[a b]中的随机数相乘,但第二列将乘以一个向量来保持求和固定的。

N = 10;
V = randi(100,[1 N]);
E = sum(V);
idx = randperm(N);
Vr = V(idx);
[~,ridx] = sort(idx);
Vr = reshape(Vr,[2 N/2]);
a = 1;
b = 3;
r1 = (b - a).*rand(1,N/2) + a;
r2 = (sum(Vr) - r1.*Vr(1,:))./Vr(2,:);
r = reshape([r1;r2],1,[]);
r = r(ridx);
Enew = sum(V.*r);

示例结果是,

V = [12      82      25      51      81      51      31      87      6       74];
r = [2.8018  0.7363  1.9281  0.5451  1.9387 -0.4909  1.3076  0.8904  2.9236  0.8440];

E = 500以及Enew

我只是将一个随机数分配给一对(它可以被视为半随机!)。

答案 3 :(得分:0)

好的,我已经找到了一种方法可以做到这一点,但它并不优雅,可能有更好的解决方案。从初始向量e开始,其中sum(e)= E,我可以随机化其值并以e结束,其中sum(e)在[(1-threshold) E的范围内,(1 +阈值 E)]。它计算量很大,而且不漂亮。

这个想法是首先将e乘以某个范围内的随机数。然后,我将检查总和是多少。如果它太大,我会减小小于范围一半的随机数的值,直到总和不再太大。如果它太小,我会进行相反的操作,并进行迭代,直到总和在所需的范围内。

e = somepredefinedvector
minrand = 0;
maxrand = 2;
randfac = (maxrand-minrand).*rand(1,N) + minrand;
e = randfac.*e;
threshold = 0.001;

while sum(e) < (1-threshold)*E || sum(e) > (1+threshold)*E
    if sum(e) > (1+threshold)*E
        for j = 1:N
            if randfac(j) > (maxrand-minrand)/2
                e(j) = e(j)/randfac(j);
                randfac(j) = ((maxrand-minrand)/2-minrand).*rand(1,1) + minrand;
                e(j) = randfac(j)*e(j);
            end
            if sum(e) > (1-threshold)*E && sum(e) < (1+threshold)*E
                break
            end
        end
    elseif sum(e) < (1-threshold)*E
        for j = 1:N
            if randfac(j) < (maxrand-minrand)/2
                e(j) = e(j)/randfac(j);
                randfac(j) = (maxrand-(maxrand-minrand)/2).*rand(1,1) + (maxrand-minrand)/2;
                e(j) = randfac(j)*e(j);
            end
            if sum(e) > (1-threshold)*E && sum(e) < (1+threshold)*E
                break
            end
        end
    end
end