% $Id: RDieHarder.Rnw,v 1.3 2007/05/16 20:13:37 edd Exp $ \documentclass[10pt]{article} \usepackage{vmargin,url,hyperref,booktabs,graphicx,rotating} \usepackage[authoryear,round]{natbib} \setpapersize{USletter} % use USletter paper \setmarginsrb{1in}{1in}{1in}{1in}{0pt}{0pt}{\footheight}{\footskip} \hypersetup{ hyperindex,% colorlinks,% linktocpage,% plainpages=false,% linkcolor=DarkBlue,% citecolor=DarkBlue,% urlcolor=DarkBlue,% pdfstartview=Fit,% pdfview={XYZ null null null}% } \RequirePackage{color} \definecolor{Red}{rgb}{0.7,0,0} \definecolor{Blue}{rgb}{0,0,0.8} \definecolor{DarkBlue}{rgb}{0.1,0.1,0.4} \definecolor{DarkGrey}{rgb}{0.15,0.15,0.15} %% from jss.cls \let\code=\texttt \let\proglang=\textsf \newcommand{\pkg}[1]{{\normalfont\fontseries{b}\selectfont #1}} %% shortcuts \newcommand{\diehard}{\textrm{DieHard}} \newcommand{\dieharder}{\textrm{Die}\textsl{Harder}} \newcommand{\rdieharder}{\pkg{RDieHarder}} \newcommand{\wikinote}[2]{#2\footnote{C.f.~the Wikipedia entry \url{http://www.wikipedia.org/wiki/#1}.}} %% \begin{document} \SweaveOpts{engine=R,eps=FALSE} %\VignetteIndexEntry{RDieHarder} %\VignetteDepends{RDieHarder} %\VignetteKeywords{random number generator, tests} %\VignettePackage{RDieHarder} <>= library(RDieHarder) options(SweaveHooks=list(twofig=function() {par(mfrow=c(1,2))}, twofig2=function() {par(mfrow=c(2,1))}, onefig=function() {par(mfrow=c(1,1))})) prettyVersion <- packageDescription("RDieHarder")$Version prettyDate <- format(Sys.Date(), "%B %e, %Y") @ \title{\pkg{RDieHarder}: An R interface to the \dieharder\ suite of Random Number Generator Tests} \author{\href{http://dirk.eddelbuettel.com}{Dirk Eddelbuettel} \\ Debian \\ \url{edd@debian.org} \and \href{http://www.phy.duke.edu/~rgb}{Robert G. Brown} \\ Physics, Duke University \\ \url{rgb@phy.duke.edu} } \date{Initial Version as of May 2007\\ \footnotesize Rebuilt on \Sexpr{prettyDate} using RDieHarder \Sexpr{prettyVersion}} \maketitle \iffalse \begin{abstract} \noindent The \pkg{RDieHarder} package provides the R language and environment with access to the \dieharder\ suite of tests for random number generators (RNGs). It allows interactive tests of random numbers generators directly from R, with further analysis in R of data generated by \dieharder. This paper describes the background and motivation of \dieharder, the \rdieharder\ package, shows two simple examples, and discusses current limitations and possible extensions left for future work. \end{abstract} \fi \section{Introduction} Random number generators are critically important for computational statistics. Simulation methods are becoming ever more common for estimation; Monte Carlo Markov Chain is but one approach. Also, simulation methods such as the Bootstrap have long been used in inference and are becoming a standard part of a rigorous analysis. As random number generators are at the heart of the simulation-based methods used throughout statistical computing, `good' random numbers are therefore a crucial aspect of a statistical, or quantitative, computing environment. However, there are very few tools that allow us to separate `good' from `bad' random number generators. Based on work that started with the \pkg{random} package \citep{Eddelbuettel:random:2007} (which provides functions that access a non-deterministic random number generator (NDRNG) based on a physical source of randomness), we wanted to compare the particular NDRNG to the RNGs implemented in GNU R \citep{RCore:R:2007} itself, as well as to several RNGs from the GNU GSL \citep{gsl:2007}, a general-purpose scientific computing library. Such a comparison is possible with the \dieharder\ test suite by \cite{Brown:dieharder:2007} which extends the \diehard\ test suite by Marsaglia. From this work, we became interested in making \dieharder\ directly accessible from GNU R. The \rdieharder\ package presented here allows such access. This paper is organized as follows. Section 2 describes the history and design of the \dieharder\ suite. Section 3 describes the \rdieharder\ package facilities, and section 4 shows some examples. Section 5 discusses current limitations and possible extensions before section 6 concludes. \section{\dieharder} \dieharder\ is described at length in \cite{Brown:dieharderpaper:2006}. Due to space limitations, this section cannot provide as much detail and will cover only a few key aspects of the DieHarder suite. \subsection{\diehard} \dieharder\ reimplements and extends George Marsaglia's \textsl{Diehard Battery of Tests of Randomness} \citep{Marsaglia:1996}. Due to both its robust performance over a wide variety of RNGs, as well as an ability to discern numerous RNGs as weak, \diehard\ has become something close to a `gold standard' for assessing RNGs. However, there are a number of drawbacks with the existing \diehard\ test battery code and implementation. First, Marsaglia undertook a large amount of the original work a number of years ago when computing resources were, compared to today's standards, moderately limited. Second, neither the Fortran nor the (translated) C sources are particularly well documented, or commented. Third, the library design is not modular in a way that encourages good software engineering. Fourth, and last but not least, no licensing statement is provided with the sources or on the support website. This led one of the authors of this paper (rgb) to a multi-year effort of rewriting the existing tests from \diehard\ in a) standard C in a modular and extensible format, along with extensive comments, and to b) relicense it under the common and understood GNU GPL license (that is also used for GSL, R, the Linux kernel, and numerous other projects) allowing for wider use. Moreover, new tests from NIST were added (see next subsection) and some genuinely new tests were developed (see below). \subsection{STS} The National Institute of Standards and Technology (NIST) has developed its own test suite, the 'Statistical Test Suite' (STS). These tests are focussed on bit-level tests of randomness and bit sequences. %\marginpar{TODO: expand} Currently, three tests based on the STS suite are provided by \dieharder: \textsl{STS Monobit}, \textsl{STS Runs} and \textsl{STS Block}. \subsection{RGB extensions} %\marginpar{TODO: expand} Three new tests have been developed by rgb. A fourth 'test' is a timing function: for many contexts, not only do the mathematical properties of a generator matter, but so does computational cost measured in computing time that is required for a number of draws. \subsection{Basic methodology} Let us suppose a random number generator can provides a sequence of $N$ uniform draws from the range $[0, 1)$. As the number of draws increases, the mean of the sum of all these values should, under the null hypothesis of a proper generator, converge closer and closer to $\mu = N / 2$. Each of these $N$ draws forms one experiment. If $N$ is sufficiently large, then the means of all experiments should be normally distributed with a standard deviation of $\sigma = \sqrt{ N / 12}$.\footnote{This is known as the Irwin-Hall distribution, see \url{http://en.wikipedia.org/wiki/Irwin-Hall_distribution}.} Given this asymptotic result, we can, for any given experiment $i \in 1, \ldots, M$ transform the given sum $x_i$ of $N$ draws into a probability value $p_i$ using the inverse normal distribution.\footnote{Running \code{print(quantile(pnorm(replicate(M,(sum(runif(N))-N/2)/sqrt(N/12))), seq(0,1,by=0.1))*100, digits=2)} performs a Monte Carlo simulation of $M$ experiments using $N$ uniform deviates to illustrate this. Suitable values are e.g. \code{N <- 1000; M <- 500}.} The key insight is that, under the null hypothesis of a perfect generator, these $p_i$ values should be uniformly distributed. Using our set of $M$ probability values, we can compute one 'meta-test' of whether we can reject the null of a perfect generator by rejecting that our $M$ probability values are not uniformly distributed. One suitable test is for example the non-parametric \wikinote{Kolmogorov-Smirnov\_test}{Kolmogorov-Smirnov (KS)} statistic. \dieharder\ uses the \wikinote{Kuiper\%27s\_test}{Kuiper} variant of the KS test which uses the combination $D_+ + D_-$ of the maximum and minimum distance to the alternative distribution, instead of using just one of these as in the case of the KS test. This renders the test more sensitive across the entire test region. \subsection{GSL framework} \dieharder\ is primarily focussed on tests for RNGs. Re-implementing RNGs in order to supply input to the tests is therefore not an objective of the library. The GNU Scientific Library (GSL), on the other hand, provides over 1000 mathematical functions, including a large number of random number generators. Using the GSL 1.9.0 release, the following generators are defined\footnote{This is based on the trailing term in each identifier defined in \texttt{/usr/include/gsl/gsl\_rng.h}.}: \begin{quote} \small \texttt{borosh13 coveyou cmrg fishman18 fishman20 fishman2x gfsr4 knuthran knuthran2 knuthran2002 lecuyer21 minstd mrg mt19937 mt19937\_1999 mt19937\_1998 r250 ran0 ran1 ran2 ran3 rand rand48 random128\_bsd random128\_glibc2 random128\_libc5 random256\_bsd random256\_glibc2 random256\_libc5 random32\_bsd random32\_glibc2 random32\_libc5 random64\_bsd random64\_glibc2 random64\_libc5 random8\_bsd random8\_glibc2 random8\_libc5 random\_bsd random\_glibc2 random\_libc5 randu ranf ranlux ranlux389 ranlxd1 ranlxd2 ranlxs0 ranlxs1 ranlxs2 ranmar slatec taus taus2 taus113 transputer tt800 uni uni32 vax waterman14 zuf} \end{quote} The GNU GSL, a well-known and readily available library of high quality, therefore provides a natural fit for \dieharder. All of these generators are available in \dieharder\ via a standardized interface in which a generator is selected, parameterized as needed and the called via the external GSL library against which \dieharder\ is linked. Beyond these GSL generators, \dieharder\ also provides two generators based on the `devices' \texttt{/dev/random} and \texttt{/dev/urandom} that are commonly available on Unix. They provide non-deterministic random-numbers based on entropy generated by the operating system. \dieharder\ also offers a text and a raw file input generators. Lastly, a new algorithmic generator named 'ca' that is based on cellular automata has recently been added as well. \subsection{R random number generators} To assess the quality of the non-deterministic RNG provided in the GNU R add-on package \pkg{random}, benchmark comparisons with the generators provided by the R language and environment have been a natural choice. To this end, one of the authors (edd) ported the R generator code (taken from R 2.4.0) to the GNU GSL random number generator framework used by \dieharder. %\marginpar{TODO: use R sources from R 2.5.0} This allows a direct comparison of the \pkg{random} generator with those it complements in R. It then follows somewhat naturally that the other generators available in \dieharder, as well as the \dieharder\ tests, should also be available in R. This provided the motivation for the R package presented here. \subsection{Source code and building \dieharder} Recent versions of \dieharder\ use the GNU autotools. On Unix system, the steps required to build and install \dieharder\ should only be the familiar steps \texttt{configure; make; sudo make install}. For Debian, initial packages have been provided and are currently available at \url{http://dirk.eddelbuettel.com/code/tmp}. Within due course, these packages should be uploaded to Debian, and thus become part of the next Debian (and Ubuntu) releases. \dieharder\ is also expected to be part of future Fedora Core (and other RPM-based distribution) releases. On Windows computers and other systems, manual builds should also be possible given that the source code is written in standard C. \section{\rdieharder} The \rdieharder\ package provides one key function: \texttt{dieharder}. It can be called with several arguments. The first one is the name of the random number generator, and the second one is the name of the test to be applied. For both options, the textual arguments are matched against internal vectors to obtain a numeric argument index; alternatively the index could be supplied directly. The remaining arguments (currently) permit to set the number of samples (i.e.~the number of experiments run, and thus the sample size for the final Kolmogorov-Smirnov test), the random number generator seed and whether or not verbose operation is desired. The returned object is of class \texttt{dieharder}, inheriting from the standard class \texttt{htest} common for all hypothesis tests. The standard print method for \texttt{htest} is used; however not all possible slots are being filled (as there is for example no choice of alternative hypothesis). A custom summary method is provided that also computes the Kolmogorov-Smirnov and Wilcoxon tests in R and displays a simple stem-and-leaf plot. Lastly, a custom plot method shows both a histogram and kernel density estimate, as well as the empirical cumulative distribution function. \section{Examples} The possibly simplest usage of \rdieharder\ is provided in the examples section of the help page. The code \texttt{dh <- dieharder; summary(dh); plot(dh)} simply calls the \texttt{dieharder} function using the default arguments, invokes a summary and then calls plot on the object.\footnote{We omit the output here due to space constraints.} A more interesting example follows below. We select the \texttt{2dsphere} test for the generators \texttt{ran0} and \texttt{mt19937} with a given seed. The results based on both the Kuiper KS test and the KS test suggest that we would reject \texttt{ran0} but not \texttt{mt19937}, which is in accordance with common knowledge about the latter (the Mersenne Twister) being a decent RNG. It is worth nothing that the Wilcoxon test centered on $\mu=0.5$ would not reject the null at conventional levels for \texttt{ran0}. \setkeys{Gin}{width=0.47\textwidth} <>= if (file.exists("RDieHarder.Rdata")) load("RDieHarder.Rdata") @ \begin{figure}[htbp] \begin{center} % <>= if (!exists("dh")) dh <- dieharder("ran0","diehard_2dsphere",seed=2) #dh plot(dh) @ <>= if (!exists("dh1")) dh1 <- dieharder("mt19937","diehard_2dsphere",seed=2) #dh1 plot(dh1) @ % \caption{Comparison of \texttt{ran0} and \texttt{mt19937} under test \texttt{2dsphere}} \end{center} \end{figure} A programmatic example follows. We define a short character vector containing the names of the six R RNGs, apply the \dieharder\ function to each of these, and then visualize the resulting $p$-values in simple qqplot. \setkeys{Gin}{width=0.85\textwidth} \begin{figure}[htbp] \begin{center} \begin{footnotesize} % <>= rngs <- c("R_wichmann_hill", "R_marsaglia_multic", "R_super_duper", "R_mersenne_twister", "R_knuth_taocp", "R_knuth_taocp2") if (!exists("rl")) rl <- lapply(rngs, function(rng) dieharder(rng, "diehard_runs", seed=12345)) oldpar <- par(mfrow=c(2,3), mar=c(2,3,3,1)) invisible(lapply(rl, function(res) { qqplot(res$data, seq(0, 1, length.out=length(res$data)), main=paste(res$generator, ":", round(res$p.value, digits=3)), ylab="", type="S") abline(0, 1, col='gray') })) par(oldpar) # reset graph defaults @ % \end{footnotesize} \caption{Comparing six GNU R generators under the \texttt{runs} test} \end{center} \end{figure} <<>= save(dh, dh1, rl, file="RDieHarder.Rdata") @ All six generators provide $p$-value plots that are close to the ideal theoretical outcome (shown in gray). Unsurprisingly, $p$-values for the Kuiper KS test also show no support for rejecting these generators. \section{Current Limitations and Future Research} The implementation of \rdieharder\ presented here leaves a number of avenues for future improvement and research. Some of these pertain to \dieharder\ itself -- adding new, more sophisticated, more systematic tests including those from the STS suite and tests that probe bitlevel randomness in unique new ways. Others pertain more to the integration of \dieharder\ with R, which is the topic of this work. Not all of \dieharder's features are yet supported in this initial port. In the near future we expect to add code to deal with tests that support extra parameters, or that return more than one p-value per instance of a test. Ultimately, \rdieharder\ should support the full set of options of the the command-line version of \dieharder. There is no direct interface from the R generators to the \rdieharder\ module for evaluation; rather, the 'ported' R generators are called from the libdieharder library. This could introduce coding/porting errors, and also prevents the direct use of user-added generators that R supports. It would be worthwhile to overcome this by directly letting \rdieharder\ call back into R to generate draws. On the other hand, the current setup corresponds more closely to the command-line version of \dieharder. Next, the R generators in \dieharder\ may need to be updated to the 2.5.0 code. The GSL RNGs provided by libdieharder may as well be exported to R via \rdieharder\ given that the GSL library is already linked in. Indeed, it would be worthwhile to {\em integrate} the two projects and both avoid needless code duplication and ensure even more eyes checking both the quality and accuracy of the code in both. It could be useful to also build \rdieharder\ with an `embedded' libdieharder rather than relying on an externally installed libdieharder. This may make it easier to build \rdieharder\ for systems without libdieharder (and on Windows). Likewise, it is possible to reorganize the \dieharder\ front-end code into a common library to avoid duplication of code with \rdieharder. Lastly, on the statistical side, an empirical analysis of size/power between KS, Wilcoxon and other alternatives for generating a final p-value from the vector of p-values returned from \dieharder\ tests suggests itself. Similarly, empirical comparisons between the resolving power of the various tests (some of which may not actually be terribly useful in the sense that they yield new information about the failure modes of any given RNG) could be undertaken. Lastly, there is always room for new generators, new tests, and new visualizations. One thing that one should remember while experimenting with \dieharder\ is that there really is no such thing as a {\em random} number {\em generator}. It is therefore likely that {\em all} RNGs will fail any given (valid) test if one cranks up the ``resolution'' up high enough by accumulating enough samples per p-value, enough p-values per run. It is also true that a number of Marsaglia's tests have target distributions that were computed empirically by simulation (with the best RNGs and computers available at the time). Here one has to similarly remember that one can do in a few hours of work what it would have taken him months if not years of simulation to equal back when the target statistics were evaluated. It is by no means unlikely that a ``problem'' that \dieharder\ eventually resolves is not not the quality of the RNG but rather the accuracy of the target statistics. These are some of the things that are a matter for future research to decide. A major motivation for writing \dieharder\, and making it open source, and integrating it with $R$, is to facilitate precisely this sort of research in an easy to use, consistent testing framework. We {\em welcome} the critical eyes and constructive suggestions of the statstical community and invite their participation in examining the code and algorithms used in \dieharder. \section{Conclusion} The \rdieharder\ package presented here introduces several new features. First, it makes the \dieharder\ suite \citep{Brown:dieharder:2007} available for interactive use from the GNU R environment. Second, it also exports \dieharder\ results directly to R for further analysis and visualization. Third, it adds adds additional RNGs from GNU R to those from GNU GSL that were already testable in \dieharder. Fourth, it provides a re-distribution of the \dieharder\ `test engine' via GNU R. \bibliographystyle{plainnat} \bibliography{RDieHarder} \end{document}