Hello there, For example; If I want to generate 5 random integer numbers with a sum of 20, how can I do that?
" ... example = ceil(10*rand(100, 5)) ... "

1 commentaire

Rik
Rik le 20 Déc 2020
Why did you edit away your question? It is stored on Google cache anyway, so it's easy to restore.

Connectez-vous pour commenter.

 Réponse acceptée

Roger Stafford
Roger Stafford le 4 Mar 2017
function R = randfixedsumint(m,n,S);
% This generates an m by n array R. Each row will sum to S, and
% all elements are all non-negative integers. The probabilities
% of each possible set of row elements are all equal.
% RAS - Mar. 4, 2017
if ceil(m)~=m|ceil(n)~=n|ceil(S)~=S|m<1|n<1|S<0
error('Improper arguments')
else
P = ones(S+1,n);
for in = n-1:-1:1
P(:,in) = cumsum(P(:,in+1));
end
R = zeros(m,n);
for im = 1:m
s = S;
for in = 1:n
R(im,in) = sum(P(s+1,in)*rand<=P(1:s,in));
s = s-R(im,in);
end
end
end
return

6 commentaires

Walter Roberson
Walter Roberson le 4 Mar 2017
Thanks, Roger.
Could I point you to https://www.mathworks.com/matlabcentral/answers/327941-row-column-summation-constraints-in-random-binary-matrix ? My reframing of the problem there gets down to a constrained version of integer partitioning, where there is a per-bucket maximum.
Hello Walter & Roger, I just wanted to mention a certain way using the the partition method, which produces one vector 'c' at a time. I know how to vectorize it to make a matrix but have not done so yet (famous last words!). I make no claims on how this might compare with Roger's version.
% n = number of terms
% s = the sum
% zero allowed
a = randperm(s+n-1);
b = [0 a(1:n-1) s+n]; % 'a' makes up the separators
c = diff(sort(b))-1;
% zero not allowed
if n > s
error('sum is not large enough since all integers are >=1');
end
a = randperm(s-1);
b = [0 a(1:n-1) s]; % 'a' makes up the separators
c = diff(sort(b));
Navid Mohammadzadeh
Navid Mohammadzadeh le 17 Nov 2017
Modifié(e) : Walter Roberson le 20 Avr 2020
Regards both of you: I have developed and used your function. Since I need to make a random vector having a sum of all array equal to 20 and it does not have any zero in. Meanwhile, in my case, the maximum number is moved in the middle.
S = 20;
n = 5;
m = 1;
while true
P = ones(S+1,n);
for in = n-1:-1:1
P(:,in) = cumsum(P(:,in+1));
end
R = zeros(m,n);
for im = 1:m
s = S;
for in = 1:n
R(im,in) = sum(P(s+1,in)*rand<=P(1:s,in));
s = s-R(im,in);
end
end
x = find(R<=0);
if x~=0
continue
else
break
end
end
indMaxArry = ceil(n/2);
R = circshift(sort(R),[0,indMaxArry])
tlig zied
tlig zied le 19 Avr 2020
please, how can I modify this code to have values between 1 and s/2 ?
Yu Takahashi
Yu Takahashi le 9 Fév 2021
Modifié(e) : Walter Roberson le 10 Fév 2021
Wondering whether it is possible to specify the max and min of the devided value? i.e., something like what you kindly provided in the randfixedsum function, thanks!
Ref
Bruno Luong
Bruno Luong le 12 Août 2023
@Walter Roberson "Wondering whether it is possible to specify the max and min of the devided value?"

Connectez-vous pour commenter.

Plus de réponses (2)

Walter Roberson
Walter Roberson le 2 Mar 2017

1 vote

9 commentaires

