Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HeuristicLab.BinPacking/HeuristicLab.Problems.BinPacking/3.3/Encodings/PackingPlans/BinPacking3D.cs @ 9599

Last change on this file since 9599 was 9599, checked in by jhelm, 12 years ago

#1966: Bugfixing; Refactoring; Performancetuning;

File size: 18.2 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2012 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
4 *
5 * This file is part of HeuristicLab.
6 *
7 * HeuristicLab is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * HeuristicLab is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
19 */
20#endregion
21
22using System;
23using System.Collections.Generic;
24using System.Linq;
25using System.Text;
26using HeuristicLab.Problems.BinPacking.Interfaces;
27using HeuristicLab.Problems.BinPacking.PackingItem;
28using HeuristicLab.Problems.BinPacking.Shapes;
29using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
30using HeuristicLab.Core;
31using HeuristicLab.Common;
32using HeuristicLab.Parameters;
33using HeuristicLab.Data;
34using HeuristicLab.Collections;
35using HeuristicLab.Problems.BinPacking.Dimensions;
36using HeuristicLab.Problems.BinPacking.PackingBin;
37
38namespace HeuristicLab.Encodings.PackingEncoding.PackingPlan {
39  [Item("BinPacking3D", "Represents a single-bin packing for a 3D bin-packing problem.")]
40  [StorableClass]
41  public class BinPacking3D : BinPacking<ThreeDimensionalPacking, CuboidPackingBin, CuboidPackingItem> {
42
43    public BinPacking3D(CuboidPackingBin binMeasures)
44      : base(binMeasures) {
45      //ExtremePoints = new HashSet<ThreeDimensionalPacking>();
46      ExtremePoints = new SortedSet<ThreeDimensionalPacking>(new EPComparer3D());
47      ExtremePoints.Add(binMeasures.Origin);
48    }
49    [StorableConstructor]
50    protected BinPacking3D(bool deserializing) : base(deserializing) { }
51    protected BinPacking3D(BinPacking3D original, Cloner cloner)
52      : base(original, cloner) {
53      this.depthWasDoubled = original.depthWasDoubled;
54      this.ExtremePoints = new SortedSet<ThreeDimensionalPacking>(original.ExtremePoints, new EPComparer3D());
55    }
56    public override IDeepCloneable Clone(Cloner cloner) {
57      return new BinPacking3D(this, cloner);
58    }
59                                       
60    protected override void GenerateNewExtremePointsForNewItem(CuboidPackingItem newItem, ThreeDimensionalPacking position) {
61      int newWidth = position.Rotated ? newItem.Depth : newItem.Width;
62      int newDepth = position.Rotated ? newItem.Width : newItem.Depth;
63
64      //Find ExtremePoints beginning from sourcepointX
65      var sourcePointX = new ThreeDimensionalPacking(0, position.X + newWidth, position.Y, position.Z);
66      if (sourcePointX.X < BinMeasures.Width && sourcePointX.Y < BinMeasures.Height && sourcePointX.Z < BinMeasures.Depth) {
67        //Traversing down the y-axis           
68        ThreeDimensionalPacking current = new ThreeDimensionalPacking(0, sourcePointX.X, sourcePointX.Y, sourcePointX.Z);
69        while (current.Y > 0 && !IsPointOccupied(ThreeDimensionalPacking.MoveDown (current))) {
70          current = ThreeDimensionalPacking.MoveDown(current);
71        }
72        ExtremePoints.Add((ThreeDimensionalPacking)current.Clone());
73        while (current.X > 0 && !IsPointOccupied(ThreeDimensionalPacking.MoveLeft(current))) {
74          current = ThreeDimensionalPacking.MoveLeft(current);
75        }
76        ExtremePoints.Add(current);
77
78        //Traversing down the z-axis                 
79        current = new ThreeDimensionalPacking(0, sourcePointX.X, sourcePointX.Y, sourcePointX.Z);
80        while (current.Z > 0 && !IsPointOccupied(ThreeDimensionalPacking.MoveBack (current))) {
81          current = ThreeDimensionalPacking.MoveBack(current);
82        }
83        ExtremePoints.Add((ThreeDimensionalPacking)current.Clone());
84        while (current.Y > 0 && !IsPointOccupied(ThreeDimensionalPacking.MoveDown(current))) {
85          current = ThreeDimensionalPacking.MoveDown(current);
86        }
87        ExtremePoints.Add(current);
88      }
89
90
91
92
93      //Find ExtremePoints beginning from sourcepointY
94      var sourcePointY = new ThreeDimensionalPacking(0, position.X, position.Y + newItem.Height, position.Z);
95      if (sourcePointY.X < BinMeasures.Width && sourcePointY.Y < BinMeasures.Height && sourcePointY.Z < BinMeasures.Depth) {
96        //Traversing down the x-axis         
97        ThreeDimensionalPacking current = new ThreeDimensionalPacking(0, sourcePointY.X, sourcePointY.Y, sourcePointY.Z);
98        while (current.X > 0 && !IsPointOccupied(ThreeDimensionalPacking.MoveLeft(current))) {
99          current = ThreeDimensionalPacking.MoveLeft(current);
100        }
101        ExtremePoints.Add((ThreeDimensionalPacking)current.Clone());
102        while (current.Y > 0 && !IsPointOccupied(ThreeDimensionalPacking.MoveDown(current))) {
103          current = ThreeDimensionalPacking.MoveDown(current);
104        }
105        ExtremePoints.Add(current);
106
107        //Traversing down the z-axis                                                                   
108        current = new ThreeDimensionalPacking(0, sourcePointY.X, sourcePointY.Y, sourcePointY.Z);
109        while (current.Z > 0 && !IsPointOccupied(ThreeDimensionalPacking.MoveBack(current))) {
110          current = ThreeDimensionalPacking.MoveBack(current);
111        }
112        ExtremePoints.Add((ThreeDimensionalPacking)current.Clone());
113        while (current.Y > 0 && !IsPointOccupied(ThreeDimensionalPacking.MoveDown(current))) {
114          current = ThreeDimensionalPacking.MoveDown(current);
115        }
116        ExtremePoints.Add(current);
117      }
118
119
120
121
122
123      //Find ExtremePoints beginning from sourcepointZ
124      var sourcePointZ = new ThreeDimensionalPacking(0, position.X, position.Y, position.Z + newDepth);
125      if (sourcePointZ.X < BinMeasures.Width && sourcePointZ.Y < BinMeasures.Height && sourcePointZ.Z < BinMeasures.Depth) {
126        //Traversing down the x-axis                                                                             
127        ThreeDimensionalPacking current = new ThreeDimensionalPacking(0, sourcePointZ.X, sourcePointZ.Y, sourcePointZ.Z);
128        while (current.X > 0 && !IsPointOccupied(ThreeDimensionalPacking.MoveLeft(current))) {
129          current = ThreeDimensionalPacking.MoveLeft(current);
130        }
131        ExtremePoints.Add((ThreeDimensionalPacking)current.Clone());
132        while (current.Y > 0 && !IsPointOccupied(ThreeDimensionalPacking.MoveDown(current))) {
133          current = ThreeDimensionalPacking.MoveDown(current);
134        }
135        ExtremePoints.Add(current);
136
137        //Traversing down the y-axis                                                                     
138        current = new ThreeDimensionalPacking(0, sourcePointZ.X, sourcePointZ.Y, sourcePointZ.Z);
139        while (current.Y > 0 && !IsPointOccupied(ThreeDimensionalPacking.MoveDown(current))) {
140          current = ThreeDimensionalPacking.MoveDown(current);
141        }
142        ExtremePoints.Add((ThreeDimensionalPacking)current.Clone());
143        while (current.X > 0 && !IsPointOccupied(ThreeDimensionalPacking.MoveLeft(current))) {
144          current = ThreeDimensionalPacking.MoveLeft(current);
145        }
146        ExtremePoints.Add(current);
147      }
148
149      //ExtremePoints.RemoveWhere(ep => IsPointOccupied (ep));
150
151      //ExtremePoints = new HashSet<ThreeDimensionalPacking>(ExtremePoints.
152      //  OrderBy(ep => ep.Z).
153      //  ThenBy(ep => ep.X).
154      //  ThenBy(ep => ep.Y)//.ThenBy(ep => ShortestPossibleSideFromPoint(ep))
155      //  );
156    }
157
158    public override ThreeDimensionalPacking FindExtremePointForItem(CuboidPackingItem measures, bool rotated, bool stackingConstraints) {
159
160      CuboidPackingItem item = new CuboidPackingItem(
161        rotated ? measures.Depth : measures.Width,
162        measures.Height,
163        rotated ? measures.Width : measures.Depth,
164        measures.TargetBin);
165
166      int epIndex = 0;
167      while (epIndex < ExtremePoints.Count && (
168        !IsPositionFeasible(item, ExtremePoints.ElementAt(epIndex))
169        || !IsSupportedByAtLeastOnePoint(item, ExtremePoints.ElementAt(epIndex))
170        || (stackingConstraints && !IsStaticStable(item, ExtremePoints.ElementAt(epIndex)))
171        || (stackingConstraints && !IsWeightSupported(item, ExtremePoints.ElementAt(epIndex)))
172      )) { epIndex++; }
173
174      if (epIndex < ExtremePoints.Count) {
175        var result = ExtremePoints.ElementAt(epIndex);
176        result.Rotated = rotated;
177        return result;
178      }
179      return null;
180    }
181
182    public override ThreeDimensionalPacking FindPositionBySliding(CuboidPackingItem measures, bool rotated) {
183      //Starting-position at upper right corner (=left bottom point of item-rectangle is at position item.width,item.height)
184      ThreeDimensionalPacking currentPosition = new ThreeDimensionalPacking(0,
185        BinMeasures.Width - (rotated ? measures.Depth : measures.Width),
186        BinMeasures.Height - measures.Height,
187        BinMeasures.Depth - (rotated ? measures.Width : measures.Depth), rotated);
188      //Slide the item as far as possible to the bottom
189      while (IsPositionFeasible(measures, ThreeDimensionalPacking.MoveDown(currentPosition))
190        || IsPositionFeasible(measures, ThreeDimensionalPacking.MoveLeft(currentPosition))
191        || IsPositionFeasible(measures, ThreeDimensionalPacking.MoveBack(currentPosition))) {
192        //Slide the item as far as possible to the left
193          while (IsPositionFeasible(measures, ThreeDimensionalPacking.MoveLeft(currentPosition))
194        || IsPositionFeasible(measures, ThreeDimensionalPacking.MoveBack(currentPosition))) {
195          //Slide the item as far as possible to the back
196          while (IsPositionFeasible(measures, ThreeDimensionalPacking.MoveBack(currentPosition))) {
197            currentPosition = ThreeDimensionalPacking.MoveBack(currentPosition);
198          }
199          if (IsPositionFeasible(measures, ThreeDimensionalPacking.MoveLeft(currentPosition)))
200            currentPosition = ThreeDimensionalPacking.MoveLeft(currentPosition);
201        }
202          if (IsPositionFeasible(measures, ThreeDimensionalPacking.MoveDown(currentPosition)))
203            currentPosition = ThreeDimensionalPacking.MoveDown(currentPosition);
204      }
205
206      return IsPositionFeasible(measures, currentPosition) ? currentPosition : null;
207    }
208   
209    public override void SlidingBasedPacking(ref List<int> sequence, ItemList<CuboidPackingItem> itemMeasures) {
210      var temp = new List<int>(sequence);
211      for (int i = 0; i < temp.Count; i++) {
212        var item = itemMeasures[temp[i]];
213        var position = FindPositionBySliding(item, false);
214        if (position != null) {
215          PackItem(temp[i], item, position);
216          sequence.Remove(temp[i]);
217        }
218      }
219    }
220    public override void SlidingBasedPacking(ref List<int> sequence, ItemList<CuboidPackingItem> itemMeasures, Dictionary<int, bool> rotationArray) {
221      var temp = new List<int>(sequence);
222      for (int i = 0; i < temp.Count; i++) {
223        var item = itemMeasures[temp[i]];
224        var position = FindPositionBySliding(item, rotationArray[i]);
225        if (position != null) {
226          PackItem(temp[i], item, position);
227          sequence.Remove(temp[i]);
228        }
229      }
230    }
231    public override void ExtremePointBasedPacking(ref List<int> sequence, ItemList<CuboidPackingItem> itemMeasures, bool stackingConstraints) {
232      var temp = new List<int>(sequence);
233      foreach (int itemID in temp) {
234        var item = itemMeasures[itemID];
235        var positionFound = FindExtremePointForItem(item, false, stackingConstraints);
236        if (positionFound != null) {
237          PackItem(itemID, item, positionFound);
238          sequence.Remove(itemID);
239        }
240      }
241    }
242    public override void ExtremePointBasedPacking(ref List<int> sequence, ItemList<CuboidPackingItem> itemMeasures, bool stackingConstraints, Dictionary<int, bool> rotationArray) {
243      var temp = new List<int>(sequence);
244      foreach (int itemID in temp) {
245        var item = itemMeasures[itemID];
246        var positionFound = FindExtremePointForItem(item, rotationArray[itemID], stackingConstraints);
247        if (positionFound != null) {
248          PackItem(itemID, item, positionFound);
249          sequence.Remove(itemID);
250        }
251      }
252    }
253                                                   
254    public override int ShortestPossibleSideFromPoint(ThreeDimensionalPacking position) {
255
256      int shortestSide = int.MaxValue;
257      int width = BinMeasures.Width;
258      int height = BinMeasures.Height;
259      int depth = BinMeasures.Depth;
260
261      if (position.X >= width || position.Y >= height || position.Z >= depth)
262        return shortestSide;
263
264      ThreeDimensionalPacking current = new ThreeDimensionalPacking (0, position.X, position.Y, position.Z);
265      while (current.X < width && IsPointOccupied(current)) { current = ThreeDimensionalPacking.MoveRight(current); }
266      if (current.X - position.X < shortestSide)
267        shortestSide = current.X - position.X;
268
269
270      current = new ThreeDimensionalPacking(0, position.X, position.Y, position.Z);
271      while (current.Y < height && IsPointOccupied(current)) { current = ThreeDimensionalPacking.MoveUp (current); }
272      if (current.Y - position.Y < shortestSide)
273        shortestSide = current.Y - position.Y;
274
275
276      current = new ThreeDimensionalPacking(0, position.X, position.Y, position.Z);
277      while (current.Z < depth && IsPointOccupied(current)) { current = ThreeDimensionalPacking.MoveFront(current); }
278      if (current.Z - position.Z < shortestSide)
279        shortestSide = current.Z - position.Z;
280
281      return shortestSide;
282    }
283    public override bool IsStaticStable(CuboidPackingItem item, ThreeDimensionalPacking position) {
284      //Static stability is given, if item is placed on the ground
285      if (position.Y == 0)
286        return true;
287
288      if (IsPointOccupied (new ThreeDimensionalPacking (0, position.X, position.Y - 1, position.Z))
289        && IsPointOccupied (new ThreeDimensionalPacking (0, position.X + item.Width-1, position.Y - 1, position.Z))
290        && IsPointOccupied (new ThreeDimensionalPacking (0, position.X, position.Y - 1, position.Z + item.Depth-1))
291        && IsPointOccupied (new ThreeDimensionalPacking (0, position.X + item.Width-1, position.Y - 1, position.Z + item.Depth-1)))
292        return true;
293
294
295      //if (occupiedPoints[position.X, position.Y - 1, position.Z] != -1
296      //  && occupiedPoints[position.X + item.Width - 1, position.Y - 1, position.Z] != -1
297      //  && occupiedPoints[position.X, position.Y - 1, position.Z + item.Depth - 1] != -1
298      //  && occupiedPoints[position.X + item.Width - 1, position.Y - 1, position.Z + item.Depth - 1] != -1)
299      //  return true;
300
301      //int groundCount = 0;
302      //for (int x = ep.X; x < ep.X + item.Width - 1; x++) {
303      //  for (int z = ep.Z; z < ep.Z + item.Depth - 1; z++) {
304      //    if (occupiedPoints[x,ep.Y-1, z] != -1)                                                     
305      //      groundCount++;
306      //  }
307      //}
308      //double stableGround = (double)(groundCount) / (double)(item.Width * item.Depth);
309      //if (stableGround > 0.75)
310      //  return true;
311
312      return false;
313    }
314
315    [Storable]
316    private bool depthWasDoubled = false;
317    public void DoubleDepth() {
318      if (!depthWasDoubled) {
319        var oldDepth = BinMeasures.Depth;
320        BinMeasures.Depth = BinMeasures.Depth * 2;
321        //OccupiedPoints.ChangeBinMeasures(BinMeasures);
322        depthWasDoubled = true;
323      }
324    }
325         
326    public bool IsSupportedByAtLeastOnePoint(CuboidPackingItem item, ThreeDimensionalPacking position) {
327      if (position.Y == 0)
328        return true;
329
330      int y = position.Y - 1;
331      for (int x = position.X; x < position.X + item.Width; x++)
332        for (int z = position.Z; z < position.Z + item.Depth; z++)
333          if (IsPointOccupied(new ThreeDimensionalPacking(0, x, y, z)))
334            return true;
335     
336      return false;
337    }
338    public bool IsWeightSupported(CuboidPackingItem item, ThreeDimensionalPacking ep) {
339      if (ep.Y == 0)
340        return true;
341
342      if (ItemMeasures[PointOccupation(new ThreeDimensionalPacking(0, ep.X, ep.Y - 1, ep.Z))].SupportsStacking(item)
343        && ItemMeasures[PointOccupation(new ThreeDimensionalPacking(0, ep.X + item.Width-1, ep.Y - 1, ep.Z))].SupportsStacking(item)
344        && ItemMeasures[PointOccupation(new ThreeDimensionalPacking(0, ep.X, ep.Y - 1, ep.Z + item.Depth-1))].SupportsStacking(item)
345        && ItemMeasures[PointOccupation(new ThreeDimensionalPacking(0, ep.X + item.Width-1, ep.Y - 1, ep.Z + item.Depth-1))].SupportsStacking(item))
346        return true;
347
348      return false;
349    }   
350   
351
352    protected override void InitializeOccupationLayers() {
353      for (int i = 0; i*10 <= BinMeasures.Depth; i += 1) {
354        OccupationLayers[i] = new List<int>();
355      }
356    }
357    protected override void AddNewItemToOccupationLayers(int itemID, CuboidPackingItem measures, ThreeDimensionalPacking position) {
358      int z1 = position.Z / 10;
359      int z2 = (position.Z + (position.Rotated ? measures.Width : measures.Depth)) / 10;
360
361      for (int i = z1; i <= z2; i++)
362        OccupationLayers[i].Add(itemID);
363    }
364    protected override List<int> GetLayerItemIDs(ThreeDimensionalPacking position) {
365      return OccupationLayers[position.Z / 10];
366    }
367    protected override List<int> GetLayerItemIDs(CuboidPackingItem measures, ThreeDimensionalPacking position) {
368      List<int> result = new List<int>();
369      int z1 = position.Z / 10;
370      int z2 = (position.Z + (position.Rotated ? measures.Width : measures.Depth)) / 10;
371
372      for (int i = z1; i <= z2; i++)
373        result.AddRange(OccupationLayers[i]);
374
375      return result;
376    }
377  }
378  public class EPComparer3D : IComparer<ThreeDimensionalPacking> {
379    public int Compare(ThreeDimensionalPacking a, ThreeDimensionalPacking b) {
380        int result = a.Z.CompareTo (b.Z);
381      if (result == 0)
382        result = a.X.CompareTo (b.X);
383      if (result == 0)
384        result = a.Y.CompareTo(b.Y);
385
386      return result;
387    }
388  }
389}
Note: See TracBrowser for help on using the repository browser.