Free cookie consent management tool by TermsFeed Policy Generator

source: branches/2817-BinPackingSpeedup/HeuristicLab.Problems.BinPacking/3.3/3D/ExtremePointCreation/PointProjectionBasedEPCreator.cs @ 15820

Last change on this file since 15820 was 15820, checked in by rhanghof, 7 years ago

#2817:

  • Fixes for pruning
File size: 11.4 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2018 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 HeuristicLab.Common;
23using HeuristicLab.Problems.BinPacking3D.ExtremePointPruning;
24using HeuristicLab.Problems.BinPacking3D.Geometry;
25using HeuristicLab.Problems.BinPacking3D.ResidualSpaceCalculation;
26using System;
27using System.Collections.Generic;
28using System.Linq;
29using System.Text;
30using System.Threading.Tasks;
31
32namespace HeuristicLab.Problems.BinPacking3D.ExtremePointCreation {
33
34  /// <summary>
35  /// This extreme point creation class uses the point projection based method by Crainic, T. G., Perboli, G., & Tadei, R. for creating extreme points.
36  /// Each extreme point of an item is being projectet backwards, downwards and to the left.
37  /// A new extreme point will be created where this projections instersects with another item or the bin boundins.
38  /// </summary>
39  public class PointProjectionBasedEPCreator : ExtremePointCreator {
40    /// <summary>
41    /// This lock object is needed because of creating the extreme points in an parallel for loop.
42    /// </summary>
43    protected object _lockAddExtremePoint = new object();
44
45    protected override void UpdateExtremePoints(BinPacking3D binPacking, PackingItem item, PackingPosition position) {
46      binPacking.ExtremePoints.Clear();
47
48      if (binPacking.Items.Count <= 0) {
49        return;
50      }
51     
52      // generate all new extreme points parallel. This speeds up the creator.
53      var items = binPacking.Items.OrderBy(x => x.Value.Layer);
54      Parallel.ForEach(items.Where(x => x.Value.Layer < item.Layer), i => {
55        PackingItem it = i.Value;
56        PackingPosition pos = binPacking.Positions[i.Key];
57        GenerateNewExtremePointsForItem(binPacking, it, pos);
58      });
59     
60      Parallel.ForEach(items.Where(x => x.Value.Layer >= item.Layer), i => {
61        PackingItem it = i.Value;
62        PackingPosition pos = binPacking.Positions[i.Key];
63        GenerateNewExtremePointsForItem(binPacking, it, pos);
64      });
65
66      // remove not needed extreme points.
67      foreach (var extremePoint in binPacking.ExtremePoints.ToList()) {
68        // check if a residual space can be removed
69        foreach (var rs in extremePoint.Value.ToList()) {
70          if (ResidualSpaceCanBeRemoved(binPacking, extremePoint.Key, rs)) {
71            ((IList<ResidualSpace>)extremePoint.Value).Remove(rs);
72          }
73        }
74        // if the current extreme point has no more residual spaces, it can be removed.
75        if (((IList<ResidualSpace>)extremePoint.Value).Count <= 0) {
76          binPacking.ExtremePoints.Remove(extremePoint);
77        }
78      }
79
80    }
81
82    /// <summary>
83    /// Returns true if a given residual space can be removed.
84    /// The given residual space can be removed if it is within another residual space and
85    /// - neither the position of the other residual space and the current extreme point have an item below or
86    /// - the current extreme point has an item below.
87    /// </summary>
88    /// <param name="binPacking"></param>
89    /// <param name="position"></param>
90    /// <param name="rs"></param>
91    /// <returns></returns>
92    private bool ResidualSpaceCanBeRemoved(BinPacking3D binPacking, PackingPosition position, ResidualSpace rs) {
93      foreach (var extremePoint in binPacking.ExtremePoints) {
94        if (position.Equals(extremePoint.Key)) {
95          continue;
96        }
97        if (IsWithinResidualSpaceOfAnotherExtremePoint(new Vector3D(position), rs, extremePoint.Key, extremePoint.Value)) {
98          var itemBelowEp = LiesOnAnyItem(binPacking, extremePoint.Key);
99          var itemBelowPos = LiesOnAnyItem(binPacking, position);
100
101          if (itemBelowEp || !itemBelowEp && !itemBelowPos) {
102            return true;
103          }
104        }
105      }
106      return false;
107    }
108
109    /// <summary>
110    /// Returns true if the given position lies on an item or an the ground.
111    /// </summary>
112    /// <param name="binPacking"></param>
113    /// <param name="position"></param>
114    /// <returns></returns>
115    private bool LiesOnAnyItem(BinPacking3D binPacking, PackingPosition position) {
116      if (position.Y == 0) {
117        return true;
118      }
119
120      var items = binPacking.Items.Where(x => {
121        var itemPosition = binPacking.Positions[x.Key];
122        var item = x.Value;
123        int width = item.Width;
124        int depth = item.Depth;
125
126        return itemPosition.Y + item.Height == position.Y &&
127               itemPosition.X <= position.X && position.X < itemPosition.X + width &&
128               itemPosition.Z <= position.Z && position.Z < itemPosition.Z + depth;
129      });
130
131      return items.Count() > 0;
132    }
133
134
135    /// <summary>
136    /// Adds a new extreme point an the related residual spaces to a given bin packing.
137    /// - The given position has to be valid.
138    /// - The extreme point does not exist in the bin packing.
139    /// - There must be at minimum one valid residual space. A residual space is invalid if the space is zero.
140    /// </summary>
141    /// <param name="binPacking"></param>
142    /// <param name="position"></param>
143    /// <returns>True = the given point and its related residual spaces were successfully added to the bin packing</returns>
144    protected override bool AddExtremePoint(BinPacking3D binPacking, PackingPosition position) {
145      if (position == null) {
146        return false;
147      }
148
149      if (PointIsInAnyItem(binPacking, new Vector3D(position))) {
150        return false;
151      }
152
153      // this is necessary if the extreme points are being created in a parallel loop.
154      lock (_lockAddExtremePoint) {
155        if (binPacking.ExtremePoints.ContainsKey(position)) {
156          return false;
157        }
158
159        var rs = CalculateResidualSpace(binPacking, new Vector3D(position));
160
161        if (rs.Count() <= 0) {
162          return false;
163        }
164
165        binPacking.ExtremePoints.Add(position, rs);
166        return true;
167      }
168    }
169
170    /// <summary>
171    /// Getnerates the extreme points for a given item.
172    /// It creates extreme points by using a point projection based method and
173    /// creates points by using an edge projection based method.
174    /// </summary>
175    /// <param name="binPacking"></param>
176    /// <param name="newItem"></param>
177    /// <param name="position"></param>
178    protected override void GenerateNewExtremePointsForItem(BinPacking3D binPacking, PackingItem newItem, PackingPosition position) {
179      PointProjectionForNewItem(binPacking, newItem, position);
180    }
181
182    #region Extreme point creation by using a point projection based method
183
184    /// <summary>
185    /// This method creates extreme points by using a point projection based method.
186    /// For each item there will be created three points and each of the points will be projected twice.
187    /// The direction of the projection depends on position of the point.
188    /// </summary>
189    /// <param name="binPacking"></param>
190    /// <param name="newItem"></param>
191    /// <param name="position"></param>
192    protected void PointProjectionForNewItem(BinPacking3D binPacking, PackingItem newItem, PackingPosition position) {
193      int newWidth = newItem.Width;
194      int newDepth = newItem.Depth;
195      var binShape = binPacking.BinShape;
196      var sourcePoint = new PackingPosition(position.AssignedBin, position.X + newWidth, position.Y, position.Z);
197      PointProjection(binPacking, sourcePoint, ProjectDown);
198      PointProjection(binPacking, sourcePoint, ProjectBackward);
199
200      sourcePoint = new PackingPosition(position.AssignedBin, position.X, position.Y + newItem.Height, position.Z);
201      PointProjection(binPacking, sourcePoint, ProjectLeft);
202      PointProjection(binPacking, sourcePoint, ProjectBackward);
203
204      sourcePoint = new PackingPosition(position.AssignedBin, position.X, position.Y, position.Z + newDepth);
205      PointProjection(binPacking, sourcePoint, ProjectDown);
206      PointProjection(binPacking, sourcePoint, ProjectLeft);
207    }
208
209
210    /// <summary>
211    /// Projects a given point by using the given projection method to the neares item.
212    /// The given projection method returns a point which lies on a side of the nearest item in the direction.
213    /// </summary>
214    /// <param name="binPacking"></param>
215    /// <param name="position"></param>
216    /// <param name="projectionMethod"></param>
217    private void PointProjection(BinPacking3D binPacking, PackingPosition position, Func<BinPacking3D, Vector3D, Vector3D> projectionMethod) {
218      Vector3D sourcePoint = new Vector3D(position);
219      if (sourcePoint.X < binPacking.BinShape.Width && sourcePoint.Y < binPacking.BinShape.Height && sourcePoint.Z < binPacking.BinShape.Depth) {
220        Vector3D point = projectionMethod?.Invoke(binPacking, sourcePoint);
221        if (point != null) {
222          AddExtremePoint(binPacking, new PackingPosition(position.AssignedBin, point.X, point.Y, point.Z));
223        }
224      }
225    }
226    #endregion
227
228    /// <summary>
229    /// Updates the residual spaces.
230    /// It removes not needed ones.
231    /// A residual space will be removed if the space is a subspace of another one and
232    /// the current one has no item below or both have an item below.
233    /// </summary>
234    /// <param name="binPacking"></param>
235    /// <param name="item"></param>
236    /// <param name="position"></param>
237    protected override void UpdateResidualSpace(BinPacking3D binPacking, PackingItem item, PackingPosition position) {
238    }
239
240    /// <summary>
241    /// Returns true if any item in the bin packing encapsulates the given point
242    /// </summary>
243    /// <param name="binPacking"></param>
244    /// <param name="point"></param>
245    /// <returns></returns>
246    private bool PointIsInAnyItem(BinPacking3D binPacking, Vector3D point) {
247      foreach (var item in binPacking.Items) {
248        PackingPosition position = binPacking.Positions[item.Key];
249        var depth = item.Value.Depth;
250        var width = item.Value.Width;
251        if (position.X <= point.X && point.X < position.X + width &&
252            position.Y <= point.Y && point.Y < position.Y + item.Value.Height &&
253            position.Z <= point.Z && point.Z < position.Z + depth) {
254          return true;
255        }
256      }
257      return false;
258    }
259
260
261    /// <summary>
262    /// Calculates the residual spaces for an extreme point.
263    /// </summary>
264    /// <param name="binPacking"></param>
265    /// <param name="pos"></param>
266    /// <returns></returns>
267    protected override IEnumerable<ResidualSpace> CalculateResidualSpace(BinPacking3D binPacking, Vector3D pos) {
268      return ResidualSpaceCalculatorFactory.CreateCalculator().CalculateResidualSpaces(binPacking, pos);
269    }
270  }
271}
Note: See TracBrowser for help on using the repository browser.