Free cookie consent management tool by TermsFeed Policy Generator

source: stable/HeuristicLab.Problems.BinPacking/3.3/2D/ProblemBase.cs @ 15016

Last change on this file since 15016 was 14162, checked in by gkronber, 8 years ago

#2641: first import of bin packing problem (TODO: persistence and sample)

File size: 12.0 KB
Line 
1#region License Information
2
3/* HeuristicLab
4 * Copyright (C) 2002-2016 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
5 *
6 * This file is part of HeuristicLab.
7 *
8 * HeuristicLab is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * HeuristicLab is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
20 */
21
22#endregion
23
24using System.Linq;
25using HeuristicLab.Common;
26using HeuristicLab.Core;
27using HeuristicLab.Data;
28using HeuristicLab.Optimization;
29using HeuristicLab.Parameters;
30using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
31using HeuristicLab.Problems.Instances;
32
33namespace HeuristicLab.Problems.BinPacking2D {
34  [StorableClass]
35  public abstract class ProblemBase<TEnc, TSol> :
36    SingleObjectiveBasicProblem<TEnc>, IProblemInstanceConsumer<BPPData>, IProblemInstanceExporter<BPPData>
37    where TEnc : class, IEncoding
38    where TSol : class, IItem {
39    protected readonly string SolutionEvaluatorParameterName = "SolutionEvaluator";
40    public readonly string EncodedSolutionName = "EncodedSolution";
41    #region Default Instance
42    private readonly BPPData defaultInstance = new BPPData() {
43      Name = "2D BPP Default Instance",
44      Description = "The default instance for 2D Bin Packing.",
45      BinShape = new PackingShape(20, 16),
46      Items = new PackingItem[] {
47        new PackingItem(3,  8, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
48        new PackingItem(5,  3, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
49        new PackingItem(9,  3, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
50        new PackingItem(2,  7, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
51        new PackingItem(5,  3, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
52        new PackingItem(9,  3, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
53        new PackingItem(2,  7, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
54        new PackingItem(5,  3, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
55        new PackingItem(9,  3, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
56        new PackingItem(2,  7, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
57        new PackingItem(5,  3, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
58        new PackingItem(9,  3, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
59        new PackingItem(2,  7, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
60        new PackingItem(5,  3, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
61        new PackingItem(9,  3, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
62        new PackingItem(2,  7, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
63        new PackingItem(5,  3, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
64        new PackingItem(9,  3, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
65        new PackingItem(2,  7, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
66        new PackingItem(5,  3, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
67        new PackingItem(9,  3, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
68        new PackingItem(2,  7, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
69        new PackingItem(5,  3, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
70        new PackingItem(9,  3, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
71        new PackingItem(2,  7, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
72        new PackingItem(5,  3, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
73        new PackingItem(9,  3, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
74        new PackingItem(2,  7, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
75        new PackingItem(5,  3, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
76        new PackingItem(9,  3, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
77        new PackingItem(2,  7, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
78        new PackingItem(5,  3, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
79        new PackingItem(9,  3, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
80        new PackingItem(2,  7, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
81        new PackingItem(5,  3, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
82        new PackingItem(9,  3, new PackingShape(20, 16)) { Material = 1, Weight = 1.0},
83        new PackingItem(2,  7, new PackingShape(20, 16)) { Material = 1, Weight = 1.0}
84      },
85    };
86    #endregion
87
88    #region parameter properties
89    public IValueParameter<IDecoder<TSol>> DecoderParameter {
90      get { return (IValueParameter<IDecoder<TSol>>)Parameters["Decoder"]; }
91    }
92    public IValueParameter<IEvaluator> SolutionEvaluatorParameter {
93      get { return (IValueParameter<IEvaluator>)Parameters[SolutionEvaluatorParameterName]; }
94    }
95    public IValueParameter<ReadOnlyItemList<PackingItem>> ItemsParameter {
96      get { return (IValueParameter<ReadOnlyItemList<PackingItem>>)Parameters["Items"]; }
97    }
98    public IValueParameter<PackingShape> BinShapeParameter {
99      get { return (IValueParameter<PackingShape>)Parameters["BinShape"]; }
100    }
101    public IValueParameter<Solution> BestKnownSolutionParameter {
102      get { return (IValueParameter<Solution>)Parameters["BestKnownSolution"]; }
103    }
104    public IFixedValueParameter<IntValue> LowerBoundParameter {
105      get { return (IFixedValueParameter<IntValue>)Parameters["LowerBound"]; }
106    }
107    #endregion
108
109    #region properties
110    public IDecoder<TSol> Decoder {
111      get { return DecoderParameter.Value; }
112      set { DecoderParameter.Value = value; }
113    }
114    public IEvaluator SolutionEvaluator {
115      get { return SolutionEvaluatorParameter.Value; }
116      set { SolutionEvaluatorParameter.Value = value; }
117    }
118    public ReadOnlyItemList<PackingItem> Items {
119      get { return ItemsParameter.Value; }
120      set { ItemsParameter.Value = value; }
121    }
122    public PackingShape BinShape {
123      get { return BinShapeParameter.Value; }
124      set { BinShapeParameter.Value = value; }
125    }
126    public Solution BestKnownSolution {
127      get { return BestKnownSolutionParameter.Value; }
128      set { BestKnownSolutionParameter.Value = value; }
129    }
130    public int LowerBound {
131      get { return LowerBoundParameter.Value.Value; }
132    }
133    public int NumberOfItems {
134      get { return Items == null ? 0 : Items.Count; }
135    }
136    #endregion
137
138    // persistence
139    [StorableConstructor]
140    protected ProblemBase(bool deserializing) : base(deserializing) { }
141
142    // cloning
143    protected ProblemBase(ProblemBase<TEnc, TSol> original, Cloner cloner)
144      : base(original, cloner) {
145    }
146
147    protected ProblemBase()
148      : base() {
149      var defaultEvaluator = new PackingRatioEvaluator();
150      Parameters.Add(new ValueParameter<IDecoder<TSol>>("Decoder", "The decoder translates a permutation to a packing solution candidiates"));
151      Parameters.Add(new ValueParameter<IEvaluator>(SolutionEvaluatorParameterName, "The evaluator calculates qualities of solution candidates", defaultEvaluator));
152      Parameters.Add(new ValueParameter<ReadOnlyItemList<PackingItem>>("Items", "The items which must be packed into bins"));
153      Parameters.Add(new ValueParameter<PackingShape>("BinShape", "The size of bins into which items must be packed"));
154      Parameters.Add(new OptionalValueParameter<Solution>("BestKnownSolution", "The best solution found so far"));
155      Parameters.Add(new FixedValueParameter<IntValue>("LowerBound", "A lower bound for the number of bins that is necessary to pack all items"));
156
157      Load(defaultInstance);
158    }
159
160    public override bool Maximization { get { return true; } }
161
162
163    public override double Evaluate(Individual individual, IRandom random) {
164      var encodedSolutionCand = (TSol)individual[EncodedSolutionName];
165      var decoder = Decoder;
166      var solution = decoder.Decode(encodedSolutionCand, BinShape, Items);
167      return SolutionEvaluator.Evaluate(solution);
168    }
169
170    public override void Analyze(Individual[] individuals, double[] qualities, ResultCollection results, IRandom random) {
171      base.Analyze(individuals, qualities, results, random);
172      Analyze(individuals.Select(i => (TSol)i[EncodedSolutionName]).ToArray(), qualities, results, random);
173    }
174
175    public virtual void Analyze(TSol[] individuals, double[] qualities, ResultCollection results, IRandom random) {
176      var bestSolutionResultName = "Best Packing Solution";
177      var numContainersResultName = "Nr of Containers";
178      var binUtilResultName = "Overall Bin Utilization";
179
180      if (!results.ContainsKey(bestSolutionResultName)) results.Add(new Result(bestSolutionResultName, typeof(Solution)));
181      if (!results.ContainsKey(numContainersResultName)) results.Add(new Result(numContainersResultName, typeof(IntValue)));
182      if (!results.ContainsKey(binUtilResultName)) results.Add(new Result(binUtilResultName, typeof(DoubleValue)));
183
184
185      // find index of item with max quality
186      int bestIdx = 0;
187      for (int j = 1; j < qualities.Length; j++)
188        if (qualities[j] > qualities[bestIdx]) bestIdx = j;
189
190
191      // update best solution so far
192      var bestSolution = results[bestSolutionResultName].Value as Solution;
193      if (bestSolution == null ||
194        bestSolution.Quality.Value < qualities[bestIdx]) {
195
196        var newBestSolution = Decoder.Decode(individuals[bestIdx], BinShape, Items);
197        newBestSolution.Quality = new DoubleValue(qualities[bestIdx]);
198        results[bestSolutionResultName].Value = newBestSolution;
199        results[numContainersResultName].Value = new IntValue(newBestSolution.NrOfBins);
200        results[binUtilResultName].Value = new DoubleValue(BinUtilizationEvaluator.CalculateBinUtilization(newBestSolution));
201
202        // update best known solution
203        var bestKnownQuality = BestKnownQualityParameter.Value;
204        if (bestKnownQuality == null ||
205            bestKnownQuality.Value < qualities[bestIdx]) {
206          BestKnownQualityParameter.ActualValue = new DoubleValue(qualities[bestIdx]);
207          BestKnownSolutionParameter.ActualValue = newBestSolution;
208        }
209      }
210    }
211
212
213    #region Problem instance handling
214    public void Load(BPPData data) {
215      BestKnownSolutionParameter.Value = null;
216      BestKnownQualityParameter.Value = null;
217
218      if (data.BestKnownQuality.HasValue)
219        BestKnownQuality = data.BestKnownQuality.Value;
220
221      BinShape = data.BinShape;
222      var items = new ItemList<PackingItem>(data.Items);
223      items.Sort((x, y) => y.CompareTo(x));
224      Items = items.AsReadOnly();
225
226      ApplyHorizontalOrientation();
227      LowerBoundParameter.Value.Value = CalculateLowerBound();
228    }
229
230
231    public BPPData Export() {
232      return new BPPData {
233        Name = Name,
234        Description = Description,
235        BinShape = BinShape,
236        Items = Items.ToArray()
237      };
238    }
239    #endregion
240
241
242    #region helpers
243    private void ApplyHorizontalOrientation() {
244      BinShape.ApplyHorizontalOrientation();
245      foreach (var shape in Items) {
246        shape.ApplyHorizontalOrientation();
247      }
248    }
249
250    private int CalculateLowerBound() {
251      //This is the obvious continuous lower bound calculation; Martello and Vigo proposed a better way but it has not been implemented yet;
252      int itemsVol = Items.Select(x => x.Volume).Sum();
253      int binVol = BinShape.Volume;
254      return (itemsVol + binVol - 1) / (binVol);
255    }
256
257    #endregion
258  }
259}
Note: See TracBrowser for help on using the repository browser.