Line data Source code
1 : // Copyright 2023 The terCAD team. All rights reserved. 2 : // Use of this source code is governed by a CC BY-NC-ND 4.0 license that can be found in the LICENSE file. 3 : 4 : import 'dart:math'; 5 : 6 : import 'package:flutter/material.dart'; 7 : 8 : class MonteCarloSimulation { 9 : final Random random = Random(); 10 : final int cycles; 11 : final double coercion; 12 : 13 0 : MonteCarloSimulation({this.cycles = 30, this.coercion = 1}); 14 : 15 0 : List<Offset> generate(List<Offset> scope, double step, double max) { 16 0 : final List<List<double>> distribution = []; 17 0 : for (int i = 0; i < scope.length; i++) { 18 0 : final state = mcNormal(scope[i].dy, coercion, cycles); 19 0 : for (int j = 0; j < state.length; j++) { 20 0 : if (j >= distribution.length) { 21 0 : distribution.add([]); 22 : } 23 0 : distribution[j].add(state[j]); 24 : } 25 : } 26 0 : double posX = scope.last.dx + step; 27 0 : List<Offset> result = []; 28 : int idx = 0; 29 0 : while (posX <= max) { 30 0 : result.add(Offset(posX, distribution[idx][distribution[idx].length * random.nextDouble() ~/ 1])); 31 0 : posX += step; 32 0 : idx++; 33 : } 34 : return result; 35 : } 36 : 37 0 : List<double> mcNormal(double mean, double stdDev, int samples) { 38 0 : List<double> results = []; 39 0 : for (int i = 0; i < samples; i++) { 40 0 : results.add(_normalRandom(mean, stdDev)); 41 : } 42 : return results; 43 : } 44 : 45 0 : double _normalRandom(double mean, double stdDev) { 46 0 : double u1 = random.nextDouble(); 47 0 : double u2 = random.nextDouble(); 48 0 : double z0 = sqrt(-2.0 * log(u1)) * cos(2 * pi * u2); 49 0 : return mean + stdDev * z0; 50 : } 51 : }