예제 #1
0
        /// <summary>
        /// R/S анализ ряда (последовательные вычисления)
        /// </summary>
        /// <param name="A">Массив входных данных</param>
        /// <param name="periodLength">Стартовая длина периода</param>
        /// <param name="startGIndex">Начальный индекс в массиве, с которого берутся данные</param>
        /// <param name="endGIndex">Конечный индекс в массиве, до которого берутся данные (включительно)</param>
        /// <param name="maxPeriodLength">Максимальная длина периода, до которого ведется расчет</param>
        /// <returns>Таблицу полученных R/S-точек и коэффициенты регрессии (A - соответствет H)</returns>
        public static ResultRS RS_Analyse(float[] A, int periodLength, int startGIndex, int endGIndex, int maxPeriodLength)
        {
            //кол-во RS-результатов
            int resLength = maxPeriodLength - periodLength + 1;

            //результаты RS-анализа
            PointRS[] result = new PointRS[resLength];
            //последний индекс в массиве
            int lastIndex = endGIndex;
            //первый индекс в массиве
            //конечный локальный индекс
            int startIndex, endIndex, startIndexNow;
            //ср. значение RS для данного периода
            float averageRS;
            int   j = 0;
            //текущая длина периода
            int currentPeriodLength = periodLength;
            //Кол-во периодов
            int periodCount = (endGIndex - startGIndex + 1) / currentPeriodLength;

            //Устанавливаем длину прогресбара
            CalculateStart.CreateEvent(resLength + 1, "R/S analyse...");
            do
            {
                startIndex = lastIndex;
                endIndex   = lastIndex;
                averageRS  = 0;
                for (int i = 1; i <= periodCount; i++)
                {
                    startIndex = endIndex - currentPeriodLength + 1;
                    averageRS += GetRS(A, startIndex, endIndex);
                    endIndex  -= startIndex - 1;
                }
                startIndexNow = startIndex;
                averageRS    /= periodCount;
                result[j].n   = Math.Log10((float)currentPeriodLength / 2);
                result[j].rs  = Math.Log10(averageRS);
                result[j].h   = result[j].rs / result[j].n;
                j++;
                currentPeriodLength++;
                //Кол-во периодов
                periodCount = (endGIndex - startGIndex + 1) / currentPeriodLength;
                //Увеличиваем прогресбар
                Calculus.CreateEvent(j);
            }while (currentPeriodLength <= maxPeriodLength);
            KRegression regression = MathProcess.SimpleRegression(result);
            ResultRS    res;

            res.points     = result;
            res.regression = regression;
            return(res);
        }
예제 #2
0
        /// <summary>
        /// R/S анализ ряда (параллельные вычисления)
        /// </summary>
        /// <param name="A">Массив входных данных</param>
        /// <param name="periodLength">Стартовая длина периода</param>
        /// <param name="startGIndex">Начальный индекс в массиве, с которого берутся данные</param>
        /// <param name="endGIndex">Конечный индекс в массиве, до которого берутся данные (включительно)</param>
        /// <param name="maxPeriodLength">Максимальная длина периода, до которого ведется расчет</param>
        /// <param name="threadCount">Количество потоков (распараллеливание вычислений)</param>
        /// <returns>Таблицу полученных R/S-точек и коэффициенты регрессии (A - соответствет H)</returns>
        public static ResultRS RS_Analyse(float[] A, int currentPeriodLength, int startGIndex, int endGIndex, int maxPeriodLength, int threadCount)
        {
            //кол-во RS-результатов
            int resLength = maxPeriodLength - currentPeriodLength + 1;

            //результаты RS-анализа
            PointRS[] result = new PointRS[resLength];
            //Длина периода на поток
            int periodIntervalLength = resLength / threadCount;
            //Остаток (т.к. длина может не поделится на цело на число потоков)
            int remainder = resLength - periodIntervalLength * threadCount;
            //Максимальный период для первого потока = общий интервал + остаток
            int maxPeriodLengthLocal = periodIntervalLength + remainder + currentPeriodLength - 1;

            //Потоки
            Thread[] threads = new Thread[threadCount];
            //Потоковые экземпляры, проводящие R/S анализ
            RS_AnalyseThread[] rsat = new RS_AnalyseThread[threadCount];
            //Первый поток пошел
            rsat[0]    = new RS_AnalyseThread(A, currentPeriodLength, startGIndex, endGIndex, maxPeriodLengthLocal, 0);
            threads[0] = new Thread(new ThreadStart(rsat[0].RS_Analyse));
            //Устанавливаем длину прогресбара для 1 процесса
            resLength = maxPeriodLengthLocal - currentPeriodLength + 1;
            CalculateStart.CreateEvent(resLength, "R/S analyse 1", 0);
            threads[0].Start();
            //Запускаем остальные потоки
            int j = 2;

            for (int i = 1; i < threadCount; i++)
            {
                //с какого периода начинать считать
                currentPeriodLength = maxPeriodLengthLocal + 1;
                //до какого периода считать
                maxPeriodLengthLocal += periodIntervalLength;
                //Запуск потока
                rsat[i]    = new RS_AnalyseThread(A, currentPeriodLength, startGIndex, endGIndex, maxPeriodLengthLocal, i);
                threads[i] = new Thread(new ThreadStart(rsat[i].RS_Analyse));
                //Устанавливаем длину прогресбара для i процесса
                resLength = maxPeriodLengthLocal - currentPeriodLength + 1;
                CalculateStart.CreateEvent(resLength, "R/S analyse " + j.ToString(), i);
                threads[i].Start();
                j++;
            }
            //Ждем выполнения всех потоков
            for (int i = 0; i < threadCount; i++)
            {
                threads[i].Join();
            }
            //Сшиваем все результаты в один массив
            int indexResult = 0;

            for (int i = 0; i < threadCount; i++)
            {
                rsat[i].result.CopyTo(result, indexResult);
                indexResult += rsat[i].result.Length;
            }
            //Регрессия
            KRegression regression = MathProcess.SimpleRegression(result, (int)(result.Length / 2.5), result.Length - 1);
            //KRegression regression = MathProcess.SimpleRegression(result, 0, result.Length - 1);
            ResultRS res;

            res.points     = result;
            res.regression = regression;
            GC.Collect(GC.GetGeneration(A));
            GC.Collect(GC.GetGeneration(rsat));
            GC.Collect(GC.GetGeneration(threads));
            GC.Collect(GC.GetGeneration(result));
            GC.WaitForPendingFinalizers();
            GC.Collect();
            GC.Collect();
            GC.WaitForPendingFinalizers();
            GC.Collect();
            return(res);
        }