【问题标题】:Flatten a grouped list and sort according to frequency of items (production planning)展平分组列表并根据项目的频率排序(生产计划)
【发布时间】:2021-05-23 23:14:21
【问题描述】:

我有以下分组数据结构(用于生产计划系统):

Product A | Variant A | Color Red: 10 items 
Product A | Variant A | Color Blue: 5 items
Product A | Variant B | Color Red: 2 items
Product B | Variant C | Color Black: 5 items 
... 

例如,我有 500 种产品要生产,每周有 50 个生产时段。

我需要根据每个分组的项目数量来填充插槽。

如何从该分组中创建一个顺序列表,以确保更频繁地生产具有较高计数的产品分组?

店里的产品种类齐全是很有必要的。因此,不可能在一周内生产 50 件变体 A,然后再生产 50 件下一个变体。生产计划系统应确保在生产 4 周后有良好的产品范围,但较受欢迎的产品也应比其他产品获得更多的产量。

我使用 C# 来实现系统,但任何语言/算法的想法都会很有帮助。

非常感谢!

【问题讨论】:

  • 您需要对“一系列产品”进行精确的规格说明。最小值和最大值有多少以及这些数字如何取决于受欢迎程度。 流行度是如何定义的?等等……只有你才能开始开发算法。在你最喜欢的搜索引擎中搜索“生产计划算法”,会给你很多结果。有些人使用遗传算法、启发式算法和带有奇怪首字母缩写词的算法。主要是学术论文。如果担心您的问题没有简单的答案。
  • 感谢您的快速回复!在这种情况下,我们可以从订购商品的数量中得出受欢迎程度。在范围方面:我只是想解释为什么需要分发订单。我去看看搜索结果!

标签: c# list algorithm linq sorting


【解决方案1】:

最直接的方法是根据每个要生产的物品在要生产的物品总数中的比例(所有组的总和)按比例分配 50 个可用插槽。

I.E.:让我们假设这 4 行是此时要生产的所有项目。

Product A | Variant A | Color Red: 32 items 
Product A | Variant A | Color Blue: 15 items
Product A | Variant B | Color Red: 12 items
Product B | Variant C | Color Black: 5 items 

必须按降序对组进行排序,以确保编号最大的组首先被分配用于生产。

那么要生产的物品总数为 32+15+12+5 = 64。

基于每个组的比例(权重)分配可用插槽将是:

50* 32/64 =25 items for the 1st group
50* 15/64 = 11 items for the 2nd group
50* 12/64 =  9  items for the 3rd group
50* 5/64 =3  items for the 4th group

然后剩余部分(由于四舍五入)可以递归地或整个组项目的其余部分分布。

这里是递归剩余分配的实现,直到它被完全分配,并且根据每个组的剩余需求在每轮递归中更新比率。

 public class Group
{
    public string Product { get; set; }
    public string Variant { get; set; }
    public string Color { get; set; }
    public int NeededToProduce { get; set; }
    public int AllocatedForProd { get; set; }

}

public class Calculation
{
    public Calculation()
    {
        AllocateProdSlots(this._prodSlots, this._groups);
    }
    private List<Group> _groups = new List<Group>()
    {
        new Group () {Product = "A", Variant = "A", Color = "Red",  NeededToProduce = 32  , AllocatedForProd = 0},
        new Group () {Product = "A", Variant = "A", Color = "Blue", NeededToProduce = 15 , AllocatedForProd = 0},
        new Group () {Product = "A", Variant = "B", Color = "Red",  NeededToProduce = 12 , AllocatedForProd = 0},
        new Group () {Product = "B", Variant = "C", Color = "Black", NeededToProduce = 5 , AllocatedForProd = 0},

    }  ;

    private int _prodSlots = 50;


    private void AllocateProdSlots( int remainingProdSlots, List<Group> groups)
    {

        groups = groups.OrderByDescending(g => g.NeededToProduce).ToList<Group>();  
                   
        decimal total = GetTotalNumberOfItemsInGroups();
        
        foreach(var g in groups)
        {
            if (remainingProdSlots > 0)
            {

                int remainingNeedGroup = g.NeededToProduce - g.AllocatedForProd;
                int allocation = Decimal.ToInt32( remainingNeedGroup / total * remainingProdSlots);

                if (allocation <= remainingNeedGroup)
                    g.AllocatedForProd += allocation;
                else g.AllocatedForProd += remainingNeedGroup;

                if (allocation == 0 && remainingNeedGroup > 0 && remainingProdSlots > 0) //rounded down
                {
                    g.AllocatedForProd += 1;     //give such group 1 slot
                    allocation = 1;
                }

                remainingProdSlots -= allocation;
                Console.WriteLine($" NumberToProduce {g.NeededToProduce}; AllocatedForProd {g.AllocatedForProd}; remainingProdSlots {remainingProdSlots};");
            }
            else break;

        }

        if (remainingProdSlots > 0) //we still have a remainder after the above allocation round - call another round to sart on the remaining slots
        {
            Console.WriteLine($"Remainder to be allocated in the next round {remainingProdSlots}");
            AllocateProdSlots(remainingProdSlots, groups);
        }
         

    }

    private decimal GetTotalNumberOfItemsInGroups()
    {
        return _groups.Sum(g => g.NeededToProduce);
    }


}

【讨论】:

  • 不错的方法!谢谢你:)
【解决方案2】:

必须按降序对组进行排序,以确保编号最大的组首先被分配用于生产。

我没有在您的原始序列中看到组或产品。您没有“带有变体的组”我只看到一个根据产品名称订购的平面“产品变体”序列。对我来说,您的输入序列似乎是内部连接的结果。

如果您想要“编号”最高的产品,只需按“编号”排序即可。

 // get your input sequence with ProductName, VariantName, Color, ItemCount:
IEnumerable<...> products = ...

// order them, the highest ItemCount first:
var productsOrderedByDescendingItemCount = products.OrderByDescending(
    product => product.ItemCount);

【讨论】:

    猜你喜欢
    • 2013-12-28
    • 2018-05-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-27
    相关资源
    最近更新 更多