Пример #1
0
        /// <summary>
        /// metodo per stabilire se è possibile
        /// trovare una posizione in cui nestare
        /// un nuovo item
        /// </summary>
        /// <param name="temporaryBin"></param>
        /// <param name="temporaryItem"></param>
        /// <returns></returns>
        public Bin <Tuple> IsBestPositionFound(Bin <Tuple> temporaryBin, Item temporaryItem, string itemAllocationMethod)
        {
            //se l'item non è nestabile (ovvero le sue dimensioni eccedano quelle del bin)
            //setto comunque l'item come removed, altrimenti la lista di item non sarà mai empty e hsolve non va avanti

            /*if(temporaryItem.Height > temporaryBin.Height || temporaryItem.Width > temporaryBin.Width)
             * {
             *  temporaryItem.IsRemoved = true;
             *  return temporaryBin;
             * }*/

            //item nestabile, procedo
            SetFeasiblePoints(temporaryBin);

            //se il bin non contiene punti
            if (temporaryBin.Points.Count == 0)
            {
                return(temporaryBin);
            }
            else if (temporaryBin.Points.Count == 1 && //se il bin contiene 1 solo punto e quel punto è (0,0)
                     temporaryBin.Points.ElementAt(0).Pposition == 0 &&
                     temporaryBin.Points.ElementAt(0).Qposition == 0)
            {
                Item pricedItem = new Item()
                {
                    Height      = temporaryItem.Height,
                    Width       = temporaryItem.Width,
                    Id          = temporaryItem.Id,
                    Price       = temporaryItem.Price,
                    TLqPosition = temporaryItem.Height,
                    BRpPosition = temporaryItem.Width,
                    TRpPosition = temporaryItem.Width,
                    TRqPosition = temporaryItem.Height
                };
                if (IsBorderObserved(pricedItem, temporaryBin.Height, temporaryBin.Width))
                {
                    temporaryBin.NestedItems = new List <Item>
                    {
                        pricedItem
                    };
                    HandleOperationsPostNestedItem(temporaryBin, temporaryItem, temporaryBin.Points.ElementAt(0), pricedItem);
                }
                else
                {
                    pricedItem = new Item()
                    {
                        Height      = temporaryItem.Width,
                        Width       = temporaryItem.Height,
                        Id          = temporaryItem.Id,
                        Price       = temporaryItem.Price,
                        TLqPosition = temporaryItem.Width,
                        BRpPosition = temporaryItem.Height,
                        TRpPosition = temporaryItem.Height,
                        TRqPosition = temporaryItem.Width
                    };
                    if (IsBorderObserved(pricedItem, temporaryBin.Height, temporaryBin.Width))
                    {
                        temporaryBin.NestedItems = new List <Item>
                        {
                            pricedItem
                        };
                        HandleOperationsPostNestedItem(temporaryBin, temporaryItem, temporaryBin.Points.ElementAt(0), pricedItem);
                    }
                }


                //Console.WriteLine("item " + pricedItem.Id + "(" + pricedItem.Height + ", " + pricedItem.Width + ") nested in "
                //      + temporaryBin.Points.ElementAt(0).PfinalPosition + ", " +
                //  temporaryBin.Points.ElementAt(0).QfinalPosition + ", " + temporaryBin.Points.ElementAt(0).Rposition + " BIN " + temporaryBin.Id);
                return(temporaryBin);
            }
            else if (temporaryBin.Points.Count > 1)//se il bin contiene n punti
            {
                foreach (Tuple feasiblePoint in temporaryBin.Points)
                {
                    if (!feasiblePoint.IsUsed)
                    {
                        Item newPricedItem = null;
                        if (feasiblePoint.Rposition == 0)
                        {
                            //assegno le coordinate di partenza al nuovo item da nestare, poi inzio a muoverlo
                            newPricedItem = new Item()
                            {
                                Height      = temporaryItem.Height,
                                Width       = temporaryItem.Width,
                                Id          = temporaryItem.Id,
                                Price       = temporaryItem.Price,
                                BLpPosition = feasiblePoint.Pposition,
                                BLqPosition = feasiblePoint.Qposition,
                                BRpPosition = feasiblePoint.Pposition + temporaryItem.Width,
                                BRqPosition = feasiblePoint.Qposition,
                                TLpPosition = feasiblePoint.Pposition,
                                TLqPosition = feasiblePoint.Qposition + temporaryItem.Height,
                                TRpPosition = feasiblePoint.Pposition + temporaryItem.Width,
                                TRqPosition = feasiblePoint.Qposition + temporaryItem.Height
                            };
                        }
                        else if (feasiblePoint.Rposition == 1)
                        {
                            newPricedItem = new Item()
                            {
                                Height      = temporaryItem.Width,
                                Width       = temporaryItem.Height,
                                Id          = temporaryItem.Id,
                                Price       = temporaryItem.Price,
                                BLpPosition = feasiblePoint.Pposition,
                                BLqPosition = feasiblePoint.Qposition,
                                BRpPosition = feasiblePoint.Pposition + temporaryItem.Height,
                                BRqPosition = feasiblePoint.Qposition,
                                TLpPosition = feasiblePoint.Pposition,
                                TLqPosition = feasiblePoint.Qposition + temporaryItem.Width,
                                TRpPosition = feasiblePoint.Pposition + temporaryItem.Height,
                                TRqPosition = feasiblePoint.Qposition + temporaryItem.Width
                            };
                        }
                        feasiblePoint.HatchedArea = GetHatchedArea(temporaryBin, newPricedItem, feasiblePoint);
                    }
                }

                //trovo la tupla con lo scarto minore tra quelle ancora disponibili
                //(Where(x => x.HatchedArea >= 0) filtra solo le tuple con hatched area = 0)
                Tuple minHatchedAreaTuple = temporaryBin.Points.Where(x => x.IsUsed == false && x.HatchedArea >= 0)
                                            .OrderBy(x => x.HatchedArea)
                                            .FirstOrDefault();

                //se non riesco a trovare la tupla, vuol dire che le tuple sono finite

                if (minHatchedAreaTuple == null)
                {
                    return(temporaryBin);
                }

                //controllo se ho più tuple che hanno lo stesso scarto (il minore)
                IList <Tuple> minHatchedAreaPoints = new List <Tuple>();
                foreach (Tuple point in temporaryBin.Points)
                {
                    if (point.HatchedArea == minHatchedAreaTuple.HatchedArea && !point.IsUsed)
                    {
                        minHatchedAreaPoints.Add(point);
                    }
                }

                if (minHatchedAreaPoints.Count == 1)
                {
                    Tuple minHatchedAreaPoint = minHatchedAreaPoints.ElementAt(0);
                    Item  pricedItem          = null;
                    if (minHatchedAreaPoint.Rposition == 0)
                    {
                        pricedItem = new Item()
                        {
                            Height      = temporaryItem.Height,
                            Width       = temporaryItem.Width,
                            Id          = temporaryItem.Id,
                            Price       = temporaryItem.Price,
                            BLpPosition = minHatchedAreaPoint.PfinalPosition,
                            BLqPosition = minHatchedAreaPoint.QfinalPosition,
                            BRpPosition = minHatchedAreaPoint.PfinalPosition + temporaryItem.Width,
                            BRqPosition = minHatchedAreaPoint.QfinalPosition,
                            TLpPosition = minHatchedAreaPoint.PfinalPosition,
                            TLqPosition = minHatchedAreaPoint.QfinalPosition + temporaryItem.Height,
                            TRpPosition = minHatchedAreaPoint.PfinalPosition + temporaryItem.Width,
                            TRqPosition = minHatchedAreaPoint.QfinalPosition + temporaryItem.Height
                        };
                    }
                    else if (minHatchedAreaPoint.Rposition == 1)
                    {
                        pricedItem = new Item()
                        {
                            Height      = temporaryItem.Width,
                            Width       = temporaryItem.Height,
                            Id          = temporaryItem.Id,
                            Price       = temporaryItem.Price,
                            BLpPosition = minHatchedAreaPoint.PfinalPosition,
                            BLqPosition = minHatchedAreaPoint.QfinalPosition,
                            BRpPosition = minHatchedAreaPoint.PfinalPosition + temporaryItem.Height,
                            BRqPosition = minHatchedAreaPoint.QfinalPosition,
                            TLpPosition = minHatchedAreaPoint.PfinalPosition,
                            TLqPosition = minHatchedAreaPoint.QfinalPosition + temporaryItem.Width,
                            TRpPosition = minHatchedAreaPoint.PfinalPosition + temporaryItem.Height,
                            TRqPosition = minHatchedAreaPoint.QfinalPosition + temporaryItem.Width
                        };
                    }
                    //Console.WriteLine("item " + pricedItem.Id + "(" + pricedItem.Height + ", " + pricedItem.Width + ") nested in "
                    //  + minHatchedAreaPoint.PfinalPosition + ", " +
                    //minHatchedAreaPoint.QfinalPosition + ", " + minHatchedAreaPoint.Rposition + " BIN " + temporaryBin.Id);

                    temporaryBin.NestedItems.Add(pricedItem);
                    HandleOperationsPostNestedItem(temporaryBin, temporaryItem, minHatchedAreaPoint, pricedItem);
                    return(temporaryBin);
                }
                else if (minHatchedAreaPoints.Count > 1)
                {
                    Tuple minCoordinatePoint = ApplyRule(minHatchedAreaPoints, itemAllocationMethod);
                    Item  pricedItem         = null;
                    if (minCoordinatePoint.Rposition == 0)
                    {
                        pricedItem = new Item()
                        {
                            Height      = temporaryItem.Height,
                            Width       = temporaryItem.Width,
                            Id          = temporaryItem.Id,
                            Price       = temporaryItem.Price,
                            BLpPosition = minCoordinatePoint.PfinalPosition,
                            BLqPosition = minCoordinatePoint.QfinalPosition,
                            BRpPosition = minCoordinatePoint.PfinalPosition + temporaryItem.Width,
                            BRqPosition = minCoordinatePoint.QfinalPosition,
                            TLpPosition = minCoordinatePoint.PfinalPosition,
                            TLqPosition = minCoordinatePoint.QfinalPosition + temporaryItem.Height,
                            TRpPosition = minCoordinatePoint.PfinalPosition + temporaryItem.Width,
                            TRqPosition = minCoordinatePoint.QfinalPosition + temporaryItem.Height
                        };
                    }
                    else if (minCoordinatePoint.Rposition == 1)
                    {
                        pricedItem = new Item()
                        {
                            Height      = temporaryItem.Width,
                            Width       = temporaryItem.Height,
                            Id          = temporaryItem.Id,
                            Price       = temporaryItem.Price,
                            BLpPosition = minCoordinatePoint.PfinalPosition,
                            BLqPosition = minCoordinatePoint.QfinalPosition,
                            BRpPosition = minCoordinatePoint.PfinalPosition + temporaryItem.Height,
                            BRqPosition = minCoordinatePoint.QfinalPosition,
                            TLpPosition = minCoordinatePoint.PfinalPosition,
                            TLqPosition = minCoordinatePoint.QfinalPosition + temporaryItem.Width,
                            TRpPosition = minCoordinatePoint.PfinalPosition + temporaryItem.Height,
                            TRqPosition = minCoordinatePoint.QfinalPosition + temporaryItem.Width
                        };
                    }

                    //Console.WriteLine("item " + pricedItem.Id + "(" + pricedItem.Height + ", " + pricedItem.Width + ") nested in "
                    //  + minCoordinatePoint.PfinalPosition + ", " +
                    //minCoordinatePoint.QfinalPosition + ", " + minCoordinatePoint.Rposition + " BIN " + temporaryBin.Id);

                    temporaryBin.NestedItems.Add(pricedItem);
                    HandleOperationsPostNestedItem(temporaryBin, temporaryItem, minCoordinatePoint, pricedItem);

                    return(temporaryBin);
                }
            }
            return(temporaryBin);
        }
