#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.ParameterConfigurationTreeEncoding {
[StorableClass]
public class ParameterConfigurationTree : ParameterizedValueConfiguration, IEnumerable {
[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
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;
this.parameterConfigurations.Add(new SingleValuedParameterConfiguration("Algorithm", algproblemitem.AlgorithmParameter));
this.parameterConfigurations.Add(new SingleValuedParameterConfiguration("Problem", algproblemitem.ProblemParameter));
// 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;
}
public ParameterConfigurationTree() { }
[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();
foreach (var p in original.parameters) {
this.parameters.Add(p.Key, cloner.Clone(p.Value));
}
}
public override IDeepCloneable Clone(Cloner cloner) {
return new ParameterConfigurationTree(this, cloner);
}
[StorableHook(HookType.AfterDeserialization)]
private void AfterDeserialization() {
if (ProblemConfiguration != null) ProblemConfiguration.ValuesReadOnly = true;
}
#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();
}
#endregion
public override void Parameterize(IParameterizedItem item) {
this.parameters.Clear();
var algorithm = item as IAlgorithm;
var problem = algorithm.Problem;
ProblemConfiguration.Parameterize(problem);
AlgorithmConfiguration.Parameterize(algorithm);
algorithm.CollectParameterValues(this.Parameters);
}
public Experiment GenerateExperiment(IAlgorithm algorithm, bool createBatchRuns, int repetitions) {
Experiment experiment = new Experiment();
foreach (ParameterizedValueConfiguration combination in this) {
IAlgorithm clonedAlg = (IAlgorithm)algorithm.Clone();
clonedAlg.Name = combination.ParameterInfoString;
combination.Parameterize(clonedAlg);
clonedAlg.StoreAlgorithmInEachRun = false;
if (createBatchRuns) {
BatchRun batchRun = new BatchRun(string.Format("BatchRun: {0}", combination.ParameterInfoString));
batchRun.Optimizer = clonedAlg;
batchRun.Repetitions = repetitions;
experiment.Optimizers.Add(batchRun);
} else {
experiment.Optimizers.Add(clonedAlg);
}
}
return experiment;
}
public Experiment GenerateExperiment(IAlgorithm algorithm) {
return GenerateExperiment(algorithm, false, 0);
}
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) MetaOptimizationUtil.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();
if (!string.IsNullOrEmpty(algorithmInfo)) {
sb.Append("Algorithm (");
sb.Append(algorithmInfo);
sb.Append(")");
}
if (!string.IsNullOrEmpty(problemInfo)) {
if (sb.Length > 0)
sb.Append(", ");
sb.Append("Problem( ");
sb.Append(problemInfo);
sb.Append(")");
}
return sb.ToString();
}
}
public override void CollectOptimizedParameterNames(List parameterNames, string prefix) {
AlgorithmConfiguration.CollectOptimizedParameterNames(parameterNames, string.Empty);
ProblemConfiguration.CollectOptimizedParameterNames(parameterNames, string.Empty);
}
}
}