FW: bad rand generator: distribution/prevalences/periodicity

Discussion specific to NXT-G, NXC, NBC, RobotC, Lejos, and more.
HaWe
Posts: 2500
Joined: 04 Nov 2014, 19:00

FW: bad rand generator: distribution/prevalences/periodicity

Post by HaWe »

hello,
I now have tested the random number generator of the Lego FW statistically by 1 million randomizations of numbers between 0-15 (inclusive)
The result is shocking:
Some numbers are generated almost twice as often as others, and, worse, they are always even the same at different test runs :
Lego fw rand function, run number 1
Lego fw rand function, run number 1
LegoRand1.jpg (27.28 KiB) Viewed 9976 times
Lego fw rand function, run number 2
Lego fw rand function, run number 2
LegoRand2.jpg (27.39 KiB) Viewed 9976 times
this is the test code:

Code: Select all

// Test on statistical equal distribution of Lego and customized randomization

#define printf1( _x, _y, _format1, _value1) { \
  string sval1 = FormatNum(_format1, _value1); \
  TextOut(_x, _y, sval1); \
}
char LCDline[]={56,48,40,32,24,16,8,0};

task main(){
  long i, j;
  long H[16];            // prevalence counter array


                         // print output matrix
  for (j=0; j<16; ++j) {
    printf1(0+(j%2)*50, LCDline[j/2], "%2d:", j);
  }

  //srand(1);       // standard seed (only for customized randomization function)

  for (i=0; i<1000000; ++i) {
  
    // 1 Million randomizations of numbers between 0...15
  
    j=rand()%16;        // std Lego FW randomization function
    // alternatively:
    //j=rand_()%16;       // customized randomization function
    
    H[j]+=1;            // add +1 to the prevalence to the related counter
       
                        // print prevalence test distribution
                        
    printf1(16+(j%2)*50,LCDline[j/2], "%5d", H[j]);
  }
  
  PlaySound(SOUND_FAST_UP);
  
  while(1) {}
}

Now I tested the code I got from a guy from a German Informatik-Forum https://bildungs-foren.de/foren/viewforum.php?f=3 which I already published here in a different thread :

Code: Select all

// Test on statistical equal distribution
//of Lego and customized randomization functions

#define printf1( _x, _y, _format1, _value1) { \
  string sval1 = FormatNum(_format1, _value1); \
  TextOut(_x, _y, sval1); \
}
char LCDline[]={56,48,40,32,24,16,8,0};


//********************************************
// randomize functions
//********************************************

// global variables and functions to plant a random seed and to randomize
// how to use:
// srand(x)                         // x = val. for repet. sequences
// myVar = rand_() % 100;           // assignes a random number


unsigned long _RAND_SEED_ = 1;      // 1= default value (program start)
unsigned long _OLD_SEED_  = 1;


//--------------------------------------------

unsigned long rand_()               // random function
{
  _RAND_SEED_ = _RAND_SEED_ * 1103515245 + 12345;
  return (_RAND_SEED_ % (RAND_MAX + 1));
}

//--------------------------------------------

void srand(unsigned long seed)      // seeds for a new random series
{

  if (seed==0)                      // 0: a "real" randomized random seed
    {seed = abs(CurrentTick()*BatteryLevel());}  // substitute to time(0)

  else
  if (seed==-1) {                   // -1: restore last random series
    seed = _OLD_SEED_;
  }

  _OLD_SEED_  = seed;
  _RAND_SEED_ = seed;               // patch for rand_ function
}


//--------------------------------------------


task main(){
  long i, j;
  long H[16];            // prevalence counter array


                         // print output matrix
  for (j=0; j<16; ++j) {
    printf1(0+(j%2)*50, LCDline[j/2], "%2d:", j);
  }

                         //  (only for customized randomization function)
  srand(1);              //  reproducible standard seeds 1 (2, 3, 4, ...)
                         //  alternatively:
  //srand(0);            //  randomized random seed (time(0)*Voltage)

  for (i=0; i<1000000; ++i) {
  
    // 1 Million randomizations of numbers between 0...15
  
    //j=rand()%16;        // std Lego FW randomization function
    // alternatively:

    j=rand_()%16;       // customized randomization function
    
    
    H[j]+=1;            // add +1 to the prevalence to the related counter

                        // print prevalence test distribution
                        
    printf1(16+(j%2)*50,LCDline[j/2], "%5d", H[j]);
  }
  
  PlaySound(SOUND_FAST_UP);
  
  while(1) {}

}
Result: absolutely equally distributed prevalence!
custom rand_ function, initialized by standard seed = 1
custom rand_ function, initialized by standard seed = 1
CustRand1.jpg (27.53 KiB) Viewed 9976 times
Last edited by HaWe on 09 Jun 2013, 15:46, edited 7 times in total.
HaWe
Posts: 2500
Joined: 04 Nov 2014, 19:00

Re: Lego FW: extreme poor equal distribution of random series

Post by HaWe »

ps:
this is the 2nd run of the custom random function rand_(), seed(0)= (systemTime*BatterLevel) - also perfectly equally distributed:
custom random function, 2nd run, seed(0)= (systemTime*BatterLevel)
custom random function, 2nd run, seed(0)= (systemTime*BatterLevel)
CustRand0.jpg (27.37 KiB) Viewed 9976 times
muntoo
Posts: 834
Joined: 01 Oct 2010, 02:54
Location: Your Worst Nightmare
Contact:

