using System; using System.Collections.Generic; using HEAL.Attic; using HeuristicLab.Common; using HeuristicLab.Core; using HeuristicLab.Data; using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding; using HeuristicLab.Parameters; namespace HeuristicLab.Problems.DataAnalysis.Symbolic.Regression.SingleObjective.Evaluators { [Item("Constraint ConstOpt NMSE Evaluator", "")] [StorableType("DED36D85-A4BA-4019-B12D-C523F7327899")] public class SymbolicRegressionSingleObjectiveConstraintConstOptNmseEvaluator : SymbolicRegressionSingleObjectiveEvaluator { private const string UseConstOptParameterName = "Use ConstOpt"; private const string ConstOptIterationsParameterName = "ConstOpt Iterations"; private const string PenalityMultiplierParameterName = "ConstraintsPenalityMultiplier"; public IFixedValueParameter UseConstOptParamerter => (IFixedValueParameter) Parameters[UseConstOptParameterName]; public IFixedValueParameter ConstOpterIterationsParameter => (IFixedValueParameter) Parameters[ConstOptIterationsParameterName]; public ILookupParameter PenalityMultiplierParameter => (ILookupParameter)Parameters[PenalityMultiplierParameterName]; public bool UseConstOpt { get => UseConstOptParamerter.Value.Value; set => UseConstOptParamerter.Value.Value = value; } public int ConstOptIterations { get => ConstOpterIterationsParameter.Value.Value; set => ConstOpterIterationsParameter.Value.Value = value; } [StorableConstructor] protected SymbolicRegressionSingleObjectiveConstraintConstOptNmseEvaluator(StorableConstructorFlag _) : base(_) {} protected SymbolicRegressionSingleObjectiveConstraintConstOptNmseEvaluator( SymbolicRegressionSingleObjectiveConstraintConstOptNmseEvaluator original, Cloner cloner) : base(original, cloner) { } public override IDeepCloneable Clone(Cloner cloner) { return new SymbolicRegressionSingleObjectiveConstraintConstOptNmseEvaluator(this, cloner); } public SymbolicRegressionSingleObjectiveConstraintConstOptNmseEvaluator() { Parameters.Add(new FixedValueParameter(UseConstOptParameterName, "Define whether constOpt is active or not.", new BoolValue(true))); Parameters.Add(new FixedValueParameter(ConstOptIterationsParameterName, "Define how many constOpt iterations should be performed.", new IntValue(10))); Parameters.Add(new LookupParameter(PenalityMultiplierParameterName, "Lookup parameter for the penality multiplier.", "PenalityMultiplier")); } public override bool Maximization => false; [StorableHook(HookType.AfterDeserialization)] private void AfterDeserialization() { if (!Parameters.ContainsKey(UseConstOptParameterName)) { Parameters.Add(new FixedValueParameter(UseConstOptParameterName, "Define whether constOpt is active or not.", new BoolValue(true))); } if (!Parameters.ContainsKey(ConstOptIterationsParameterName)) { Parameters.Add(new FixedValueParameter(ConstOptIterationsParameterName, "Define how many constOpt iterations should be performed.", new IntValue(10))); } if (!Parameters.ContainsKey(PenalityMultiplierParameterName)) Parameters.Add(new LookupParameter(PenalityMultiplierParameterName, "Lookup parameter for the penality multiplier.", "PenalityMultiplier")); } public override IOperation InstrumentedApply() { var rows = GenerateRowsToEvaluate(); var solution = SymbolicExpressionTreeParameter.ActualValue; var problemData = ProblemDataParameter.ActualValue; var interpreter = SymbolicDataAnalysisTreeInterpreterParameter.ActualValue; var estimationLimits = EstimationLimitsParameter.ActualValue; var applyLinearScaling = false; var constantOptimizationIterations = ConstOptIterations; var constantOptimizationUpdateVariableWeights = true; //Use Const Opt if(UseConstOpt) SymbolicRegressionConstantOptimizationEvaluator.OptimizeConstants(interpreter, solution, problemData, rows, applyLinearScaling, constantOptimizationIterations, constantOptimizationUpdateVariableWeights, estimationLimits.Lower, estimationLimits.Upper); var penalityMultiplier = PenalityMultiplierParameter.ActualValue?.Value ?? 1.0; var quality = Calculate(interpreter, solution, estimationLimits.Lower, estimationLimits.Upper, problemData, rows, applyLinearScaling, penalityMultiplier); QualityParameter.ActualValue = new DoubleValue(quality); return base.InstrumentedApply(); } public static double Calculate( ISymbolicDataAnalysisExpressionTreeInterpreter interpreter, ISymbolicExpressionTree solution, double lowerEstimationLimit, double upperEstimationLimit, IRegressionProblemData problemData, IEnumerable rows, bool applyLinearScaling, double penalityMultiplier) { var estimatedValues = interpreter.GetSymbolicExpressionTreeValues(solution, problemData.Dataset, rows); var targetValues = problemData.Dataset.GetDoubleValues(problemData.TargetVariable, rows); var constraints = problemData.IntervalConstraints.EnabledConstraints; var variableRanges = problemData.VariableRanges.GetReadonlyDictionary(); var boundedEstimatedValues = estimatedValues.LimitToRange(lowerEstimationLimit, upperEstimationLimit); var nmse = OnlineNormalizedMeanSquaredErrorCalculator.Calculate(targetValues, boundedEstimatedValues, out var errorState); if (!SymbolicRegressionConstraintAnalyzer.ConstraintsSatisfied(constraints, variableRanges, solution, out double error)) { if (double.IsNaN(error) || double.IsInfinity(error)) nmse += penalityMultiplier * 1.0; else nmse += penalityMultiplier * error; nmse = Math.Min(1.0, nmse); } if (errorState != OnlineCalculatorError.None) nmse = 1.0; return nmse; } public override double Evaluate( IExecutionContext context, ISymbolicExpressionTree tree, IRegressionProblemData problemData, IEnumerable rows) { SymbolicDataAnalysisTreeInterpreterParameter.ExecutionContext = context; EstimationLimitsParameter.ExecutionContext = context; ApplyLinearScalingParameter.ExecutionContext = context; var penalityMultiplier = PenalityMultiplierParameter.ActualValue?.Value ?? 1.0; var nmse = Calculate(SymbolicDataAnalysisTreeInterpreterParameter.ActualValue, tree, EstimationLimitsParameter.ActualValue.Lower, EstimationLimitsParameter.ActualValue.Upper, problemData, rows, ApplyLinearScalingParameter.ActualValue.Value, penalityMultiplier); SymbolicDataAnalysisTreeInterpreterParameter.ExecutionContext = null; EstimationLimitsParameter.ExecutionContext = null; ApplyLinearScalingParameter.ExecutionContext = null; return nmse; } } }