#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.Generic;
using System.Linq;
using HEAL.Attic;
using HeuristicLab.Analysis;
using HeuristicLab.Common;
using HeuristicLab.Core;
using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
using HeuristicLab.Optimization;
using HeuristicLab.Parameters;
namespace HeuristicLab.Problems.DataAnalysis.Symbolic.Regression {
[StorableType("4318C6BD-E0A1-45FE-AC30-96E7F73B51FB")]
public class SymbolicRegressionConstraintAnalyzer : SymbolicDataAnalysisAnalyzer, ISymbolicDataAnalysisInterpreterOperator, ISymbolicExpressionTreeAnalyzer {
private const string ConstraintViolationsResultName = "Constraint Violations";
private const string ProblemDataParameterName = "ProblemData";
private const string SymbolicDataAnalysisTreeInterpreterParameterName = "SymbolicDataAnalysisTreeInterpreter";
#region parameter properties
public ILookupParameter RegressionProblemDataParameter {
get { return (ILookupParameter)Parameters[ProblemDataParameterName]; }
}
public ILookupParameter SymbolicDataAnalysisTreeInterpreterParameter {
get { return (ILookupParameter)Parameters[SymbolicDataAnalysisTreeInterpreterParameterName]; }
}
#endregion
#region properties
public RegressionProblemData RegressionProblemData {
get { return RegressionProblemDataParameter.ActualValue; }
}
public ISymbolicDataAnalysisExpressionTreeInterpreter Interpreter {
get { return SymbolicDataAnalysisTreeInterpreterParameter.ActualValue; }
}
#endregion
public virtual bool EnabledByDefault {
get { return false; }
}
[StorableConstructor]
protected SymbolicRegressionConstraintAnalyzer(StorableConstructorFlag _) : base(_) {
}
protected SymbolicRegressionConstraintAnalyzer(SymbolicRegressionConstraintAnalyzer original, Cloner cloner)
: base(original, cloner) {
}
public override IDeepCloneable Clone(Cloner cloner) {
return new SymbolicRegressionConstraintAnalyzer(this, cloner);
}
public SymbolicRegressionConstraintAnalyzer() {
Parameters.Add(new LookupParameter(ProblemDataParameterName, "The problem data of the symbolic data analysis problem."));
Parameters.Add(new LookupParameter(SymbolicDataAnalysisTreeInterpreterParameterName, "The interpreter for symbolic data analysis expression trees."));
}
[StorableHook(HookType.AfterDeserialization)]
private void AfterDeserialization() {
}
static Dictionary CheckConstraints(ISymbolicExpressionTree model,
IRegressionProblemData problemData) {
var constraints = IntervalConstraintsParser.Parse(((RegressionProblemData)problemData).IntervalConstraints.Value);
var constraintViolations = new Dictionary();
var variableRanges = ((RegressionProblemData)problemData).VariableRanges.VariableIntervals;
foreach (var constraint in constraints) {
if (!constraintViolations.ContainsKey(constraint)) {
constraintViolations.Add(constraint, CheckConstraint(model, variableRanges, constraint));
}
}
return constraintViolations;
}
static Dictionary CheckConstraints(ISymbolicRegressionModel model,
IRegressionProblemData problemData) {
return CheckConstraints(model.SymbolicExpressionTree, problemData);
}
static bool CheckConstraint(ISymbolicExpressionTree model, Dictionary variableRanges,
IntervalConstraint constraint) {
var intervalInterpreter = new IntervalInterpreter();
if (constraint.Variable != null) {
if (!constraint.IsDerivation) {
var res = intervalInterpreter.GetSymbolicExpressionTreeInterval(model,
variableRanges);
if (!constraint.Interval.Contains(res, constraint.InclusiveLowerBound,
constraint.InclusiveUpperBound)) {
return false;
}
} else {
var dTree = model;
for (var i = 0; i < constraint.NumberOfDerivation; ++i) {
dTree = DerivativeCalculator.Derive(dTree, constraint.Variable);
}
var res = intervalInterpreter.GetSymbolicExpressionTreeInterval(dTree,
variableRanges);
if (!constraint.Interval.Contains(res, constraint.InclusiveLowerBound,
constraint.InclusiveUpperBound)) {
return false;
}
}
}
return true;
}
static bool CheckConstraint(ISymbolicRegressionModel model, Dictionary variableRanges, IntervalConstraint constraint) {
return CheckConstraint(model.SymbolicExpressionTree, variableRanges, constraint);
}
public override IOperation Apply() {
var results = ResultCollectionParameter.ActualValue;
if (!results.ContainsKey(ConstraintViolationsResultName)) {
var newDataTable = new DataTable(ConstraintViolationsResultName);
results.Add(new Result(ConstraintViolationsResultName, "Chart displaying the constraint violations.",
newDataTable));
}
var dataTable = (DataTable)results[ConstraintViolationsResultName].Value;
var problemData = RegressionProblemData;
var constraintViolations = new Dictionary();
var constraints = IntervalConstraintsParser.Parse(problemData.IntervalConstraints.Value);
if (dataTable.Rows.Count == 0) {
foreach (var constraint in constraints) {
if (!dataTable.Rows.ContainsKey(constraint.Expression)) {
dataTable.Rows.Add(new DataRow(constraint.Expression));
}
}
}
foreach (var constraint in constraints) {
constraintViolations.Add(constraint.Expression, 0);
}
foreach (var tree in this.SymbolicExpressionTree) {
var checkedConstraints = CheckConstraints(tree, problemData);
foreach (var kvp in checkedConstraints) {
if (!kvp.Value)
constraintViolations[kvp.Key.Expression]++;
}
}
foreach (var kvp in constraintViolations) {
dataTable.Rows[kvp.Key].Values.Add(kvp.Value);
}
return base.Apply();
}
}
}