Re: Lego FW:extrem poor equal distribution of random prevalences

Post by muntoo »

I know. My "randomly generated" mazes were so un-random, and followed a very obvious pattern that I'd almost given up trying to generate random mazes. Even the Mersenne Twister didn't work, for some reason. Or maybe it was my code
(I might have done something dumb like:

Code: Select all

int rand4()
{
    return(Random() >= 4 ? 3 : Random());
}
)
Image

Commit to LEGO Mindstorms Robotics Stack Exchange:
bit.ly/MindstormsSE


Commit to LEGO Stack Exchange: bit.ly/Area51LEGOcommit
HaWe
Posts: 2500
Joined: 04 Nov 2014, 19:00

Re: Lego FW:extrem poor equal distribution of random prevalences

Post by HaWe »

if you wish try my code! :)
spillerrec
Posts: 358
Joined: 01 Oct 2010, 06:37
Location: Denmark
Contact:

Re: Lego FW:extrem poor equal distribution of random prevalences

Post by spillerrec »

I don't know much about the subject, however I know it is normally recommended not to use modulus when using small ranges.
Try the standard NXC random function instead:

Code: Select all

j=Random(16);
It is only about 26000 right now, but they are perfectly equally distributed.

I remember looking into the NBC code for rand() and Random() and they are quite different and I think there was something weird with one of them. I don't quite remember what (as it was half a year ago) and I don't have time today since I need to attend my final exam in Computer Science tomorrow...

ARGH, the NXT automatically turned off at about 36000... -__-
My blog: http://spillerrec.dk/category/lego/
RICcreator, an alternative to nxtRICeditV2: http://riccreator.sourceforge.net/
HaWe
Posts: 2500
Joined: 04 Nov 2014, 19:00

Re: Lego FW:extrem poor equal distribution of random prevalences

Post by HaWe »

modulo is the regular way to get a range of random numbers by using rand() in ANSI C code.
http://www.c-plusplus.de/forum/39344
http://www.daniweb.com/software-develop ... reads/1769
if modulo gives faulty prevalences then (edit: above all!) also the underlying NXC rand() function is faulty (independend of the size of the range, whether small or big).
But maybe the not-C-function Random() might indeed work better...
Last edited by HaWe on 16 Jun 2011, 21:53, edited 1 time in total.
spillerrec
Posts: 358
Joined: 01 Oct 2010, 06:37
Location: Denmark
Contact:

Re: Lego FW:extrem poor equal distribution of random prevalences

Post by spillerrec »

Yes, modulus is the regular way, but that doesn't mean it is the best way.
As far as I have heard the issue is that many number generators isn't random enough at the lower significant bits, so you need to use bits at a higher range of bit to ensure that it is completely random. This is where modulus with lower values fail.
If you do a bit of searching you can find some of the other methods to limit rand() which does not use modulus.

Both rand() and Random( x ) use the same random number generator however Random( x ) limits the range with some arithmetics I didn't quite understood, but as you can see it clearly makes a difference. I will look into how the NBC code is generated tomorrow.
My blog: http://spillerrec.dk/category/lego/
RICcreator, an alternative to nxtRICeditV2: http://riccreator.sourceforge.net/
HaWe
Posts: 2500
Joined: 04 Nov 2014, 19:00

Re: Lego FW:extrem poor equal distribution of random prevalences

Post by HaWe »

spiller wrote:As far as I have heard the issue is that many number generators isn't random enough at the lower significant bits
Helmut wrote:if modulo gives faulty prevalences then (above all!) also the underlying NXC rand() function is faulty (independend of the size of the range, whether small or big).
MY random generator IS good enough even at low bits :)
I'm on a "long weekend vacation" from Friday enening, but some other tests will have to be done, e.g. the examiniation of the statistical equal deviation of the difference of all sequential numbers to prove if there are obscured serial dependencies of generated numbers...
... the equal distribution of 2 consecutive numbers...
...the examiniation of the statistical Normal (Gaussian) deviation of the differences of the differences of the the statistical equal deviation of all sequential numbers...
...and then other tests if there are illegal clusters of sequential sub-series ("real random numbers series" in fact always have some "legal clusters" but the difference of both is not easily to distinguish (or: differ?) from each other )...
...and...
...and...
muntoo
Posts: 834
Joined: 01 Oct 2010, 02:54
Location: Your Worst Nightmare
Contact:

Re: Lego FW:extrem poor equal distribution of random prevalences

Post by muntoo »

I've set up a Mercurial repository for NXC-based RNG libraries here. If you want to become a contributor (and are comfortable with version control systems), PM me your email or "fork and pull request".
Image

Commit to LEGO Mindstorms Robotics Stack Exchange:
bit.ly/MindstormsSE


Commit to LEGO Stack Exchange: bit.ly/Area51LEGOcommit
muntoo
Posts: 834
Joined: 01 Oct 2010, 02:54
Location: Your Worst Nightmare
Contact:

Re: Lego FW:extrem poor equal distribution of random prevalences

Post by muntoo »

Here's how Java implements their rejection sampling for Random.nextInt(). You don't want to be out done by those losers, do you? :)
Image

Commit to LEGO Mindstorms Robotics Stack Exchange:
bit.ly/MindstormsSE


Commit to LEGO Stack Exchange: bit.ly/Area51LEGOcommit
Post Reply

Who is online

Users browsing this forum: No registered users and 3 guests