Free cookie consent management tool by TermsFeed Policy Generator

source: branches/2521_ProblemRefactoring/HeuristicLab.Problems.Knapsack/3.3/KnapsackProblem.cs @ 17567

Last change on this file since 17567 was 17567, checked in by abeham, 4 years ago

#2521: work in progress

File size: 11.4 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 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;
26using HEAL.Attic;
27using HeuristicLab.Analysis;
28using HeuristicLab.Common;
29using HeuristicLab.Core;
30using HeuristicLab.Data;
31using HeuristicLab.Encodings.BinaryVectorEncoding;
32using HeuristicLab.Optimization;
33using HeuristicLab.Optimization.Operators;
34using HeuristicLab.Parameters;
35
36namespace HeuristicLab.Problems.Knapsack {
37  [Item("Knapsack Problem (KSP)", "Represents a Knapsack problem.")]
38  [Creatable(CreatableAttribute.Categories.CombinatorialProblems, Priority = 200)]
39  [StorableType("8CEDAFA2-6E0A-4D4B-B6C6-F85CC58B824E")]
40  public sealed class KnapsackProblem : BinaryVectorProblem {
41
42    #region Parameter Properties
43    public ValueParameter<IntValue> KnapsackCapacityParameter {
44      get { return (ValueParameter<IntValue>)Parameters["KnapsackCapacity"]; }
45    }
46    public ValueParameter<IntArray> WeightsParameter {
47      get { return (ValueParameter<IntArray>)Parameters["Weights"]; }
48    }
49    public ValueParameter<IntArray> ValuesParameter {
50      get { return (ValueParameter<IntArray>)Parameters["Values"]; }
51    }
52    public OptionalValueParameter<BinaryVector> BestKnownSolutionParameter {
53      get { return (OptionalValueParameter<BinaryVector>)Parameters["BestKnownSolution"]; }
54    }
55    #endregion
56
57    #region Properties
58    public new int Dimension {
59      get { return base.Dimension; }
60      set { DimensionRefParameter.Value.Value = value; }
61    }
62    public int KnapsackCapacity {
63      get { return KnapsackCapacityParameter.Value.Value; }
64      set { KnapsackCapacityParameter.Value.Value = value; }
65    }
66    public IntArray Weights {
67      get { return WeightsParameter.Value; }
68      set { WeightsParameter.Value = value; }
69    }
70    public IntArray Values {
71      get { return ValuesParameter.Value; }
72      set { ValuesParameter.Value = value; }
73    }
74    public BinaryVector BestKnownSolution {
75      get { return BestKnownSolutionParameter.Value; }
76      set { BestKnownSolutionParameter.Value = value; }
77    }
78    private BestKnapsackSolutionAnalyzer BestKnapsackSolutionAnalyzer {
79      get { return Operators.OfType<BestKnapsackSolutionAnalyzer>().FirstOrDefault(); }
80    }
81    #endregion
82
83    [StorableConstructor]
84    private KnapsackProblem(StorableConstructorFlag _) : base(_) { }
85    private KnapsackProblem(KnapsackProblem original, Cloner cloner)
86      : base(original, cloner) {
87      RegisterEventHandlers();
88    }
89    public KnapsackProblem()
90      : base(new BinaryVectorEncoding("Selection")) {
91      Maximization = true;
92      Parameters.Add(new ValueParameter<IntValue>("KnapsackCapacity", "Capacity of the Knapsack.", new IntValue(1)));
93      Parameters.Add(new ValueParameter<IntArray>("Weights", "The weights of the items.", new IntArray(5)));
94      Parameters.Add(new ValueParameter<IntArray>("Values", "The values of the items.", new IntArray(5)));
95      Parameters.Add(new OptionalValueParameter<BinaryVector>("BestKnownSolution", "The best known solution of this Knapsack instance."));
96
97      DimensionRefParameter.Value = new IntValue(Weights.Length, @readonly: true);
98      InitializeRandomKnapsackInstance();
99
100      InitializeOperators();
101      RegisterEventHandlers();
102    }
103
104    public override ISingleObjectiveEvaluationResult Evaluate(BinaryVector solution, IRandom random, CancellationToken cancellationToken) {
105      var totalWeight = 0.0;
106      var totalValue = 0.0;
107      for (var i = 0; i < solution.Length; i++) {
108        if (!solution[i]) continue;
109        totalWeight += Weights[i];
110        totalValue += Values[i];
111      }
112      var quality = totalWeight > KnapsackCapacity ? KnapsackCapacity - totalWeight : totalValue;
113      return new SingleObjectiveEvaluationResult(quality);
114    }
115
116    public override IDeepCloneable Clone(Cloner cloner) {
117      return new KnapsackProblem(this, cloner);
118    }
119
120    [StorableHook(HookType.AfterDeserialization)]
121    private void AfterDeserialization() {
122      RegisterEventHandlers();
123    }
124
125    private void RegisterEventHandlers() {
126      Evaluator.QualityParameter.ActualNameChanged += Evaluator_QualityParameter_ActualNameChanged;
127      KnapsackCapacityParameter.ValueChanged += KnapsackCapacityParameter_ValueChanged;
128      WeightsParameter.ValueChanged += WeightsParameter_ValueChanged;
129      WeightsParameter.Value.Reset += WeightsValue_Reset;
130      ValuesParameter.ValueChanged += ValuesParameter_ValueChanged;
131      ValuesParameter.Value.Reset += ValuesValue_Reset;
132    }
133
134    #region Events
135    protected override void OnEncodingChanged() {
136      base.OnEncodingChanged();
137      Parameterize();
138    }
139    //TODO check with abeham if this is really necessary
140    //protected override void OnSolutionCreatorChanged() {
141    //  base.OnSolutionCreatorChanged();
142    //  Parameterize();
143    //}
144    protected override void OnEvaluatorChanged() {
145      base.OnEvaluatorChanged();
146      Evaluator.QualityParameter.ActualNameChanged += Evaluator_QualityParameter_ActualNameChanged;
147      Parameterize();
148    }
149    protected override void DimensionOnChanged() {
150      base.DimensionOnChanged();
151      if (Weights.Length != Dimension) {
152        ((IStringConvertibleArray)WeightsParameter.Value).Length = Dimension;
153      }
154      if (Values.Length != Dimension) {
155        ((IStringConvertibleArray)ValuesParameter.Value).Length = Dimension;
156      }
157      Parameterize();
158    }
159    private void Evaluator_QualityParameter_ActualNameChanged(object sender, EventArgs e) {
160      Parameterize();
161    }
162    private void KnapsackCapacityParameter_ValueChanged(object sender, EventArgs e) {
163      Parameterize();
164    }
165    private void WeightsParameter_ValueChanged(object sender, EventArgs e) {
166      Parameterize();
167      WeightsParameter.Value.Reset += WeightsValue_Reset;
168    }
169    private void WeightsValue_Reset(object sender, EventArgs e) {
170      if (WeightsParameter.Value != null && ValuesParameter.Value != null) {
171        ((IStringConvertibleArray)ValuesParameter.Value).Length = Weights.Length;
172        Dimension = Weights.Length;
173      }
174      Parameterize();
175    }
176    private void ValuesParameter_ValueChanged(object sender, EventArgs e) {
177      Parameterize();
178      ValuesParameter.Value.Reset += ValuesValue_Reset;
179    }
180    private void ValuesValue_Reset(object sender, EventArgs e) {
181      if (WeightsParameter.Value != null && ValuesParameter.Value != null) {
182        ((IStringConvertibleArray)WeightsParameter.Value).Length = Values.Length;
183        Dimension = Values.Length;
184      }
185      Parameterize();
186    }
187    #endregion
188
189    #region Helpers
190    private void InitializeOperators() {
191      Operators.Add(new KnapsackImprovementOperator());
192      Operators.Add(new KnapsackPathRelinker());
193      Operators.Add(new KnapsackSimultaneousPathRelinker());
194      Operators.Add(new QualitySimilarityCalculator());
195      Operators.Add(new NoSimilarityCalculator());
196
197      Operators.Add(new BestKnapsackSolutionAnalyzer());
198      Operators.Add(new PopulationSimilarityAnalyzer(Operators.OfType<ISolutionSimilarityCalculator>()));
199
200      Operators.Add(new KnapsackOneBitflipMoveEvaluator());
201      Parameterize();
202    }
203    private void Parameterize() {
204      var operators = new List<IItem>();
205
206      if (BestKnapsackSolutionAnalyzer != null) {
207        operators.Add(BestKnapsackSolutionAnalyzer);
208        BestKnapsackSolutionAnalyzer.MaximizationParameter.ActualName = MaximizationParameter.Name;
209        BestKnapsackSolutionAnalyzer.MaximizationParameter.Hidden = true;
210        BestKnapsackSolutionAnalyzer.BestKnownQualityParameter.ActualName = BestKnownQualityParameter.Name;
211        BestKnapsackSolutionAnalyzer.BestKnownQualityParameter.Hidden = true;
212        BestKnapsackSolutionAnalyzer.BestKnownSolutionParameter.ActualName = BestKnownSolutionParameter.Name;
213        BestKnapsackSolutionAnalyzer.BestKnownSolutionParameter.Hidden = true;
214        BestKnapsackSolutionAnalyzer.KnapsackCapacityParameter.ActualName = KnapsackCapacityParameter.Name;
215        BestKnapsackSolutionAnalyzer.KnapsackCapacityParameter.Hidden = true;
216        BestKnapsackSolutionAnalyzer.WeightsParameter.ActualName = WeightsParameter.Name;
217        BestKnapsackSolutionAnalyzer.WeightsParameter.Hidden = true;
218        BestKnapsackSolutionAnalyzer.ValuesParameter.ActualName = ValuesParameter.Name;
219        BestKnapsackSolutionAnalyzer.ValuesParameter.Hidden = true;
220      }
221      foreach (var op in Operators.OfType<IKnapsackMoveEvaluator>()) {
222        operators.Add(op);
223        op.KnapsackCapacityParameter.ActualName = KnapsackCapacityParameter.Name;
224        op.KnapsackCapacityParameter.Hidden = true;
225        op.WeightsParameter.ActualName = WeightsParameter.Name;
226        op.WeightsParameter.Hidden = true;
227        op.ValuesParameter.ActualName = ValuesParameter.Name;
228        op.ValuesParameter.Hidden = true;
229
230        var bitflipMoveEval = op as IKnapsackOneBitflipMoveEvaluator;
231        if (bitflipMoveEval != null) {
232          foreach (var moveOp in Encoding.Operators.OfType<IOneBitflipMoveQualityOperator>()) {
233            moveOp.MoveQualityParameter.ActualName = bitflipMoveEval.MoveQualityParameter.ActualName;
234            moveOp.MoveQualityParameter.Hidden = true;
235          }
236        }
237      }
238      foreach (var op in Operators.OfType<ISingleObjectiveImprovementOperator>()) {
239        operators.Add(op);
240        op.SolutionParameter.ActualName = Encoding.Name;
241        op.SolutionParameter.Hidden = true;
242      }
243      foreach (var op in Operators.OfType<ISingleObjectivePathRelinker>()) {
244        operators.Add(op);
245        op.ParentsParameter.ActualName = Encoding.Name;
246        op.ParentsParameter.Hidden = true;
247      }
248      foreach (var op in Operators.OfType<ISolutionSimilarityCalculator>()) {
249        operators.Add(op);
250        op.SolutionVariableName = Encoding.Name;
251        op.QualityVariableName = Evaluator.QualityParameter.ActualName;
252      }
253
254      if (operators.Count > 0) Encoding.ConfigureOperators(Operators);
255    }
256    #endregion
257
258    private void InitializeRandomKnapsackInstance() {
259      var sysrand = new System.Random();
260
261      var itemCount = sysrand.Next(10, 100);
262      Weights = new IntArray(itemCount);
263      Values = new IntArray(itemCount);
264
265      double totalWeight = 0;
266
267      for (int i = 0; i < itemCount; i++) {
268        var value = sysrand.Next(1, 10);
269        var weight = sysrand.Next(1, 10);
270
271        Values[i] = value;
272        Weights[i] = weight;
273        totalWeight += weight;
274      }
275
276      KnapsackCapacity = (int)Math.Round(0.7 * totalWeight);
277      Dimension = Weights.Length;
278    }
279  }
280}
Note: See TracBrowser for help on using the repository browser.