using System; using HeuristicLab.Collections; using HeuristicLab.Common; using HeuristicLab.Core; using HeuristicLab.Optimization; using HeuristicLab.Parameters; using HeuristicLab.Persistence.Default.CompositeSerializers.Storable; namespace HeuristicLab.Operators { [Item("EngineAlgorithmOperator", "An operator the encapsulates a complete algorithm.")] [StorableClass] public class EngineAlgorithmOperator : AlgorithmOperator { [Storable] private OperatorGraph algorithmOperatorGraph; [Storable] protected EngineAlgorithm algorithm; public EngineAlgorithm Algorithm { get { return algorithm; } set { if (value == algorithm) return; if (algorithm != null) { DeregisterAlgorithmEvents(); if (algorithmOperatorGraph != null) DeregisterOperatorGraphEvents(); OperatorGraph.InitialOperator = null; OperatorGraph.Operators.Clear(); } algorithm = value; OnAlgorithmChanged(); if (algorithm != null) { foreach (IOperator op in algorithm.OperatorGraph.Operators) OperatorGraph.Operators.Add(op); OperatorGraph.InitialOperator = algorithm.OperatorGraph.InitialOperator; RegisterAlgorithmEvents(); if (algorithm.OperatorGraph != null) { algorithmOperatorGraph = algorithm.OperatorGraph; RegisterOperatorGraphEvents(); } } } } #region Events public event EventHandler AlgorithmChanged; protected virtual void OnAlgorithmChanged() { UpdateParameters(); EventHandler handler = AlgorithmChanged; if (handler != null) handler(this, EventArgs.Empty); } private void RegisterAlgorithmEvents() { algorithm.OperatorGraphChanged += algorithm_OperatorGraphChanged; algorithm.ProblemChanged +=new EventHandler(algorithm_ProblemChanged); } void algorithm_ProblemChanged(object sender, EventArgs e) { UpdateParameters(); } private void DeregisterAlgorithmEvents() { algorithm.OperatorGraphChanged -= algorithm_OperatorGraphChanged; } void algorithm_OperatorGraphChanged(object sender, EventArgs e) { if (algorithmOperatorGraph != null) DeregisterOperatorGraphEvents(); algorithmOperatorGraph = null; if (algorithm.OperatorGraph != null) { algorithmOperatorGraph = algorithm.OperatorGraph; RegisterOperatorGraphEvents(); } } private void RegisterOperatorGraphEvents() { algorithmOperatorGraph.InitialOperatorChanged += algorithmOperatorGraph_InitialOperatorChanged; algorithmOperatorGraph.Operators.CollectionReset += algorithmOperatorGraph_Operators_Changed; algorithmOperatorGraph.Operators.ItemsAdded += algorithmOperatorGraph_Operators_Changed; algorithmOperatorGraph.Operators.ItemsRemoved += algorithmOperatorGraph_Operators_Changed; } private void DeregisterOperatorGraphEvents() { algorithmOperatorGraph.InitialOperatorChanged -= algorithmOperatorGraph_InitialOperatorChanged; algorithmOperatorGraph.Operators.CollectionReset -= algorithmOperatorGraph_Operators_Changed; algorithmOperatorGraph.Operators.ItemsAdded -= algorithmOperatorGraph_Operators_Changed; algorithmOperatorGraph.Operators.ItemsRemoved -= algorithmOperatorGraph_Operators_Changed; } void algorithmOperatorGraph_Operators_Changed(object sender, CollectionItemsChangedEventArgs e) { OperatorGraph.Operators.Clear(); foreach (IOperator op in algorithmOperatorGraph.Operators) { OperatorGraph.Operators.Add(op); } } void algorithmOperatorGraph_InitialOperatorChanged(object sender, EventArgs e) { OperatorGraph.InitialOperator = algorithmOperatorGraph.InitialOperator; } private void UpdateParameters() { // TODO: match previously set parameter values IOperator successor = Successor; Parameters.Clear(); Parameters.Add(new OperatorParameter("Successor", successor)); var alg = Algorithm as IParameterizedItem; foreach (var param in alg.Parameters) { Parameters.Add(WrapParameter(param)); } if (Algorithm.Problem != null) { foreach (var param in Algorithm.Problem.Parameters) { Parameters.Add(WrapParameter(param)); } } Parameters.Add(new ValueLookupParameter>("Results", "Results collection as passed through to the inner algorithn", "Results", false)); } private static IValueLookupParameter WrapParameter(IParameter param) { IValueLookupParameter v = (IValueLookupParameter)Activator.CreateInstance(typeof(ValueLookupParameter<>).MakeGenericType(param.DataType), new object[] { param.Name, param.Description }); v.ActualName = param.Name; IValueParameter valueParam = param as IValueParameter; if (valueParam != null) v.Value = valueParam.Value; return v; } #endregion #region Construction & Cloning [StorableConstructor] protected EngineAlgorithmOperator(bool deserializing) : base(deserializing) { } protected EngineAlgorithmOperator(EngineAlgorithmOperator original, Cloner cloner) : base(original, cloner) { this.algorithm = cloner.Clone(original.algorithm); this.algorithmOperatorGraph = cloner.Clone(original.algorithmOperatorGraph); } public EngineAlgorithmOperator() { } public override IDeepCloneable Clone(Cloner cloner) { return new EngineAlgorithmOperator(this, cloner); } #endregion public override IOperation Apply() { var alg = Algorithm as IParameterizedItem; foreach (var param in alg.Parameters) { param.ActualValue = Parameters[param.Name].ActualValue; } if (Algorithm.Problem != null) { foreach (var param in Algorithm.Problem.Parameters) { param.ActualValue = Parameters[param.Name].ActualValue; } } return base.Apply(); } } }