public static double Calculate(ISymbolicDataAnalysisExpressionTreeInterpreter interpreter, ISymbolicExpressionTree tree, double lowerEstimationLimit, double upperEstimationLimit, IClassificationProblemData problemData, IEnumerable <int> rows, bool applyLinearScaling,
                                       double definiteResidualsWeight, double positiveClassResidualsWeight, double negativeClassesResidualsWeight)
        {
            IEnumerable <double>  estimatedValues = interpreter.GetSymbolicExpressionTreeValues(tree, problemData.Dataset, rows);
            IEnumerable <double>  targetValues    = problemData.Dataset.GetDoubleValues(problemData.TargetVariable, rows);
            OnlineCalculatorError errorState;

            double positiveClassValue = problemData.GetClassValue(problemData.PositiveClass);
            //get class values min/max
            double classValuesMin = problemData.ClassValues.ElementAtOrDefault(0);
            double classValuesMax = classValuesMin;

            foreach (double classValue in problemData.ClassValues)
            {
                if (classValuesMin > classValue)
                {
                    classValuesMin = classValue;
                }
                if (classValuesMax < classValue)
                {
                    classValuesMax = classValue;
                }
            }

            double quality;

            if (applyLinearScaling)
            {
                var calculator = new OnlineWeightedClassificationMeanSquaredErrorCalculator(positiveClassValue, classValuesMax, classValuesMin,
                                                                                            definiteResidualsWeight, positiveClassResidualsWeight, negativeClassesResidualsWeight);
                CalculateWithScaling(targetValues, estimatedValues, lowerEstimationLimit, upperEstimationLimit, calculator, problemData.Dataset.Rows);
                errorState = calculator.ErrorState;
                quality    = calculator.WeightedResidualsMeanSquaredError;
            }
            else
            {
                IEnumerable <double> boundedEstimatedValues = estimatedValues.LimitToRange(lowerEstimationLimit, upperEstimationLimit);
                quality = OnlineWeightedClassificationMeanSquaredErrorCalculator.Calculate(targetValues, boundedEstimatedValues, positiveClassValue, classValuesMax,
                                                                                           classValuesMin, definiteResidualsWeight, positiveClassResidualsWeight, negativeClassesResidualsWeight, out errorState);
            }
            if (errorState != OnlineCalculatorError.None)
            {
                return(Double.NaN);
            }
            return(quality);
        }
        public static double Calculate(ISymbolicDataAnalysisExpressionTreeInterpreter interpreter, ISymbolicExpressionTree tree, double lowerEstimationLimit, double upperEstimationLimit, IClassificationProblemData problemData,
                                       IEnumerable <int> rows, bool applyLinearScaling, ISymbolicClassificationModelCreator modelCreator, double normalizedMeanSquaredErrorWeightingFactor, double falseNegativeRateWeightingFactor, double falsePositiveRateWeightingFactor)
        {
            var estimatedValues        = interpreter.GetSymbolicExpressionTreeValues(tree, problemData.Dataset, rows);
            var targetClassValues      = problemData.Dataset.GetDoubleValues(problemData.TargetVariable, rows);
            var boundedEstimatedValues = estimatedValues.LimitToRange(lowerEstimationLimit, upperEstimationLimit).ToArray();
            OnlineCalculatorError errorState;
            double nmse;

            //calculate performance measures
            string positiveClassName = problemData.PositiveClass;

            double[]             classValues, thresholds;
            IEnumerable <double> estimatedClassValues = null;
            ISymbolicDiscriminantFunctionClassificationModel m;

            var model = modelCreator.CreateSymbolicClassificationModel(problemData.TargetVariable, tree, interpreter, lowerEstimationLimit, upperEstimationLimit);

            if ((m = model as ISymbolicDiscriminantFunctionClassificationModel) != null)
            {
                m.ThresholdCalculator.Calculate(problemData, boundedEstimatedValues, targetClassValues, out classValues, out thresholds);
                m.SetThresholdsAndClassValues(thresholds, classValues);
                estimatedClassValues = m.GetEstimatedClassValues(boundedEstimatedValues);
            }
            else
            {
                model.RecalculateModelParameters(problemData, rows);
                estimatedClassValues = model.GetEstimatedClassValues(problemData.Dataset, rows);
            }

            var performanceCalculator = new ClassificationPerformanceMeasuresCalculator(positiveClassName, problemData.GetClassValue(positiveClassName));

            performanceCalculator.Calculate(targetClassValues, estimatedClassValues);
            if (performanceCalculator.ErrorState != OnlineCalculatorError.None)
            {
                return(Double.NaN);
            }
            double falseNegativeRate = 1 - performanceCalculator.TruePositiveRate;
            double falsePositiveRate = performanceCalculator.FalsePositiveRate;

            if (applyLinearScaling)
            {
                throw new NotSupportedException("The Weighted Performance Measures Evaluator does not suppport linear scaling!");
            }
            nmse = OnlineNormalizedMeanSquaredErrorCalculator.Calculate(targetClassValues, boundedEstimatedValues, out errorState);
            if (errorState != OnlineCalculatorError.None)
            {
                return(Double.NaN);
            }
            return(normalizedMeanSquaredErrorWeightingFactor * nmse + falseNegativeRateWeightingFactor * falseNegativeRate + falsePositiveRateWeightingFactor * falsePositiveRate);
        }