Пример #2
0
        public void Initialize(Configuration configuration, string pricingRule, IPricingUtilities PricingUtilities)
        {
            Sequences = new List <Sequence>
            {
                new Sequence(),
                new Sequence()
            };

            //inizializzo il prezzo v associato ad ogni item j
            Items   = new List <Item>();
            Bins    = new List <Bin>();
            Counter = 0;

            foreach (Dimension dimension in configuration.Dimensions)
            {
                Item item = new Item()
                {
                    Height = dimension.Height,
                    Width  = dimension.Width,
                    Id     = Counter,
                    Price  = PricingUtilities.ComputePricingRule(pricingRule, dimension.Height, dimension.Width)
                };
                Items.Add(item);

                //inserisco ogni item prezzato e i nuovi punti disponibili
                //in un bin diverso
                Bin bin = new Bin()
                {
                    Id          = Counter,
                    Height      = configuration.BinHeight,
                    Width       = configuration.BinWidth,
                    NestedItems = new List <Item>()
                    {
                        item
                    },
                    Points = new List <Position>()
                    {
                        new Position()
                        {
                            Pposition = 0,
                            Qposition = item.Height,
                            Rposition = 0,
                            IsUsed    = false
                        },
                        new Position()
                        {
                            Pposition = 0,
                            Qposition = item.Height,
                            Rposition = 1,
                            IsUsed    = false
                        },
                        new Position()
                        {
                            Pposition = item.Width,
                            Qposition = 0,
                            Rposition = 0,
                            IsUsed    = false
                        },
                        new Position()
                        {
                            Pposition = item.Width,
                            Qposition = 0,
                            Rposition = 1,
                            IsUsed    = false
                        }
                    }
                };

                Bins.Add(bin);
                Counter += 1;
            }

            //inizializzo il costo della soluzione con il numero degli elementi
            Zstar = Counter;

            //inizializzo il numero di iterazioni
            Iter = 0;

            //calcolo il lower bound ed il relativo intervallo
            //double lowerBound;
            MaxIter = configuration.MaxIter;
        }
