Free cookie consent management tool by TermsFeed Policy Generator

source: branches/HeuristicLab.BinPacking/HeuristicLab.Problems.BinPacking.3D/3.3/BinPacking3D.cs @ 13806

Last change on this file since 13806 was 13612, checked in by gkronber, 9 years ago

#1966: refactoring: core compiles

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