Reputation: 378
I need to generate n random real values P[0], P[1], ..., P[n-1] which satisfy the following constraints:
Pmin[0] <= P[0] <= Pmax[0]
Pmin[1] <= P[1] <= Pmax[1]
...
Pmin[n-1] <= P[n-1] <= Pmax[n-1]
P[0] + P[1] + ... + P[n-1] = S
Any idea how to do this efficiently?
Upvotes: 1
Views: 175
Reputation: 4942
For every i, assign P[i] := Pmin[i]
Compute the sum
If sum>S, then stop (it's impossible)
For every i:
If P[i]+S-sum <= Pmax[i]
P[i] = P[i]+S-sum
Stop (it's done :-)
sum = sum+Pmax[i]-P[i]
P[i] = Pmax[i]
Go for next i
Stop (it's impossible)
Ooops, sorry, you said random... that's not so trivial. Let me think about it...
Run the previous algorithm to have a starting point. Now compute the total margin above and below. The margin above is the sum of individual margins Pmax[i]-P[i] for every i. The margin below is the sum of individual margins P[i]-Pmin[i] for every i.
Traverse all the elements but one in a random order, visiting each one of them exactly once. For every one of them:
Then adjust the remaining element to fit the sum S.
Regarding the traversal in random order, see the Knuth shuffles.
Upvotes: 0
Reputation: 28292
In general, it is not possible to solve this problem if choosing elements uniformly at random from the given ranges.
Example 1: Say that Pmin[i] = 0 and Pmax[i] = 1. Say that n = 10 and S = 100. Then there is no solution, since the greatest possible sum is 10.
Example 2: Say that Pmin[i] = 0 and Pmax[i] = 1. Say that n = 10 and S = 10. Then there is exactly one solution: choose P[i] = 1.
It is possible to write an algorithm such that the resulting sequence is chosen uniformly at random from the set of possible solutions; this is quite different from saying that the P[i] are uniformly distributed between Pmin[i] and Pmax[i].
The basic idea is to, at each stage, further restrict your range, as follows:
If you are able to obey those rules when picking each P[i], there's a solution, and you will find one at random. Otherwise, there is not a solution.
Note that to actually make this select solutions at random, it's probably best to shuffle the indices, perform this algorithm, and then rearrange the sequence so that it's in the proper order. You can shuffle in O(n), do this algorithm (recommend dynamic programming here, since you can build solutions bottom-up) and then spit out the sequence by "unshuffling" the resulting sequence.
Upvotes: 1