Пример #3
0
        /// <summary>
        /// metodo per gestire le operazioni post item nestato
        /// </summary>
        /// <param name="temporaryBin"></param>
        /// <param name="temporaryItem"></param>
        /// <param name="point"></param>
        private void HandleOperationsPostNestedItem(Bin <Tuple> temporaryBin, Item sortedTemporaryItem, Tuple point, Item pricedItem)
        {
            //recupero il punto dalla lista usando l'id. tale punto lo setterò poi ad usato
            var matchingPoints = temporaryBin.Points.Where(x => x.Pposition == point.PfinalPosition &&
                                                           x.Qposition == point.QfinalPosition &&
                                                           x.PfinalPosition == point.PfinalPosition &&
                                                           x.QfinalPosition == point.QfinalPosition);

            //.FirstOrDefault();

            //gestisco il fatto che ci possano essere più punti che portano alle stesse coordinate finali
            if (matchingPoints != null)
            {
                foreach (Tuple matchingPoint in matchingPoints)
                {
                    matchingPoint.IsUsed = true;
                }
            }
            else
            {
                matchingPoints = temporaryBin.Points.Where(x => x.PfinalPosition == point.PfinalPosition &&
                                                           x.QfinalPosition == point.QfinalPosition);
                //.FirstOrDefault();
                foreach (Tuple matchingPoint in matchingPoints)
                {
                    matchingPoint.IsUsed = true;
                }
            }
            //===============================================

            //controllo se non è più possibile usare dei punti
            foreach (Tuple p in temporaryBin.Points)
            {
                foreach (Tuple matchingPoint in matchingPoints)
                {
                    //cerco punti "coperti" dal nuovo item nestato
                    if ((p.Pposition >= pricedItem.BLpPosition && p.Pposition < pricedItem.BRpPosition &&
                         p.Qposition >= pricedItem.BLqPosition && p.Qposition < pricedItem.TLqPosition) ||

                        (p.PfinalPosition == matchingPoint.PfinalPosition && //cerco punti che, dopo push down and left portavano alle stesse coordinate finali
                         p.QfinalPosition == matchingPoint.QfinalPosition &&
                         pricedItem.BRpPosition >= p.Pposition &&
                         pricedItem.TLqPosition >= p.Qposition))
                    {
                        p.IsUsed = true;
                    }
                }
            }

            //controllo se il primo nuovo punto (TL) da aggiungere è già presente nella lista temporaryBin.Points e non è statao usato
            Tuple pointFound = temporaryBin.Points.Where(x => x.Pposition == point.PfinalPosition &&
                                                         x.Qposition == point.QfinalPosition + pricedItem.Height &&
                                                         x.IsUsed == false).FirstOrDefault();

            //definisco il primo nuovo punto
            Tuple firstPoint = new Tuple()
            {
                Pposition = point.PfinalPosition,
                Qposition = point.QfinalPosition + pricedItem.Height,
                Rposition = 0,
                IsUsed    = false
            };

            //controllo se il primo nuovo punto è idoneo ad essere aggiunto perché
            //potrebbe essere erroneaemente creato sul lato di un item già in soluzione
            bool isPointLyingOnItemSide = false;

            foreach (Item ni in temporaryBin.NestedItems)
            {
                if (firstPoint.Qposition == ni.BLqPosition &&
                    firstPoint.Pposition > ni.BLpPosition &&
                    firstPoint.Pposition < ni.BRpPosition)
                {
                    isPointLyingOnItemSide = true;
                    break;
                }
            }

            //aggiungo il primo nuovo punto
            if (pointFound == null && !isPointLyingOnItemSide)
            {
                temporaryBin.Points.Add(firstPoint);

                firstPoint = new Tuple()
                {
                    Pposition = point.PfinalPosition,
                    Qposition = point.QfinalPosition + pricedItem.Height,
                    Rposition = 1,
                    IsUsed    = false
                };

                temporaryBin.Points.Add(firstPoint);
            }
            else
            {
                pointFound = null;
            }

            isPointLyingOnItemSide = false;

            //controllo se il secondo nuovo punto (BR) da aggiungere è già presente nella lista temporaryBin.Points e non è statao usato
            pointFound = temporaryBin.Points.Where(x => x.Pposition == point.PfinalPosition + pricedItem.Width &&
                                                   x.Qposition == point.QfinalPosition &&
                                                   x.IsUsed == false).FirstOrDefault();

            //definisco il secondo nuovo punto
            Tuple secondPoint = new Tuple()
            {
                Pposition = point.PfinalPosition + pricedItem.Width,
                Qposition = point.QfinalPosition,
                Rposition = 0,
                IsUsed    = false
            };

            //controllo se il secondo nuovo punto è idoneo ad essere aggiunto perché
            //potrebbe essere erroneaemente creato sul lato di un item già esistente
            foreach (Item ni in temporaryBin.NestedItems)
            {
                if (secondPoint.Pposition == ni.BLpPosition &&
                    secondPoint.Qposition > ni.BLqPosition &&
                    secondPoint.Qposition < ni.TLqPosition)
                {
                    isPointLyingOnItemSide = true;
                    break;
                }
            }

            //aggiungo il secondo nuovo punto
            if (pointFound == null && !isPointLyingOnItemSide)
            {
                temporaryBin.Points.Add(secondPoint);

                secondPoint = new Tuple()
                {
                    Pposition = point.PfinalPosition + pricedItem.Width,
                    Qposition = point.QfinalPosition,
                    Rposition = 1,
                    IsUsed    = false
                };

                temporaryBin.Points.Add(secondPoint);
            }

            //setto item a nestato
            sortedTemporaryItem.IsRemoved = true;
        }