/
onequ1z
/
JavaCoursePaperTulSU
Обзор
Документация
Войти
/
onequ1z
/
JavaCoursePaperTulSU
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
src/test/java/ru/dmitry/montecarlo/service/MonteCarloParallelTest.java
251 строка
10 KB
tayno
Добавлена опциональная многопоточная реализация MonteCarlo
08 дек 2025, 09:25
08 дек 2025, 09:25
a8e3739
Код
Авторство
О чём код?
package ru.dmitry.montecarlo.service; import org.junit.jupiter.api.Test; import ru.dmitry.montecarlo.model.MonteCarloResult; import ru.dmitry.montecarlo.model.Point; import ru.dmitry.montecarlo.model.Rectangle; import ru.dmitry.montecarlo.model.TriangleGEF; import java.util.Random; import static org.junit.jupiter.api.Assertions.*; /** * Тесты для многопоточного варианта метода Монте-Карло. */ class MonteCarloParallelTest { @Test void testEstimateAreaWithSingleThreadFallsBackToSingleThreaded() { // Arrange Point a = new Point(0.0, 0.0); Point b = new Point(10.0, 0.0); Point c = new Point(10.0, 10.0); Point d = new Point(0.0, 10.0); Rectangle rectangle = new Rectangle(a, b, c, d); Point g = new Point(0.0, 4.0 / 3.0); Point e = new Point(1.0, 2.0); Point f = new Point(2.0 / 3.0, 0.0); TriangleGEF triangle = new TriangleGEF(g, e, f); MonteCarloParallel parallel = new MonteCarloParallel(1); MonteCarlo single = new MonteCarlo(); long samples = 1000L; Random rng1 = new Random(12345L); Random rng2 = new Random(12345L); // Act MonteCarloResult parallelResult = parallel.estimateArea(triangle, rectangle, samples, rng1); MonteCarloResult singleResult = single.estimateArea(triangle, rectangle, samples, rng2); // Assert - результаты должны быть одинаковыми assertEquals(singleResult.getSamples(), parallelResult.getSamples()); assertEquals(singleResult.getHits(), parallelResult.getHits()); assertEquals(singleResult.getEstimatedArea(), parallelResult.getEstimatedArea(), 1e-10); assertEquals(singleResult.getRelativeErrorPercent(), parallelResult.getRelativeErrorPercent(), 1e-10); } @Test void testEstimateAreaWithMultipleThreads() { // Arrange Point a = new Point(0.0, 0.0); Point b = new Point(10.0, 0.0); Point c = new Point(10.0, 10.0); Point d = new Point(0.0, 10.0); Rectangle rectangle = new Rectangle(a, b, c, d); Point g = new Point(0.0, 4.0 / 3.0); Point e = new Point(1.0, 2.0); Point f = new Point(2.0 / 3.0, 0.0); TriangleGEF triangle = new TriangleGEF(g, e, f); MonteCarloParallel parallel = new MonteCarloParallel(4); long samples = 10000L; Random rng = new Random(54321L); // Act MonteCarloResult result = parallel.estimateArea(triangle, rectangle, samples, rng); // Assert assertNotNull(result); assertEquals(samples, result.getSamples()); assertTrue(result.getHits() >= 0 && result.getHits() <= samples); assertTrue(result.getEstimatedArea() >= 0.0 && result.getEstimatedArea() <= rectangle.area() + 1e-9); assertTrue(result.getDurationMillis() >= 0); assertTrue(result.getRelativeErrorPercent() >= 0.0); } @Test void testReproducibilityWithSameSeed() { // Arrange Point a = new Point(0.0, 0.0); Point b = new Point(10.0, 0.0); Point c = new Point(10.0, 10.0); Point d = new Point(0.0, 10.0); Rectangle rectangle = new Rectangle(a, b, c, d); Point g = new Point(0.0, 4.0 / 3.0); Point e = new Point(1.0, 2.0); Point f = new Point(2.0 / 3.0, 0.0); TriangleGEF triangle = new TriangleGEF(g, e, f); MonteCarloParallel parallel1 = new MonteCarloParallel(4); MonteCarloParallel parallel2 = new MonteCarloParallel(4); long samples = 5000L; long seed = 99999L; // Act Random rng1 = new Random(seed); Random rng2 = new Random(seed); MonteCarloResult result1 = parallel1.estimateArea(triangle, rectangle, samples, rng1); MonteCarloResult result2 = parallel2.estimateArea(triangle, rectangle, samples, rng2); // Assert - результаты должны быть воспроизводимыми // Примечание: из-за особенностей создания seed'ов для потоков, точное совпадение // может не гарантироваться, но общее количество попаданий должно быть близким assertEquals(result1.getSamples(), result2.getSamples()); // Проверяем, что результаты близки (могут отличаться из-за порядка выполнения потоков) assertTrue(Math.abs(result1.getHits() - result2.getHits()) <= 2, "Количество попаданий должно быть близким при одинаковом seed"); } @Test void testEstimateAreaWithZeroSamples() { // Arrange Point a = new Point(0.0, 0.0); Point b = new Point(10.0, 0.0); Point c = new Point(10.0, 10.0); Point d = new Point(0.0, 10.0); Rectangle rectangle = new Rectangle(a, b, c, d); Point g = new Point(0.0, 4.0 / 3.0); Point e = new Point(1.0, 2.0); Point f = new Point(2.0 / 3.0, 0.0); TriangleGEF triangle = new TriangleGEF(g, e, f); MonteCarloParallel parallel = new MonteCarloParallel(4); Random rng = new Random(); // Act MonteCarloResult result = parallel.estimateArea(triangle, rectangle, 0L, rng); // Assert assertNotNull(result); assertEquals(0L, result.getSamples()); assertEquals(0L, result.getHits()); assertEquals(0.0, result.getEstimatedArea(), 1e-10); assertEquals(0.0, result.getRelativeErrorPercent(), 1e-10); } @Test void testEstimateAreaWithNegativeSamples() { // Arrange Point a = new Point(0.0, 0.0); Point b = new Point(10.0, 0.0); Point c = new Point(10.0, 10.0); Point d = new Point(0.0, 10.0); Rectangle rectangle = new Rectangle(a, b, c, d); Point g = new Point(0.0, 4.0 / 3.0); Point e = new Point(1.0, 2.0); Point f = new Point(2.0 / 3.0, 0.0); TriangleGEF triangle = new TriangleGEF(g, e, f); MonteCarloParallel parallel = new MonteCarloParallel(4); Random rng = new Random(); // Act MonteCarloResult result = parallel.estimateArea(triangle, rectangle, -100L, rng); // Assert assertNotNull(result); assertEquals(0L, result.getSamples()); assertEquals(0L, result.getHits()); assertEquals(0.0, result.getEstimatedArea(), 1e-10); } @Test void testEstimateAreaThrowsExceptionOnNullFigure() { // Arrange Point a = new Point(0.0, 0.0); Point b = new Point(10.0, 0.0); Point c = new Point(10.0, 10.0); Point d = new Point(0.0, 10.0); Rectangle rectangle = new Rectangle(a, b, c, d); MonteCarloParallel parallel = new MonteCarloParallel(4); Random rng = new Random(); // Act & Assert assertThrows(IllegalArgumentException.class, () -> { parallel.estimateArea(null, rectangle, 1000L, rng); }); } @Test void testEstimateAreaThrowsExceptionOnNullRectangle() { // Arrange Point g = new Point(0.0, 4.0 / 3.0); Point e = new Point(1.0, 2.0); Point f = new Point(2.0 / 3.0, 0.0); TriangleGEF triangle = new TriangleGEF(g, e, f); MonteCarloParallel parallel = new MonteCarloParallel(4); Random rng = new Random(); // Act & Assert assertThrows(IllegalArgumentException.class, () -> { parallel.estimateArea(triangle, null, 1000L, rng); }); } @Test void testEstimateAreaThrowsExceptionOnNullRng() { // Arrange Point a = new Point(0.0, 0.0); Point b = new Point(10.0, 0.0); Point c = new Point(10.0, 10.0); Point d = new Point(0.0, 10.0); Rectangle rectangle = new Rectangle(a, b, c, d); Point g = new Point(0.0, 4.0 / 3.0); Point e = new Point(1.0, 2.0); Point f = new Point(2.0 / 3.0, 0.0); TriangleGEF triangle = new TriangleGEF(g, e, f); MonteCarloParallel parallel = new MonteCarloParallel(4); // Act & Assert assertThrows(IllegalArgumentException.class, () -> { parallel.estimateArea(triangle, rectangle, 1000L, null); }); } @Test void testDifferentThreadCountsProduceValidResults() { // Arrange Point a = new Point(0.0, 0.0); Point b = new Point(10.0, 0.0); Point c = new Point(10.0, 10.0); Point d = new Point(0.0, 10.0); Rectangle rectangle = new Rectangle(a, b, c, d); Point g = new Point(0.0, 4.0 / 3.0); Point e = new Point(1.0, 2.0); Point f = new Point(2.0 / 3.0, 0.0); TriangleGEF triangle = new TriangleGEF(g, e, f); long samples = 10000L; long seed = 88888L; // Act & Assert - проверяем, что разные количества потоков дают валидные результаты for (int threads : new int[]{1, 2, 4, 8}) { MonteCarloParallel parallel = new MonteCarloParallel(threads); Random rng = new Random(seed); MonteCarloResult result = parallel.estimateArea(triangle, rectangle, samples, rng); assertNotNull(result); assertEquals(samples, result.getSamples()); assertTrue(result.getHits() >= 0 && result.getHits() <= samples); assertTrue(result.getEstimatedArea() >= 0.0 && result.getEstimatedArea() <= rectangle.area() + 1e-9); } } }