/
onequ1z
/
JavaCoursePaperTulSU
Обзор
Документация
Войти
/
onequ1z
/
JavaCoursePaperTulSU
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
src/main/java/ru/dmitry/montecarlo/service/ExperimentRunner.java
143 строки
6 KB
tayno
Добавлена опциональная многопоточная реализация MonteCarlo
08 дек 2025, 09:22
08 дек 2025, 09:22
43ff8f6
Код
Авторство
О чём код?
package ru.dmitry.montecarlo.service; import ru.dmitry.montecarlo.model.ExperimentResult; import ru.dmitry.montecarlo.model.Figure; import ru.dmitry.montecarlo.model.MonteCarloResult; import ru.dmitry.montecarlo.model.Rectangle; import java.util.Random; /** * Запускает серию экспериментов Монте-Карло для различных значений N * и агрегирует результаты (средние значения и стандартные отклонения). */ public class ExperimentRunner { private final MonteCarloEstimator estimator; /** * Создаёт ExperimentRunner с заданным оценщиком Монте-Карло. * * @param estimator оценщик Монте-Карло (однопоточный или многопоточный) */ public ExperimentRunner(MonteCarloEstimator estimator) { this.estimator = estimator; } /** * Запускает серию экспериментов Монте-Карло для различных значений N. * <p> * Для каждого значения N выполняется заданное количество повторов, * результаты агрегируются с вычислением средних значений и стандартных отклонений. * * @param figure фигура, для которой оценивается площадь * @param rectangle ограничивающий прямоугольник * @param nValues массив значений N (количество испытаний для каждого эксперимента) * @param repeats количество повторов для каждого значения N * @param rng генератор случайных чисел * @return агрегированные результаты по каждому N, содержащие статистику * @throws IllegalArgumentException если figure, rectangle или rng равны null */ public ExperimentResult runExperiments(Figure figure, Rectangle rectangle, long[] nValues, int repeats, Random rng) { if (figure == null) { throw new IllegalArgumentException("Figure не может быть null"); } if (rectangle == null) { throw new IllegalArgumentException("Rectangle не может быть null"); } if (rng == null) { throw new IllegalArgumentException("Random generator не может быть null"); } if (nValues == null || nValues.length == 0 || repeats <= 0) { return new ExperimentResult(new ExperimentResult.NStats[0]); } ExperimentResult.NStats[] allStats = new ExperimentResult.NStats[nValues.length]; for (int i = 0; i < nValues.length; i++) { long n = nValues[i]; MonteCarloResult[] runs = performRepeats(figure, rectangle, n, repeats, rng); allStats[i] = aggregateForN(n, runs); } return new ExperimentResult(allStats); } /** * Выполняет заданное количество повторов эксперимента для одного значения N. * * @param figure фигура * @param rectangle прямоугольник * @param n количество испытаний * @param repeats количество повторов * @param rng генератор случайных чисел * @return массив результатов для каждого повтора */ private MonteCarloResult[] performRepeats(Figure figure, Rectangle rectangle, long n, int repeats, Random rng) { MonteCarloResult[] runs = new MonteCarloResult[repeats]; for (int r = 0; r < repeats; r++) { runs[r] = estimator.estimateArea(figure, rectangle, n, rng); } return runs; } /** * Агрегирует результаты нескольких запусков для одного значения N. * Вычисляет средние значения и стандартные отклонения для площади, ошибки и времени. * * @param n количество испытаний * @param runs массив результатов запусков * @return статистика по всем запускам */ private ExperimentResult.NStats aggregateForN(long n, MonteCarloResult[] runs) { int count = runs.length; if (count == 0) { return new ExperimentResult.NStats(n, runs, 0.0, 0.0, 0.0, 0.0, 0.0); } // Вычисляем средние значения double sumArea = 0.0; double sumError = 0.0; double sumDuration = 0.0; for (MonteCarloResult run : runs) { sumArea += run.getEstimatedArea(); sumError += run.getRelativeErrorPercent(); sumDuration += run.getDurationMillis(); } double avgArea = sumArea / count; double avgError = sumError / count; double avgDuration = sumDuration / count; // Вычисляем стандартные отклонения double sumSqArea = 0.0; double sumSqError = 0.0; for (MonteCarloResult run : runs) { double da = run.getEstimatedArea() - avgArea; double de = run.getRelativeErrorPercent() - avgError; sumSqArea += da * da; sumSqError += de * de; } double stdArea = count > 1 ? Math.sqrt(sumSqArea / (count - 1)) : 0.0; double stdError = count > 1 ? Math.sqrt(sumSqError / (count - 1)) : 0.0; return new ExperimentResult.NStats( n, runs, avgArea, avgError, avgDuration, stdArea, stdError ); } }