using System; using System.Collections.Generic; using System.Linq; using System.Text; using HeuristicLab.Core; using HeuristicLab.Common; using HeuristicLab.Persistence.Default.CompositeSerializers.Storable; using HeuristicLab.Optimization; using HeuristicLab.Data; using System.Collections; namespace HeuristicLab.Problems.MetaOptimization { // todo: storable, name, descr, ... [StorableClass] public class ParameterConfigurationTree : ValueConfiguration, IEnumerable { [Storable] private DoubleValue bestQuality; public DoubleValue BestQuality { get { return bestQuality; } set { if (bestQuality != value) { if (bestQuality != null) DeregisterQualityEvents(); bestQuality = value; if (bestQuality != null) RegisterQualityEvents(); OnQualityChanged(); } } } [Storable] private DoubleValue averageQuality; public DoubleValue AverageQuality { get { return averageQuality; } set { averageQuality = value; } } [Storable] private DoubleValue worstQuality; public DoubleValue WorstQuality { get { return worstQuality; } set { worstQuality = value; } } [Storable] private DoubleValue qualityVariance; public DoubleValue QualityVariance { get { return qualityVariance; } set { qualityVariance = value; } } [Storable] private DoubleValue qualityStandardDeviation; public DoubleValue QualityStandardDeviation { get { return qualityStandardDeviation; } set { qualityStandardDeviation = value; } } [Storable] private TimeSpanValue averageExecutionTime; public TimeSpanValue AverageExecutionTime { get { return averageExecutionTime; } set { averageExecutionTime = 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; } } #region constructors and cloning public ParameterConfigurationTree(EngineAlgorithm algorithm) : base(null, algorithm.GetType()) { this.Optimize = true; // root must always be optimized this.BestQuality = new DoubleValue(); this.parameters = new Dictionary(); PopulateParameterConfigurations(algorithm); Initialize(); } public ParameterConfigurationTree() { Initialize(); } [StorableConstructor] protected ParameterConfigurationTree(bool deserializing) : base(deserializing) { } protected ParameterConfigurationTree(ParameterConfigurationTree original, Cloner cloner) : base(original, cloner) { this.bestQuality = cloner.Clone(original.BestQuality); this.averageQuality = cloner.Clone(original.averageQuality); this.worstQuality = cloner.Clone(original.worstQuality); this.qualityStandardDeviation = cloner.Clone(original.qualityStandardDeviation); this.qualityVariance = cloner.Clone(original.qualityVariance); this.averageExecutionTime = cloner.Clone(original.averageExecutionTime); 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)); } Initialize(); } public override IDeepCloneable Clone(Cloner cloner) { return new ParameterConfigurationTree(this, cloner); } [StorableHook(HookType.AfterDeserialization)] private void AfterDeserialization() { Initialize(); } #endregion private void Initialize() { //if (algorithm != null) RegisterAlgorithmEvents(); if (bestQuality != null) RegisterQualityEvents(); } public virtual void CollectResultValues(IDictionary values) { values.Add("RunsAverageExecutionTime", AverageExecutionTime); values.Add("Repetitions", Repetitions); values.Add("RunsBestQuality", BestQuality); values.Add("RunsAverageQuality", AverageQuality); values.Add("RunsWorstQuality", WorstQuality); values.Add("RunsQualityVariance", QualityVariance); values.Add("RunsQualityStandardDeviation", QualityStandardDeviation); values.Add("Runs", Runs); } public virtual void CollectParameterValues(IDictionary values) { foreach (var p in parameters) { values.Add(p); } } #region Events //public event EventHandler AlgorithmChanged; //private void OnAlgorithmChanged() { // var handler = AlgorithmChanged; // if (handler != null) handler(this, EventArgs.Empty); //} public event EventHandler QualityChanged; private void OnQualityChanged() { var handler = QualityChanged; if (handler != null) handler(this, EventArgs.Empty); } //private void RegisterAlgorithmEvents() { //} //private void DeregisterAlgorithmEvents() { //} private void RegisterQualityEvents() { BestQuality.ValueChanged += new EventHandler(Quality_ValueChanged); } private void DeregisterQualityEvents() { BestQuality.ValueChanged -= new EventHandler(Quality_ValueChanged); } private void Quality_ValueChanged(object sender, EventArgs e) { OnQualityChanged(); } #endregion public override void Parameterize(IParameterizedItem item) { base.Parameterize(item); this.parameters.Clear(); ((IAlgorithm)item).CollectParameterValues(this.Parameters); } public Experiment GenerateExperiment(IAlgorithm algorithm, bool createBatchRuns, int repetitions) { Experiment experiment = new Experiment(); foreach (IValueConfiguration 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.Algorithm = 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; } public long GetCombinationCount() { long cnt = 0; foreach (var c in this) { cnt++; } return cnt; } } }