// Autocorrelation tests whether or not a generator produces independent results. // The parameters are the dataset ds, // start, the first index looked at by the test // and jump, the ith index looked starting at (start) func Autocorrelation(ds *RandGenerator.Dataset, start, jump int) (float64, float64) { // Index1 and Index2 keep tracks of when to break from the loop, as the array will be out of bounds when index2 is exceeds M var ( index1 = start index2 = start + jump total = 0.0 k int ) // Summation of each of the potentially correlated indices for k = 0; index2 < ds.Len(); k++ { total += ds.Get(index1) * ds.Get(index2) index1 = start + jump*k index2 = start + jump*(k+1) } // Now, take the total and divide it by the number of iterations + 1 mu := total / float64((k + 1)) mu -= 0.25 // Magic number provided by Professor Lipschultz in the slides // calculate the variance squaredVal := float64(13*k + 7) demoninator := float64(12 * (k + 1)) variance := math.Sqrt(squaredVal) / demoninator return mu, variance }
// The first option maps the difference between the value and the mean to a binary enum func generateMeanRuns(ds *RandGenerator.Dataset) []bool { runs := make([]bool, ds.Len()) mean := ds.Mean() for i := 0; int(i) < int(ds.Len()); i++ { point := ds.Get(i) runs[i] = math.Signbit(point - mean) } return runs }
// The second method takes the difference between increasing indices and maps the sign of the difference to a binary result func generateDifferenceRuns(ds *RandGenerator.Dataset) []bool { runs := make([]bool, ds.Len()-1) for i := 0; i < ds.Len()-1; i++ { point1 := ds.Get(i) point2 := ds.Get(i + 1) runs[i] = math.Signbit(point1 - point2) } return runs }
func KolmogorovSmirnov(ds *RandGenerator.Dataset) float64 { ds = ds.Subset(0, 100).Sort() // only select the first 100 numbers, and sort them max := 0.0 // Find the maximum difference from the expected value to the observed value for i := 0; i < ds.Len(); i++ { observed := ds.Get(i) expected := float64(i) / float64(ds.Len()) distence := math.Abs(observed - expected) if distence > max { max = distence } } return max }
func ChiSquared(ds *RandGenerator.Dataset) float64 { var buckets []int = make([]int, 10) for i := 0; i < 10; i++ { buckets[i] = 0 } for i := 0; i < ds.Len(); i++ { num := ds.Get(i) switch { case num < 0.1: buckets[0] += 1 case 0.1 <= num && num < 0.2: buckets[1] += 1 case 0.2 <= num && num < 0.3: buckets[2] += 1 case 0.3 <= num && num < 0.4: buckets[3] += 1 case 0.4 <= num && num < 0.5: buckets[4] += 1 case 0.5 <= num && num < 0.6: buckets[5] += 1 case 0.6 <= num && num < 0.7: buckets[6] += 1 case 0.7 <= num && num < 0.8: buckets[7] += 1 case 0.8 <= num && num < 0.9: buckets[8] += 1 case 0.9 <= num && num < 1.0: buckets[9] += 1 default: log.Fatal("Generate produced a value greater than 1.0") } } testStatistic := 0.0 for _, bucket := range buckets { var expected = ds.Len() / 10.0 bucketVal := float64(bucket) testStatistic += ((bucketVal - float64(expected)) * (bucketVal - float64(expected))) / float64(expected) } return testStatistic }
func main() { app := cli.NewApp() var ( size int outputFile string gen RandGenerator.Generator ds *RandGenerator.Dataset ) const ( SEED = 122949823 ) app.Flags = []cli.Flag{ cli.IntFlag{ Name: "n", Value: 10000, Usage: "number of elements to generate. Defaults to 10000. NOTE: Kolgorov only uses the first 100", Destination: &size, }, cli.StringFlag{ Name: "f", Value: "output.txt", Usage: "File to which the output is written, defaults to output.txt", Destination: &outputFile, }, } // Specifies how to interact with the command line tool. // See https://github.com/codegangsta/cli for explanation app.Commands = []cli.Command{ { Name: "kolmogorov", Aliases: []string{"k"}, Usage: "run the Kolmogov-Smirnov Test for uniformity", Action: func(c *cli.Context) { println("Please specify a subcommand. See -h for a list of commands.") cli.ShowSubcommandHelp(c) }, Subcommands: []cli.Command{ { Name: "stdlib", Usage: "uses the Golang standard library generator, found in 'golang.org/pkg/math/rand'", Action: func(c *cli.Context) { gen = rand.New(rand.NewSource(SEED)) ds = RandGenerator.NewDataset(gen, size) fmt.Printf("Standard Library Kolmogorov Test Statistic:\t%f\n", StatTests.KolmogorovSmirnov(ds)) }, }, { Name: "lipschultz", Usage: "uses the generator seeded as a = 101427, c = 321, m = 1 << 16", Action: func(c *cli.Context) { gen = RandGenerator.LipschultzGen() gen.Seed(SEED) ds = RandGenerator.NewDataset(gen, size) fmt.Printf("Lipschultz Kolmogorov Test Statistic:\t%f\n", StatTests.KolmogorovSmirnov(ds)) }, }, { Name: "randu", Usage: "uses the generator seeded as a = 65539, c = 0, m = 1 << 31", Action: func(c *cli.Context) { gen = RandGenerator.NewRANDUGen() gen.Seed(SEED) ds = RandGenerator.NewDataset(gen, size) fmt.Printf("RANDU Kolmogorov Test Statistic:\t%f\n", StatTests.KolmogorovSmirnov(ds)) }, }, }, }, { Name: "runs", Aliases: []string{"r"}, Usage: "runs Test for independence", Action: func(c *cli.Context) { cli.ShowSubcommandHelp(c) }, Subcommands: []cli.Command{ { Name: "stdlib", Usage: "uses the Golang standard library generator, found in 'golang.org/pkg/math/rand'", Action: func(c *cli.Context) { gen = rand.New(rand.NewSource(SEED)) ds = RandGenerator.NewDataset(gen, size) fmt.Printf("Standard Library Run Test Statistic:\t%f\n", StatTests.Run(ds, StatTests.DIFFERENCE)) }, }, { Name: "lipschultz", Usage: "uses the generator seeded as a = 101427, c = 321, m = 1 << 16", Action: func(c *cli.Context) { gen = RandGenerator.LipschultzGen() gen.Seed(SEED) ds = RandGenerator.NewDataset(gen, size) fmt.Printf("Lipschultz Run Test Statistic:\t%f\n", StatTests.Run(ds, StatTests.DIFFERENCE)) }, }, { Name: "randu", Usage: "uses the generator seeded as a = 65539, c = 0, m = 1 << 31", Action: func(c *cli.Context) { gen = RandGenerator.NewRANDUGen() gen.Seed(SEED) ds = RandGenerator.NewDataset(gen, size) fmt.Printf("RANDU Run Test Statistic:\t%f\n", StatTests.Run(ds, StatTests.DIFFERENCE)) }, }, }, }, { Name: "autocorrelation", Aliases: []string{"a"}, Usage: "autocorrelation test for independence", Action: func(c *cli.Context) { cli.ShowSubcommandHelp(c) os.Exit(0) }, Subcommands: []cli.Command{ { Name: "stdlib", Usage: "uses the Golang standard library generator, found in 'golang.org/pkg/math/rand'", Action: func(c *cli.Context) { gen = rand.New(rand.NewSource(SEED)) ds = RandGenerator.NewDataset(gen, size) mu, variance := StatTests.Autocorrelation(ds, 1, 3) fmt.Printf("Standard Library Autocorrelation Test Statistic:\t%f\n", mu/variance) }, }, { Name: "lipschultz", Usage: "uses the generator seeded as a = 101427, c = 321, m = 1 << 16", Action: func(c *cli.Context) { gen = RandGenerator.LipschultzGen() gen.Seed(SEED) ds = RandGenerator.NewDataset(gen, size) mu, variance := StatTests.Autocorrelation(ds, 1, 3) fmt.Printf("Lipschultz Autocorrelation Test Statistic:\t%f\n", mu/variance) }, }, { Name: "randu", Usage: "uses the generator seeded as a = 65539, c = 0, m = 1 << 31", Action: func(c *cli.Context) { gen = RandGenerator.NewRANDUGen() gen.Seed(SEED) ds = RandGenerator.NewDataset(gen, size) mu, variance := StatTests.Autocorrelation(ds, 1, 3) fmt.Printf("RANDU Autocorrelation Test Statistic:\t%f\n", mu/variance) }, }, }, }, { Name: "chi", Aliases: []string{"c"}, Usage: "Chi-Square Frequency Test for uniformity", Action: func(c *cli.Context) { cli.ShowSubcommandHelp(c) }, Subcommands: []cli.Command{ { Name: "stdlib", Usage: "uses the Golang standard library generator, found in 'golang.org/pkg/math/rand'", Action: func(c *cli.Context) { gen = rand.New(rand.NewSource(SEED)) ds = RandGenerator.NewDataset(gen, size) fmt.Printf("Standard Library Chi Square Test Statistic:\t%f\n", StatTests.ChiSquared(ds)) }, }, { Name: "lipschultz", Usage: "uses the generator seeded as a = 101427, c = 321, m = 1 << 16", Action: func(c *cli.Context) { gen = RandGenerator.LipschultzGen() gen.Seed(SEED) ds = RandGenerator.NewDataset(gen, size) fmt.Printf("Lipschultz Chi Square Test Statistic:\t%f\n", StatTests.ChiSquared(ds)) }, }, { Name: "randu", Usage: "uses the generator seeded as a = 65539, c = 0, m = 1 << 31", Action: func(c *cli.Context) { gen = RandGenerator.NewRANDUGen() gen.Seed(SEED) ds = RandGenerator.NewDataset(gen, size) fmt.Printf("RANDU Chi Square Test Statistic:\t%f\n", StatTests.ChiSquared(ds)) }, }, }, }, } app.Run(os.Args) file, err := os.Create(outputFile) if err != nil { panic(err) } // close file on exit and check for its returned error defer func() { if err := file.Close(); err != nil { panic(err) } }() w := bufio.NewWriter(file) defer w.Flush() for i := 0; i < ds.Len(); i++ { val := ds.Get(i) w.WriteString(fmt.Sprintf("%f\n", val)) } }