Example #1
0
        public void FindAll()
        {
            var materials = new WoodList();

            materials.Load("materials.csv");

            var parts = new WoodList();

            parts.Load("parts.csv");
            foreach (string dimension in parts.Keys)
            {
                var dimensionMaterials = materials[dimension];
                var dimensionParts     = parts[dimension];

                if (dimensionMaterials.Distinct().Count() == 1)
                {
                    CutOrder cutOrder = FillLongestToShortest(dimension, dimensionMaterials.First(), dimensionParts);
                    if (CutOrderFound != null)
                    {
                        CutOrderFound(this, new CutOrderEventArgs(cutOrder));
                    }
                }
                else
                {
                    throw new NotSupportedException("Cannot calculate optimal for varying material lengths");
                }
            }
        }
Example #2
0
        private static void Main(string[] args)
        {
            CutOrder     cutOrder = CutListCalculator.FindOptimal();
            const string outFile  = "out.csv";

            File.WriteAllText(outFile, cutOrder.ToString());
        }
Example #3
0
        public static CutOrder FindOptimal()
        {
            var calculator            = new CutListCalculator();
            var dimensionOptimals     = new Dictionary <string, CutOrder>();
            var dimensionWasteLengths = new Dictionary <string, decimal>();

            calculator.CutOrderFound += (sender, e) =>
            {
                string dimension = e.CutOrder.First().Key.Dimension;
                lock (dimensionOptimals)
                {
                    lock (dimensionWasteLengths)
                    {
                        CutOrder optimalCutOrder;
                        if (!dimensionOptimals.TryGetValue(dimension, out optimalCutOrder))
                        {
                            dimensionOptimals.Add(dimension, e.CutOrder);
                            return;
                        }
                        decimal optimalWasteLength;
                        if (!dimensionWasteLengths.TryGetValue(dimension, out optimalWasteLength))
                        {
                            optimalWasteLength = optimalCutOrder.ComputeWaste();
                            dimensionWasteLengths.Add(dimension, optimalWasteLength);
                        }


                        // Compute the waste length fo the current cut order
                        decimal wasteLength = e.CutOrder.ComputeWaste();

                        // If the waste length of the current is better than the best, then use current as the best going forward
                        if (wasteLength < optimalWasteLength)
                        {
                            dimensionWasteLengths[dimension] = wasteLength;
                            dimensionOptimals[dimension]     = e.CutOrder;
                        }
                    }
                }
            };

            calculator.FindAll();

            var optimal = new CutOrder();

            foreach (string dimension in dimensionOptimals.Keys)
            {
                foreach (Board board in dimensionOptimals[dimension].Keys)
                {
                    optimal.Add(board, dimensionOptimals[dimension][board]);
                }
            }
            return(optimal);
        }
Example #4
0
        public object Clone()
        {
            var cutOrder = new CutOrder();

            foreach (Board board in Keys)
            {
                var boardCopy = new Board {
                    Dimension = board.Dimension, Length = board.Length
                };
                var cutListCopy = new List <decimal>(this[board]);
                cutOrder.Add(boardCopy, cutListCopy);
            }

            return(cutOrder);
        }
Example #5
0
        private CutOrder FillLongestToShortest(string dimension, decimal boardLength, List <decimal> parts)
        {
            if (parts.Any(x => x > boardLength))
            {
                throw new ArgumentException("parts cannot contain any lengths longer than boardLength", "parts");
            }
            var     cutOrder           = new CutOrder();
            decimal currentBoardLength = 0M;
            var     currentBoardCuts   = new List <decimal>();
            bool    isFirst            = true;

            var remainingParts = new List <decimal>(parts);

            while (remainingParts.Count > 0)
            {
                if (isFirst)
                {
                    decimal firstCut = remainingParts[0];
                    currentBoardCuts.Add(firstCut);
                    remainingParts.RemoveAt(0);
                    currentBoardLength = boardLength - firstCut;
                    isFirst            = false;
                    continue;
                }

                // Advanced strategy: for the last two cuts on the board when we have three or more cuts to go,
                // find the max two-cut sum that will fit on the current board from the list of available boards
                PartPair lastCutPair = GetLongestPartPair(remainingParts, currentBoardLength);
                if (lastCutPair != null)
                {
                    remainingParts.Remove(lastCutPair.LargerPart);
                    remainingParts.Remove(lastCutPair.SmallerPart);
                    currentBoardCuts.Add(lastCutPair.LargerPart);
                    currentBoardCuts.Add(lastCutPair.SmallerPart);
                    cutOrder.Add(new Board {
                        Dimension = dimension, Length = boardLength
                    }, currentBoardCuts);

                    currentBoardLength = boardLength;
                    currentBoardCuts   = new List <decimal>();
                    isFirst            = true;
                    continue;
                }


                // Normal strategy: select the longest cut from the remaining parts that will fit on the current board
                decimal cut =
                    remainingParts.FirstOrDefault(x => currentBoardLength >= (x + Settings.Default.BladeWidth));
                if (cut != 0M)
                {
                    currentBoardCuts.Add(cut);
                    remainingParts.Remove(cut);
                    cut += Settings.Default.BladeWidth;
                    currentBoardLength -= cut;
                    continue;
                }

                cutOrder.Add(new Board {
                    Dimension = dimension, Length = boardLength
                }, currentBoardCuts);
                currentBoardCuts   = new List <decimal> ();
                currentBoardLength = boardLength;
                isFirst            = true;
            }
            if (currentBoardCuts.Count > 0)
            {
                cutOrder.Add(new Board {
                    Dimension = dimension, Length = boardLength
                }, currentBoardCuts);
            }

            return(cutOrder);
        }
Example #6
0
 public CutOrderEventArgs(CutOrder cutOrder)
 {
     CutOrder = cutOrder;
 }