#region License Information /* HeuristicLab * Copyright (C) 2002-2010 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 HeuristicLab.Collections; using HeuristicLab.Common; using HeuristicLab.Core; using HeuristicLab.Data; using HeuristicLab.Optimization; using HeuristicLab.Persistence.Default.CompositeSerializers.Storable; using HeuristicLab.Problems.DataAnalysis; namespace HeuristicLab.Algorithms.DataAnalysis { [Item("Cross Validation", "Cross Validation wrapper for data analysis algorithms.")] [Creatable("Data Analysis")] [StorableClass] public sealed class CrossValidation : NamedItem, IOptimizer { //TODO cloning, persistence, creation of clonedAlgs, execution logic, ... public CrossValidation() : base() { name = ItemName; description = ItemDescription; executionState = ExecutionState.Stopped; executionTime = TimeSpan.Zero; Runs = new RunCollection(); algorithmTemplate = null; clonedAlgorithms = new ItemCollection(); RegisterClonedAlgorithmEvents(); readOnlyClonedAlgorithms = null; folds = new IntValue(1); samplesStart = new IntValue(0); samplesEnd = new IntValue(0); numberOfWorkers = new IntValue(1); } #region properties private IAlgorithm algorithmTemplate; public IAlgorithm AlgorithmTemplate { get { return algorithmTemplate; } set { if (algorithmTemplate != value) { if (value != null && value.Problem != null && !(value.Problem is IDataAnalysisProblem)) throw new ArgumentException("Only algorithms with a DataAnalysisProblem could be used for the cross validation."); if (algorithmTemplate != null) DeregisterAlgorithmTemplateEvents(); algorithmTemplate = value; if (algorithmTemplate != null) RegisterAlgorithmTemplateEvents(); OnAlgorithmTemplateChanged(); } } } public IDataAnalysisProblem Problem { get { if (algorithmTemplate == null) return null; return (IDataAnalysisProblem)algorithmTemplate.Problem; } } private ItemCollection clonedAlgorithms; private ReadOnlyItemCollection readOnlyClonedAlgorithms; public IItemCollection ClonedAlgorithms { get { if (readOnlyClonedAlgorithms == null) readOnlyClonedAlgorithms = clonedAlgorithms.AsReadOnly(); return readOnlyClonedAlgorithms; } } private IntValue folds; public IntValue Folds { get { return folds; } } private IntValue samplesStart; public IntValue SamplesStart { get { return SamplesStart; } } private IntValue samplesEnd; public IntValue SamplesEnd { get { return SamplesEnd; } } private IntValue numberOfWorkers; public IntValue NumberOfWorkers { get { return numberOfWorkers; } } private RunCollection runs; public RunCollection Runs { get { return runs; } private set { if (value == null) throw new ArgumentNullException(); if (runs != value) { if (runs != null) DeregisterRunsEvents(); runs = value; if (runs != null) RegisterRunsEvents(); } } } private ExecutionState executionState; public ExecutionState ExecutionState { get { return executionState; } private set { if (executionState != value) { executionState = value; OnExecutionStateChanged(); OnItemImageChanged(); } } } private TimeSpan executionTime; public TimeSpan ExecutionTime { get { return executionTime; } private set { executionTime = value; OnExecutionTimeChanged(); } } #endregion public void Prepare() { OnPrepared(); } public void Prepare(bool clearRuns) { if (clearRuns) runs.Clear(); Prepare(); } public void Start() { OnStarted(); } public void Pause() { OnPaused(); } public void Stop() { OnStopped(); } #region events public event EventHandler AlgorithmTemplateChanged; private void OnAlgorithmTemplateChanged() { Prepare(); EventHandler handler = AlgorithmTemplateChanged; if (handler != null) handler(this, EventArgs.Empty); } private void RegisterAlgorithmTemplateEvents() { algorithmTemplate.ProblemChanged += new EventHandler(algorithmTemplate_ProblemChanged); } private void DeregisterAlgorithmTemplateEvents() { algorithmTemplate.ProblemChanged -= new EventHandler(algorithmTemplate_ProblemChanged); } private void algorithmTemplate_ProblemChanged(object sender, EventArgs e) { SamplesStart.Value = 0; SamplesEnd.Value = Problem.DataAnalysisProblemData.Dataset.Rows; } private void RegisterClonedAlgorithmEvents() { clonedAlgorithms.ItemsAdded += new CollectionItemsChangedEventHandler(ClonedAlgorithms_ItemsAdded); clonedAlgorithms.ItemsRemoved += new CollectionItemsChangedEventHandler(ClonedAlgorithms_ItemsRemoved); clonedAlgorithms.CollectionReset += new CollectionItemsChangedEventHandler(ClonedAlgorithms_CollectionReset); } private void ClonedAlgorithms_ItemsAdded(object sender, CollectionItemsChangedEventArgs e) { foreach (IAlgorithm algorithm in e.Items) RegisterClonedAlgorithmEvents(algorithm); } private void ClonedAlgorithms_ItemsRemoved(object sender, CollectionItemsChangedEventArgs e) { foreach (IAlgorithm algorithm in e.Items) DeregisterClonedAlgorithmEvents(algorithm); } private void ClonedAlgorithms_CollectionReset(object sender, CollectionItemsChangedEventArgs e) { foreach (IAlgorithm algorithm in e.Items) RegisterClonedAlgorithmEvents(algorithm); foreach (IAlgorithm algorithm in e.OldItems) DeregisterClonedAlgorithmEvents(algorithm); } private void RegisterClonedAlgorithmEvents(IAlgorithm algorithm) { algorithm.Runs.ItemsAdded += new CollectionItemsChangedEventHandler(Algorithm_Runs_Added); algorithm.Paused += new EventHandler(Algorithm_Paused); algorithm.Stopped += new EventHandler(Algorithm_Stopped); } private void DeregisterClonedAlgorithmEvents(IAlgorithm algorithm) { algorithm.Runs.ItemsAdded -= new CollectionItemsChangedEventHandler(Algorithm_Runs_Added); algorithm.Paused -= new EventHandler(Algorithm_Paused); algorithm.Stopped -= new EventHandler(Algorithm_Stopped); } private void Algorithm_Runs_Added(object sender, CollectionItemsChangedEventArgs e) { throw new NotImplementedException("TODO added finished run to actual results if the cross validation is running"); } private void Algorithm_Paused(object sender, EventArgs e) { throw new NotImplementedException("TODO pause the cross validation if an algorithm no algorithm is running."); } private void Algorithm_Stopped(object sender, EventArgs e) { throw new NotImplementedException("TODO stop the cross validation if all algorithms are stopped. and start remaining prepared algs"); } public event EventHandler ExecutionStateChanged; private void OnExecutionStateChanged() { EventHandler handler = ExecutionStateChanged; if (handler != null) handler(this, EventArgs.Empty); } public event EventHandler ExecutionTimeChanged; private void OnExecutionTimeChanged() { EventHandler handler = ExecutionTimeChanged; if (handler != null) handler(this, EventArgs.Empty); } public event EventHandler Prepared; private void OnPrepared() { ExecutionState = ExecutionState.Prepared; EventHandler handler = Prepared; if (handler != null) handler(this, EventArgs.Empty); } public event EventHandler Started; private void OnStarted() { ExecutionState = ExecutionState.Started; EventHandler handler = Started; if (handler != null) handler(this, EventArgs.Empty); } public event EventHandler Paused; private void OnPaused() { ExecutionState = ExecutionState.Paused; EventHandler handler = Paused; if (handler != null) handler(this, EventArgs.Empty); } public event EventHandler Stopped; private void OnStopped() { ExecutionState = ExecutionState.Stopped; EventHandler handler = Stopped; if (handler != null) handler(this, EventArgs.Empty); } public event EventHandler> ExceptionOccurred; private void OnExceptionOccurred(Exception exception) { EventHandler> handler = ExceptionOccurred; if (handler != null) handler(this, new EventArgs(exception)); } private void RegisterRunsEvents() { runs.CollectionReset += new CollectionItemsChangedEventHandler(Runs_CollectionReset); runs.ItemsAdded += new CollectionItemsChangedEventHandler(Runs_ItemsAdded); runs.ItemsRemoved += new CollectionItemsChangedEventHandler(Runs_ItemsRemoved); } private void DeregisterRunsEvents() { runs.CollectionReset -= new CollectionItemsChangedEventHandler(Runs_CollectionReset); runs.ItemsAdded -= new CollectionItemsChangedEventHandler(Runs_ItemsAdded); runs.ItemsRemoved -= new CollectionItemsChangedEventHandler(Runs_ItemsRemoved); } private void Runs_CollectionReset(object sender, CollectionItemsChangedEventArgs e) { foreach (IRun run in e.OldItems) { IItem item; run.Results.TryGetValue("Execution Time", out item); TimeSpanValue executionTime = item as TimeSpanValue; if (executionTime != null) ExecutionTime -= executionTime.Value; } foreach (IRun run in e.Items) { IItem item; run.Results.TryGetValue("Execution Time", out item); TimeSpanValue executionTime = item as TimeSpanValue; if (executionTime != null) ExecutionTime += executionTime.Value; } } private void Runs_ItemsAdded(object sender, CollectionItemsChangedEventArgs e) { foreach (IRun run in e.Items) { IItem item; run.Results.TryGetValue("Execution Time", out item); TimeSpanValue executionTime = item as TimeSpanValue; if (executionTime != null) ExecutionTime += executionTime.Value; } } private void Runs_ItemsRemoved(object sender, CollectionItemsChangedEventArgs e) { foreach (IRun run in e.Items) { IItem item; run.Results.TryGetValue("Execution Time", out item); TimeSpanValue executionTime = item as TimeSpanValue; if (executionTime != null) ExecutionTime -= executionTime.Value; } } #endregion } }