Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Problems.Knapsack/3.3/KnapsackProblem.cs @ 6042

Last change on this file since 6042 was 6042, checked in by abeham, 13 years ago

#1425

  • Changed LocalImprovementOperators
    • Changed interface (made Problem a property, added a property that denotes the type of the problem that it can be applied on, added some general parameters)
    • Added some parameters and wiring
    • Changed move discovery and parameterization and added a helper class to ease finding compatible move operators
    • Discovering only IMultiMoveOperators and IExhaustiveMoveOperators and putting the multi move ones first
    • Fixed bug in Apply method that could create an endless string of nested execution contexts
    • Removed all problem specific analyzers in the two local improvement operators and only left the BestAverageWorstQualityAnalyzer since it doesn't make any sense to perform diversity or allele analysis during local improvement in the most common case and those analyzers take a lot of time (one can always add them manually should he/she be interested). The analyzers in the VNS's Analyzer parameter are left untouched.
  • Removed shaking operator and interface from VNS plugin and added that to Optimization and Optimization.Operators
  • Changed some ValueParameters to ConstrainedValueParameters and added type discovery to fill them (using the ProblemType property to get compatible local improvement operators)
  • Added missing GPL license headers
  • Changed some ValueParameters to the new FixedValueParameters
  • Added an additional encoding specific ShakingOperator to each encoding and added that to each problem
    • reason is that only the problem/encoding can really decide if a shaking operator is meaningful or not
  • Fixed an unrelated bug in the BestAverageWorstQualityAnalyzer that I encountered (and made the fix backwards compatible)
    • Also added a snippet for creating the backwards compatible comment marker and region
  • Fixed the operator graph of the VNS main loop
    • The condition to continue only when the local search was not successful is not necessary and is not part of the VNS definition as far as I know it (only condition to break the inner loop is when k reaches k_max)
  • Changed the ShakingOperator to input current index and output the maximum number of neighborhoods instead of a boolean that indicates that the last index has been reached since the maximum number is a little more generally useful and equally powerful in modeling
    • Remodeled the VNS main loop to check for k < k_max in order to continue the inner loop
  • other changes that I forgot...

Still necessary

  • test, test, test
  • check for backwards compatible breakers
  • add a maximum evaluated solutions stop criterion
  • optionally: implement fast problem specific local search improvement operators that do not build on the whole generic overhead (e.g. a 2-opt TSP specific local search operator). The idea of VNS is really to converge to a local optimum which is difficult to achieve using the current rather limited termination options
