Пример #1
0
        public static MedianPolish GetMedianPolish(double?[,] matrix, double epsilon, int maxIterations)
        {
            int             rowCount        = matrix.GetLength(0);
            int             columnCount     = matrix.GetLength(1);
            double          overallConstant = 0;
            Vector <double> rowEffects      = new DenseVector(rowCount);
            Vector <double> columnEffects   = new DenseVector(columnCount);

            double?[,] residuals = (double?[, ])matrix.Clone();
            double oldSum = 0;

            for (int iteration = 0; iteration < maxIterations; iteration++)
            {
                for (int iRow = 0; iRow < rowCount; iRow++)
                {
                    double median = GetRow(residuals, iRow).Median();
                    SetRow(residuals, iRow, GetRow(residuals, iRow).Select(value => value - median));
                    rowEffects[iRow] += median;
                }
                double cDelta = columnEffects.Median();
                columnEffects    = columnEffects.Subtract(cDelta);
                overallConstant += cDelta;
                for (int iCol = 0; iCol < columnCount; iCol++)
                {
                    double median = GetColumn(residuals, iCol).Median();
                    SetColumn(residuals, iCol, GetColumn(residuals, iCol).Select(value => value - median));
                    columnEffects[iCol] += median;
                }
                double rDelta = rowEffects.Median();
                rowEffects       = rowEffects.Subtract(rDelta);
                overallConstant += rDelta;
                double newSum = 0;
                foreach (var value in residuals)
                {
                    newSum += Math.Abs(value.GetValueOrDefault());
                }
                bool converged = newSum == 0 || Math.Abs(newSum - oldSum) < epsilon * newSum;
                if (converged)
                {
                    break;
                }
                oldSum = newSum;
            }
            return(new MedianPolish
            {
                ColumnEffects = columnEffects.ToArray(),
                OverallConstant = overallConstant,
                Residuals = residuals,
                RowEffects = rowEffects.ToArray()
            });
        }