Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HeuristicLab.BinPacking/HeuristicLab.Problems.BinPacking/3.3/Decoders/3D/EP/ExtremePointsFunctions3D.cs @ 9440

Last change on this file since 9440 was 9440, checked in by jhelm, 11 years ago

#1966: Implemented new encoding (MultiComponentVector/MCV); Implemented move-operators for MCV and GV encodings; Implemented new decoding-methods for PS, GV and MCV encodings (ExtremePoint-based packing);

File size: 20.4 KB
Line 
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using System.Text;
5using HeuristicLab.Collections;
6using HeuristicLab.Core;
7using HeuristicLab.Encodings.PackingEncoding.GroupingVector;
8using HeuristicLab.Encodings.PackingEncoding.MultiComponentVector;
9using HeuristicLab.Encodings.PackingEncoding.PackingSequence;
10using HeuristicLab.Problems.BinPacking.Dimensions;
11using HeuristicLab.Problems.BinPacking.Interfaces;
12using HeuristicLab.Problems.BinPacking.PackingBin;
13using HeuristicLab.Problems.BinPacking.PackingItem;
14using HeuristicLab.Problems.BinPacking.Shapes;
15
16namespace HeuristicLab.Problems.BinPacking.Decoders {
17  public static class ExtremePointsFunctions3D {
18
19
20
21
22    public static ObservableDictionary<int, ThreeDimensionalPacking> ExtremePointBasedPacking(ref MultiComponentVectorEncoding solution,
23        ItemList<CuboidPackingItem> itemMeasures, CuboidPackingBin binMeasures) {
24
25      #region Preperations
26      int lowerBound = solution.PackingInformations.Max(x => x.AssignedBin);
27      int nrOfBins = lowerBound + 1;
28
29      //Get all indexes of items for every bin according to grouping-vector                     
30      Dictionary<int, List<PackingInformation>> unpackedItemIndexesPerBin = new Dictionary<int, List<PackingInformation>>();
31      Dictionary<int, HashSet<ThreeDimensionalPacking>> extremePointsForBin = new Dictionary<int, HashSet<ThreeDimensionalPacking>>();
32      var occupiedPoints = new List<int[, ,]>();
33
34      for (int i = 0; i < nrOfBins; i++) {       
35        unpackedItemIndexesPerBin[i] = solution.PackingInformations
36          .Where(pi => pi.AssignedBin == i)
37          .ToList();
38
39        extremePointsForBin[i] = new HashSet<ThreeDimensionalPacking>();
40        extremePointsForBin[i].Add(new ThreeDimensionalPacking(i, 0, 0, 0, false));
41        occupiedPoints = IncreaseBinCountForOccupiedPoints(occupiedPoints, binMeasures);
42      }
43
44      ObservableDictionary<int, ThreeDimensionalPacking> itemPositions = new ObservableDictionary<int, ThreeDimensionalPacking>();
45      var remainingItems = new List<PackingInformation>();
46
47      #endregion Preperations
48
49
50      //Iterate over all bin-lists
51      for (int binNr = 0; binNr < nrOfBins; binNr++) {
52        //Iterate over the current bin-item-list and find feasible positions in the current bin for each item
53        var unpackedItems = unpackedItemIndexesPerBin[binNr];
54        for (int i = 0; i < unpackedItems.Count; i++) {
55          var itemIndex = unpackedItems[i].ItemIndex;
56          var item = itemMeasures[itemIndex];
57
58          extremePointsForBin[binNr] = new HashSet<ThreeDimensionalPacking>(extremePointsForBin[binNr].OrderBy(ep => ep.AssignedBin).ThenBy(ep => ShortestPossibleSideFromEP(ep, occupiedPoints, binMeasures)));
59          var positionFound = FindExtremePointForItem(itemIndex, itemMeasures, binMeasures, extremePointsForBin[binNr], occupiedPoints, itemPositions, unpackedItems[i].Rotated);
60          if (positionFound != null) {
61            extremePointsForBin[binNr].Remove(positionFound);
62            itemPositions[itemIndex] = positionFound;
63            occupiedPoints = OccupyPointsForNewItem(occupiedPoints, item, positionFound, itemIndex);
64            extremePointsForBin[binNr] = GenerateNewExtremePointsForNewItem(extremePointsForBin[binNr], occupiedPoints, item, positionFound, binMeasures);
65          } else
66            remainingItems.Add(unpackedItems[i]);
67        }
68      }
69
70
71      //Packing of remaining items   
72      //Iterate over all bin-lists
73      for (int binNr = 0; binNr < nrOfBins && remainingItems.Count > 0; binNr++) {
74        var unpackedItems = new List<PackingInformation>(remainingItems);
75        //Iterate over all the remaining items
76        for (int i = 0; i < unpackedItems.Count; i++) {
77          var itemIndex = unpackedItems[i].ItemIndex;
78          var item = itemMeasures[itemIndex];
79
80          extremePointsForBin[binNr] = new HashSet<ThreeDimensionalPacking>(extremePointsForBin[binNr].OrderBy(ep => ep.AssignedBin).ThenBy(ep => ShortestPossibleSideFromEP(ep, occupiedPoints, binMeasures)));
81          var positionFound = FindExtremePointForItem(itemIndex, itemMeasures, binMeasures, extremePointsForBin[binNr], occupiedPoints, itemPositions, unpackedItems[i].Rotated);
82          if (positionFound != null) {
83            extremePointsForBin[binNr].Remove(positionFound);
84            itemPositions[itemIndex] = positionFound;
85            occupiedPoints = OccupyPointsForNewItem(occupiedPoints, item, positionFound, itemIndex);
86            extremePointsForBin[binNr] = GenerateNewExtremePointsForNewItem(extremePointsForBin[binNr], occupiedPoints, item, positionFound, binMeasures);
87            remainingItems.Remove(unpackedItems[i]);
88            if (binNr <= lowerBound) {
89              InsertItemgeneAfterLastItemgeneOfUsedBin(ref solution, itemIndex, binNr);
90            }
91          }
92        }
93        if (remainingItems.Count > 0 && binNr + 1 >= nrOfBins) {
94          extremePointsForBin[nrOfBins] = new HashSet<ThreeDimensionalPacking>();
95          extremePointsForBin[nrOfBins].Add(new ThreeDimensionalPacking(nrOfBins, 0, 0, 0, false));
96          occupiedPoints = IncreaseBinCountForOccupiedPoints(occupiedPoints, binMeasures);
97          nrOfBins++;
98        }
99      }
100
101      return itemPositions;
102    }
103    private static void InsertItemgeneAfterLastItemgeneOfUsedBin(ref MultiComponentVectorEncoding solution, int itemIndex, int binNr) {
104      var itemgene = solution.PackingInformations.Find(pi => pi.ItemIndex == itemIndex);
105      solution.PackingInformations.Remove (itemgene);
106      itemgene.AssignedBin = binNr;
107      int targetIndex = solution.PackingInformations.FindLastIndex(pi => pi.AssignedBin == binNr);
108      solution.PackingInformations.Insert(targetIndex + 1, itemgene);
109    }
110
111
112    public static ObservableDictionary<int, ThreeDimensionalPacking> ExtremePointBasedPacking(GroupingVectorEncoding solution,
113        ItemList<CuboidPackingItem> itemMeasures, CuboidPackingBin binMeasures) {
114
115      #region Preperations
116      int nrOfBins = solution.GroupingVector.Max() + 1;
117
118      //Get all indexes of items for every bin according to grouping-vector
119      Dictionary<int, List<int>> unpackedItemIndexesPerBin = new Dictionary<int, List<int>>();   
120      Dictionary<int, HashSet<ThreeDimensionalPacking>> extremePointsForBin = new Dictionary<int, HashSet<ThreeDimensionalPacking>>();
121      var occupiedPoints = new List<int[, ,]>();
122
123      for (int i = 0; i < nrOfBins; i++) {
124        unpackedItemIndexesPerBin[i] = solution.GroupingVector
125          .Select((Value, Index) => new { Value, Index })
126          .Where(temp => temp.Value == i)
127          .Select(temp => temp.Index).ToList();
128
129        extremePointsForBin[i] = new HashSet<ThreeDimensionalPacking>();
130        extremePointsForBin[i].Add(new ThreeDimensionalPacking(i, 0, 0, 0, false));   
131        occupiedPoints = IncreaseBinCountForOccupiedPoints(occupiedPoints, binMeasures);
132      }
133
134      ObservableDictionary<int, ThreeDimensionalPacking> itemPositions = new ObservableDictionary<int, ThreeDimensionalPacking>();
135      var remainingItems = new List<int>();
136
137      #endregion Preperations
138
139             
140
141      //Iterate over all bin-lists
142      for (int binNr = 0; binNr < nrOfBins; binNr++) {
143        //Iterate over the current bin-item-list and find feasible positions in the current bin for each item
144        var unpackedItems = unpackedItemIndexesPerBin[binNr];
145        for (int i = 0; i < unpackedItems.Count; i++) {
146          var itemIndex = unpackedItems[i];
147          var item = itemMeasures[itemIndex];
148
149          extremePointsForBin[binNr] = new HashSet<ThreeDimensionalPacking>(extremePointsForBin[binNr].OrderBy(ep => ep.AssignedBin).ThenBy(ep => ShortestPossibleSideFromEP(ep, occupiedPoints, binMeasures)));
150          var positionFound = FindExtremePointForItem(itemIndex, itemMeasures, binMeasures, extremePointsForBin[binNr], occupiedPoints, itemPositions);
151          if (positionFound != null) {
152            extremePointsForBin[binNr].Remove(positionFound);
153            itemPositions[itemIndex] = positionFound;
154            occupiedPoints = OccupyPointsForNewItem(occupiedPoints, item, positionFound, itemIndex);
155            extremePointsForBin[binNr] = GenerateNewExtremePointsForNewItem(extremePointsForBin[binNr], occupiedPoints, item, positionFound, binMeasures);
156          } else
157            remainingItems.Add(itemIndex);
158        }
159      }
160
161
162
163      //Packing of remaining items   
164      //Iterate over all bin-lists
165      for (int binNr = 0; binNr < nrOfBins && remainingItems.Count > 0; binNr++) {
166        var unpackedItems = new List<int>(remainingItems);
167        //Iterate over all the remaining items
168        for (int i = 0; i < unpackedItems.Count; i++) {
169          var itemIndex = unpackedItems[i];
170          var item = itemMeasures[itemIndex];
171
172          extremePointsForBin[binNr] = new HashSet<ThreeDimensionalPacking>(extremePointsForBin[binNr].OrderBy(ep => ep.AssignedBin).ThenBy(ep => ShortestPossibleSideFromEP(ep, occupiedPoints, binMeasures)));
173          var positionFound = FindExtremePointForItem(itemIndex, itemMeasures, binMeasures, extremePointsForBin[binNr], occupiedPoints, itemPositions);
174          if (positionFound != null) {
175            extremePointsForBin[binNr].Remove(positionFound);
176            itemPositions[itemIndex] = positionFound;
177            occupiedPoints = OccupyPointsForNewItem(occupiedPoints, item, positionFound, itemIndex);
178            extremePointsForBin[binNr] = GenerateNewExtremePointsForNewItem(extremePointsForBin[binNr], occupiedPoints, item, positionFound, binMeasures);       
179            remainingItems.Remove(itemIndex);
180          }
181        }
182        if (remainingItems.Count > 0 && binNr + 1 >= nrOfBins) {
183          extremePointsForBin[nrOfBins] = new HashSet<ThreeDimensionalPacking>();
184          extremePointsForBin[nrOfBins].Add(new ThreeDimensionalPacking(nrOfBins, 0, 0, 0, false));
185          occupiedPoints = IncreaseBinCountForOccupiedPoints(occupiedPoints, binMeasures);
186          nrOfBins++;
187        }
188      }
189
190      return itemPositions;
191    }
192
193
194    public static ObservableDictionary<int, ThreeDimensionalPacking> ExtremePointBasedPacking(PackingSequenceEncoding solution,
195        ItemList<CuboidPackingItem> itemMeasures, CuboidPackingBin binMeasures) {
196
197      #region Preperations
198      var itemPositions = new ObservableDictionary<int, ThreeDimensionalPacking>(); 
199      int nrOfBins = 1;
200
201      var occupiedPoints = new List<int[, ,]>();
202      occupiedPoints = IncreaseBinCountForOccupiedPoints(occupiedPoints, binMeasures);
203
204      HashSet<ThreeDimensionalPacking> extremePoints = new HashSet<ThreeDimensionalPacking>();
205      extremePoints.Add(new ThreeDimensionalPacking(0, 0, 0, 0, false));
206      #endregion
207
208      foreach (int itemIndex in solution.PackingSequence) {
209        var item = itemMeasures[itemIndex];
210        extremePoints = new HashSet<ThreeDimensionalPacking>(extremePoints.OrderBy(ep => ep.AssignedBin).ThenBy(ep => ShortestPossibleSideFromEP(ep, occupiedPoints, binMeasures)));
211        var positionFound = FindExtremePointForItem(itemIndex, itemMeasures, binMeasures, extremePoints, occupiedPoints, itemPositions);
212        if (positionFound != null) {
213          extremePoints.Remove(positionFound);
214        }
215        else {
216          positionFound = new ThreeDimensionalPacking(nrOfBins, 0, 0, 0);
217          occupiedPoints = IncreaseBinCountForOccupiedPoints(occupiedPoints, binMeasures);
218          nrOfBins++;
219        }
220        itemPositions[itemIndex] = positionFound;
221        occupiedPoints = OccupyPointsForNewItem(occupiedPoints, item, positionFound, itemIndex);
222        extremePoints = GenerateNewExtremePointsForNewItem(extremePoints, occupiedPoints, item, positionFound, binMeasures);
223      }
224
225      return itemPositions;
226    }
227
228
229    private static ThreeDimensionalPacking FindExtremePointForItem(int itemIndex, ItemList<CuboidPackingItem> itemMeasures, CuboidPackingBin binMeasures,
230        HashSet<ThreeDimensionalPacking> extremePoints, List<int[, ,]> occupiedPoints, ObservableDictionary<int, ThreeDimensionalPacking> itemPositions) {
231          return FindExtremePointForItem(itemIndex, itemMeasures, binMeasures, extremePoints, occupiedPoints, itemPositions, false);
232    }
233    private static ThreeDimensionalPacking FindExtremePointForItem(int itemIndex, ItemList<CuboidPackingItem> itemMeasures, CuboidPackingBin binMeasures,
234        HashSet<ThreeDimensionalPacking> extremePoints, List<int[,,]> occupiedPoints, ObservableDictionary<int, ThreeDimensionalPacking> itemPositions, bool rotated) {
235
236      var itemFromList = itemMeasures[itemIndex];
237      CuboidPackingItem item = new CuboidPackingItem(
238        rotated ? itemFromList.Depth : itemFromList.Width,
239        itemFromList.Height,
240        rotated ? itemFromList.Width : itemFromList.Depth,
241        itemFromList.TargetBin);
242
243      int epIndex = 0;
244      while (epIndex < extremePoints.Count &&
245        (!DeepestBottomLeftFunctions.IsPositionFeasible(binMeasures, extremePoints.ElementAt(epIndex).AssignedBin, item, extremePoints.ElementAt(epIndex), itemPositions, itemMeasures) ||
246        !IsStaticStable(occupiedPoints[extremePoints.ElementAt(epIndex).AssignedBin], item, extremePoints.ElementAt(epIndex))))
247      { epIndex++; }
248
249      if (epIndex < extremePoints.Count) {
250        var result = extremePoints.ElementAt(epIndex);
251        result.Rotated = rotated;
252        return result;
253      }
254      return null;
255    }
256    private static List<int[, ,]> IncreaseBinCountForOccupiedPoints(List<int[, ,]> occupiedPoints, CuboidPackingBin binMeasures) {
257      occupiedPoints.Add(new int[binMeasures.Width, binMeasures.Height, binMeasures.Depth]);
258      int lastIndex = occupiedPoints.Count - 1;
259      for (int w = 0; w < binMeasures.Width; w++) {
260        for (int h = 0; h < binMeasures.Height; h++) {
261          for (int d = 0; d < binMeasures.Depth; d++) {
262            occupiedPoints[lastIndex][w, h, d] = -1;
263          }
264        }
265      }
266      return occupiedPoints;
267    }
268    private static bool IsStaticStable(int[, ,] occupiedPoints, CuboidPackingItem item, ThreeDimensionalPacking ep) {
269      //Static stability is given, if item is placed on the ground
270      if (ep.Y == 0)
271        return true;
272
273      if (occupiedPoints[ep.X, ep.Y - 1, ep.Z] != -1
274        && occupiedPoints[ep.X + item.Width - 1, ep.Y - 1, ep.Z] != -1
275        && occupiedPoints[ep.X, ep.Y - 1, ep.Z + item.Depth - 1] != -1
276        && occupiedPoints[ep.X + item.Width - 1, ep.Y - 1, ep.Z + item.Depth - 1] != -1)
277        return true;
278
279      //int groundCount = 0;
280      //for (int x = ep.X; x < ep.X + item.Width - 1; x++) {
281      //  for (int z = ep.Z; z < ep.Z + item.Depth - 1; z++) {
282      //    if (occupiedPoints[x,ep.Y-1, z] != -1)                                                     
283      //      groundCount++;
284      //  }
285      //}
286      //double stableGround = (double)(groundCount) / (double)(item.Width * item.Depth);
287      //if (stableGround > 0.75)
288      //  return true;
289
290      return false;
291    }
292    private static List<int[, ,]>  OccupyPointsForNewItem(List<int[, ,]> occupiedPoints, CuboidPackingItem newItem, ThreeDimensionalPacking position, int itemIndex) {
293      int width = position.Rotated ? newItem.Depth : newItem.Width;
294      int depth = position.Rotated ? newItem.Width : newItem.Depth;
295      for (int w = position.X; w < position.X + width; w++) {
296        for (int h = position.Y; h < position.Y + newItem.Height; h++) {
297          for (int d = position.Z; d < position.Z + depth; d++) {
298            occupiedPoints[position.AssignedBin][w,h,d] = itemIndex;
299          }
300        }
301      }
302      return occupiedPoints;
303    }
304    private static HashSet<ThreeDimensionalPacking> GenerateNewExtremePointsForNewItem(HashSet<ThreeDimensionalPacking> extremePoints, List<int[, ,]> occupiedPoints,
305        CuboidPackingItem newItem, ThreeDimensionalPacking position, CuboidPackingBin binMeasures) {
306      int currentBin = position.AssignedBin;
307
308      int newWidth = position.Rotated ? newItem.Depth : newItem.Width;
309      int newDepth = position.Rotated ? newItem.Width : newItem.Depth;
310
311      //Find ExtremePoints beginning from sourcepointX
312      var sourcePointX = new ThreeDimensionalPacking(currentBin, position.X + newWidth, position.Y, position.Z);
313      if (sourcePointX.X < binMeasures.Width && sourcePointX.Y < binMeasures.Height && sourcePointX.Z < binMeasures.Depth) {
314        //Traversing down the y-axis                                                                           
315        int currentYValue = sourcePointX.Y;
316        while (currentYValue > 0 && occupiedPoints[currentBin][sourcePointX.X, currentYValue, sourcePointX.Z] == -1) {
317          currentYValue--;
318        }
319        extremePoints.Add(new ThreeDimensionalPacking(currentBin, sourcePointX.X, currentYValue, sourcePointX.Z));
320
321        //Traversing down the z-axis
322        int currentZValue = sourcePointX.Z;
323        while (currentZValue > 0 && occupiedPoints[currentBin][sourcePointX.X, sourcePointX.Y, currentZValue - 1] == -1) {
324          currentZValue--;
325        }
326        extremePoints.Add(new ThreeDimensionalPacking(currentBin, sourcePointX.X, sourcePointX.Y, currentZValue));
327      }
328
329
330
331
332      //Find ExtremePoints beginning from sourcepointY
333      var sourcePointY = new ThreeDimensionalPacking(currentBin, position.X, position.Y + newItem.Height, position.Z);
334      if (sourcePointY.X < binMeasures.Width && sourcePointY.Y < binMeasures.Height && sourcePointY.Z < binMeasures.Depth) {
335        //Traversing down the x-axis 
336        int currentXValue = sourcePointY.X;
337        while (currentXValue > 0 && occupiedPoints[currentBin][currentXValue - 1, sourcePointY.Y, sourcePointY.Z] == -1) {
338          currentXValue--;
339        }
340        extremePoints.Add(new ThreeDimensionalPacking(currentBin, currentXValue, sourcePointY.Y, sourcePointY.Z));
341
342        //Traversing down the z-axis
343        int currentZValue = sourcePointY.Z;
344        while (currentZValue > 0 && occupiedPoints[currentBin][sourcePointY.X, sourcePointY.Y, currentZValue - 1] == -1) {
345          currentZValue--;
346        }
347        extremePoints.Add(new ThreeDimensionalPacking(currentBin, sourcePointY.X, sourcePointY.Y, currentZValue));
348      }
349
350
351
352
353
354      //Find ExtremePoints beginning from sourcepointZ
355      var sourcePointZ = new ThreeDimensionalPacking(currentBin, position.X, position.Y, position.Z + newDepth);
356      if (sourcePointZ.X < binMeasures.Width && sourcePointZ.Y < binMeasures.Height && sourcePointZ.Z < binMeasures.Depth) {
357        //Traversing down the x-axis 
358        int currentXValue = sourcePointZ.X;
359        while (currentXValue > 0 && occupiedPoints[currentBin][currentXValue - 1, sourcePointZ.Y, sourcePointZ.Z] == -1) {
360          currentXValue--;
361        }
362        extremePoints.Add(new ThreeDimensionalPacking(currentBin, currentXValue, sourcePointZ.Y, sourcePointZ.Z));
363
364        //Traversing down the y-axis                                                                           
365        int currentYValue = sourcePointZ.Y;
366        while (currentYValue > 0 && occupiedPoints[currentBin][sourcePointZ.X, currentYValue, sourcePointZ.Z] == -1) {
367          currentYValue--;
368        }
369        extremePoints.Add(new ThreeDimensionalPacking(currentBin, sourcePointZ.X, currentYValue, sourcePointZ.Z));
370      }
371
372
373      return extremePoints;
374    }
375    private static int ShortestPossibleSideFromEP(ThreeDimensionalPacking ep, List<int[, ,]> occupiedPoints, CuboidPackingBin binMeasures) {
376      int shortestSide = int.MaxValue;
377
378      if (ep.X >= binMeasures.Width || ep.Y >= binMeasures.Height || ep.Z >= binMeasures.Depth)
379        return shortestSide;
380
381      int currentX = ep.X;
382      while (currentX < binMeasures.Width && occupiedPoints[ep.AssignedBin][currentX, ep.Y, ep.Z] == -1) { currentX++; }   
383      if (currentX - ep.X < shortestSide)
384        shortestSide = currentX - ep.X;
385
386      int currentY = ep.Y;
387      while (currentY < binMeasures.Height && occupiedPoints[ep.AssignedBin][ep.X, currentY, ep.Z] == -1) { currentY++;  }
388      if (currentY - ep.Y < shortestSide)
389        shortestSide = currentY - ep.Y;
390
391      int currentZ = ep.Z;
392      while (currentZ < binMeasures.Depth && occupiedPoints[ep.AssignedBin][ep.X, ep.Y, currentZ] == -1) { currentZ++; }
393      if (currentZ - ep.Z < shortestSide)
394        shortestSide = currentZ - ep.Z;
395
396      return shortestSide;
397    }
398  }
399}
Note: See TracBrowser for help on using the repository browser.