/* ---------------------------------------------------------------------------- randtest.C mbwall 9may98 Copyright (c) 1998 Matthew Wall, all rights reserved DESCRIPTION: Program to test the random number generator in GAlib. ---------------------------------------------------------------------------- */ #include #include #include #include #include static const int HIST_SIZE=501; static const int NFLIPS=10000; static const long int NUM_CHECKS=1000000L; static const int RCHI=100; int main(int argc, char **argv) { cerr << "This program checks the random number generators in GAlib.\n"; cerr << "These are not rigorous statistical tests, but they should\n"; cerr << "give you a quick indication of whether or not the library is\n"; cerr << "working properly. Command-line options include:\n\n"; cerr << " [+-]chi - do the chi square test (default)\n"; cerr << " [+-]hist - do the histogram tests. Histograms should be\n"; cerr << " nearlyflat, i.e. each number has an equal chance\n"; cerr << " of beingchosen.\n"; cerr << " [+-]bnds - do the bounds tests. All numbers generated\n"; cerr << " should be within the limits specified in the\n"; cerr << " test.\n"; cerr << " [+-]means - do the means tests. A few thousand invocations\n"; cerr << " of each random number function are made, and the\n"; cerr << " averages of these calls are displayed with the\n"; cerr << " number that should have been found.\n"; cerr << " seed n - specify the seed number to use for the RNG. You\n"; cerr << " should get the same results every time if you\n"; cerr << " specify the same seed every time. A seed of 0\n"; cerr << " tells the lib to pick its own seed based upon the\n"; cerr << " current time.\n"; cerr << "\n"; cerr.flush(); int dohist = 0; int dobnds = 0; int domeans = 0; int dochisq = 1; int seed = 0; int i; for(i=1; i= argc) { cerr << "You must enter a number when specifying a random seed.\n"; exit(1); } else { seed = atoi(argv[i]); } } else if(strcmp("+chi", argv[i]) == 0){ dochisq = 1; } else if(strcmp("-chi", argv[i]) == 0){ dochisq = 0; } else if(strcmp("+hist", argv[i]) == 0){ dohist = 1; } else if(strcmp("-hist", argv[i]) == 0){ dohist = 0; } else if(strcmp("+bnds", argv[i]) == 0){ dobnds = 1; } else if(strcmp("-bnds", argv[i]) == 0){ dobnds = 0; } else if(strcmp("+means", argv[i]) == 0){ domeans = 1; } else if(strcmp("-means", argv[i]) == 0){ domeans = 0; } } // Tell us which RNG we're using... cout << argv[0] << ": Random Number Test\n"; cout << "Using the " << GAGetRNG() << " random number generator (RNG).\n"; // initialize the RNG by calling the seed routine with our seed if(seed) cout << "Using specified random seed " << seed << "\n"; GARandomSeed(seed); cout << "Library thinks the random seed is " << GAGetRandomSeed() << "\n"; // the basic chi square test for randomness of a RNG // must do it more than once since it might be wrong about one in ten // times. The error is r*t/N - N and should be within 2*sqrt(r) of r. if(dochisq) { cout << "\n"; cerr << "chi-square test...\n"; cout << "running the chi-square test for randomness of the RNG...\n"; cout << " (there will be some failures of the chi-square test)\n"; int ii; double elimit = 2*sqrt((double)RCHI); double chisq = 0.0; long int NCHI=1000; // NCHI should be >= 10 * RCHI long int f[RCHI]; cerr << " integer test (" << NCHI << ")...\n"; cout << " integer test (" << NCHI << "): chi-squared should be within "; cout << elimit << " of " << RCHI << "\n"; cout.flush(); for(ii=0; ii<10; ii++) { memset(f, 0, RCHI * sizeof(long int)); for(i=0; i elimit) cout << "***failed***"; cout << "\n"; } cout.flush(); NCHI = 10000; cerr << " integer test (" << NCHI << ")...\n"; cout << " integer test (" << NCHI << "): chi-squared should be within "; cout << elimit << " of " << RCHI << "\n"; cout.flush(); for(ii=0; ii<10; ii++) { memset(f, 0, RCHI * sizeof(long int)); long int i; long int t; for(i=0; i elimit) cout << "***failed***"; cout << "\n"; } cout.flush(); NCHI = 10000; cerr << " integer test (" << NCHI << ")...\n"; cout << " integer test (" << NCHI << "): chi-squared should be within "; cout << elimit << " of " << RCHI << "\n"; cout.flush(); for(ii=0; ii<10; ii++) { memset(f, 0, RCHI * sizeof(long int)); long int i; long int t; for(i=0; i elimit) cout << "***failed***"; cout << "\n"; } cout.flush(); NCHI = 100000; cerr << " integer test (" << NCHI << ")...\n"; cout << " integer test (" << NCHI << "): chi-squared should be within "; cout << elimit << " of " << RCHI << "\n"; cout.flush(); for(ii=0; ii<10; ii++) { memset(f, 0, RCHI * sizeof(long int)); long int i; long int t; for(i=0; i elimit) cout << "***failed***"; cout << "\n"; } cout.flush(); } // histograms of the tests if(dohist) { cout << "\n"; cerr << "histograms...\n"; cout << "plotting histograms of calls to random number functions...\n"; int i, j, histogram[HIST_SIZE]; memset(histogram, 0, HIST_SIZE*sizeof(int)); cout << "\n100 random integers in [0, 1] with GARandomInt():\n"; for(i=0; i<100; i++) histogram[GARandomInt()]++; for(i=0; i<=1; i++){ cout << i << "\t"; for(j=0; j 5){ err += 1; } } if(err) cout << " " << err << " values out of bounds.\n"; else cout << "ok\n"; cout.flush(); cerr << " " << NUM_CHECKS << " GARandomInt(0,3)...\n"; cout << "GARandomInt(0,3) ..."; cout.flush(); err = 0; for(ii=0; ii 3){ err += 1; } } if(err) cout << " " << err << " values out of bounds.\n"; else cout << "ok\n"; cout.flush(); cerr << " " << NUM_CHECKS << " GARandomInt(200,255)...\n"; cout << "GARandomInt(200,255) ..."; cout.flush(); err = 0; for(ii=0; ii 255){ err += 1; } } if(err) cout << " " << err << " values out of bounds.\n"; else cout << "ok\n"; cout.flush(); float valf, lastf=0.0; cerr << " " << NUM_CHECKS << " GARandomFloat(-10,5)...\n"; cout << "GARandomFloat(-10,5) ..."; cout.flush(); for(ii=0; ii 5){ err += 1; lastf = valf; } } if(err) cout << " " << err << " values out of bounds (" << lastf << ").\n"; else cout << "ok\n"; cout.flush(); cerr << " " << NUM_CHECKS << " GARandomFloat(0,3)...\n"; cout << "GARandomFloat(0,3) ..."; cout.flush(); err = 0; for(ii=0; ii 3){ err += 1; lastf = valf; } } if(err) cout << " " << err << " values out of bounds (" << lastf << ").\n"; else cout << "ok\n"; cout.flush(); cerr << " " << NUM_CHECKS << " GARandomFloat(200,255)...\n"; cout << "GARandomFloat(200,255) ..."; cout.flush(); err = 0; for(ii=0; ii 255){ err += 1; lastf = valf; } } if(err) cout << " " << err << " values out of bounds (" << lastf << ").\n"; else cout << "ok\n"; cout.flush(); double vald, lastd=0.0; cerr << " " << NUM_CHECKS << " GARandomDouble(-10,5)...\n"; cout << "GARandomDouble(-10,5) ..."; cout.flush(); for(ii=0; ii 5){ err += 1; lastd = vald; } } if(err) cout << " " << err << " values out of bounds (" << lastd << ").\n"; else cout << "ok\n"; cout.flush(); cerr << " " << NUM_CHECKS << " GARandomDouble(0,3)...\n"; cout << "GARandomDouble(0,3) ..."; cout.flush(); err = 0; for(ii=0; ii 3){ err += 1; lastd = vald; } } if(err) cout << " " << err << " values out of bounds (" << lastd << ").\n"; else cout << "ok\n"; cout.flush(); cerr << " " << NUM_CHECKS << " GARandomDouble(200,255)...\n"; cout << "GARandomDouble(200,255) ..."; cout.flush(); err = 0; for(ii=0; ii 255){ err += 1; lastd = vald; } } if(err) cout << " " << err << " values out of bounds (" << lastd << ").\n"; else cout << "ok\n"; cout.flush(); } return 0; }