Free cookie consent management tool by TermsFeed Policy Generator

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

Last change on this file since 15229 was 15229, checked in by abeham, 7 years ago

#2762:

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