Algorithm 带约束的随机分布对象算法

Algorithm 带约束的随机分布对象算法,algorithm,random,distribution,Algorithm,Random,Distribution,帮我找到一个好的算法 我有一个装满n个球的袋子。(以28个球为例。) 这个包里的球每个都有一种颜色。有0个不接受红球。) 所有的球都被认为是不同的,即使它们是相同的颜色。(桶C得到红色球1而不是红色球2的可能性与桶C得到红色球2而不是红色球1的可能性不同。) 编辑以添加我的想法: 我不知道这是否有相同的可能性,所有的可能性,因为我想。我还没有计算出效率——它看起来还不算太差。 这包含一个断言,我不确定它是否总是正确的。 如果你知道的话,请评论这些事情 Choose a ball from the

帮我找到一个好的算法

我有一个装满n个球的袋子。(以28个球为例。)

这个包里的球每个都有一种颜色。有0个不接受红球。)

所有的球都被认为是不同的,即使它们是相同的颜色。(桶C得到红色球1而不是红色球2的可能性与桶C得到红色球2而不是红色球1的可能性不同。)

编辑以添加我的想法:

我不知道这是否有相同的可能性,所有的可能性,因为我想。我还没有计算出效率——它看起来还不算太差。 这包含一个断言,我不确定它是否总是正确的。 如果你知道的话,请评论这些事情

Choose a ball from the bag at random. (Call it "this ball".)

If this ball fits and is allowed in a number of buckets > 0:
    Choose one of those buckets at random and put this ball in that bucket.

else (this ball is not allowed in any bucket that it fits in):
    Make a list of colors that can go in buckets that are not full.
    Make a list of balls of those colors that are in full buckets that this ball is allowed in.
    If that 2nd list is length 0 (There are no balls of colors from the 1st list in the bucket that allows the color of this ball):
        ASSERT: (Please show me an example situation where this might not be the case.)
                There is a 3rd bucket that is not involved in the previously used buckets in this algorithm.
                (One bucket is full and is the only one that allows this ball.
                 A second bucket is the only one not full and doesn't allow this ball or any ball in the first bucket.
                 The 3rd bucket is full must allow some color that is in the first bucket and must have some ball that is allowed in the second bucket.)
        Choose, at random, a ball from the 3rd bucket balls of colors that fit in the 2nd bucket, and move that ball to the 2nd bucket.
        Choose, at random, a ball from the 1st bucket balls of colors that fit in the 3rd bucket, and move that ball to the 3rd bucket.
        Put "this ball" (finally) in the 1st bucket.
    else:
        Choose a ball randomly from that list, and move it to a random bucket that is not full.
        Put "this ball" in a bucket that allows it.
Next ball.
这里有一个O(n^3)时间算法。(3来自铲斗的数量。)

我们首先绘制一个暴力枚举算法,然后提取一个有效的计数算法,然后演示如何采样

我们使用具有两个嵌套循环的算法进行枚举。外环在球中迭代。每个球的颜色并不重要;只是它可以放在某些桶里,而不能放在其他桶里。在每个外部迭代开始时,我们有一个部分解列表(到目前为止考虑的球分配给桶)。内环在部分解之上;通过以所有有效的方式扩展赋值,我们向一个新列表添加了几个部分解。(初始列表有一个元素,即空赋值。)

为了更有效地计算解决方案,我们应用了一种称为动态编程或游程编码的技术,具体取决于您如何看待它。如果两个部分解在每个存储桶中具有相同的计数(在算法的生命周期内有O(n^3)个可能性),则其中一个的所有有效扩展都是另一个的有效扩展,反之亦然。我们可以用一个计数来注释列表元素,并放弃部分解的每个“等价类”的所有代表,但不包括一个

最后,为了得到一个随机样本,而不是随意选择代表,当我们合并两个列表条目时,我们根据每一方的计数按比例从每一方抽取代表

使用Python代码(为了简单起见,O(n^4);数据结构可能会有所改进)

