简体   繁体   English

将数量分配到桶中-不均匀

[英]Distribute quantities into buckets - Not evenly

I've been searching around for a solution to this, but I think because of how I'm thinking about it, my search phrases might be a bit loaded in favor of topics that aren't completely relevant. 我一直在寻找解决方案,但是我认为由于我的想法,我的搜索短语可能会有点偏向那些不完全相关的主题。

I have a number, say 950,000. 我有一个数字,例如950,000。 This represents an inventory of [widgets] within an entire system. 这表示整个系统中的[小部件]清单。 I have about 200 "buckets" that should each receive a portion of this inventory such that there are no widgets left over. 我大约有200个“存储桶”,每个存储桶都应接收此清单的一部分,这样就不会剩下任何窗口小部件。

What I would like to happen is for each bucket to receive different amounts. 我想让每个存储桶收到不同的金额。 I don't have any solid code to show right now, but here's some pesudo code to illustrate what I've been thinking: 我现在没有任何可靠的代码可以显示,但是这里有一些伪代码来说明我一直在想的事情:

//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;
}

Is this a statistically/mathematically proper way to handle this, or is there a distribution formula out there that handles this? 这是在统计/数学上正确的方式来处理此问题,还是那里有一个分配公式可以处理此问题? The kicker is that while this pseudo code would run 200 times (so each bucket has a chance to alter its quantities) it would have to run X number of times depending on the TYPE of widget (which currently stands at just 11 flavors, but is expected to expand significantly in the future). 更重要的是,虽然此伪代码将运行200次(因此每个存储桶都有机会更改其数量),但根据小部件的类型(目前只有11种口味,但它必须运行X次)。预计将来会大大扩展)。

{EDIT} This system is for a commodity trading game. {EDIT}该系统用于商品交易游戏。 Quantities at the 200 shops must differ because the inventory will determine the price at that station. 200家商店的数量必须有所不同,因为库存将决定该站点的价格。 The distro can't be even because that would make all prices the same. 发行版甚至不可能,因为那样会使所有价格相同。 Over time, prices will naturally get out of balance, but the inventory must start out off-balance. 随着时间的流逝,价格自然会失衡,但是库存必须开始失衡。 And all inventories have to be at least similar in scope (ie, no one shop can have 1 item, and another have 900,000) 并且所有库存的范围都必须至少相似(即,没有一家商店可以拥有一件商品,而另一家商店可以拥有900,000件商品)

Sure, there is a solution. 当然,有解决方案。 You could use Dirichlet Distribution for such task. 您可以将Dirichlet Distribution用于此类任务。 Property of the distribution is that 分布的属性是

Sum i x i = 1 i x i = 1

So solution would be to sample 200 (equal the number of buckets) random values from Dirichlet, and then multiply each value by 950,000 (or whatever total inventory is) and that would give you number of items per bucket. 因此,解决方案是从Dirichlet采样200个(等于存储桶数)随机值,然后将每个值乘以950,000(或任何总库存量),这将为您提供每个存储桶的项目数。 If you want non-uniform sampling, you could tweak alpha in the Dirichlet sampling. 如果要进行非均匀采样,可以在Dirichlet采样中调整alpha

Items per bucket shall be rounded up/down, of course, but that is pretty trivial 当然,每个存储桶中的项目都应向上/向下取整,但这是微不足道的

I have Dirichlet sampling in C# somewhere, if you struggle to implement it - tell me and I would dig it out 如果您难以实现它,我会在某个地方用C#进行Dirichlet采样-告诉我,我会把它挖掘出来

UPDATE UPDATE

I found some code, .NET Core 2, below is the excerpt. 我找到了一些代码,.NET Core 2,摘录如下。 I used to sample Dirichlet RNs with the sample alpha s, making all of them different is trivial. 我曾经用alpha样本对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;
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM