#region License Information /* HeuristicLab * Copyright (C) 2002-2016 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.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"; 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]; } } 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; FixParentLinks(tree); var problemData = ProblemDataParameter.ActualValue; var estimationLimits = EstimationLimitsParameter.ActualValue; var interpreter = InterpreterParameter.ActualValue; var estimatedValues = interpreter.GetSymbolicExpressionTreeValues(tree, problemData.Dataset, problemData.TrainingIndices).ToArray(); var targetValues = problemData.Dataset.GetDoubleValues(problemData.TargetVariable, problemData.TrainingIndices).ToArray(); if (estimatedValues.Length != targetValues.Length) throw new ArgumentException("Number of elements in target and estimated values enumeration do not match."); var linearScalingCalculator = new OnlineLinearScalingParameterCalculator(); for (int i = 0; i < estimatedValues.Length; ++i) { var estimated = estimatedValues[i]; var target = targetValues[i]; if (!double.IsNaN(estimated) && !double.IsInfinity(estimated)) linearScalingCalculator.Add(estimated, target); } double alpha = linearScalingCalculator.Alpha; double beta = linearScalingCalculator.Beta; if (linearScalingCalculator.ErrorState != OnlineCalculatorError.None) { alpha = 0.0; beta = 1.0; } var scaled = estimatedValues.Select(x => x * beta + alpha).LimitToRange(estimationLimits.Lower, estimationLimits.Upper).ToArray(); 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; var scaleEstimatedValues = ScaleEstimatedValuesParameter.ActualValue; if (!scaleEstimatedValues.Value) scaled = estimatedValues.LimitToRange(estimationLimits.Lower, estimationLimits.Upper).ToArray(); if (variables.ContainsKey("EstimatedValues")) { variables["EstimatedValues"].Value = new DoubleArray(scaled); } else { variables.Add(new Core.Variable("EstimatedValues", new DoubleArray(scaled))); } return base.Apply(); } private static void FixParentLinks(ISymbolicExpressionTree tree) { foreach (var node in tree.IterateNodesPrefix().Where(x => x.SubtreeCount > 0)) { foreach (var s in node.Subtrees) { if (s.Parent != node) s.Parent = node; } } } } }