#region License Information /* HeuristicLab * Copyright (C) 2002-2019 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, ISymbolicExpressionTreeAnalyzer { private const string ConstraintViolationsResultName = "Constraint Violations"; private const string ProblemDataParameterName = "ProblemData"; #region parameter properties public ILookupParameter RegressionProblemDataParameter { get { return (ILookupParameter) Parameters[ProblemDataParameterName]; } } #endregion public override bool EnabledByDefault => 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() : base(){ Parameters.Add(new LookupParameter(ProblemDataParameterName, "The problem data of the symbolic data analysis problem.")); } [StorableHook(HookType.AfterDeserialization)] private void AfterDeserialization() { } public override IOperation Apply() { var problemData = RegressionProblemDataParameter.ActualValue; var trees = SymbolicExpressionTreeParameter.ActualValue; var results = ResultCollectionParameter.ActualValue; var constraints = problemData.IntervalConstraints.Constraints.Where(x => x.Enabled); var variableRanges = problemData.VariableRanges.VariableIntervals; if (!results.ContainsKey(ConstraintViolationsResultName)) { var newDataTable = new DataTable(ConstraintViolationsResultName); foreach (var constraint in constraints) { newDataTable.Rows.Add(new DataRow(constraint.Expression)); } results.Add(new Result(ConstraintViolationsResultName, "Chart displaying the constraint violations.", newDataTable)); } var dataTable = (DataTable)results[ConstraintViolationsResultName].Value; var interpreter = new IntervalInterpreter(); foreach (var constraint in constraints) { int violations = 0; foreach (var tree in trees) { var satisfied = SymbolicRegressionConstraintAnalyzer.ConstraintSatisfied(constraint, interpreter, variableRanges, tree); if (!satisfied) violations++; } dataTable.Rows[constraint.Expression].Values.Add(violations); } return base.Apply(); } public static bool ConstraintSatisfied(IntervalConstraint constraint, IntervalInterpreter intervalInterpreter, IDictionary variableRanges, ISymbolicExpressionTree solution) { if (constraint.Variable != null && !variableRanges.ContainsKey(constraint.Variable)) throw new ArgumentException($"The given variable {constraint.Variable} in the constraint does not exists in the model.", nameof(IntervalConstraintsParser)); Interval resultInterval; if (!constraint.IsDerivation) { resultInterval = intervalInterpreter.GetSymbolicExpressionTreeInterval(solution, variableRanges); } else { var tree = solution; for (var i = 0; i < constraint.NumberOfDerivation; ++i) { tree = DerivativeCalculator.Derive(tree, constraint.Variable); } resultInterval = intervalInterpreter.GetSymbolicExpressionTreeInterval(tree, variableRanges); } var satisfied = constraint.Interval.Contains(resultInterval, constraint.InclusiveLowerBound, constraint.InclusiveUpperBound); return satisfied; } public static bool ConstraintsSatisfied(IEnumerable constraints, IDictionary variableRanges, ISymbolicExpressionTree solution) { var intervalInterpreter = new IntervalInterpreter(); foreach (var constraint in constraints) { if (constraint.Variable != null && !variableRanges.ContainsKey(constraint.Variable)) throw new ArgumentException($"The given variable {constraint.Variable} in the constraint does not exists in the model.", nameof(IntervalConstraintsParser)); var satisfied = ConstraintSatisfied(constraint, intervalInterpreter, variableRanges, solution); if (!satisfied) return false; } return true; } } }