Is there an efficient way to generate a random combination of N integers such that—
- each integer is in the interval [
min
,max
], - the combination of integers has a mean of
mean
, and - the combination is chosen uniformly at random from among all possible combinations?
I am aware that this problem can be solved in the following way:
- Use the algorithm given in Smith and Tromble ("Sampling from the Unit Simplex", 2004) to generate N random non-negative integers with the sum
N * mean - N * min
. - Add
min
to each number generated this way. - If any number is greater than
max
, go to step 1.
However, this algorithm is slow if max
is much less than N * mean
. For example, according to my tests, the algorithm rejects, on average—
- about 1.6 samples if
N = 7, min = 3, max = 10, mean = 6
, but - about 30.6 samples if
N = 20, min = 3, max = 10, mean = 6
.
Is there a way to modify this algorithm to be efficient for large N while still meeting the requirements above?
The following code example is given in Ruby, but my question is independent of programming language:
def posintwithsum(n, total)
raise if n <= 0 or total <=0
ls = [0]
ret = []
while ls.length < n
c = 1+rand(total-1)
found = false
for j in 1...ls.length
if ls[j] == c
found = true
break
end
end
if found == false;ls.push(c);end
end
ls.sort!
ls.push(total)
for i in 1...ls.length
ret.push(ls[i] - ls[i - 1])
end
return ret
end
def integersWithSum(n, total)
raise if n <= 0 or total <=0
ret = posintwithsum(n, total + n)
for i in 0...ret.length
ret[i] = ret[i] - 1
end
return ret
end
# Generate 100 combinations
mn=3
mx=10
mean=6
n=7
100.times {
while true
pp=integersWithSum(n,n*mean-n*mn).map{|x| x+mn }
if !pp.find{|x| x>mx }
p pp; break # Output the sample and break
end
end
}
Aucun commentaire:
Enregistrer un commentaire