Roger Stafford
Roger Stafford le 2 Mar 2017
Unfortunately, the numbers from ‘randfixedsum’ will rarely be integers. However, I can conceive of a method of rounding and sorting its results which would transform such numbers into integers with the proper sum. I’m too sleepy to work on it for now - tomorrow maybe.
Walter Roberson
Walter Roberson le 2 Mar 2017
In the case of integers, one approach is to work with Partitions . Unfortunately the partitions routines I see at the moment are designed to list all of the possibilities rather than to choose one at random.
Jan
Jan le 2 Mar 2017
@Roger: What about creating the numbers with the sum 20*2^53 by randfixedsum and dividing the values by 2^53? This might cause some inaccuracies in the last bit due to rounding, but this might be negligible for the OP.
wang syr
wang syr le 2 Mar 2017
Modifié(e) : wang syr le 2 Mar 2017
Unfortunately, randfixedsum doesn't generate right.
For example; "aaa= ceil(randfixedsum(10,10,300,3,31))" >>> row sum values: 301, 299, 306, etc.
Roger Stafford
Roger Stafford le 2 Mar 2017
@syracus syr: That is not how I would do the correction.
I just thought of a completely different method for the case where you have a fixed sum of a fixed number of positive integers:
random_posint_partition = @(of_what, num_rows, number_of_partitions) accumarray( [repmat((1:num_rows).',of_what, 1), randi(number_of_partitions, num_rows*of_what, 1)], 1);
Example run:
>> random_posint_partition(20,7,5)
ans =
4 3 4 5 4
5 3 3 5 4
3 6 1 6 4
3 6 4 5 2
5 3 6 2 4
4 6 8 1 1
5 1 6 4 4
>> sum(ans,2)
ans =
20
20
20
20
20
20
20
That is, the first parameter gives the number which is to be partitioned, the second parameter gives the number of different times you want the generation to be done, and the third parameter gives the number of pieces to partition into.
... I thought it would be a lot harder to come up with a fair method!
Oops, I just discovered that this can generate entries with a count of 0. :( For example,
6 5 5 4 0
The adjusted version is
random_posint_partition = @(of_what, num_rows, number_of_partitions) 1 + accumarray( [repmat((1:num_rows).',of_what-number_of_partitions, 1), randi(number_of_partitions, num_rows*(of_what-number_of_partitions), 1)], 1);
Roger Stafford
Roger Stafford le 4 Mar 2017
Modifié(e) : Roger Stafford le 4 Mar 2017
@Walter. The distribution of values one gets with this method you have described depends very heavily upon the assumption that is made about the underlying statistics involved. By my calculations, using your method, the probability of getting the result [4,4,4,4,4] is 305,540,235,000 times as likely as that of getting the result [20,0,0,0,0]. (I’m assuming your original method, which would allow zero integers.) It is equivalent to tossing 20 pebbles into 5 cans at random and recording the sum of pebbles in each can. In other words, the distribution is heavily weighted in favor of roughly equal values among the five integers.
However, suppose you assume instead that you are in a five dimensional “hyper-cube” of integer space, each integer of which can vary from 0 to 20, and that each integer-valued point in this cube has an equal a priori probability, namely, 1/(21^5). Then suppose, as a conditional probability, that we restrict ourselves to the subset in which the five integers must have 20 as their sum. Such a conditional probability distribution will give [4,4,4,4,4] and [20,0,0,0,0] an equal conditional probability, as opposed to the above enormous difference. This latter kind of conditional probability is analogous to the kind of conditional probability assumption that is the basis of my ‘randfixedsum’ algorithm #9700 for continuous distributions. If we were to use an integer adjustment to the results of randfixedsum, this latter is roughly the kind of integer distribution we would obtain.
Walter Roberson
Walter Roberson le 4 Mar 2017
Ah. I don't think I know how to implement your suggestion, though, at least not without generating all of the possible choices that sum to 20 and then picking one at random.
John D'Errico's https://www.mathworks.com/matlabcentral/fileexchange/12009-partitions-of-an-integer can calculate all of the possible partitions; a question is whether we can avoid having to take that step.
Walter Roberson
Walter Roberson le 4 Mar 2017
https://en.wikipedia.org/wiki/Partition_(number_theory)#Restricted_part_size_or_number_of_parts talks about restricted partitioning briefly, and ties it to change making problems, which does indeed sound equivalent to the approach I was taking. Those are in turn tied to knapsack problems.

Connectez-vous pour commenter.

Bruno Luong
Bruno Luong le 10 Août 2020
m = 5;
n = 3;
s = 10;
This will generate uniform distribution with sum criteria
% generate non-negative integer random (m x n) array row-sum to s
[~,r] = maxk(rand(m,s+n-1),n-1,2);
z = zeros(m,1);
r = diff([z, sort(r,2), (s+n)+z],1,2)-1;

1 commentaire

Bimal Ghimire
Bimal Ghimire le 4 Oct 2020
While generating conditional random numbers, how can we generate random numbers that has a limit of some maximum value and have certain specified sum value?

Connectez-vous pour commenter.

Catégories

En savoir plus sur Random Number Generation dans Centre d'aide et File Exchange

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by