#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 HeuristicLab.Core;
using HeuristicLab.Data;
using System;
using HeuristicLab.Common;
using System.Linq;
using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
using HeuristicLab.Problems.DataAnalysis.Symbolic;
using System.Collections.Generic;
using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
using HeuristicLab.Problems.DataAnalysis.Regression.Symbolic;
using HeuristicLab.Problems.DataAnalysis.MultiVariate.Regression.Symbolic.Interfaces;
using HeuristicLab.Parameters;
namespace HeuristicLab.Problems.DataAnalysis.MultiVariate.Regression.Symbolic.Evaluators {
[Item("PartialDerivativeEvaluator", "Evaluator for implict equation modelling")]
[StorableClass]
public class PartialDerivativeEvaluator : SingleObjectiveSymbolicVectorRegressionEvaluator {
public PartialDerivativeEvaluator(bool deserializing) : base(deserializing) { }
public PartialDerivativeEvaluator()
: base() {
}
public override double Evaluate(SymbolicExpressionTree tree, ISymbolicExpressionTreeInterpreter interpreter, MultiVariateDataAnalysisProblemData problemData, IEnumerable targetVariables, IEnumerable rows, DoubleArray lowerEstimationBound, DoubleArray upperEstimationBound) {
Dataset dataset = problemData.Dataset;
IEnumerable estimatedValues = interpreter.GetSymbolicExpressionTreeValues(tree, dataset, rows);
var sortedNames = targetVariables.OrderBy(x => x);
var pairs = from v1 in sortedNames
from v2 in sortedNames.Skip(1)
where v1.CompareTo(v2) < 0
select new { x = v1, y = v2 };
double meanErrorSum = 0;
foreach (var pair in pairs) {
double errorSum = 0;
string variableX = pair.x;
string variableY = pair.y;
var dFdX = new SymbolicExpressionTree(PartialSymbolicDifferential.Apply((SymbolicExpressionTreeNode)tree.Root.Clone(), variableX, variableY));
IEnumerable estimatedDfDx = interpreter.GetSymbolicExpressionTreeValues(dFdX, dataset, rows).ToList();
var dFdY = new SymbolicExpressionTree(PartialSymbolicDifferential.Apply((SymbolicExpressionTreeNode)tree.Root.Clone(), variableY, variableX));
IEnumerable estimatedDfDy = interpreter.GetSymbolicExpressionTreeValues(dFdY, dataset, rows).ToList();
List rowsList = rows.ToList();
int n = rowsList.Count;
int x = dataset.GetVariableIndex(variableX);
int y = dataset.GetVariableIndex(variableY);
var estimatedDfDxEnumerator = estimatedDfDx.GetEnumerator();
var estimatedDfDyEnumerator = estimatedDfDy.GetEnumerator();
var rowsEnumerator = rows.GetEnumerator();
// skip 1
estimatedDfDxEnumerator.MoveNext();
estimatedDfDyEnumerator.MoveNext();
rowsEnumerator.MoveNext();
for (int i = 1; i < n - 1; i++) {
// evaluate next
estimatedDfDxEnumerator.MoveNext();
estimatedDfDyEnumerator.MoveNext();
rowsEnumerator.MoveNext();
double dFdXValue = estimatedDfDxEnumerator.Current;
double dFdYValue = estimatedDfDyEnumerator.Current;
double dXdY = GetLocalDifferential(dataset, rowsEnumerator.Current, x, y);
if ((dFdXValue.IsAlmost(0.0) && dFdYValue.IsAlmost(0.0))) {
errorSum += Math.Log(1 + Math.Abs(dXdY));
} else if (dFdXValue.IsAlmost(0.0) ||
double.IsInfinity(dFdXValue) || double.IsNaN(dFdXValue) ||
double.IsInfinity(dFdYValue) || double.IsNaN(dFdYValue)) {
errorSum += 1000000;
} else {
double error = dXdY - dFdYValue / dFdXValue;
errorSum += Math.Log(1 + Math.Abs(error));
// errorSum += error * error;
}
}
meanErrorSum += errorSum / n;
}
meanErrorSum /= pairs.Count();
return meanErrorSum;
}
private double GetLocalDifferential(Dataset dataset, int i, int varX, int varY) {
return
(dataset[i + 1, varX] - dataset[i - 1, varX]) /
(dataset[i + 1, varY] - dataset[i - 1, varY]);
}
}
}