Free cookie consent management tool by TermsFeed Policy Generator

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

Last change on this file was 17745, checked in by mkommend, 4 years ago

#2971: Added first draft of results implementation and problem adaptation.

File size: 9.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.Linq;
24using System.Threading;
25using HEAL.Attic;
26using HeuristicLab.Analysis;
27using HeuristicLab.Common;
28using HeuristicLab.Core;
29using HeuristicLab.Data;
30using HeuristicLab.Encodings.BinaryVectorEncoding;
31using HeuristicLab.Optimization;
32using HeuristicLab.Optimization.Operators;
33using HeuristicLab.Parameters;
34
35namespace HeuristicLab.Problems.Knapsack {
36  [Item("Knapsack Problem (KSP)", "Represents a Knapsack problem.")]
37  [Creatable(CreatableAttribute.Categories.CombinatorialProblems, Priority = 200)]
38  [StorableType("8CEDAFA2-6E0A-4D4B-B6C6-F85CC58B824E")]
39  public sealed class KnapsackProblem : BinaryVectorProblem {
40
41    #region Parameter Properties
42    [Storable] public ValueParameter<IntValue> KnapsackCapacityParameter { get; private set; }
43    [Storable] public ValueParameter<IntArray> WeightsParameter { get; private set; }
44    [Storable] public ValueParameter<IntArray> ValuesParameter { get; private set; }
45    [Storable] public OptionalValueParameter<BinaryVector> BestKnownSolutionParameter { get; private set; }
46    #endregion
47
48    #region Properties
49    public int KnapsackCapacity {
50      get { return KnapsackCapacityParameter.Value.Value; }
51      set { KnapsackCapacityParameter.Value.Value = value; }
52    }
53    public IntArray Weights {
54      get { return WeightsParameter.Value; }
55      set { WeightsParameter.Value = value; }
56    }
57    public IntArray Values {
58      get { return ValuesParameter.Value; }
59      set { ValuesParameter.Value = value; }
60    }
61    public BinaryVector BestKnownSolution {
62      get { return BestKnownSolutionParameter.Value; }
63      set { BestKnownSolutionParameter.Value = value; }
64    }
65    #endregion
66
67    [StorableConstructor]
68    private KnapsackProblem(StorableConstructorFlag _) : base(_) { }
69    private KnapsackProblem(KnapsackProblem original, Cloner cloner)
70      : base(original, cloner) {
71      KnapsackCapacityParameter = cloner.Clone(original.KnapsackCapacityParameter);
72      WeightsParameter = cloner.Clone(original.WeightsParameter);
73      ValuesParameter = cloner.Clone(original.ValuesParameter);
74      BestKnownSolutionParameter = cloner.Clone(original.BestKnownSolutionParameter);
75      RegisterEventHandlers();
76    }
77    public KnapsackProblem()
78      : base(new BinaryVectorEncoding("Selection")) {
79      Encoding.LengthParameter.ReadOnly = DimensionRefParameter.ReadOnly = true;
80      Maximization = true;
81      Parameters.Add(KnapsackCapacityParameter = new ValueParameter<IntValue>("KnapsackCapacity", "Capacity of the Knapsack.", new IntValue(1)));
82      Parameters.Add(WeightsParameter = new ValueParameter<IntArray>("Weights", "The weights of the items.", new IntArray(5)));
83      Parameters.Add(ValuesParameter = new ValueParameter<IntArray>("Values", "The values of the items.", new IntArray(5)));
84      Parameters.Add(BestKnownSolutionParameter = new OptionalValueParameter<BinaryVector>("BestKnownSolution", "The best known solution of this Knapsack instance."));
85      Dimension = Weights.Length;
86
87      InitializeRandomKnapsackInstance();
88
89      InitializeOperators();
90      RegisterEventHandlers();
91    }
92
93    public override ISingleObjectiveEvaluationResult Evaluate(BinaryVector solution, IRandom random, CancellationToken cancellationToken) {
94      var totalWeight = 0.0;
95      var totalValue = 0.0;
96      for (var i = 0; i < solution.Length; i++) {
97        if (!solution[i]) continue;
98        totalWeight += Weights[i];
99        totalValue += Values[i];
100      }
101      var quality = totalWeight > KnapsackCapacity ? KnapsackCapacity - totalWeight : totalValue;
102      return new SingleObjectiveEvaluationResult(quality);
103    }
104
105    public override void Analyze(ISingleObjectiveSolutionContext<BinaryVector>[] solutionContexts, IRandom random) {
106      base.Analyze(solutionContexts, random);
107
108      //TODO reimplement code below using results directly
109
110      //var best = GetBestSolution(solutions, qualities);
111
112      //if (double.IsNaN(BestKnownQuality) || IsBetter(best.Item2, BestKnownQuality)) {
113      //  BestKnownQuality = best.Item2;
114      //  BestKnownSolution = (BinaryVector)best.Item1.Clone();
115      //}
116
117      //IResult result;
118      //if (!results.TryGetValue("Best Knapsack Solution", out result)) {
119      //  results.Add(result = new Result("Best Knapsack Solution", typeof(KnapsackSolution)));
120      //}
121      //var solution = (KnapsackSolution)result.Value;
122      //if (solution == null) {
123      //  solution = new KnapsackSolution((BinaryVector)best.Item1.Clone(), new DoubleValue(best.Item2),
124      //    KnapsackCapacityParameter.Value, WeightsParameter.Value, ValuesParameter.Value);
125      //  result.Value = solution;
126      //} else {
127      //  if (IsBetter(best.Item2, solution.Quality.Value)) {
128      //    solution.BinaryVector = (BinaryVector)best.Item1.Clone();
129      //    solution.Quality = new DoubleValue(best.Item2);
130      //    solution.Capacity = KnapsackCapacityParameter.Value;
131      //    solution.Weights = WeightsParameter.Value;
132      //    solution.Values = ValuesParameter.Value;
133      //  }
134      //}
135    }
136
137    public override IDeepCloneable Clone(Cloner cloner) {
138      return new KnapsackProblem(this, cloner);
139    }
140
141    [StorableHook(HookType.AfterDeserialization)]
142    private void AfterDeserialization() {
143      RegisterEventHandlers();
144    }
145
146    private void RegisterEventHandlers() {
147      WeightsParameter.ValueChanged += WeightsParameter_ValueChanged;
148      WeightsParameter.Value.Reset += (_, __) => SyncValuesToWeights();
149      ValuesParameter.ValueChanged += ValuesParameter_ValueChanged;
150      ValuesParameter.Value.Reset += (_, __) => SyncWeightsToValues();
151    }
152
153    #region Events
154    protected override void DimensionOnChanged() {
155      base.DimensionOnChanged();
156      if (Weights.Length != Dimension) {
157        ((IStringConvertibleArray)WeightsParameter.Value).Length = Dimension;
158      }
159      if (Values.Length != Dimension) {
160        ((IStringConvertibleArray)ValuesParameter.Value).Length = Dimension;
161      }
162    }
163    private void WeightsParameter_ValueChanged(object sender, EventArgs e) {
164      WeightsParameter.Value.Reset += (_, __) => SyncValuesToWeights();
165      SyncValuesToWeights();
166    }
167    private void ValuesParameter_ValueChanged(object sender, EventArgs e) {
168      ValuesParameter.Value.Reset += (_, __) => SyncWeightsToValues();
169      SyncWeightsToValues();
170    }
171    private void SyncWeightsToValues() {
172      if (WeightsParameter.Value != null && ValuesParameter.Value != null) {
173        ((IStringConvertibleArray)WeightsParameter.Value).Length = Values.Length;
174        Dimension = Values.Length;
175      }
176    }
177    private void SyncValuesToWeights() {
178      if (WeightsParameter.Value != null && ValuesParameter.Value != null) {
179        ((IStringConvertibleArray)ValuesParameter.Value).Length = Weights.Length;
180        Dimension = Weights.Length;
181      }
182    }
183    #endregion
184
185    #region Helpers
186    private void InitializeOperators() {
187      Operators.AddRange(new IItem[] { new KnapsackImprovementOperator(),
188      new KnapsackPathRelinker(), new KnapsackSimultaneousPathRelinker(),
189      new QualitySimilarityCalculator(), new NoSimilarityCalculator(),
190      new KnapsackOneBitflipMoveEvaluator()});
191      Operators.Add(new PopulationSimilarityAnalyzer(Operators.OfType<ISolutionSimilarityCalculator>()));
192
193      ParameterizeOperators();
194    }
195
196    protected override void ParameterizeOperators() {
197      base.ParameterizeOperators();
198      Parameterize();
199    }
200
201    private void Parameterize() {
202      foreach (var op in Operators.OfType<IKnapsackMoveEvaluator>()) {
203        op.KnapsackCapacityParameter.ActualName = KnapsackCapacityParameter.Name;
204        op.KnapsackCapacityParameter.Hidden = true;
205        op.WeightsParameter.ActualName = WeightsParameter.Name;
206        op.WeightsParameter.Hidden = true;
207        op.ValuesParameter.ActualName = ValuesParameter.Name;
208        op.ValuesParameter.Hidden = true;
209      }
210    }
211    #endregion
212
213    private void InitializeRandomKnapsackInstance() {
214      var sysrand = new System.Random();
215
216      var itemCount = sysrand.Next(10, 100);
217      Weights = new IntArray(itemCount);
218      Values = new IntArray(itemCount);
219
220      double totalWeight = 0;
221
222      for (int i = 0; i < itemCount; i++) {
223        var value = sysrand.Next(1, 10);
224        var weight = sysrand.Next(1, 10);
225
226        Values[i] = value;
227        Weights[i] = weight;
228        totalWeight += weight;
229      }
230
231      KnapsackCapacity = (int)Math.Round(0.7 * totalWeight);
232      Dimension = Weights.Length;
233    }
234  }
235}
Note: See TracBrowser for help on using the repository browser.