#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
}
}