Ejemplo n.º 1
0
        private async static Task <Solution> Pack_async(PartList parts, BoardList stock)
        {
            List <Task> threads    = new List <Task>();
            int         stockcount = stock.Count;

            Solution[] solutions = new Solution[stockcount];

            for (int i = 0; i < stockcount; i++)
            {
                threads.Add(
                    Task.Factory.StartNew(async(o) =>
                {
                    int ii                 = (int)o;
                    Item iStock            = stock[ii];
                    PartList mycopyofParts = parts.Copy();
                    Part iPart             = mycopyofParts[0];
                    mycopyofParts.RemoveAt(0);

                    if (!iStock.TrySplit(iPart, out Item H1, out Item H2, out Item V1, out Item V2))
                    {
                        return;
                    }

                    if (mycopyofParts.Count == 0)
                    {
                        solutions[ii] = new Solution(iPart, iStock);
                        return;
                    }

                    BoardList myVstock = stock.Copy();
                    myVstock.Remove(iStock);
                    myVstock.AddRange(V2, V1);
                    Solution solV = PackALL(mycopyofParts, myVstock);
                    if (solV != null)
                    {
                        solutions[ii] = new Solution(iPart, iStock);
                        solutions[ii].AddRange(solV);
                        return;
                    }

                    BoardList myHstock = stock.Copy();
                    myHstock.Remove(iStock);
                    myHstock.AddRange(H2, H1);
                    Solution solH = PackALL(mycopyofParts, myHstock);
                    if (solH != null)
                    {
                        solutions[ii] = new Solution(iPart, iStock);
                        solutions[ii].AddRange(solH);
                        return;
                    }
                }, i));
            }
            Task.WaitAll(threads.ToArray());


            return(solutions.FirstOrDefault(t => t != null));
        }
Ejemplo n.º 2
0
        public async static Task <Solution> Packold(PartList parts, BoardList boards)
        {
            #region // Algorithm : ...

            /*
             * for each board
             *  remove all parts that will not fit on board
             *  do
             *      Get the combos of parts that have cumalative area smaller than board, but bigger than 90% of board (we aim high...)
             *      level=level*level
             *  while combos.count = 0
             *  sort combos by cum area desc
             *  foreach combo
             *      if can fit on board, break
             *
             * end for each board
             * keep board with leaste waste
             *
             * repeat for boards and parts left
             *
             */
            #endregion
            if (parts.Count * boards.Count == 0)
            {
                return(null);
            }

            if (!parts.All(t => boards.Any(q => q.BiggerThan(t))))
            {
                return(null);
            }

            PartList  mycopyofParts  = parts.Copy();
            BoardList mycopyofBoards = boards.Copy();
            mycopyofParts.Sort(Part.CompareByAreaDecending);

            Solution CompleteSolution = new Solution()
            {
                TotalStockArea = boards.Sum(t => t.Area)
            };
            do
            {
                double          minCoverageRatio = 0.9;
                int             boardcount       = mycopyofBoards.Count;
                List <Solution> iSolutionSet     = new List <Solution>();
                object          lockobj          = new object();
                do
                {
                    List <Task> threads = new List <Task>();
                    Trace.WriteLine($"Getting combinations for {boardcount} boards [{string.Join(",", mycopyofBoards.Select(t => t.Name))}] and {mycopyofParts.Count} parts with at least {minCoverageRatio * 100} % coverage");

                    for (int j = 0; j < boardcount; j++)
                    {
                        // get the best solution for every board
                        threads.Add(
                            Task.Factory.StartNew((o) =>
                        {
                            Item iBoard = mycopyofBoards[(int)o];
                            var iCombos = GetCombos(mycopyofParts, iBoard, 0, minCoverageRatio * iBoard.Area);
                            iCombos.Sort(Combo.CompareByCumAreaDesc);
                            Trace.WriteLine($"Finding combinations for board {iBoard.Name}");

                            Solution topSolution = null;
                            Combo topCombo       = iCombos.FirstOrDefault(q => (topSolution = BruteForce.Pack_async(q.AsPartList(), iBoard).Result) != null);
                            if (topSolution != null)
                            {
                                Trace.WriteLine($"Best satisfactory combination for board {iBoard.Name}: [{string.Join(",", topCombo.Select(q => q.Name))}] ; coverage = {(topSolution.PlacedArea / iBoard.Area * 100):0.0} %, waste = {topSolution.Waste / 1000000} m\u00b2");
                                iSolutionSet.Add(topSolution);
                            }
                            else
                            {
                                Trace.WriteLine($"No satisfactory combination for board {iBoard.Name}");
                            }
                        }, j)
                            );
                    }
                    Task.WaitAll(threads.ToArray());

                    minCoverageRatio -= minCoverageRatio * minCoverageRatio;
                    if (minCoverageRatio < 0.5)
                    {
                        minCoverageRatio = 0;
                    }
                } while (iSolutionSet.Count == 0);

                // keep the best solution
                iSolutionSet.Sort(Solution.CompareByWasteAscending);

                // check if there is another solution that did not include any of these ...
                foreach (var topSol in iSolutionSet)
                {
                    // if none of the parts in this solution is already part of the kept solutions
                    if (!topSol.Any(t => CompleteSolution.FirstOrDefault(q => q.Part.Name == t.Part.Name) != null))
                    {
                        // add this solution to the kept solutions
                        Item topBoard = topSol.First().Stock;
                        Trace.WriteLine($"Keeping solution for board {topBoard.Name}: [{string.Join(",", topSol.Select(q => q.Part.Name))}] ; coverage = {(topSol.PlacedArea / topBoard.Area * 100):0.0} %, waste = {topSol.Waste / 1000000} m\u00b2");
                        CompleteSolution.AddRange(topSol);

                        // remove the parts and boards
                        topSol.ForEach(t => mycopyofParts.Remove(t.Part));
                        mycopyofBoards.Remove(topBoard);
                    }
                }

                Trace.WriteLine($"{mycopyofBoards.Count} boards and {mycopyofParts.Count} parts remain");
                Trace.WriteLine("");

                if (mycopyofBoards.Count == 0 && mycopyofParts.Count > 0)
                {
                    return(null);
                }
            } while (mycopyofParts.Count > 0);

            return(CompleteSolution);
        }