#region License Information
/* HeuristicLab
* Copyright (C) 2002-2008 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.Diagnostics;
using HeuristicLab.Common;
using HeuristicLab.DataAnalysis;
using HeuristicLab.GP.Interfaces;
using System.Collections.Generic; // double.IsAlmost extension
using System.Linq;
using System.Xml;
namespace HeuristicLab.GP.StructureIdentification {
///
/// Evaluates FunctionTrees recursively by interpretation of the function symbols in each node.
/// Scales the output of the function-tree to the desired output range of the target variable by linear transformation
/// Not thread-safe!
///
public class ScalingTreeEvaluator : HL3TreeEvaluator, ITreeEvaluator {
public ScalingTreeEvaluator() : base() { } // for persistence
public ScalingTreeEvaluator(double minValue, double maxValue)
: base(minValue, maxValue) {
}
private string targetVariable;
public string TargetVariable {
get { return targetVariable; }
set { targetVariable = value; }
}
public override double Evaluate(int sampleIndex) {
PC = 0;
this.sampleIndex = sampleIndex;
double estimation = EvaluateBakedCode();
//if (double.IsPositiveInfinity(estimation)) estimation = UpperEvaluationLimit;
//else if (double.IsNegativeInfinity(estimation)) estimation = LowerEvaluationLimit;
//else if (double.IsNaN(estimation)) estimation = UpperEvaluationLimit;
return estimation;
}
public override IEnumerable Evaluate(Dataset dataset, IFunctionTree tree, IEnumerable rows) {
int targetVariableIndex = dataset.GetVariableIndex(targetVariable);
// evaluate for all rows
PrepareForEvaluation(dataset, tree);
var result = (from row in rows
let y = Evaluate(row)
let y_ = dataset.GetValue(row, targetVariableIndex)
select new { Row = row, Estimation = y, Target = y_ }).ToArray();
// calculate alpha and beta on the subset of rows with valid values
var filteredResult = result.Where(x => IsValidValue(x.Target) && IsValidValue(x.Estimation));
var target = filteredResult.Select(x => x.Target);
var estimation = filteredResult.Select(x => x.Estimation);
double a, b;
if (filteredResult.Count() > 2) {
double tMean = target.Sum() / target.Count();
double xMean = estimation.Sum() / estimation.Count();
double sumXT = 0;
double sumXX = 0;
foreach (var r in result) {
double x = r.Estimation;
double t = r.Target;
sumXT += (x - xMean) * (t - tMean);
sumXX += (x - xMean) * (x - xMean);
}
b = sumXT / sumXX;
a = tMean - b * xMean;
} else {
b = 1.0;
a = 0.0;
}
// return scaled results
return from r in result
let scaledR = Math.Min(Math.Max(r.Estimation * b + a, LowerEvaluationLimit), UpperEvaluationLimit)
select double.IsNaN(scaledR) ? UpperEvaluationLimit : scaledR;
}
private bool IsValidValue(double d) {
return !double.IsInfinity(d) && !double.IsNaN(d);
}
public override object Clone(IDictionary clonedObjects) {
ScalingTreeEvaluator clone = (ScalingTreeEvaluator)base.Clone(clonedObjects);
clone.targetVariable = targetVariable;
return clone;
}
public override System.Xml.XmlNode GetXmlNode(string name, System.Xml.XmlDocument document, IDictionary persistedObjects) {
XmlNode node = base.GetXmlNode(name, document, persistedObjects);
XmlAttribute targetVariableAttribute = document.CreateAttribute("TargetVariable");
targetVariableAttribute.Value = targetVariable;
node.Attributes.Append(targetVariableAttribute);
return node;
}
public override void Populate(XmlNode node, IDictionary restoredObjects) {
base.Populate(node, restoredObjects);
targetVariable = node.Attributes["TargetVariable"].Value;
}
}
}