Random 如何在OCaml中测试随机模块?

Random 如何在OCaml中测试随机模块?,random,ocaml,Random,Ocaml,OCaml有一个问题,我想知道它是如何测试自己的随机性的。然而,我不知道他们到底在做什么。我知道它试图用另外两个相关性测试来测试卡方检验。以下是测试部分的代码: 卡方检验 (* Return the sum of the squares of v[i0,i1[ *) let rec sumsq v i0 i1 = if i0 >= i1 then 0.0 else if i1 = i0 + 1 then Pervasives.float v.(i0) *. Pervasives.f

OCaml有一个问题,我想知道它是如何测试自己的随机性的。然而,我不知道他们到底在做什么。我知道它试图用另外两个相关性测试来测试
卡方检验。以下是测试部分的代码:

卡方检验

(* Return the sum of the squares of v[i0,i1[ *)
let rec sumsq v i0 i1 =
  if i0 >= i1 then 0.0
  else if i1 = i0 + 1 then Pervasives.float v.(i0) *. Pervasives.float v.(i0)
  else sumsq v i0 ((i0+i1)/2) +. sumsq v ((i0+i1)/2) i1
;;

let chisquare g n r =
  if n <= 10 * r then invalid_arg "chisquare";
  let f = Array.make r 0 in
  for i = 1 to n do
    let t = g r in
    f.(t) <- f.(t) + 1
  done;
  let t = sumsq f 0 r
  and r = Pervasives.float r
  and n = Pervasives.float n in
  let sr = 2.0 *. sqrt r in
  (r -. sr,   (r *. t /. n) -. n,   r +. sr)
;;
Q2:,为什么他们似乎对chisquare使用不同的方式

从维基上看,他们的公式是

但看起来他们用的是不同的公式,幕后是什么


其他两个相关性测试

(* This is to test for linear dependencies between successive random numbers.
*)
let st = ref 0;;
let init_diff r = st := int r;;
let diff r =
  let x1 = !st
  and x2 = int r
  in
  st := x2;
  if x1 >= x2 then
    x1 - x2
  else
    r + x1 - x2
;;

let st1 = ref 0
and st2 = ref 0
;;

(* This is to test for quadratic dependencies between successive random
   numbers.
*)
let init_diff2 r = st1 := int r; st2 := int r;;
let diff2 r =
  let x1 = !st1
  and x2 = !st2
  and x3 = int r
  in
  st1 := x2;
  st2 := x3;
  (x3 - x2 - x2 + x1 + 2*r) mod r
;;
Q3:我真的不知道这两个测试,有人能告诉我吗?

Q1:

这是一个内存使用的问题。您会注意到,对于大型阵列,sumsq的实现将因“评估期间堆栈溢出”而失败(在我的笔记本电脑上,r=200000时失败)。这是因为在添加
Pervasives.float v.(i0)*之前。pervisives.float v.(i0)
(sumsq v(i0+1)i1)
,您必须计算后者。因此,直到您计算了最后一次调用sumsq的结果,您才可以开始“向上”并添加所有内容。显然,在您的情况下,sumsq将被调用r次,因此您必须跟踪r次调用

相比之下,使用他们的方法,他们只需要跟踪log(r)调用,因为一旦计算了一半数组的sumsq,您只需要知道相应调用的结果(您可以忘记计算该结果所需的所有其他调用)

然而,还有其他方法可以达到这个效果,我不知道他们为什么选择这个(也许有人能告诉我?)。如果您想了解更多与递归和内存相关的问题,您可能应该检查一下。如果你想更多地了解他们在这里使用的技术,你应该检查一下——不过要小心,因为这里我们讨论的是内存,而维基百科的文章可能会讨论很多时间复杂性(速度)

Q2:

你应该更仔细地研究这两种表达方式。这里,所有的E_i等于n/r。如果将其替换为给定的表达式,您将发现它们使用的表达式相同:
(r*.t/.n)-。n
。虽然我没有检查边界的值,但是因为你有一个卡方分布,参数r-减去一个或两个自由度,r相当大,所以看到他们使用这种置信区间也就不足为奇了。你提到的维基百科文章应该可以帮助你很容易地计算出他们使用的置信区间

祝你好运

编辑:哎呀,我忘了Q3。我也不知道这些测试,但我相信你应该可以通过谷歌搜索“连续数字之间的线性相关性”之类的东西来找到更多关于它们的信息

编辑2:回答Jackson Tale于6月29日提出的关于置信区间的问题:

他们确实应该用卡方分布来检验它——或者,更确切地说,用卡方分布来寻找一个置信区间。然而,由于中心极限定理,具有k个自由度的卡方分布收敛到均值k和方差2k的正态律。一个经典的结果是,正常规律的95%置信区间约为[μ-1.96σ,μ+1.96σ],其中μ是平均值,σ是标准偏差——因此,这大约是平均值±标准偏差的两倍。这里,自由度的数量是(我认为)r-1~r(因为r很大),所以我说我对[r-2sqrt(r),r+2sqrt(r)]形式的置信区间并不感到惊讶。然而,现在我想起来了,我不明白为什么他们不使用±2 sqrt(2 r)。。。但我可能错过了什么。不管怎样,即使我是正确的,因为sqrt(2)>1,他们得到了一个更严格的置信区间,所以我想这不是一个真正的问题。但是他们应该记录下他们正在做的事情。。。我的意思是,他们使用的测试可能是相当标准的,所以大多数阅读他们代码的人都知道他们在做什么,但仍然

另外,你应该注意到,通常情况下,这种测试不是决定性的:一般来说,你想证明某些东西有某种效果。所以你提出了两个假设:无效假设,“没有效果”,和替代假设,“有效果”。然后,你证明,给定你的数据,零假设成立的概率非常低。所以你得出结论,另一种假设(很可能)是正确的,也就是说,存在某种影响。这是决定性的。在这里,我们想展示的是随机数生成器是好的。所以我们不想证明它产生的数字与某些定律不同,但它们符合定律。唯一的方法是执行尽可能多的测试,显示生成的数字与随机生成的数字具有相同的属性。但我们能得出的唯一结论是“如果真实数据是随机生成的,我们无法发现实际数据与我们观察到的数据之间的差异”。但这并不是OCaml开发人员缺乏严格性:人们总是这样做(例如,很多测试都需要,比如说,正态性。因此,在执行这些测试之前,您尝试找到一个测试,该测试将显示您的变量不是正态分布的。当您找不到任何变量时,您会说“哦,好吧,这个变量的正态性可能足以让我后续的测试保持”)——仅仅是因为没有其他方法可以做到这一点

无论如何,我不是统计学家,上面的考虑只是我的两分钱,所以你应该小心。例如,我确信他们使用这个特定的置信区间有更好的理由。我还认为你应该能够
(* This is to test for linear dependencies between successive random numbers.
*)
let st = ref 0;;
let init_diff r = st := int r;;
let diff r =
  let x1 = !st
  and x2 = int r
  in
  st := x2;
  if x1 >= x2 then
    x1 - x2
  else
    r + x1 - x2
;;

let st1 = ref 0
and st2 = ref 0
;;

(* This is to test for quadratic dependencies between successive random
   numbers.
*)
let init_diff2 r = st1 := int r; st2 := int r;;
let diff2 r =
  let x1 = !st1
  and x2 = !st2
  and x3 = int r
  in
  st1 := x2;
  st2 := x3;
  (x3 - x2 - x2 + x1 + 2*r) mod r
;;