using HEAL.Attic; using HeuristicLab.Collections; using HeuristicLab.Common; using HeuristicLab.Core; using HeuristicLab.Data; using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding; using HeuristicLab.Operators; using HeuristicLab.Optimization; using HeuristicLab.Parameters; using HeuristicLab.Problems.DataAnalysis; using HeuristicLab.Problems.DataAnalysis.Symbolic; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace HeuristicLab.Algorithms.OESRALPS.Analyzers { [Item("SymbolicDataAnalysisSingleObjectiveTrainingBestSolutionSlidingWindowAnalyzer", "An operator that analyzes the training best symbolic data analysis solution for single objective symbolic data analysis problems.")] [StorableType("DD82C026-CF68-40D7-A898-77EA61272DE9")] public abstract class SymbolicDataAnalysisSingleObjectiveTrainingBestSolutionSlidingWindowAnalyzer : SymbolicDataAnalysisSingleObjectiveAnalyzer, IIterationBasedOperator where S : class, ISymbolicDataAnalysisSolution where T : class, ISymbolicDataAnalysisSingleObjectiveEvaluator where U : class, IDataAnalysisProblemData { private const string TrainingBestSolutionParameterName = "Best training solution"; private const string TrainingBestSolutionQualityParameterName = "Best training solution quality"; private const string TrainingBestSolutionGenerationParameterName = "Best training solution generation"; private const string TrainingBestSolutionsHistoryParameterName = "Best training solutions history"; private const string UpdateAlwaysParameterName = "Always update best solution"; private const string IterationsParameterName = "Generations"; private const string MaximumIterationsParameterName = "Maximum Iterations"; private const string StoreHistoryParameterName = "Store History"; private const string TrainingPartitionParameterName = "TrainingPartition"; private const string RandomParameterName = "GlobalRandom"; private const string ProblemDataParameterName = "ProblemData"; private const string EvaluatorParameterName = "Evaluator"; private const string SymbolicDataAnalysisTreeInterpreterParameterName = "SymbolicExpressionTreeInterpreter"; private bool isTrainingEventInitialized = false; private bool reevaluateTrainingResult = false; #region parameter properties public ILookupParameter TrainingBestSolutionParameter { get { return (ILookupParameter)Parameters[TrainingBestSolutionParameterName]; } } public ILookupParameter TrainingBestSolutionQualityParameter { get { return (ILookupParameter)Parameters[TrainingBestSolutionQualityParameterName]; } } public ILookupParameter TrainingBestSolutionGenerationParameter { get { return (ILookupParameter)Parameters[TrainingBestSolutionGenerationParameterName]; } } public ILookupParameter> TrainingBestSolutionsHistoryParameter { get { return (ILookupParameter>)Parameters[TrainingBestSolutionsHistoryParameterName]; } } public IFixedValueParameter UpdateAlwaysParameter { get { return (IFixedValueParameter)Parameters[UpdateAlwaysParameterName]; } } public ILookupParameter IterationsParameter { get { return (ILookupParameter)Parameters[IterationsParameterName]; } } public IValueLookupParameter MaximumIterationsParameter { get { return (IValueLookupParameter)Parameters[MaximumIterationsParameterName]; } } public IFixedValueParameter StoreHistoryParameter { get { return (IFixedValueParameter)Parameters[StoreHistoryParameterName]; } } public IValueLookupParameter TrainingPartitionParameter { get { return (IValueLookupParameter)Parameters[TrainingPartitionParameterName]; } } public ILookupParameter RandomParameter { get { return (ILookupParameter)Parameters[RandomParameterName]; } } public ILookupParameter ProblemDataParameter { get { return (ILookupParameter)Parameters[ProblemDataParameterName]; } } public ILookupParameter EvaluatorParameter { get { return (ILookupParameter)Parameters[EvaluatorParameterName]; } } public ILookupParameter SymbolicDataAnalysisTreeInterpreterParameter { get { return (ILookupParameter)Parameters[SymbolicDataAnalysisTreeInterpreterParameterName]; } } #endregion #region properties public S TrainingBestSolution { get { return TrainingBestSolutionParameter.ActualValue; } set { TrainingBestSolutionParameter.ActualValue = value; } } public DoubleValue TrainingBestSolutionQuality { get { return TrainingBestSolutionQualityParameter.ActualValue; } set { TrainingBestSolutionQualityParameter.ActualValue = value; } } public bool UpdateAlways { get { return UpdateAlwaysParameter.Value.Value; } set { UpdateAlwaysParameter.Value.Value = value; } } public bool StoreHistory { get { return StoreHistoryParameter.Value.Value; } set { StoreHistoryParameter.Value.Value = value; } } #endregion [StorableConstructor] protected SymbolicDataAnalysisSingleObjectiveTrainingBestSolutionSlidingWindowAnalyzer(StorableConstructorFlag _) : base(_) { } protected SymbolicDataAnalysisSingleObjectiveTrainingBestSolutionSlidingWindowAnalyzer(SymbolicDataAnalysisSingleObjectiveTrainingBestSolutionSlidingWindowAnalyzer original, Cloner cloner) : base(original, cloner) { } public SymbolicDataAnalysisSingleObjectiveTrainingBestSolutionSlidingWindowAnalyzer() : base() { Parameters.Add(new LookupParameter(RandomParameterName, "The random generator.")); Parameters.Add(new LookupParameter(ProblemDataParameterName, "The problem data of the symbolic data analysis problem.")); Parameters.Add(new LookupParameter(EvaluatorParameterName, "The operator to use for fitness evaluation on the validation partition.")); Parameters.Add(new LookupParameter(SymbolicDataAnalysisTreeInterpreterParameterName, "The interpreter for symbolic data analysis expression trees.")); Parameters.Add(new LookupParameter(TrainingBestSolutionParameterName, "The best training symbolic data analyis solution.")); Parameters.Add(new LookupParameter(TrainingBestSolutionQualityParameterName, "The quality of the training best symbolic data analysis solution.")); Parameters.Add(new LookupParameter(TrainingBestSolutionGenerationParameterName, "The generation in which the best training solution was found.")); Parameters.Add(new FixedValueParameter(UpdateAlwaysParameterName, "Determines if the best training solution should always be updated regardless of its quality.", new BoolValue(true))); Parameters.Add(new LookupParameter(IterationsParameterName, "The number of performed iterations.")); Parameters.Add(new ValueLookupParameter(MaximumIterationsParameterName, "The maximum number of performed iterations.") { Hidden = true }); Parameters.Add(new FixedValueParameter(StoreHistoryParameterName, "Flag that determines whether all encountered best solutions should be stored as results.", new BoolValue(false))); Parameters.Add(new LookupParameter>(TrainingBestSolutionsHistoryParameterName, "The history of the best training symbolic data analysis solutions.")); Parameters.Add(new ValueLookupParameter(TrainingPartitionParameterName, "The current training sliding window position or range.")); UpdateAlwaysParameter.Hidden = true; } public override IOperation Apply() { var results = ResultCollection; #region create results if (!results.ContainsKey(TrainingBestSolutionParameter.Name)) results.Add(new Result(TrainingBestSolutionParameter.Name, TrainingBestSolutionParameter.Description, typeof(S))); if (!results.ContainsKey(TrainingBestSolutionQualityParameter.Name)) results.Add(new Result(TrainingBestSolutionQualityParameter.Name, TrainingBestSolutionQualityParameter.Description, typeof(DoubleValue))); if (!results.ContainsKey(TrainingBestSolutionGenerationParameter.Name) && IterationsParameter.ActualValue != null) results.Add(new Result(TrainingBestSolutionGenerationParameter.Name, TrainingBestSolutionGenerationParameter.Description, typeof(IntValue))); if (StoreHistory && !results.ContainsKey(TrainingBestSolutionsHistoryParameter.Name)) { results.Add(new Result(TrainingBestSolutionsHistoryParameter.Name, TrainingBestSolutionsHistoryParameter.Description, typeof(ItemList))); TrainingBestSolutionsHistoryParameter.ActualValue = new ItemList(); results[TrainingBestSolutionsHistoryParameter.Name].Value = TrainingBestSolutionsHistoryParameter.ActualValue; } #endregion if (TrainingPartitionParameter.ActualValue != null && !isTrainingEventInitialized) { TrainingPartitionParameter.ActualValue.ValueChanged += TrainingPartition_ValueChanged; isTrainingEventInitialized = true; } #region find best tree double bestQuality = Maximization.Value ? double.NegativeInfinity : double.PositiveInfinity; ISymbolicExpressionTree bestTree = null; ISymbolicExpressionTree[] tree = SymbolicExpressionTree.ToArray(); double[] quality = Quality.Select(x => x.Value).ToArray(); for (int i = 0; i < tree.Length; i++) { if (IsBetter(quality[i], bestQuality, Maximization.Value)) { bestQuality = quality[i]; bestTree = tree[i]; } } #endregion if (TrainingPartitionParameter.ActualValue != null && (UpdateAlways || (reevaluateTrainingResult && TrainingBestSolutionQuality != null && TrainingPartitionParameter.ActualValue != null))) { var evaluator = EvaluatorParameter.ActualValue; var problemData = ProblemDataParameter.ActualValue; IExecutionContext childContext = (IExecutionContext)ExecutionContext.CreateChildOperation(evaluator); var currentValidationBestSolution = (S)results[TrainingBestSolutionParameterName].Value; TrainingBestSolutionQuality.Value = evaluator.Evaluate( childContext, currentValidationBestSolution.Model.SymbolicExpressionTree, problemData, Enumerable.Range( TrainingPartitionParameter.ActualValue.Start, TrainingPartitionParameter.ActualValue.End - TrainingPartitionParameter.ActualValue.Start )); results[TrainingBestSolutionQualityParameter.Name].Value = TrainingBestSolutionQuality; results[TrainingBestSolutionGenerationParameter.Name].Value = IterationsParameter.ActualValue; reevaluateTrainingResult = false; } if (bestTree != null && (UpdateAlways || TrainingBestSolutionQuality == null || IsBetter(bestQuality, TrainingBestSolutionQuality.Value, Maximization.Value))) { TrainingBestSolution = CreateSolution(bestTree, bestQuality); TrainingBestSolutionQuality = new DoubleValue(bestQuality); if (IterationsParameter.ActualValue != null) TrainingBestSolutionGenerationParameter.ActualValue = new IntValue(IterationsParameter.ActualValue.Value); results[TrainingBestSolutionParameter.Name].Value = TrainingBestSolution; results[TrainingBestSolutionQualityParameter.Name].Value = TrainingBestSolutionQuality; if (TrainingBestSolutionGenerationParameter.ActualValue != null) results[TrainingBestSolutionGenerationParameter.Name].Value = TrainingBestSolutionGenerationParameter.ActualValue; if (StoreHistory) { TrainingBestSolutionsHistoryParameter.ActualValue.Add(TrainingBestSolution); } } UniformSubScopesProcessor subScopesProcessor = new UniformSubScopesProcessor(); subScopesProcessor.Operator = EvaluatorParameter.ActualValue; subScopesProcessor.Depth.Value = 1; var operation = ExecutionContext.CreateChildOperation(subScopesProcessor); var successor = base.Apply(); return new OperationCollection() { operation, successor }; } private void TrainingPartition_ValueChanged(object sender, EventArgs e) { reevaluateTrainingResult = true; } protected abstract S CreateSolution(ISymbolicExpressionTree bestTree, double bestQuality); private bool IsBetter(double lhs, double rhs, bool maximization) { if (maximization) return lhs > rhs; else return lhs < rhs; } } }