%export batch
        battery_of_batches
        batch_chi_squared battery_of_batch_chi_squared_results
%include "~ids/misc/lib/miralib/stdenv.def"
%include "random"

batch == sequence || but intended to be finite

|| EXPORTED FUNCTIONS

battery_of_batches :: num -> real -> [batch]
|| produces a battery of "batches", where a batch is a finite truncation of a 
|| test sequence (first argument is truncation length).
|| Note: real input should be "irrational" (see comment of 
|| battery_of_test_sequences).
  battery_of_batches n = map (first n) . battery_of_test_sequences

batch_chi_squared :: [real] -> batch -> real
  batch_chi_squared partition b = chi_squared (batch_analysis partition b)

battery_of_batch_chi_squared_results :: [real] -> num -> real -> [real]
|| partition -> required size of each batch -> battery seed -> answers!
|| Note: battery seed must be "irrational" as explained in comment of
|| battery_of_test_sequences
  battery_of_batch_chi_squared_results partition batch_size
    = map (batch_chi_squared partition) . (battery_of_batches batch_size)









|| SUPPORT FUNCTIONS

create_bins :: [real] -> [(real -> bool, real)]
|| creates filters for each of the n "bins" marked out by the n-1 boundary
|| positions given in the input. The expected probabilities for each bin
|| [assuming a uniform [0,1) distribution] are also computed.
|| example: create_bin [.2,.7] gives in effect
|| [(lambda x => 0 <=x<.2, .2),
||  (lambda x => .2<=x<.7, .5),
||  (lambda x => .7<=x< 1, .3)].
  create_bins = create_bins_from 0
                where
                create_bins_from here [] = [(range_filter here 1, 1-here)]
                create_bins_from here (h:t)
                  = (range_filter here h, h-here):create_bins_from h t
                range_filter min sup x = min<=x & x<sup

actual_bin_contents :: batch -> [real -> bool] -> [num]
|| gives the actual count, for each bin, of the elements of the batch that
|| belong to it
  actual_bin_contents b = map (submit_to_bin b)
                          where
                          submit_to_bin b bin = sum (map (bool_to_num . bin) b)

expected_bin_contents :: num -> [real] -> [num]
  expected_bin_contents batch_size = map (* batch_size)

batch_analysis :: [real] -> batch -> [(num,num)]
|| gives actual and expected frequencies for each bin defined by the
|| partition (first argument), for the batch in question (second argument)
  batch_analysis partition b
    = zip2 (actual_bin_contents b bins)
           (expected_bin_contents (#b) expected_probabilities)
      where
      (bins, expected_probabilities) = unzip2 (create_bins partition)

chi_squared :: [(num,num)] -> real
  chi_squared = sum . map contribution
                where
                contribution (actual, expected) = (actual-expected)^2 / expected