#/usr/bin/env蟒蛇3
导入集合
随机输入
def make_键(铲斗、铲斗尺寸):
返回元组(bucket_size[bucket]用于bucket中的bucket)
def样品(球、最终桶尺寸):
桶=列表(最终桶大小)
partials={(0,)*len(bucket):(1,[])}
对于球中球:
next_partials={}
对于count,partials.values()中的partial:
对于球形铲斗:
next_partial=partial+[桶]
key=make_key(bucket、collections.Counter(下一个部分))
如果输入下一部分:
现有部分计数,现有部分=下一部分[键]
总计数=现有计数+计数
next\u partials[键]=(总\u计数,如果是随机的,则为现有\u partial.randrange(总\u计数)<现有\u计数,否则为下一个\u partial)
其他:
下一部分[键]=(计数,下一部分)
部分=下一部分
返回部分[make_key(桶、最终桶大小)][1]
def test():
红色={'A','C'}
绿色={B',C'}
蓝色={'A','B'}
紫色={B'}
球=[红色]*8+[绿色]*8+[蓝色]*8+[紫色]*4
最终桶大小={A':7,'B':11,'C':10}
返回样品(球、最终桶尺寸)
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
打印(test())

我真的不确定在随机、正确和有效的分发之间,您想要做什么权衡

如果你想要一个完全随机的分布,只需挑选一个球,然后把它随机放在一个桶里,它就可以进去了。这将是相当有效的,但你可能很容易使桶溢出

如果你想确保所有的分布都是正确的和随机的,你可以试着让所有的分布都是正确的,然后随机选择一个,但是这可能是非常低效的,因为创建所有分布可能性的基本蛮力算法的复杂度几乎是NumberOfBucket^NumberOfBalls

创建所有正确案例的更好算法是尝试按颜色构建所有案例来验证您的两个规则(一个桶B1只能有N1个球,一个桶只能接受某些颜色)。例如:

//let a distribution D be a tuple N1,...,Nx of the current number of balls each bucket can accept

void DistributeColor(Distribution D, Color C) {
  DistributeBucket(D,B1,C);
}

void DistributeBucket(Distribution D, Bucket B, Color C) {
  if B.canAccept(C) {
    for (int i = 0; i<= min(D[N],C.N); i++) {
      //we put i balls of the color C in the bucket B
      C.N-=i;
      D.N-=i;
      if (C.N == 0) {
        //we got no more balls of this color
        if (isLastColor(C)){
          //this was the last color so it is a valid solution
          save(D);
        } else {
          //this was not the last color, try next color
          DistributeColor(D,nextColor(C))
        }
      } else {
        //we still got balls
        if (isNotLastBucket(B)) {
          //This was not the last bucket let's try to fill the next one
          DistributeBucket(D, nextBucket(B), C)  
        } else {
          //this was the last bucket, so this distibution is not a solution. Let's do nothing (please don't kill yourself :/ )
        }
      }
      //reset the balls for the next try
      C.N+=i;
      D.N+=i;
    }
  }
  //it feel like déjà vu
  if (isNotLastBucket(B)) {
    //This was not the last bucket let's try to fill the next one
    DistributeBucket(D, nextBucket(B), C)  
  } else {
    //this was the last bucket, so this distribution is not a solution.
  }
}
//假设分布D是每个桶可以接受的当前球数的元组N1,…,Nx
空隙分布颜色(分布D,颜色C){
配送箱(D、B1、C);
}
无效分配桶(分配D、桶B、颜色C){
如果B.canAccept(C){

对于(inti=0;i1),首先在28之间选择7:有C28,7=1184040的可能性

2秒,在剩下的21个选项中选择11:您有C21,11=352716个可能性

3剩余的10个元件位于铲斗C中

在每一步中,如果你的选择不符合规则,你就停下来再做一次

一切都使417629852640的可能性(没有限制)

这不是很有效率,但对于一个选择来说,这并不重要。如果限制不是太严格,你就不会损失太多时间


如果解决方案非常少,则必须限制组合(仅限好的颜色)。

至少在某些情况下,通过 首先,使用约束将问题简化为更易于管理的问题 大小,然后搜索解决方案空间

首先,请注意,我们可以忽略球的清晰度 算法的主要部分。仅考虑 颜色,每种颜色随机分配不同的球数是很简单的 通过在每种颜色中洗牌

为了重申这个问题并澄清等概率的概念,这里 这是一个天真的想法
//let a distribution D be a tuple N1,...,Nx of the current number of balls each bucket can accept

void DistributeColor(Distribution D, Color C) {
  DistributeBucket(D,B1,C);
}

void DistributeBucket(Distribution D, Bucket B, Color C) {
  if B.canAccept(C) {
    for (int i = 0; i<= min(D[N],C.N); i++) {
      //we put i balls of the color C in the bucket B
      C.N-=i;
      D.N-=i;
      if (C.N == 0) {
        //we got no more balls of this color
        if (isLastColor(C)){
          //this was the last color so it is a valid solution
          save(D);
        } else {
          //this was not the last color, try next color
          DistributeColor(D,nextColor(C))
        }
      } else {
        //we still got balls
        if (isNotLastBucket(B)) {
          //This was not the last bucket let's try to fill the next one
          DistributeBucket(D, nextBucket(B), C)  
        } else {
          //this was the last bucket, so this distibution is not a solution. Let's do nothing (please don't kill yourself :/ )
        }
      }
      //reset the balls for the next try
      C.N+=i;
      D.N+=i;
    }
  }
  //it feel like déjà vu
  if (isNotLastBucket(B)) {
    //This was not the last bucket let's try to fill the next one
    DistributeBucket(D, nextBucket(B), C)  
  } else {
    //this was the last bucket, so this distribution is not a solution.
  }
}