Free cookie consent management tool by TermsFeed Policy Generator

source: branches/ParameterConfigurationEncoding/HeuristicLab.Encodings.ParameterConfigurationEncoding/3.3/ParameterConfigurationTree.cs @ 8535

Last change on this file since 8535 was 8535, checked in by jkarder, 12 years ago

#1853:

  • enhanced combinations count calculation
  • restructured code
  • minor code improvements
  • added license information
File size: 15.8 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2012 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;
24using System.Collections.Generic;
25using System.Linq;
26using System.Text;
27using System.Threading;
28using HeuristicLab.Common;
29using HeuristicLab.Core;
30using HeuristicLab.Data;
31using HeuristicLab.Optimization;
32using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
33using HeuristicLab.Problems.Instances;
34
35namespace HeuristicLab.Encodings.ParameterConfigurationEncoding {
36  [Item("ParameterConfigurationTree", "Represents a parameter configuration.")]
37  [StorableClass]
38  public class ParameterConfigurationTree : ParameterizedValueConfiguration, IEnumerable {
39    [Storable]
40    private long combinationsCount;
41    public long CombinationsCount {
42      get { return combinationsCount; }
43      private set {
44        if (combinationsCount != value) {
45          combinationsCount = value;
46          OnCombinationsCountChanged();
47        }
48      }
49    }
50
51    [Storable]
52    private DoubleValue quality;
53    public DoubleValue Quality {
54      get { return quality; }
55      set {
56        if (quality != value) {
57          quality = value;
58          OnQualityChanged();
59        }
60      }
61    }
62
63    [Storable]
64    private DoubleArray normalizedQualityAverages;
65    public DoubleArray NormalizedQualityAverages {
66      get { return normalizedQualityAverages; }
67      set {
68        if (normalizedQualityAverages != value) {
69          normalizedQualityAverages = value;
70        }
71      }
72    }
73
74    [Storable]
75    private DoubleArray normalizedQualityDeviations;
76    public DoubleArray NormalizedQualityDeviations {
77      get { return normalizedQualityDeviations; }
78      set {
79        if (normalizedQualityDeviations != value) {
80          normalizedQualityDeviations = value;
81        }
82      }
83    }
84
85    [Storable]
86    private DoubleArray normalizedEvaluatedSolutions;
87    public DoubleArray NormalizedEvaluatedSolutions {
88      get { return normalizedEvaluatedSolutions; }
89      set {
90        if (normalizedEvaluatedSolutions != value) {
91          normalizedEvaluatedSolutions = value;
92        }
93      }
94    }
95
96    [Storable]
97    private DoubleArray bestQualities;
98    public DoubleArray BestQualities {
99      get { return bestQualities; }
100      set {
101        if (bestQualities != value) {
102          bestQualities = value;
103        }
104      }
105    }
106
107    [Storable]
108    private DoubleArray averageQualities;
109    public DoubleArray AverageQualities {
110      get { return averageQualities; }
111      set { averageQualities = value; }
112    }
113
114    [Storable]
115    private DoubleArray worstQualities;
116    public DoubleArray WorstQualities {
117      get { return worstQualities; }
118      set { worstQualities = value; }
119    }
120
121    [Storable]
122    private DoubleArray qualityVariances;
123    public DoubleArray QualityVariances {
124      get { return qualityVariances; }
125      set { qualityVariances = value; }
126    }
127
128    [Storable]
129    private DoubleArray qualityStandardDeviations;
130    public DoubleArray QualityStandardDeviations {
131      get { return qualityStandardDeviations; }
132      set { qualityStandardDeviations = value; }
133    }
134
135    [Storable]
136    private ItemList<TimeSpanValue> averageExecutionTimes;
137    public ItemList<TimeSpanValue> AverageExecutionTimes {
138      get { return averageExecutionTimes; }
139      set { averageExecutionTimes = value; }
140    }
141
142    [Storable]
143    private DoubleArray averageEvaluatedSolutions;
144    public DoubleArray AverageEvaluatedSolutions {
145      get { return averageEvaluatedSolutions; }
146      set { averageEvaluatedSolutions = value; }
147    }
148
149    [Storable]
150    private IntValue repetitions;
151    public IntValue Repetitions {
152      get { return repetitions; }
153      set { repetitions = value; }
154    }
155
156    [Storable]
157    protected RunCollection runs;
158    public RunCollection Runs {
159      get { return runs; }
160      set { runs = value; }
161    }
162
163    [Storable]
164    protected IDictionary<string, IItem> parameters;
165    public IDictionary<string, IItem> Parameters {
166      get { return parameters; }
167      set { parameters = value; }
168    }
169
170    [Storable]
171    private double experimentGenerationProgress;
172    public double ExperimentGenerationProgress {
173      get { return experimentGenerationProgress; }
174      private set {
175        if (experimentGenerationProgress != value) {
176          experimentGenerationProgress = value;
177          OnExperimentGenerationProgressChanged();
178        }
179      }
180    }
181
182    public ParameterizedValueConfiguration AlgorithmConfiguration {
183      get {
184        return this.ParameterConfigurations.ElementAt(0).ValueConfigurations.First() as ParameterizedValueConfiguration;
185      }
186    }
187
188    public ParameterizedValueConfiguration ProblemConfiguration {
189      get {
190        return this.ParameterConfigurations.ElementAt(1).ValueConfigurations.First() as ParameterizedValueConfiguration;
191      }
192    }
193
194    #region Constructors and Cloning
195    [StorableConstructor]
196    protected ParameterConfigurationTree(bool deserializing) : base(deserializing) { }
197    protected ParameterConfigurationTree(ParameterConfigurationTree original, Cloner cloner)
198      : base(original, cloner) {
199      this.quality = cloner.Clone(original.quality);
200      this.normalizedQualityAverages = cloner.Clone(original.normalizedQualityAverages);
201      this.normalizedQualityDeviations = cloner.Clone(original.normalizedQualityDeviations);
202      this.normalizedEvaluatedSolutions = cloner.Clone(original.normalizedEvaluatedSolutions);
203      this.bestQualities = cloner.Clone(original.BestQualities);
204      this.averageQualities = cloner.Clone(original.averageQualities);
205      this.worstQualities = cloner.Clone(original.worstQualities);
206      this.qualityStandardDeviations = cloner.Clone(original.qualityStandardDeviations);
207      this.qualityVariances = cloner.Clone(original.qualityVariances);
208      this.averageExecutionTimes = cloner.Clone(original.averageExecutionTimes);
209      this.averageEvaluatedSolutions = cloner.Clone(original.averageEvaluatedSolutions);
210      this.repetitions = cloner.Clone(original.repetitions);
211      this.runs = cloner.Clone(original.runs);
212      this.parameters = new Dictionary<string, IItem>();
213      if (original.parameters != null) {
214        foreach (var p in original.parameters) {
215          this.parameters.Add(p.Key, cloner.Clone(p.Value));
216        }
217      }
218    }
219    public ParameterConfigurationTree() : base() { }
220    public ParameterConfigurationTree(IAlgorithm algorithm, IProblem problem)
221      : base(null, algorithm.GetType(), false) {
222      this.Optimize = false;
223      this.IsOptimizable = false;
224      this.parameters = new Dictionary<string, IItem>();
225      this.Name = algorithm.ItemName;
226
227      var algProblemItem = new AlgorithmProblemItem();
228      algProblemItem.AlgorithmParameter.Value = algorithm;
229      algProblemItem.ProblemParameter.Value = problem;
230      this.discoverValidValues = false;
231
232      var algConfig = new SingleValuedParameterConfiguration("Algorithm", algProblemItem.AlgorithmParameter);
233      var problemConfig = new SingleValuedParameterConfiguration("Problem", algProblemItem.ProblemParameter);
234
235      algConfig.CombinationsCountChanged += new EventHandler(UpdateConfigurationsCount);
236      problemConfig.CombinationsCountChanged += new EventHandler(UpdateConfigurationsCount);
237
238      this.parameterConfigurations.Add(algConfig);
239      this.parameterConfigurations.Add(problemConfig);
240
241      // problems can be modified in the list of problem instances, so the parameters which are not Optimize=true,
242      // must not be modifiable in the parameter configuration tree. otherwise the parameter values would be ambiguous
243      ProblemConfiguration.ValuesReadOnly = true;
244
245      CombinationsCount = GetCombinationCount(0);
246    }
247
248    public override IDeepCloneable Clone(Cloner cloner) {
249      return new ParameterConfigurationTree(this, cloner);
250    }
251
252    [StorableHook(HookType.AfterDeserialization)]
253    private void AfterDeserialization() {
254      if (ProblemConfiguration != null) ProblemConfiguration.ValuesReadOnly = true;
255      CombinationsCount = GetCombinationCount(0);
256    }
257    #endregion
258
259    public virtual void CollectResultValues(IDictionary<string, IItem> values) {
260      values.Add("RunsAverageExecutionTimes", AverageExecutionTimes);
261      values.Add("RunsAverageEvaluatedSolutions", AverageEvaluatedSolutions);
262      values.Add("Repetitions", Repetitions);
263      values.Add("RunsBestQualities", BestQualities);
264      values.Add("RunsAverageQualities", AverageQualities);
265      values.Add("RunsWorstQualities", WorstQualities);
266      values.Add("RunsQualityVariances", QualityVariances);
267      values.Add("RunsQualityStandardDeviations", QualityStandardDeviations);
268      values.Add("QualitiesNormalized", NormalizedQualityAverages);
269      values.Add("AverageQualityNormalized", Quality);
270      values.Add("Runs", Runs);
271    }
272
273    public virtual void CollectParameterValues(IDictionary<string, IItem> values) {
274      foreach (var p in parameters) {
275        values.Add(p);
276      }
277    }
278
279    #region Events
280    public event EventHandler QualityChanged;
281    private void OnQualityChanged() {
282      var handler = QualityChanged;
283      if (handler != null) handler(this, EventArgs.Empty);
284    }
285
286    private void Quality_ValueChanged(object sender, EventArgs e) {
287      OnQualityChanged();
288    }
289
290    private void UpdateConfigurationsCount(object sender, EventArgs e) {
291      CombinationsCount = GetCombinationCount(0);
292    }
293
294    public event EventHandler ExperimentGenerationProgressChanged;
295    private void OnExperimentGenerationProgressChanged() {
296      var handler = ExperimentGenerationProgressChanged;
297      if (handler != null) handler(this, EventArgs.Empty);
298    }
299    #endregion
300
301    public override void Parameterize(IParameterizedItem item) {
302      this.parameters.Clear();
303      var algorithm = (IAlgorithm)item;
304      var problem = algorithm.Problem;
305
306      ProblemConfiguration.Parameterize(problem);
307      AlgorithmConfiguration.Parameterize(algorithm);
308
309      algorithm.CollectParameterValues(this.Parameters);
310    }
311
312    public Experiment GenerateExperiment(IAlgorithm algorithm, bool createBatchRuns, int repetitions, Dictionary<IProblemInstanceProvider, HashSet<IDataDescriptor>> problemInstances, CancellationToken ct) {
313      Experiment experiment = new Experiment();
314      var algorithms = new List<IAlgorithm>(1 + problemInstances.Values.Count) { (IAlgorithm)algorithm.Clone() };
315      foreach (var provider in problemInstances) {
316        foreach (var descriptor in provider.Value) {
317          var alg = (IAlgorithm)algorithm.Clone();
318          ProblemInstanceManager.LoadData(provider.Key, descriptor, (IProblemInstanceConsumer)alg.Problem);
319          algorithms.Add(alg);
320        }
321      }
322      ExperimentGenerationProgress = 0;
323      foreach (var alg in algorithms) {
324        foreach (ParameterizedValueConfiguration combination in this) {
325          ct.ThrowIfCancellationRequested();
326          var clonedAlg = (IAlgorithm)alg.Clone();
327          clonedAlg.Name = combination.ParameterInfoString;
328          combination.Parameterize(clonedAlg);
329          clonedAlg.StoreAlgorithmInEachRun = false;
330          if (createBatchRuns) {
331            BatchRun batchRun = new BatchRun(string.Format("BatchRun: {0}", combination.ParameterInfoString));
332            batchRun.Optimizer = clonedAlg;
333            batchRun.Repetitions = repetitions;
334            experiment.Optimizers.Add(batchRun);
335          } else {
336            experiment.Optimizers.Add(clonedAlg);
337          }
338          ExperimentGenerationProgress = (double)experiment.Optimizers.Count / (this.GetCombinationCount(0) * algorithms.Count);
339        }
340      }
341      return experiment;
342    }
343
344    public Experiment GenerateExperiment(IAlgorithm algorithm) {
345      return GenerateExperiment(algorithm, false, 0, null, CancellationToken.None);
346    }
347
348    public Experiment GenerateExperiment(IAlgorithm algorithm, bool createBatchRuns, int repetitions) {
349      return GenerateExperiment(algorithm, createBatchRuns, repetitions, null, CancellationToken.None);
350    }
351
352    public IEnumerator GetEnumerator() {
353      IEnumerator enumerator = new ParameterCombinationsEnumerator(this);
354      enumerator.Reset();
355      return enumerator;
356    }
357
358    /// <summary>
359    /// returns the number of possible parameter combinations
360    /// </summary>
361    /// <param name="max">algorithm stops counting when max is reached. zero for infinite counting</param>
362    /// <returns></returns>
363    public long GetCombinationCount(long max) {
364      long cnt = 0;
365      foreach (var c in this) {
366        cnt++;
367        if (max > 0 && cnt >= max) {
368          return cnt;
369        }
370      }
371      return cnt;
372    }
373
374    public IOptimizable GetRandomOptimizable(IRandom random) {
375      List<IOptimizable> allOptimizables = GetAllOptimizables();
376      return allOptimizables[random.Next(allOptimizables.Count)];
377    }
378
379    public override string ToString() {
380      return this.Name;
381    }
382
383    public IRun ToRun(bool clearParameters) {
384      return ToRun(this.ParameterInfoString, clearParameters);
385    }
386
387    public IRun ToRun(string name, bool clearParameters) {
388      IRun run = new Run();
389      run.Name = name;
390      this.CollectResultValues(run.Results);
391      this.CollectParameterValues(run.Parameters);
392      if (clearParameters) ClearParameters(run, this.GetOptimizedParameterNames());
393      return run;
394    }
395
396    public override string ParameterInfoString {
397      get {
398        string algorithmInfo = this.AlgorithmConfiguration.ParameterInfoString;
399        string problemInfo = this.ProblemConfiguration.ParameterInfoString;
400        var sb = new StringBuilder();
401        if (!string.IsNullOrEmpty(algorithmInfo)) {
402          sb.Append("Algorithm (");
403          sb.Append(algorithmInfo);
404          sb.Append(")");
405        }
406        if (!string.IsNullOrEmpty(problemInfo)) {
407          if (sb.Length > 0)
408            sb.Append(", ");
409          sb.Append("Problem( ");
410          sb.Append(problemInfo);
411          sb.Append(")");
412        }
413        return sb.ToString();
414      }
415    }
416
417    public override void CollectOptimizedParameterNames(List<string> parameterNames, string prefix) {
418      AlgorithmConfiguration.CollectOptimizedParameterNames(parameterNames, string.Empty);
419      ProblemConfiguration.CollectOptimizedParameterNames(parameterNames, string.Empty);
420    }
421
422    #region Helpers
423    /// <summary>
424    /// Removes those parameters from the run which are not declared in parametersToKeep
425    /// </summary>
426    private void ClearParameters(IRun run, IEnumerable<string> parametersToKeep) {
427      var parametersToRemove = new List<string>();
428      foreach (var parameter in run.Parameters) {
429        if (!parametersToKeep.Contains(parameter.Key))
430          parametersToRemove.Add(parameter.Key);
431      }
432      foreach (var parameter in parametersToRemove)
433        run.Parameters.Remove(parameter);
434    }
435    #endregion
436  }
437}
Note: See TracBrowser for help on using the repository browser.