#region License Information
/* HeuristicLab
* Copyright (C) 2002-2012 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
*
* This file is part of HeuristicLab.
*
* HeuristicLab is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* HeuristicLab is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with HeuristicLab. If not, see .
*/
#endregion
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using HeuristicLab.Common;
using HeuristicLab.Core;
using HeuristicLab.Data;
using HeuristicLab.Optimization;
using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
namespace HeuristicLab.Encodings.ParameterConfigurationEncoding {
[Item("ParameterConfigurationTree", "Represents a parameter configuration.")]
[StorableClass]
public class ParameterConfigurationTree : ParameterizedValueConfiguration, IEnumerable {
[Storable]
private long combinationsCount;
public long CombinationsCount {
get { return combinationsCount; }
private set {
if (combinationsCount != value) {
combinationsCount = value;
OnCombinationsCountChanged();
}
}
}
[Storable]
private DoubleValue quality;
public DoubleValue Quality {
get { return quality; }
set {
if (quality != value) {
quality = value;
OnQualityChanged();
}
}
}
[Storable]
private DoubleArray normalizedQualityAverages;
public DoubleArray NormalizedQualityAverages {
get { return normalizedQualityAverages; }
set {
if (normalizedQualityAverages != value) {
normalizedQualityAverages = value;
}
}
}
[Storable]
private DoubleArray normalizedQualityDeviations;
public DoubleArray NormalizedQualityDeviations {
get { return normalizedQualityDeviations; }
set {
if (normalizedQualityDeviations != value) {
normalizedQualityDeviations = value;
}
}
}
[Storable]
private DoubleArray normalizedEvaluatedSolutions;
public DoubleArray NormalizedEvaluatedSolutions {
get { return normalizedEvaluatedSolutions; }
set {
if (normalizedEvaluatedSolutions != value) {
normalizedEvaluatedSolutions = value;
}
}
}
[Storable]
private DoubleArray bestQualities;
public DoubleArray BestQualities {
get { return bestQualities; }
set {
if (bestQualities != value) {
bestQualities = value;
}
}
}
[Storable]
private DoubleArray averageQualities;
public DoubleArray AverageQualities {
get { return averageQualities; }
set { averageQualities = value; }
}
[Storable]
private DoubleArray worstQualities;
public DoubleArray WorstQualities {
get { return worstQualities; }
set { worstQualities = value; }
}
[Storable]
private DoubleArray qualityVariances;
public DoubleArray QualityVariances {
get { return qualityVariances; }
set { qualityVariances = value; }
}
[Storable]
private DoubleArray qualityStandardDeviations;
public DoubleArray QualityStandardDeviations {
get { return qualityStandardDeviations; }
set { qualityStandardDeviations = value; }
}
[Storable]
private ItemList averageExecutionTimes;
public ItemList AverageExecutionTimes {
get { return averageExecutionTimes; }
set { averageExecutionTimes = value; }
}
[Storable]
private DoubleArray averageEvaluatedSolutions;
public DoubleArray AverageEvaluatedSolutions {
get { return averageEvaluatedSolutions; }
set { averageEvaluatedSolutions = value; }
}
[Storable]
private IntValue repetitions;
public IntValue Repetitions {
get { return repetitions; }
set { repetitions = value; }
}
[Storable]
protected RunCollection runs;
public RunCollection Runs {
get { return runs; }
set { runs = value; }
}
[Storable]
protected IDictionary parameters;
public IDictionary Parameters {
get { return parameters; }
set { parameters = value; }
}
public ParameterizedValueConfiguration AlgorithmConfiguration {
get {
return this.ParameterConfigurations.ElementAt(0).ValueConfigurations.First() as ParameterizedValueConfiguration;
}
}
public ParameterizedValueConfiguration ProblemConfiguration {
get {
return this.ParameterConfigurations.ElementAt(1).ValueConfigurations.First() as ParameterizedValueConfiguration;
}
}
#region Constructors and Cloning
[StorableConstructor]
protected ParameterConfigurationTree(bool deserializing) : base(deserializing) { }
protected ParameterConfigurationTree(ParameterConfigurationTree original, Cloner cloner)
: base(original, cloner) {
this.quality = cloner.Clone(original.quality);
this.normalizedQualityAverages = cloner.Clone(original.normalizedQualityAverages);
this.normalizedQualityDeviations = cloner.Clone(original.normalizedQualityDeviations);
this.normalizedEvaluatedSolutions = cloner.Clone(original.normalizedEvaluatedSolutions);
this.bestQualities = cloner.Clone(original.BestQualities);
this.averageQualities = cloner.Clone(original.averageQualities);
this.worstQualities = cloner.Clone(original.worstQualities);
this.qualityStandardDeviations = cloner.Clone(original.qualityStandardDeviations);
this.qualityVariances = cloner.Clone(original.qualityVariances);
this.averageExecutionTimes = cloner.Clone(original.averageExecutionTimes);
this.averageEvaluatedSolutions = cloner.Clone(original.averageEvaluatedSolutions);
this.repetitions = cloner.Clone(original.repetitions);
this.runs = cloner.Clone(original.runs);
this.parameters = new Dictionary();
if (original.parameters != null) {
foreach (var p in original.parameters) {
this.parameters.Add(p.Key, cloner.Clone(p.Value));
}
}
}
public ParameterConfigurationTree() : base() { }
public ParameterConfigurationTree(IAlgorithm algorithm, IProblem problem)
: base(null, algorithm.GetType(), false) {
this.Optimize = false;
this.IsOptimizable = false;
this.parameters = new Dictionary();
this.Name = algorithm.ItemName;
var algProblemItem = new AlgorithmProblemItem();
algProblemItem.AlgorithmParameter.Value = algorithm;
algProblemItem.ProblemParameter.Value = problem;
this.discoverValidValues = false;
var algConfig = new SingleValuedParameterConfiguration("Algorithm", algProblemItem.AlgorithmParameter);
var problemConfig = new SingleValuedParameterConfiguration("Problem", algProblemItem.ProblemParameter);
algConfig.CombinationsCountChanged += new EventHandler(UpdateConfigurationsCount);
problemConfig.CombinationsCountChanged += new EventHandler(UpdateConfigurationsCount);
this.parameterConfigurations.Add(algConfig);
this.parameterConfigurations.Add(problemConfig);
// problems can be modified in the list of problem instances, so the parameters which are not Optimize=true,
// must not be modifiable in the parameter configuration tree. otherwise the parameter values would be ambiguous
ProblemConfiguration.ValuesReadOnly = true;
CombinationsCount = GetCombinationCount(0);
}
public override IDeepCloneable Clone(Cloner cloner) {
return new ParameterConfigurationTree(this, cloner);
}
[StorableHook(HookType.AfterDeserialization)]
private void AfterDeserialization() {
if (ProblemConfiguration != null) ProblemConfiguration.ValuesReadOnly = true;
CombinationsCount = GetCombinationCount(0);
}
#endregion
public virtual void CollectResultValues(IDictionary values) {
values.Add("RunsAverageExecutionTimes", AverageExecutionTimes);
values.Add("RunsAverageEvaluatedSolutions", AverageEvaluatedSolutions);
values.Add("Repetitions", Repetitions);
values.Add("RunsBestQualities", BestQualities);
values.Add("RunsAverageQualities", AverageQualities);
values.Add("RunsWorstQualities", WorstQualities);
values.Add("RunsQualityVariances", QualityVariances);
values.Add("RunsQualityStandardDeviations", QualityStandardDeviations);
values.Add("QualitiesNormalized", NormalizedQualityAverages);
values.Add("AverageQualityNormalized", Quality);
values.Add("Runs", Runs);
}
public virtual void CollectParameterValues(IDictionary values) {
foreach (var p in parameters) {
values.Add(p);
}
}
#region Events
public event EventHandler QualityChanged;
private void OnQualityChanged() {
var handler = QualityChanged;
if (handler != null) handler(this, EventArgs.Empty);
}
private void Quality_ValueChanged(object sender, EventArgs e) {
OnQualityChanged();
}
private void UpdateConfigurationsCount(object sender, EventArgs e) {
CombinationsCount = GetCombinationCount(0);
}
#endregion
public override void Parameterize(IParameterizedItem item) {
this.parameters.Clear();
var algorithm = (IAlgorithm)item;
var problem = algorithm.Problem;
ProblemConfiguration.Parameterize(problem);
AlgorithmConfiguration.Parameterize(algorithm);
algorithm.CollectParameterValues(this.Parameters);
}
public IEnumerator GetEnumerator() {
IEnumerator enumerator = new ParameterCombinationsEnumerator(this);
enumerator.Reset();
return enumerator;
}
///
/// returns the number of possible parameter combinations
///
/// algorithm stops counting when max is reached. zero for infinite counting
///
public long GetCombinationCount(long max) {
long cnt = 0;
foreach (var c in this) {
cnt++;
if (max > 0 && cnt >= max) {
return cnt;
}
}
return cnt;
}
public IOptimizable GetRandomOptimizable(IRandom random) {
List allOptimizables = GetAllOptimizables();
return allOptimizables[random.Next(allOptimizables.Count)];
}
public override string ToString() {
return this.Name;
}
public IRun ToRun(bool clearParameters) {
return ToRun(this.ParameterInfoString, clearParameters);
}
public IRun ToRun(string name, bool clearParameters) {
IRun run = new Run();
run.Name = name;
this.CollectResultValues(run.Results);
this.CollectParameterValues(run.Parameters);
if (clearParameters) ClearParameters(run, this.GetOptimizedParameterNames());
return run;
}
public override string ParameterInfoString {
get {
string algorithmInfo = this.AlgorithmConfiguration.ParameterInfoString;
string problemInfo = this.ProblemConfiguration.ParameterInfoString;
var sb = new StringBuilder(AlgorithmConfiguration.NumberedName);
if (!string.IsNullOrEmpty(algorithmInfo)) sb.AppendFormat(" ({0})", algorithmInfo);
if (!string.IsNullOrEmpty(problemInfo)) sb.AppendFormat(", {0} ({1})", ProblemConfiguration.NumberedName, problemInfo);
return sb.ToString();
}
}
public override void CollectOptimizedParameterNames(List parameterNames, string prefix) {
AlgorithmConfiguration.CollectOptimizedParameterNames(parameterNames, string.Empty);
ProblemConfiguration.CollectOptimizedParameterNames(parameterNames, string.Empty);
}
#region Helpers
///
/// Removes those parameters from the run which are not declared in parametersToKeep
///
private void ClearParameters(IRun run, IEnumerable parametersToKeep) {
var parametersToRemove = new List();
foreach (var parameter in run.Parameters) {
if (!parametersToKeep.Contains(parameter.Key))
parametersToRemove.Add(parameter.Key);
}
foreach (var parameter in parametersToRemove)
run.Parameters.Remove(parameter);
}
#endregion
}
}