生成实际值列表,总结为固定值并满足某些约束

时间:2013-02-07 15:55:47

标签: algorithm random constraints

我需要生成满足以下约束条件的n个随机实数值P [0],P [1],...,P [n-1]:

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

知道如何有效地做到这一点吗?

2 个答案:

答案 0 :(得分:1)

通常,如果从给定范围中随机均匀地选择元素,则无法解决此问题。

示例1:假设Pmin [i] = 0且Pmax [i] = 1.假设n = 10且S = 100.则没有解,因为最大可能总和为10.

示例2:假设Pmin [i] = 0且Pmax [i] = 1.假设n = 10且S = 10.那么只有一个解决方案:选择P [i] = 1.

可以编写一种算法,使得从可能的解集中随机均匀地选择结果序列;这与说P [i]在Pmin [i]和Pmax [i]之间均匀分布完全不同。

基本思路是在每个阶段进一步限制你的范围,如下所示:

  1. 范围的开始应该是以下两个量中的较大者:Pmin [i]或S-Smax [i] -P,其中Smax [i]是和Pmax [i + 1] +。 .. + Pmax [n]和P是和P [0] + ... + P [i]。这可以保证你选择一个足够大的数字来最终发挥作用。
  2. 范围的结尾应该是以下两个数量中较小的一个: Pmax [i]或S-Smin [i] -P,其中Smin [i]是和Pmin [i + 1] + ... + Pmin [n]并且P如前所述。这可以保证你选择一个足够小的数字来最终发挥作用。
  3. 如果你在挑选每个P [i]时能够遵守这些规则,那么就有一个解决方案,你会随机找到一个。否则,没有解决方案。

    请注意,要实际制作随机选择解决方案,最好是对索引进行随机播放,执行此算法,然后重新排列序列,使其处于正确的顺序。您可以在O(n)中进行随机播放,执行此算法(建议在此处进行动态编程,因为您可以自下而上构建解决方案),然后通过“取消预设”生成的序列来吐出序列。

答案 1 :(得分:0)

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)
哎呀,对不起,你说随机......这不是那么微不足道。让我考虑一下......

运行上一个算法以获得起点。现在计算上下的总保证金。上面的余量是每个i的个别边界Pmax [i] -P [i]的总和。下面的边距是每个i的单个边距P [i] -Pmin [i]的总和。

以随机顺序遍历所有元素但一个,只访问其中的每一个元素。对于他们每个人:

  • 更新上面的边距和下面的边距,从中减去当前元素的贡献。
  • 确定当前值的最小值和最大值,同时考虑到:
    • 它们必须位于区间[Pmin [i],Pmax [i]] AND
    • 这些最小值和最大值足够接近P [i],因此稍后更改其他元素可以补偿将P [i]更改为此最小值或最大值(这是上下边距所指示的值)
    • 将P [i]更改为计算区间[min,max]中的随机值并更新总和和边距(我不是100%确定边距应如何在此处更新......)

然后调整剩余元素以适合总和S.

关于随机顺序的遍历,请参阅Knuth shuffles