aboutsummaryrefslogtreecommitdiff
path: root/stdlib/source/test/lux/world/time/series/average.lux
blob: fcc65673f2f796ceececfb589b219f66e2d6eab4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
(.require
 [library
  [lux (.except)
   [abstract
    [monad (.only do)]]
   [control
    ["[0]" try]
    ["[0]" exception]]
   [math
    ["[0]" random (.only Random)]
    [number
     ["n" nat]
     ["f" frac]]]
   [world
    [time
     ["[0]" instant (.use "[1]#[0]" order)]
     ["[0]" duration (.use "[1]#[0]" equivalence)]]]
   [test
    ["_" property (.only Test)]]]]
 [\\library
  ["[0]" / (.only)
   ["/[1]" //]]])

(def (series events)
  (-> Nat
      (Random (/.Series Frac)))
  (do [! random.monad]
    [.let [duration (random.only duration.positive? random.duration)]
     offset (of ! each (duration.framed (duration.up 100 duration.normal_year))
                duration)
     .let [start (instant.after offset instant.epoch)]
     interval (of ! each (duration.framed duration.week)
                  duration)
     data (random.sequence events random.safe_frac)]
    (in [//.#start start
         //.#interval interval
         //.#data data])))

(def (well_windowed? input additional output)
  (All (_ input output)
    (-> (/.Series input) Nat (/.Series output)
        Bit))
  (let [correct_start!
        (instant#< (//.start output)
                   (//.start input))

        correct_size!
        (n.= (n.- (++ additional) (//.size input))
             (//.size output))]
    (and correct_start!
         correct_size!)))

(def .public test
  Test
  (<| (_.covering /._)
      (do [! random.monad]
        [expected_events (of ! each (|>> (n.% 10) ++) random.nat)
         input (series expected_events)
         additional (of ! each (n.% expected_events) random.nat)])
      (all _.and
           (_.coverage [/.cumulative]
             (let [output (/.cumulative input)]
               (and (instant#= (//.start input)
                               (//.start output))
                    (n.= (//.size input)
                         (//.size output)))))
           (_.coverage [/.windows]
             (<| (try.else false)
                 (do try.monad
                   [output (/.windows additional input)]
                   (in (well_windowed? input additional output)))))
           (_.coverage [/.window_size_is_too_large]
             (when (/.windows (++ expected_events) input)
               {try.#Failure error}
               (exception.match? /.window_size_is_too_large error)

               {try.#Success _}
               false))
           (<| (_.for [/.Average])
               (all _.and
                    (_.coverage [/.exponential /.simple /.weighted

                                 /.Factor /.simple_factor]
                      (let [exponential (/.exponential /.simple_factor input)
                            simple (/.simple input)
                            weighted (/.weighted input)]
                        (and (not (f.= exponential simple))
                             (not (f.= exponential weighted))
                             (not (f.= simple weighted)))))
                    (_.coverage [/.moving]
                      (<| (try.else false)
                          (do try.monad
                            [exponential (/.moving (/.exponential /.simple_factor)
                                                   additional
                                                   input)
                             simple (/.moving /.simple
                                              additional
                                              input)
                             weighted (/.moving /.weighted
                                                additional
                                                input)
                             .let [(open "//#[0]") (//.equivalence f.equivalence)]]
                            (in (and (and (well_windowed? input additional exponential)
                                          (well_windowed? input additional simple)
                                          (well_windowed? input additional weighted))
                                     (and (not (//#= exponential simple))
                                          (not (//#= exponential weighted))
                                          (not (//#= simple weighted)))
                                     )))))
                    ))
           )))