/// <summary>
        ///
        /// </summary>
        /// <param name="dataWrapper"></param>
        /// <param name="optimizerLimit">Maximum number of different combinations to try. Zero: no limit.</param>
        /// <param name="progressChanged"></param>
        /// <param name="operation"></param>
        /// <returns></returns>
        public static IEnumerable <ResultData> GetResults(DataWrapper dataWrapper, int optimizerLimit, System.Action <string> progressChanged, string operation)
        {
            int cntMax = dataWrapper.Balance.Count;
            int cnt    = 0;

            foreach (KeyValuePair <string, int> item in dataWrapper.Balance)
            {
                string product = item.Key;
                progressChanged?.Invoke($"{operation} {++cnt}/{cntMax}");
                int balance = item.Value;
                int shipped = dataWrapper.SumFactoryShipments.ContainsKey(product) ? dataWrapper.SumFactoryShipments[product] : 0;
                if (shipped == 0)
                {
                    //None of the orders can be fulfilled, but there is nothing to store
                    yield return(new ResultData(product, shipped, ResultDecision.Create(dataWrapper.GetCustomerOrdersByItemName(product), fulfill: false)));
                }
                else
                if (balance == 0)
                {
                    //All orders fulfill, nothing to store
                    yield return(new ResultData(product, shipped, ResultDecision.Create(dataWrapper.GetCustomerOrdersByItemName(product), fulfill: true)));
                }
                else
                if (balance > 0)
                {
                    //All orders fulfill, there are some product item from the factory shipments to store
                    yield return(new ResultData(product, shipped, ResultDecision.Create(dataWrapper.GetCustomerOrdersByItemName(product), fulfill: true)));
                }
                else
                if (balance < 0)
                {
                    //Some orders may be fulfilled, but not all. Optimization needed. Some product items from the factory shipments might be to store.
                    IEnumerable <ResultDecision> decisionsComplex = null; double efficiencyComplex = 0;
                    IEnumerable <ResultDecision> decisionsSimple = ResolverSimple.Resolve(shipped, dataWrapper.GetCustomerOrdersByItemName(product), out double efficiencySimple);
                    if (efficiencySimple < 1)
                    {
                        decisionsComplex = ResolverComplex.Resolve(optimizerLimit, shipped, dataWrapper.GetCustomerOrdersByItemName(product).ToArray(), efficiencySimple, out efficiencyComplex);
                    }
                    if (efficiencyComplex > efficiencySimple)
                    {
                        yield return(new ResultData(product, shipped, decisionsComplex));
                    }
                    else
                    {
                        yield return(new ResultData(product, shipped, decisionsSimple));
                    }
                }
            }
        }
예제 #2
0
        /// <summary>
        /// Simple algorithm to solve of 01-Knapsack problem
        /// </summary>
        /// <param name="shipped"></param>
        /// <param name="orders"></param>
        /// <param name="efficiency"></param>
        /// <returns></returns>
        /// <remarks>Works on sorted "weights", not recursive, only checks to swap the last added element in the "bag".</remarks>
        public static IEnumerable <ResultDecision> Resolve(int shipped, IEnumerable <CustomerOrder> orders, out double efficiency)
        {
            HashSet <ResultDecision> results = new HashSet <ResultDecision>();
            int            total             = 0;
            ResultDecision last      = null;
            int            lastTotal = 0;

            foreach (CustomerOrder item in orders)
            {
                if (total + item.Quantity <= shipped)
                {
                    ResultDecision rd = new ResultDecision(item, true);
                    results.Add(rd);
                    lastTotal = total;
                    total    += item.Quantity;
                    last      = rd;
                }
                else if (last != null && lastTotal + item.Quantity <= shipped && lastTotal + item.Quantity > total)
                {
                    results.Remove(last);
                    results.Add(new ResultDecision(last.CustomerOrder, false));

                    ResultDecision rd = new ResultDecision(item, true);
                    results.Add(rd);
                    total     = lastTotal + item.Quantity;
                    lastTotal = total;
                    last      = rd;
                }
                else
                {
                    results.Add(new ResultDecision(item, false));
                }
            }
            efficiency = total / (double)shipped;
            return(results);
        }