LINE Solver (C++)
Templated C++ port of the LINE queueing solver
Loading...
Searching...
No Matches
sim_vonneumann.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2012-2026, QORE Lab, Imperial College London
3 * All rights reserved.
4 */
5#ifndef LINE_API_SIM_SIM_VONNEUMANN_H
6#define LINE_API_SIM_SIM_VONNEUMANN_H
7
8/**
9 * @file
10 * @ingroup api_sim
11 * Von Neumann ratio test for randomness of a sequence.
12 *
13 * Port of matlab/src/api/sim/sim_vonneumann.m. The statistic is the ratio of the
14 * mean square successive difference to the variance,
15 * ratio = sum_{i=1}^{b-1} (x_{i+1}-x_i)^2 / sum_{i=1}^{b} (x_i - xbar)^2,
16 * with b the number of observations. Under the null hypothesis that x is i.i.d.
17 * normal the ratio has mean 2 and variance 4(b-2)/((b-1)(b+1)), and (ratio-2)/sd
18 * is asymptotically standard normal, so the two-sided p-value is 2(1-Phi(|z|)).
19 * Serial correlation of either sign moves the ratio away from 2: positive
20 * correlation shrinks the successive differences and pushes the ratio below 2,
21 * negative correlation pushes it above.
22 *
23 * The null mean and variance above were confirmed by Monte Carlo over
24 * b = 10, 16, 24, 32, 50 to within 0.3% in the reference.
25 *
26 * The test is TWO-SIDED and its rejection is used as a stopping rule by the
27 * QUEST procedures, so alpha here is a stage significance (0.30 by default in
28 * sim_fquest, decaying during warmup) and not the interval's coverage level.
29 *
30 * Reference: J. von Neumann, "Distribution of the Ratio of the Mean Square
31 * Successive Difference to the Variance", Ann. Math. Statist. 12(4), 1941;
32 * L. C. Young, "Randomness in Ordered Sequences", Ann. Math. Statist. 12, 1941.
33 */
34
35#include <cmath>
36#include <cstddef>
37#include <vector>
38
41#include "line/num/number.h"
42#include "line/util/error.h"
43
44namespace line {
45namespace sim {
46
47/**
48 * Outcome of the von Neumann randomness test.
49 *
50 * The statistic stays in the working type T; the standardized value and the
51 * p-value are doubles because they come out of a normal approximation, see the
52 * arithmetic note in sim_types.h.
53 */
54template <class T>
56 T ratio; ///< The von Neumann ratio
57 double zscore = 0.0; ///< Standardized statistic (ratio-2)/sd
58 double pvalue = 1.0; ///< Two-sided p-value
59 bool reject = false; ///< True when pvalue < alpha, i.e. randomness is rejected
60 std::size_t nobs = 0; ///< Number of observations b
61};
62
63/**
64 * @brief Von Neumann ratio test for randomness of a sequence.
65 *
66 * @param x the sequence, at least 3 finite observations
67 * @param alpha significance level in (0,1), 0.05 by default
68 */
69template <class T>
70VonNeumannResult<T> sim_vonneumann(const std::vector<T>& x, double alpha = 0.05) {
72 "sim_vonneumann: the p-value is a normal tail, so exact arithmetic is refused");
73 if (!(alpha > 0.0) || !(alpha < 1.0))
74 throw InputError("sim_vonneumann: alpha must be a real scalar in (0,1)");
75
76 const std::size_t b = x.size();
77 if (b < 3)
78 throw InputError("sim_vonneumann: at least 3 observations are required");
79 for (std::size_t i = 0; i < b; ++i)
80 if (!detail::num_isfinite(x[i]))
81 throw InputError("sim_vonneumann: the sequence must be finite");
82
84 for (std::size_t i = 0; i < b; ++i) sum += x[i];
85 const T mean = sum / num_traits<T>::from_int(static_cast<long>(b));
86
87 T den = num_traits<T>::from_int(0);
88 for (std::size_t i = 0; i < b; ++i) {
89 const T d = T(x[i] - mean);
90 den += T(d * d);
91 }
92 if (!(den > num_traits<T>::from_int(0)))
93 throw InputError("sim_vonneumann: the sequence is constant, the ratio is undefined");
94
95 T num = num_traits<T>::from_int(0);
96 for (std::size_t i = 1; i < b; ++i) {
97 const T d = T(x[i] - x[i - 1]);
98 num += T(d * d);
99 }
100
102 r.nobs = b;
103 r.ratio = T(num / den);
104 const double bd = static_cast<double>(b);
105 const double sd = std::sqrt(4.0 * (bd - 2.0) / ((bd - 1.0) * (bd + 1.0)));
106 r.zscore = (num_traits<T>::to_double(r.ratio) - 2.0) / sd;
107 r.pvalue = 2.0 * (1.0 - sim_normcdf(std::fabs(r.zscore)));
108 r.reject = r.pvalue < alpha;
109 return r;
110}
111
112} // namespace sim
113} // namespace line
114
115#endif // LINE_API_SIM_SIM_VONNEUMANN_H
InputError(const std::string &what)
Definition error.h:39
The exception types the port throws.
VonNeumannResult< T > sim_vonneumann(const std::vector< T > &x, double alpha=0.05)
Von Neumann ratio test for randomness of a sequence.
double sim_normcdf(double z)
Standard normal cumulative distribution function.
Definition sim_dist.h:52
Number-type abstraction for the templated API port.
Normal and Student t quantiles used by the output-analysis routines.
Shared arithmetic helpers for the templated simulation output-analysis port.
Outcome of the von Neumann randomness test.
std::size_t nobs
Number of observations b.
double zscore
Standardized statistic (ratio-2)/sd.
T ratio
The von Neumann ratio.
bool reject
True when pvalue < alpha, i.e. randomness is rejected.
double pvalue
Two-sided p-value.