#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(); } } }