Free cookie consent management tool by TermsFeed Policy Generator

source: branches/2817-BinPackingSpeedup/HeuristicLab.Problems.BinPacking/3.3/Algorithms/3D/ExtremePointAlgorithm.cs @ 15471

Last change on this file since 15471 was 15471, checked in by rhanghof, 6 years ago

#2817

  • Added some unit tests
  • Enhanced the documentation
File size: 13.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 System.Threading;
26
27using HeuristicLab.Common;
28using HeuristicLab.Core;
29using HeuristicLab.Data;
30using HeuristicLab.Encodings.PermutationEncoding;
31using HeuristicLab.Optimization;
32using HeuristicLab.Parameters;
33using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
34using HeuristicLab.Problems.BinPacking3D.Packer;
35using HeuristicLab.Problems.BinPacking3D.Decoder;
36
37using HeuristicLab.Problems.BinPacking3D.Sorting;
38
39namespace HeuristicLab.Problems.BinPacking3D {
40
41  public enum SortingMethod { All, Given, VolumeHeight, HeightVolume, AreaHeight, HeightArea, ClusteredAreaHeight, ClusteredHeightArea }
42  public enum FittingMethod { All, FirstFit, ResidualSpaceBestFit, FreeVolumeBestFit }
43
44  [Item("Extreme-point-based Bin Packing (3d)", "An implementation of the extreme-point based packing described in Crainic, T. G., Perboli, G., & Tadei, R. (2008). Extreme point-based heuristics for three-dimensional bin packing. Informs Journal on computing, 20(3), 368-384.")]
45  [StorableClass]
46  [Creatable(CreatableAttribute.Categories.SingleSolutionAlgorithms, Priority = 180)]
47  public sealed class ExtremePointAlgorithm : BasicAlgorithm {
48
49    public override Type ProblemType {
50      get { return typeof(PermutationProblem); }
51    }
52
53    public new PermutationProblem Problem {
54      get { return (PermutationProblem)base.Problem; }
55      set { base.Problem = value; }
56    }
57
58    public override bool SupportsPause {
59      get { return false; }
60    }
61
62    [Storable]
63    private readonly IValueParameter<EnumValue<SortingMethod>> sortingMethodParameter;
64    public IValueParameter<EnumValue<SortingMethod>> SortingMethodParameter {
65      get { return sortingMethodParameter; }
66    }
67
68    [Storable]
69    private readonly IValueParameter<EnumValue<FittingMethod>> fittingMethodParameter;
70    public IValueParameter<EnumValue<FittingMethod>> FittingMethodParameter {
71      get { return fittingMethodParameter; }
72    }
73
74    [Storable]
75    private readonly IValueParameter<PercentValue> deltaParameter;
76    public IValueParameter<PercentValue> DeltaParameter {
77      get { return deltaParameter; }
78    }
79
80    [Storable]
81    private readonly IValueParameter<BoolValue> sortByMaterialParameter;
82
83    public IValueParameter<BoolValue> SortByMaterialParameter {
84      get { return sortByMaterialParameter; }
85    }   
86
87    [StorableConstructor]
88    private ExtremePointAlgorithm(bool deserializing) : base(deserializing) { }
89    private ExtremePointAlgorithm(ExtremePointAlgorithm original, Cloner cloner)
90      : base(original, cloner) {
91      sortingMethodParameter = cloner.Clone(original.sortingMethodParameter);
92      fittingMethodParameter = cloner.Clone(original.fittingMethodParameter);
93      deltaParameter = cloner.Clone(original.deltaParameter);
94    }
95    public ExtremePointAlgorithm() {
96      Parameters.Add(sortingMethodParameter = new ValueParameter<EnumValue<SortingMethod>>(
97        "SortingMethod", "In which order the items should be packed.", new EnumValue<SortingMethod>(SortingMethod.All)));
98
99      Parameters.Add(fittingMethodParameter = new ValueParameter<EnumValue<FittingMethod>>(
100        "FittingMethod", "Which method to fit should be used.", new EnumValue<FittingMethod>(FittingMethod.All)));
101
102      Parameters.Add(deltaParameter = new ValueParameter<PercentValue>(
103        "Delta", "[1;100]% Clustered sorting methods use a delta parameter to determine the clusters.", new PercentValue(.1)));
104
105      Parameters.Add(sortByMaterialParameter = new ValueParameter<BoolValue>(
106        "SortByMaterial", "If this parameter is set, the items will be sorted by their material first", new BoolValue(true)));
107
108      Problem = new PermutationProblem();
109    }
110
111    public override IDeepCloneable Clone(Cloner cloner) {
112      return new ExtremePointAlgorithm(this, cloner);
113    }
114
115    [StorableHook(HookType.AfterDeserialization)]
116    private void AfterDeserialization() {
117    }
118
119    /// <summary>
120    /// Runs the extreme point algorithm and adds the results to the property <see cref="Result"/>
121    /// </summary>
122    /// <param name="token"></param>
123    protected override void Run(CancellationToken token) {
124      var items = Problem.Items;
125      var bin = Problem.BinShape;
126      var sorting = new[] { SortingMethodParameter.Value.Value };
127      if (sorting[0] == SortingMethod.All) {
128        sorting = Enum.GetValues(typeof(SortingMethod)).Cast<SortingMethod>().Where(x => x != SortingMethod.All).ToArray();
129      }
130      var fitting = new[] { fittingMethodParameter.Value.Value };
131      if (fitting[0] == FittingMethod.All) {
132        fitting = Enum.GetValues(typeof(FittingMethod)).Cast<FittingMethod>().Where(x => x != FittingMethod.All).ToArray();
133      }
134
135      //
136      var result = GetBest(bin, items, sorting, fitting, token);
137      if (result == null) {
138        throw new InvalidOperationException("No result obtained!");
139      }
140
141      Results.Add(new Result("Best Solution", "The best found solution", result.Item1));
142      Results.Add(new Result("Best Solution Quality", "The quality of the best found solution according to the evaluator", new DoubleValue(result.Item2)));
143
144      var binUtil = new BinUtilizationEvaluator();
145      var packRatio = new PackingRatioEvaluator();
146      Results.Add(new Result("Best Solution Bin Count",
147        "The number of bins in the best found solution",
148        new IntValue(result.Item1.NrOfBins)));
149      Results.Add(new Result("Best Solution Bin Utilization",
150        "The utilization given in percentage as calculated by the BinUtilizationEvaluator (total used space / total available space)",
151        new PercentValue(Math.Round(binUtil.Evaluate(result.Item1), 3))));
152
153      if (result.Item3.HasValue && sorting.Length > 1) {
154        Results.Add(new Result("Best Sorting Method",
155          "The sorting method that found the best solution",
156          new EnumValue<SortingMethod>(result.Item3.Value)));
157      }
158
159      if (result.Item4.HasValue && fitting.Length > 1) {
160        Results.Add(new Result("Best Fitting Method",
161          "The fitting method that found the best solution",
162          new EnumValue<FittingMethod>(result.Item4.Value)));
163      }
164    }
165
166    /// <summary>
167    /// Retunrs the best solution for the given parameters
168    /// </summary>
169    /// <param name="bin"></param>
170    /// <param name="items"></param>
171    /// <param name="sortings"></param>
172    /// <param name="fittings"></param>
173    /// <param name="token"></param>
174    /// <returns></returns>
175    private Tuple<Solution, double, SortingMethod?, FittingMethod?> GetBest(PackingShape bin, IList<PackingItem> items, SortingMethod[] sortings, FittingMethod[] fittings, CancellationToken token) {
176      SortingMethod? bestSorting = null;
177      FittingMethod? bestFitting = null;
178      var best = double.NaN;
179      Solution bestSolution = null;
180      foreach (var fit in fittings) {
181        foreach (var sort in sortings) {
182          IDecoder<Permutation> decoder = new ExtremePointPermutationDecoder(BinPackerFactory.CreateBinPacker(fit));
183          Permutation sortedItems;
184                   
185          if (SortByMaterialParameter.Value.Value) {
186            sortedItems = SortItemsByMaterialAndSortingMethod(bin, items, sort, DeltaParameter.Value.Value);
187          } else {
188            sortedItems = SortItemsBySortingMethod(bin, items, sort, DeltaParameter.Value.Value);
189          }
190         
191          var result = Optimize(sortedItems, bin, items, Problem.UseStackingConstraints, decoder, Problem.SolutionEvaluator);
192         
193          if (double.IsNaN(result.Item2) || double.IsInfinity(result.Item2)) {
194            continue;
195          }
196
197          if (double.IsNaN(best) || Problem.Maximization && result.Item2 > best || !Problem.Maximization && result.Item2 < best) {
198            bestSolution = result.Item1;
199            best = result.Item2;
200            bestSorting = sort;
201            bestFitting = fit;
202          }
203          if (token.IsCancellationRequested) {
204            return Tuple.Create(bestSolution, best, bestSorting, bestFitting);
205          }
206        }
207      }
208      if (double.IsNaN(best)) {
209        return null;
210      }
211      return Tuple.Create(bestSolution, best, bestSorting, bestFitting);
212    }
213
214    /// <summary>
215    /// Returns a tuple with the solution and the packing ratio depending on the given parameters
216    /// </summary>
217    /// <param name="sortedItems"></param>
218    /// <param name="bin"></param>
219    /// <param name="items"></param>
220    /// <param name="stackingConstraints"></param>
221    /// <param name="decoder"></param>
222    /// <param name="evaluator"></param>
223    /// <returns></returns>
224    private static Tuple<Solution, double> Optimize(Permutation sortedItems, PackingShape bin, IList<PackingItem> items, bool stackingConstraints, IDecoder<Permutation> decoder, IEvaluator evaluator) {
225     
226      var sol = decoder.Decode(sortedItems, bin, items, stackingConstraints);
227      var fit = evaluator.Evaluate(sol);
228
229      return Tuple.Create(sol, fit);
230    }
231   
232
233    /// <summary>
234    /// Returns a new permutation of the given items depending on the sorting method
235    /// </summary>
236    /// <param name="bin"></param>
237    /// <param name="items"></param>
238    /// <param name="sortingMethod"></param>
239    /// <param name="delta"></param>
240    /// <returns></returns>
241    private Permutation SortItemsBySortingMethod(PackingShape bin, IList<PackingItem> items, SortingMethod sortingMethod, double delta) {
242      Permutation sorted = null;
243     
244      switch (sortingMethod) {
245        case SortingMethod.Given:
246          sorted = new Permutation(PermutationTypes.Absolute, Enumerable.Range(0, items.Count).ToArray());
247          break;
248        case SortingMethod.VolumeHeight:
249          sorted = items.SortByVolumeHeight();
250          break;
251        case SortingMethod.HeightVolume:
252          sorted = items.SortByMaterialHeightVolume();
253          break;
254        case SortingMethod.AreaHeight:
255          sorted = items.SortByMaterialAreaHeight();
256          break;
257        case SortingMethod.HeightArea:
258          sorted = items.SortByMaterialHeightArea();
259          break;
260        case SortingMethod.ClusteredAreaHeight:
261          sorted = items.SortByMaterialClusteredAreaHeight(bin, delta);
262          break;
263        case SortingMethod.ClusteredHeightArea:
264          sorted = items.SortByMaterialClusteredHeightArea(bin, delta);
265          break;
266        default:
267          throw new ArgumentException("Unknown sorting method: " + sortingMethod);
268      }
269      return sorted;
270    }
271
272    /// <summary>
273    /// Returns a new permutation of the given items depending on the material and sorting method
274    /// </summary>
275    /// <param name="bin"></param>
276    /// <param name="items"></param>
277    /// <param name="sortingMethod"></param>
278    /// <param name="delta"></param>
279    /// <returns></returns>
280    private Permutation SortItemsByMaterialAndSortingMethod(PackingShape bin, IList<PackingItem> items, SortingMethod sortingMethod, double delta) {
281      Permutation sorted = null;
282
283      switch (sortingMethod) {
284        case SortingMethod.Given:
285          sorted = new Permutation(PermutationTypes.Absolute, Enumerable.Range(0, items.Count).ToArray());
286          break;
287        case SortingMethod.VolumeHeight:
288          sorted = items.SortByVolumeHeight();
289          break;
290        case SortingMethod.HeightVolume:
291          sorted = items.SortByHeightVolume();
292          break;
293        case SortingMethod.AreaHeight:
294          sorted = items.SortByAreaHeight();
295          break;
296        case SortingMethod.HeightArea:
297          sorted = items.SortByHeightArea();
298          break;
299        case SortingMethod.ClusteredAreaHeight:
300          sorted = items.SortByClusteredAreaHeight(bin, delta);
301          break;
302        case SortingMethod.ClusteredHeightArea:
303          sorted = items.SortByClusteredHeightArea(bin, delta);
304          break;
305        default:
306          throw new ArgumentException("Unknown sorting method: " + sortingMethod);
307      }
308      return sorted;
309    }
310
311
312
313    #region Sorting methods   
314
315    #endregion
316  }
317}
Note: See TracBrowser for help on using the repository browser.