File size: 16.4 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2011 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.Drawing;
25using System.Linq;
26using HeuristicLab.Common;
27using HeuristicLab.Core;
28using HeuristicLab.Data;
29using HeuristicLab.Encodings.BinaryVectorEncoding;
30using HeuristicLab.Optimization;
31using HeuristicLab.Parameters;
32using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
33using HeuristicLab.PluginInfrastructure;
34
35namespace HeuristicLab.Problems.Knapsack {
36  [Item("Knapsack Problem", "Represents a Knapsack problem.")]
37  [Creatable("Problems")]
38  [StorableClass]
39  public sealed class KnapsackProblem : ParameterizedNamedItem, ISingleObjectiveHeuristicOptimizationProblem, IStorableContent {
40    public string Filename { get; set; }
41
42    public override Image ItemImage {
43      get { return HeuristicLab.Common.Resources.VSImageLibrary.Type; }
44    }
45
46    #region Parameter Properties
47    public ValueParameter<BoolValue> MaximizationParameter {
48      get { return (ValueParameter<BoolValue>)Parameters["Maximization"]; }
49    }
50    IParameter ISingleObjectiveHeuristicOptimizationProblem.MaximizationParameter {
51      get { return MaximizationParameter; }
52    }
53    public ValueParameter<IntValue> KnapsackCapacityParameter {
54      get { return (ValueParameter<IntValue>)Parameters["KnapsackCapacity"]; }
55    }
56    public ValueParameter<IntArray> WeightsParameter {
57      get { return (ValueParameter<IntArray>)Parameters["Weights"]; }
58    }
59    public ValueParameter<IntArray> ValuesParameter {
60      get { return (ValueParameter<IntArray>)Parameters["Values"]; }
61    }
62    public ValueParameter<DoubleValue> PenaltyParameter {
63      get { return (ValueParameter<DoubleValue>)Parameters["Penalty"]; }
64    }
65    public ValueParameter<IBinaryVectorCreator> SolutionCreatorParameter {
66      get { return (ValueParameter<IBinaryVectorCreator>)Parameters["SolutionCreator"]; }
67    }
68    IParameter IHeuristicOptimizationProblem.SolutionCreatorParameter {
69      get { return SolutionCreatorParameter; }
70    }
71    public ValueParameter<IKnapsackEvaluator> EvaluatorParameter {
72      get { return (ValueParameter<IKnapsackEvaluator>)Parameters["Evaluator"]; }
73    }
74    IParameter IHeuristicOptimizationProblem.EvaluatorParameter {
75      get { return EvaluatorParameter; }
76    }
77    public OptionalValueParameter<DoubleValue> BestKnownQualityParameter {
78      get { return (OptionalValueParameter<DoubleValue>)Parameters["BestKnownQuality"]; }
79    }
80    IParameter ISingleObjectiveHeuristicOptimizationProblem.BestKnownQualityParameter {
81      get { return BestKnownQualityParameter; }
82    }
83    public OptionalValueParameter<BinaryVector> BestKnownSolutionParameter {
84      get { return (OptionalValueParameter<BinaryVector>)Parameters["BestKnownSolution"]; }
85    }
86    #endregion
87
88    #region Properties
89    public IntValue KnapsackCapacity {
90      get { return KnapsackCapacityParameter.Value; }
91      set { KnapsackCapacityParameter.Value = value; }
92    }
93    public IntArray Weights {
94      get { return WeightsParameter.Value; }
95      set { WeightsParameter.Value = value; }
96    }
97    public IntArray Values {
98      get { return ValuesParameter.Value; }
99      set { ValuesParameter.Value = value; }
100    }
101    public DoubleValue Penalty {
102      get { return PenaltyParameter.Value; }
103      set { PenaltyParameter.Value = value; }
104    }
105    public IBinaryVectorCreator SolutionCreator {
106      get { return SolutionCreatorParameter.Value; }
107      set { SolutionCreatorParameter.Value = value; }
108    }
109    ISolutionCreator IHeuristicOptimizationProblem.SolutionCreator {
110      get { return SolutionCreatorParameter.Value; }
111    }
112    public IKnapsackEvaluator Evaluator {
113      get { return EvaluatorParameter.Value; }
114      set { EvaluatorParameter.Value = value; }
115    }
116    ISingleObjectiveEvaluator ISingleObjectiveHeuristicOptimizationProblem.Evaluator {
117      get { return EvaluatorParameter.Value; }
118    }
119    IEvaluator IHeuristicOptimizationProblem.Evaluator {
120      get { return EvaluatorParameter.Value; }
121    }
122    public DoubleValue BestKnownQuality {
123      get { return BestKnownQualityParameter.Value; }
124      set { BestKnownQualityParameter.Value = value; }
125    }
126    public BinaryVector BestKnownSolution {
127      get { return BestKnownSolutionParameter.Value; }
128      set { BestKnownSolutionParameter.Value = value; }
129    }
130    public IEnumerable<IOperator> Operators {
131      get { return operators.Cast<IOperator>(); }
132    }
133    private BestKnapsackSolutionAnalyzer BestKnapsackSolutionAnalyzer {
134      get { return operators.OfType<BestKnapsackSolutionAnalyzer>().FirstOrDefault(); }
135    }
136    #endregion
137
138    [Storable]
139    private List<IOperator> operators;
140
141    [StorableConstructor]
142    private KnapsackProblem(bool deserializing) : base(deserializing) { }
143    private KnapsackProblem(KnapsackProblem original, Cloner cloner)
144      : base(original, cloner) {
145      this.operators = original.operators.Select(x => (IOperator)cloner.Clone(x)).ToList();
146      AttachEventHandlers();
147    }
148    public override IDeepCloneable Clone(Cloner cloner) {
149      return new KnapsackProblem(this, cloner);
150    }
151    public KnapsackProblem()
152      : base() {
153      RandomBinaryVectorCreator creator = new RandomBinaryVectorCreator();
154      KnapsackEvaluator evaluator = new KnapsackEvaluator();
155
156      Parameters.Add(new ValueParameter<BoolValue>("Maximization", "Set to true as the Knapsack Problem is a maximization problem.", new BoolValue(true)));
157      Parameters.Add(new ValueParameter<IntValue>("KnapsackCapacity", "Capacity of the Knapsack.", new IntValue(0)));
158      Parameters.Add(new ValueParameter<IntArray>("Weights", "The weights of the items.", new IntArray(5)));
159      Parameters.Add(new ValueParameter<IntArray>("Values", "The values of the items.", new IntArray(5)));
160      Parameters.Add(new ValueParameter<DoubleValue>("Penalty", "The penalty value for each unit of overweight.", new DoubleValue(1)));
161      Parameters.Add(new ValueParameter<IBinaryVectorCreator>("SolutionCreator", "The operator which should be used to create new Knapsack solutions.", creator));
162      Parameters.Add(new ValueParameter<IKnapsackEvaluator>("Evaluator", "The operator which should be used to evaluate Knapsack solutions.", evaluator));
163      Parameters.Add(new OptionalValueParameter<DoubleValue>("BestKnownQuality", "The quality of the best known solution of this Knapsack instance."));
164      Parameters.Add(new OptionalValueParameter<BinaryVector>("BestKnownSolution", "The best known solution of this Knapsack instance."));
165
166      creator.BinaryVectorParameter.ActualName = "KnapsackSolution";
167
168      InitializeRandomKnapsackInstance();
169
170      ParameterizeSolutionCreator();
171      ParameterizeEvaluator();
172
173      InitializeOperators();
174      AttachEventHandlers();
175    }
176
177    #region Events
178    public event EventHandler SolutionCreatorChanged;
179    private void OnSolutionCreatorChanged() {
180      EventHandler handler = SolutionCreatorChanged;
181      if (handler != null) handler(this, EventArgs.Empty);
182    }
183    public event EventHandler EvaluatorChanged;
184    private void OnEvaluatorChanged() {
185      EventHandler handler = EvaluatorChanged;
186      if (handler != null) handler(this, EventArgs.Empty);
187    }
188    public event EventHandler OperatorsChanged;
189    private void OnOperatorsChanged() {
190      EventHandler handler = OperatorsChanged;
191      if (handler != null) handler(this, EventArgs.Empty);
192    }
193    public event EventHandler Reset;
194    private void OnReset() {
195      EventHandler handler = Reset;
196      if (handler != null) handler(this, EventArgs.Empty);
197    }
198
199    private void SolutionCreatorParameter_ValueChanged(object sender, EventArgs e) {
200      SolutionCreator.BinaryVectorParameter.ActualNameChanged += new EventHandler(SolutionCreator_BinaryVectorParameter_ActualNameChanged);
201      ParameterizeSolutionCreator();
202      ParameterizeEvaluator();
203      ParameterizeAnalyzer();
204      ParameterizeOperators();
205      OnSolutionCreatorChanged();
206    }
207    private void SolutionCreator_BinaryVectorParameter_ActualNameChanged(object sender, EventArgs e) {
208      ParameterizeEvaluator();
209      ParameterizeAnalyzer();
210      ParameterizeOperators();
211    }
212    private void EvaluatorParameter_ValueChanged(object sender, EventArgs e) {
213      ParameterizeEvaluator();
214      ParameterizeAnalyzer();
215      OnEvaluatorChanged();
216    }
217    void KnapsackCapacityParameter_ValueChanged(object sender, EventArgs e) {
218      ParameterizeEvaluator();
219      ParameterizeAnalyzer();
220    }
221    void WeightsParameter_ValueChanged(object sender, EventArgs e) {
222      ParameterizeEvaluator();
223      ParameterizeAnalyzer();
224      ParameterizeSolutionCreator();
225
226      WeightsParameter.Value.Reset += new EventHandler(WeightsValue_Reset);
227    }
228    void WeightsValue_Reset(object sender, EventArgs e) {
229      ParameterizeSolutionCreator();
230
231      if (WeightsParameter.Value != null && ValuesParameter.Value != null)
232        ((IStringConvertibleArray)ValuesParameter.Value).Length = WeightsParameter.Value.Length;
233    }
234    void ValuesParameter_ValueChanged(object sender, EventArgs e) {
235      ParameterizeEvaluator();
236      ParameterizeAnalyzer();
237      ParameterizeSolutionCreator();
238
239      ValuesParameter.Value.Reset += new EventHandler(ValuesValue_Reset);
240    }
241    void ValuesValue_Reset(object sender, EventArgs e) {
242      ParameterizeSolutionCreator();
243
244      if (WeightsParameter.Value != null && ValuesParameter.Value != null)
245        ((IStringConvertibleArray)WeightsParameter.Value).Length = ValuesParameter.Value.Length;
246    }
247    void PenaltyParameter_ValueChanged(object sender, EventArgs e) {
248      ParameterizeEvaluator();
249    }
250    void OneBitflipMoveParameter_ActualNameChanged(object sender, EventArgs e) {
251      string name = ((ILookupParameter<OneBitflipMove>)sender).ActualName;
252      foreach (IOneBitflipMoveOperator op in Operators.OfType<IOneBitflipMoveOperator>()) {
253        op.OneBitflipMoveParameter.ActualName = name;
254      }
255    }
256    #endregion
257
258    #region Helpers
259    [StorableHook(HookType.AfterDeserialization)]
260    private void AfterDeserialization() {
261      // BackwardsCompatibility3.3
262      #region Backwards compatible code (remove with 3.4)
263      if (operators == null) InitializeOperators();
264      #endregion
265      AttachEventHandlers();
266    }
267
268    private void AttachEventHandlers() {
269      SolutionCreatorParameter.ValueChanged += new EventHandler(SolutionCreatorParameter_ValueChanged);
270      SolutionCreator.BinaryVectorParameter.ActualNameChanged += new EventHandler(SolutionCreator_BinaryVectorParameter_ActualNameChanged);
271      EvaluatorParameter.ValueChanged += new EventHandler(EvaluatorParameter_ValueChanged);
272      KnapsackCapacityParameter.ValueChanged += new EventHandler(KnapsackCapacityParameter_ValueChanged);
273      WeightsParameter.ValueChanged += new EventHandler(WeightsParameter_ValueChanged);
274      WeightsParameter.Value.Reset += new EventHandler(WeightsValue_Reset);
275      ValuesParameter.ValueChanged += new EventHandler(ValuesParameter_ValueChanged);
276      ValuesParameter.Value.Reset += new EventHandler(ValuesValue_Reset);
277      PenaltyParameter.ValueChanged += new EventHandler(PenaltyParameter_ValueChanged);
278    }
279    private void ParameterizeSolutionCreator() {
280      if (SolutionCreator.LengthParameter.Value == null ||
281        SolutionCreator.LengthParameter.Value.Value != WeightsParameter.Value.Length)
282        SolutionCreator.LengthParameter.Value = new IntValue(WeightsParameter.Value.Length);
283    }
284    private void ParameterizeEvaluator() {
285      if (Evaluator is KnapsackEvaluator) {
286        KnapsackEvaluator knapsackEvaluator =
287          (KnapsackEvaluator)Evaluator;
288        knapsackEvaluator.BinaryVectorParameter.ActualName = SolutionCreator.BinaryVectorParameter.ActualName;
289        knapsackEvaluator.KnapsackCapacityParameter.ActualName = KnapsackCapacityParameter.Name;
290        knapsackEvaluator.WeightsParameter.ActualName = WeightsParameter.Name;
291        knapsackEvaluator.ValuesParameter.ActualName = ValuesParameter.Name;
292        knapsackEvaluator.PenaltyParameter.ActualName = PenaltyParameter.Name;
293      }
294    }
295    private void ParameterizeAnalyzer() {
296      BestKnapsackSolutionAnalyzer.MaximizationParameter.ActualName = MaximizationParameter.Name;
297      BestKnapsackSolutionAnalyzer.BestKnownQualityParameter.ActualName = BestKnownQualityParameter.Name;
298      BestKnapsackSolutionAnalyzer.BestKnownSolutionParameter.ActualName = BestKnownSolutionParameter.Name;
299      BestKnapsackSolutionAnalyzer.BinaryVectorParameter.ActualName = SolutionCreator.BinaryVectorParameter.ActualName;
300      BestKnapsackSolutionAnalyzer.KnapsackCapacityParameter.ActualName = KnapsackCapacityParameter.Name;
301      BestKnapsackSolutionAnalyzer.WeightsParameter.ActualName = WeightsParameter.Name;
302      BestKnapsackSolutionAnalyzer.ValuesParameter.ActualName = ValuesParameter.Name;
303      BestKnapsackSolutionAnalyzer.ResultsParameter.ActualName = "Results";
304    }
305    private void InitializeOperators() {
306      operators = new List<IOperator>();
307      operators.Add(new BestKnapsackSolutionAnalyzer());
308      ParameterizeAnalyzer();
309      foreach (IBinaryVectorOperator op in ApplicationManager.Manager.GetInstances<IBinaryVectorOperator>()) {
310        if (!(op is ISingleObjectiveMoveEvaluator) || (op is IKnapsackMoveEvaluator)) {
311          operators.Add(op);
312        }
313      }
314      ParameterizeOperators();
315      InitializeMoveGenerators();
316    }
317    private void InitializeMoveGenerators() {
318      foreach (IOneBitflipMoveOperator op in Operators.OfType<IOneBitflipMoveOperator>()) {
319        if (op is IMoveGenerator) {
320          op.OneBitflipMoveParameter.ActualNameChanged += new EventHandler(OneBitflipMoveParameter_ActualNameChanged);
321        }
322      }
323    }
324    private void ParameterizeOperators() {
325      foreach (IBinaryVectorCrossover op in Operators.OfType<IBinaryVectorCrossover>()) {
326        op.ParentsParameter.ActualName = SolutionCreator.BinaryVectorParameter.ActualName;
327        op.ChildParameter.ActualName = SolutionCreator.BinaryVectorParameter.ActualName;
328      }
329      foreach (IBinaryVectorManipulator op in Operators.OfType<IBinaryVectorManipulator>()) {
330        op.BinaryVectorParameter.ActualName = SolutionCreator.BinaryVectorParameter.ActualName;
331      }
332      foreach (IBinaryVectorMoveOperator op in Operators.OfType<IBinaryVectorMoveOperator>()) {
333        op.BinaryVectorParameter.ActualName = SolutionCreator.BinaryVectorParameter.ActualName;
334      }
335      foreach (IKnapsackMoveEvaluator op in Operators.OfType<IKnapsackMoveEvaluator>()) {
336        op.KnapsackCapacityParameter.ActualName = KnapsackCapacityParameter.Name;
337        op.PenaltyParameter.ActualName = PenaltyParameter.Name;
338        op.WeightsParameter.ActualName = WeightsParameter.Name;
339        op.ValuesParameter.ActualName = ValuesParameter.Name;
340      }
341      foreach (var op in Operators.OfType<IBinaryVectorMultiNeighborhoodShakingOperator>())
342        op.BinaryVectorParameter.ActualName = SolutionCreator.BinaryVectorParameter.ActualName;
343    }
344    #endregion
345
346    private void InitializeRandomKnapsackInstance() {
347      System.Random rand = new System.Random();
348
349      int itemCount = rand.Next(10, 100);
350      Weights = new IntArray(itemCount);
351      Values = new IntArray(itemCount);
352
353      double totalWeight = 0;
354
355      for (int i = 0; i < itemCount; i++) {
356        int value = rand.Next(1, 10);
357        int weight = rand.Next(1, 10);
358
359        Values[i] = value;
360        Weights[i] = weight;
361        totalWeight += weight;
362      }
363
364      int capacity = (int)Math.Round(0.7 * totalWeight);
365      KnapsackCapacity = new IntValue(capacity);
366    }
367  }
368}
Note: See TracBrowser for help on using the repository browser.