#region License Information /* HeuristicLab * Copyright (C) 2002-2018 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 System.Collections; using System.Collections.Generic; using System.Linq; using HeuristicLab.Common; using HeuristicLab.Core; using HeuristicLab.Data; using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding; using HeuristicLab.EvolutionTracking; using HeuristicLab.Parameters; using HeuristicLab.Persistence.Default.CompositeSerializers.Storable; namespace HeuristicLab.Problems.DataAnalysis.Symbolic { [Item("UpdateQualityOperator", "Put the estimated values of the tree in the scope to be used by the phenotypic similarity calculator")] [StorableClass] public class UpdateQualityOperator : EvolutionTrackingOperator { private const string ProblemDataParameterName = "ProblemData"; private const string InterpreterParameterName = "SymbolicExpressionTreeInterpreter"; private const string EstimationLimitsParameterName = "EstimationLimits"; private const string SymbolicExpressionTreeParameterName = "SymbolicExpressionTree"; private const string ScaleEstimatedValuesParameterName = "ScaleEstimatedValues"; #region parameters public ILookupParameter ProblemDataParameter { get { return (ILookupParameter)Parameters[ProblemDataParameterName]; } } public ILookupParameter InterpreterParameter { get { return (ILookupParameter)Parameters[InterpreterParameterName]; } } public ILookupParameter EstimationLimitsParameter { get { return (ILookupParameter)Parameters[EstimationLimitsParameterName]; } } public ILookupParameter SymbolicExpressionTreeParameter { get { return (ILookupParameter)Parameters[SymbolicExpressionTreeParameterName]; } } public ILookupParameter ScaleEstimatedValuesParameter { get { return (ILookupParameter)Parameters[ScaleEstimatedValuesParameterName]; } } #endregion public UpdateQualityOperator() { Parameters.Add(new LookupParameter(ProblemDataParameterName)); Parameters.Add(new LookupParameter(InterpreterParameterName)); Parameters.Add(new LookupParameter(EstimationLimitsParameterName)); Parameters.Add(new LookupParameter(SymbolicExpressionTreeParameterName)); Parameters.Add(new LookupParameter(ScaleEstimatedValuesParameterName)); } [StorableConstructor] protected UpdateQualityOperator(bool deserializing) : base(deserializing) { } protected UpdateQualityOperator(UpdateQualityOperator original, Cloner cloner) : base(original, cloner) { } public override IDeepCloneable Clone(Cloner cloner) { return new UpdateQualityOperator(this, cloner); } public override IOperation Apply() { var tree = SymbolicExpressionTreeParameter.ActualValue; var problemData = ProblemDataParameter.ActualValue; var estimationLimits = EstimationLimitsParameter.ActualValue; var interpreter = InterpreterParameter.ActualValue; var estimatedValues = interpreter.GetSymbolicExpressionTreeValues(tree, problemData.Dataset, problemData.TrainingIndices); var targetValues = problemData.Dataset.GetDoubleValues(problemData.TargetVariable, problemData.TrainingIndices); var scaleEstimatedValues = ScaleEstimatedValuesParameter.ActualValue.Value; IEnumerable scaled; if (scaleEstimatedValues) { var linearScalingCalculator = new OnlineLinearScalingParameterCalculator(); var e1 = estimatedValues.GetEnumerator(); var e2 = targetValues.GetEnumerator(); int count = 0; while (e1.MoveNext() && e2.MoveNext()) { var estimated = e1.Current; var target = e2.Current; if (!double.IsNaN(estimated) && !double.IsInfinity(estimated)) linearScalingCalculator.Add(estimated, target); ++count; } if (e1.MoveNext() || e2.MoveNext()) throw new ArgumentException("Number of elements in target and estimated values enumeration do not match."); double alpha = linearScalingCalculator.Alpha; double beta = linearScalingCalculator.Beta; if (linearScalingCalculator.ErrorState != OnlineCalculatorError.None) { alpha = 0.0; beta = 1.0; } scaled = estimatedValues.Select(x => x * beta + alpha).LimitToRange(estimationLimits.Lower, estimationLimits.Upper); } else { scaled = estimatedValues.LimitToRange(estimationLimits.Lower, estimationLimits.Upper); } OnlineCalculatorError error; var r = OnlinePearsonsRCalculator.Calculate(targetValues, scaled, out error); if (error != OnlineCalculatorError.None) r = double.NaN; var r2 = r * r; var variables = ExecutionContext.Scope.Variables; ((DoubleValue)variables["Quality"].Value).Value = r2; //GenealogyGraph.GetByContent(tree).Quality = r2; if (variables.ContainsKey("EstimatedValues")) { variables["EstimatedValues"].Value = new DoubleArray(scaled.ToArray()); } else { variables.Add(new Core.Variable("EstimatedValues", new DoubleArray(scaled.ToArray()))); } return base.Apply(); } } }