mc_forecast 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 387e653e97a687f2ab7618e2612c38fae72ddb5bc87485b44998005cab548d3d
4
- data.tar.gz: 161aca02d0cb2ded0c143908ee9d4747078bd73888974d026b08d8039ccb117a
3
+ metadata.gz: 82e81b59b88ffa6eadba70aef437ecec5c040b890b19d7f64f8237eb59fc7c56
4
+ data.tar.gz: 729b9f9d931b338f5860427d1aaba73aea35c847eedb018d72c39a7486c7f551
5
5
  SHA512:
6
- metadata.gz: f075afc3d8b5c2c234c50fc2b58ea66da44a6bb6cfbc3058982c6a131aa374576b1ec7c953bb1b21f81c0cddba46233be67c8fddc09887049f060db37f903848
7
- data.tar.gz: c0e17a7551d1ba892b7d372e1a1424eda9b8ee3231b68420e6a03e773cde672d6fad125529f99e72d7a1c810aed6b30b6a6ac4e12ebbfa9adfb06a96b8174454
6
+ metadata.gz: 4ce13d962a1c9e82f52e101387f6c8627fdac52187000e5ceb5a25bc7513bc9929cd94d6fc6faaf5196f7bcc90336bb69be642c774abe93a205b43464bbc20f1
7
+ data.tar.gz: ea2d982df7f53a36558969c1d8361ea477d817895f92a4118cb23472eaa3066b85ce9efffcc12f804894facf1303f8dffe68c2b2bb9fd8865125d0ba516a41fd
@@ -2,7 +2,7 @@ require "deep_dup"
2
2
 
3
3
  module McForecast
4
4
  class Simulation
5
- def run(init_state: nil, trials: 1_000, steps: 1, quantiles: [0.025, 0.975])
5
+ def run(init_state: nil, trials: 1_000, steps: 1, quantiles: [0.025, 0.16, 0.84, 0.975])
6
6
  events = {}
7
7
  (0..trials - 1).each do |trial|
8
8
  state = DeepDup.deep_dup(init_state)
@@ -24,33 +24,51 @@ module McForecast
24
24
 
25
25
  # Return an analysis of the events, containing:
26
26
  # { event_name:
27
- # { mean: [...], # per step
27
+ # {
28
+ # sum: { mean: ...,
29
+ # quantiles:
30
+ # { 0.025: ..., 0.975: ... }},
31
+ # mean: [...], # per step
28
32
  # quantiles:
29
33
  # { 0.025: [...],
30
34
  # 0.975: [...]
31
35
  # }}}
32
36
  def analyze(events, quantiles)
33
37
  events.transform_values do |steps| # array(steps) of arrays(trials)
34
- a = if quantiles.any?
35
- # only need to sort if we request answers on any quantiles
36
- steps.map do |trials|
37
- # could avoid sorting with some creativity, but probably fine for our data lengths so far
38
- trials.sort.values_at(*quantile_indices(trials.length, quantiles))
39
- end.transpose # a[step][]
40
- else
41
- []
42
- end
43
-
44
38
  {
45
- mean: steps.map { |trials| Rational(trials.sum || 0, trials.length) },
46
- quantiles: quantiles.zip(a).to_h
39
+ sum: sum(steps, quantiles),
40
+ # besides the total sum we may want to have a sum for multiples of our base period
41
+ # (or week/month/quarter/year but that gets a bit complicated)
42
+ mean: steps.map { |trials| (trials.sum || 0).to_f / trials.length },
43
+ quantiles: quantiles.zip(step_quantiles(quantiles, steps)).to_h
47
44
  }
48
45
  end
49
46
  end
50
47
 
51
- def quantile_indices(n_trials, quantiles)
48
+ def sum(steps, quantiles)
49
+ sums = steps.transpose.map(&:sum) # gives a sum of this event, per trial
50
+ {
51
+ mean: (sums.sum || 0).to_f / steps[0].length,
52
+ # sort all of the sums, and take the elements closest to the chosen quantiles, and then make a nice hash
53
+ quantiles: quantiles.zip(sums.sort.values_at(*quantile_indices(steps[0].length, quantiles))).to_h
54
+ }
55
+ end
56
+
57
+ def step_quantiles(quantiles, steps)
58
+ if quantiles.any?
59
+ # only need to sort if we request answers on any quantiles
60
+ steps.map do |trials|
61
+ # could avoid sorting with some creativity, but probably fine for our data lengths so far
62
+ trials.sort.values_at(*quantile_indices(trials.length, quantiles))
63
+ end.transpose # a[step][]
64
+ else
65
+ []
66
+ end
67
+ end
68
+
69
+ def quantile_indices(count, quantiles)
52
70
  quantiles.map do |q|
53
- (q * (n_trials - 1)).round.to_i.clamp(0, n_trials - 1)
71
+ (q * (count - 1)).round.to_i.clamp(0, count - 1)
54
72
  end
55
73
  end
56
74
  end
@@ -1,3 +1,3 @@
1
1
  module McForecast
2
- VERSION = "0.1.1".freeze
2
+ VERSION = "0.2.0".freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mc_forecast
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daan van Vugt
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-12-08 00:00:00.000000000 Z
11
+ date: 2024-03-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: deep_dup