【问题标题】:Distribute quantities into buckets - Not evenly将数量分配到桶中 - 不均匀
【发布时间】:2018-08-17 02:20:00
【问题描述】:

我一直在寻找解决此问题的方法,但我认为由于我的想法,我的搜索词组可能有点偏向于不完全相关的主题。

我有一个数字,比如说 950,000。这表示整个系统中的 [widgets] 清单。我有大约 200 个“桶”,每个“桶”都应该接收该库存的一部分,这样就不会留下任何小部件。

我希望每个存储桶收到不同的金额。我现在没有任何可靠的代码可以展示,但这里有一些伪代码来说明我一直在想什么:

//List<BucketObject> _buckets is a collection of "buckets", each of which has a "quantity" property for holding these numbers.

int _widgetCnt = 950000;
int _bucketCnt = _buckets.Count;     //LINQ
//To start, each bucket receives (_widgetCnt / _bucketCnt) or 4750.

for (int _b = 0; b< _bucketCnt - 1; i++)
{
     int _rndAmt = _rnd.Next(1, _buckets[i].Quantity/2); //Take SOME from this bucket...
     int _rndBucket = _rnd.Next(0,_bucketCnt - 1);    //Get a random bucket index from the List<BucketObject> collection.

     _buckets.ElementAt(_rndBucket).Quantity += _rndAmt;
     _buckets.ElementAt(i).Quantity -= _rndAmt;
}

这是处理这个问题的统计/数学正确方法,还是有一个分布公式可以处理这个问题?更重要的是,虽然这个伪代码会运行 200 次(因此每个存储桶都有机会改变其数量),但它必须运行 X 次,具体取决于小部件的类型(目前只有 11 种口味,但预计未来会大幅扩张)。

{编辑} 该系统用于商品交易游戏。 200 家商店的数量必须不同,因为库存将决定该站的价格。该发行版甚至不可能,因为这会使所有价格都相同。随着时间的推移,价格自然会失衡,但库存必须从失衡开始。并且所有库存必须至少在范围上相似(即,没有一家商店可以拥有 1 件商品,而另一家商店可以拥有 900,000 件商品)

【问题讨论】:

  • 这是一款商品交易游戏,这是一种初始种子方法,用于将数量的物品分配到游戏世界的不同商店。我不希望数量相等,因为商店中商品的数量决定了价格;如果所有价格都相同,那么在一个港口的买卖与其他港口没有区别。
  • 将一个项目放入第一个桶中,将两个项目放入第二个桶中,依此类推,直到最后一个桶,您将所有剩余的项目放入其中。这满足您的要求...
  • 我计划在数字混乱后在后台进行更有针对性的模拟,此外还有玩家活动,以确保玩家不会总是有一个单一的、静态的交易路线可以在它们之间跳动赚大钱。我只需要在第一时间把这些数字弄乱就可以了。

标签: c# random distribution


【解决方案1】:

当然,有一个解决方案。您可以使用 Dirichlet Distribution 来完成此类任务。分布的性质是

总和i xi = 1

因此,解决方案是从 Dirichlet 中抽取 200 个(等于桶数)随机值,然后将每个值乘以 950,000(或任何总库存),这样就可以得出每个桶的项目数。如果您想要非均匀采样,您可以在 Dirichlet 采样中调整 alpha

当然,每个桶的项目应该向上/向下四舍五入,但这很简单

我在某处的 C# 中有 Dirichlet 采样,如果您难以实现它 - 告诉我,我会挖掘出来

更新

我找到了一些代码,.NET Core 2,下面是摘录。我曾经用样本alphas 对 Dirichlet RN 进行抽样,使它们都不同是微不足道的。

//
// Dirichlet sampling, using Gamma sampling from Math .NET
//

using MathNet.Numerics.Distributions;
using MathNet.Numerics.Random;

static void SampleDirichlet(double alpha, double[] rn)
{
    if (rn == null)
        throw new ArgumentException("SampleDirichlet:: Results placeholder is null");

    if (alpha <= 0.0)
        throw new ArgumentException($"SampleDirichlet:: alpha {alpha} is non-positive");

    int n = rn.Length;
    if (n == 0)
        throw new ArgumentException("SampleDirichlet:: Results placeholder is of zero size");

    var gamma = new Gamma(alpha, 1.0);

    double sum = 0.0;
    for(int k = 0; k != n; ++k) {
        double v = gamma.Sample();
        sum  += v;
        rn[k] = v;
    }

    if (sum <= 0.0)
        throw new ApplicationException($"SampleDirichlet:: sum {sum} is non-positive");

    // normalize
    sum = 1.0 / sum;
    for(int k = 0; k != n; ++k) {
        rn[k] *= sum;
    }
}

【讨论】:

  • 我知道我要杀了这个可怕的,所以提前道歉......但是使用带有 200 个桶的 Dirichlet 会产生一系列介于 0 和 1 之间的值(每个代表一个桶200 桶集合),这些值将代表总数 950,000 的百分比,因此(大致)200 桶中的数量总和为 950,000...?诚然,我能找到的关于 Dirichlet 的信息比我习惯的要多得多:D
  • @ChrisSmith using Dirichlet with the 200 buckets would produce a series of values between 0 and 1 (each representing a single bucket in the 200 bucket collection), and those values would represent a percent of the total 950,000 so that (roughly) the sum of the quantities in the 200 buckets is 950,000...? 绝对正确。它会自动正确汇总。
  • 太棒了!我会试试看。谢谢!
猜你喜欢
  • 1970-01-01
  • 2019-03-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-15
  • 1970-01-01
  • 2012-07-02
  • 2021-11-29
相关资源
最近更新 更多