Pseudo Random

yanomano's picture

I'am trying to generate "Pseudo Random" coordinates for a points structure in javascript, because i need persistents values each time the composition start to run. Basically it is not that bad, however there is a sort of diagonal of fixed points which is tricky...Any Advices ?

Here is the code and the demo comp:

var result = new Object();
 
function (__structure Points) main (__index Iterations,__number SeedX,__number SeedY)
{
   var Maxi=0.5; 
   var Mini=-1;
   var P= new Array()
 
   var CurrentPosition= new Array()
   var Step=1/(Iterations-1)
 
      for (var i=0;i<Iterations;i++){
         P[i]=new Object()
         CurrentPosition[i]=Step*i
 
         /* Generate Pseudo random */
         P[i][0] = i * CurrentPosition[i] % SeedX
         P[i][1] = i * CurrentPosition[i] % SeedY
         P[i][2] = 0
 
         /* Normalize*/
         P[i][0]= P[i][0]*(Maxi-Mini)+Mini;
                   P[i][1] =P[i][1]*(Maxi-Mini)+Mini; 
 
                        }
 
   result.Points=P;
   return result;
}
PreviewAttachmentSize
JS_PseudoRandom.qtz2.66 KB

cwright's picture
Re: Pseudo Random

The diagonal happens due to the way you're using i (iteration counter) directly (not offset any) -- at the beginning, it'll be less than your SeedX/SeedY values, so the modulo won't cause it to wrap (giving random positions).

To work around that, you need to offset the i value to get it to wrap every time. this is pretty simple to do: just add a value larger than SeedX/SeedY to i, like this:

var result = new Object();
 
function (__structure Points) main (__index Iterations,__number SeedX,__number SeedY)
{
   var Maxi=0.5; 
   var Mini=-1;
   var P= new Array()
 
   var CurrentPosition= new Array()
   var Step=1/(Iterations-1)
 
      for (var i=0;i<Iterations;i++){
         P[i]=new Object()
         CurrentPosition[i]=Step*i
 
         /* Generate Pseudo random */
         P[i][0] = (i+1000) * CurrentPosition[i] % SeedX
         P[i][1] = (i+1000) * CurrentPosition[i] % SeedY
         P[i][2] = 0
 
         /* Normalize*/
         P[i][0]= (P[i][0]*(Maxi-Mini)+Mini)/2;
           P[i][1] =(P[i][1]*(Maxi-Mini)+Mini)/2; 
 
                        }
 
   result.Points=P;
   return result;
}

I picked 1000 just because it was convenient -- you could add something derived from SeedX/SeedY ((SeedX23 + SeedY41+101)) to make it always work.

(edit: oh, I added the /2's in there too, to make sure I could see the whole diagonals -- you can take that out without affecting the distribution any).

yanomano's picture
Re: Pseudo Random

Thanks Christopher :) Efficiently it is much better :) I don't want to see perfect , which is a bit incongrous regarding randoms numbers ;) Also very good idea to add values derived from seeds...

usefuldesign.au's picture
Re: Pseudo Random

There's still some organic looking order here, if you bump the iter to 500+ it looks like bacteria or something. Was messing with it and a diagonal jumped out at me for a few specific seed values. Chaos/Order :)

I was watching a video by a guy who programmed a $1 microprocessor to have rnd noise to drive an LED. Asked how he generated noise and he said he ran a counter and then watched the bit that changed the most (by which I gather he actually meant change the most randomly not the 2^0 bit).

That only gives a binary change but if you did it 8 times you could generate an integer I suppose. Any clues on that kind of methodology cwright?

PreviewAttachmentSize
JS_PseudoRandom_diagonal.qtz3.1 KB

usefuldesign.au's picture
Re: Pseudo Random

Video about rnd noise. Check the flag waving comment 2:30! haha White noise 6:45. Think this involves random time intervals also a very high speeds c.f. QC frame rates so maybe not so relevant after all.

Thought the LED array people on this site would be interested in this anyhow.

What If Bacteria Designed Computers? from Jared Boone on Vimeo.

cwright's picture
Re: Pseudo Random

usefuldesign.au wrote:
That only gives a binary change but if you did it 8 times you could generate an integer I suppose. Any clues on that kind of methodology cwright?

Using a random single-bit generator to generate bytes is kinda wasteful in software (hardware RNGs will use this method, because it's easy to do in hardware, but in software single-bit manipulation is expensive because the CPUs are designed to work on groups of 8-64 bits (or even 128 bits, in the case of SSE) at a time.)

There are several very good deterministic (seeded) random number generators -- the mersenne twister, or MWC are two decent methods. MT requires a lot of code + computation, but MWC is super-simple to implement, and very fast (it's like 3 operations per output word). yanomano's algorithm here is similar to mwc, but it a much weaker form (it's easier to compute though, so it's a reasonable tradeoff for non-cryptographically useful randomness).

usefuldesign.au's picture
Re: Pseudo Random

mmm okay that can get quite technical given the C code I just saw... thanks for the reference, cwright.

yanomano's picture
Re: Pseudo Random

I have tried to affine the code for pseudo random : the idea was to take the first pass of iterated X values and re-inject it in the loop to dilute the Y values. It works fine but it's much better with also a second pass for X. The seed need to be constrain to a very short time slot with an interpolation patch, however it's very difficult to visually catch the loop. Here is the code and the demo patch:

var result = new Object();
 
function (__structure Points) main (__index Iterations,__number Seed)
{   
    var P= new Array()
 
    var CurrentPosition= new Array()
    var Step=1/(Iterations-1)
 
        for (var i=0;i<Iterations;i++){
            P[i]=new Object()
            CurrentPosition[i]=Step*i+1
 
            /* Generate Pseudo random */
            P[i][0] = (i+999.33) * CurrentPosition[i] % Seed
 
            /* [i].Y take the result of[i].X as a value*/
            P[i][1] = (i+P[i][0]*999) * CurrentPosition[i] % (Seed+0.03)
 
            /*second pass for [i].X now taking [i].Y also as a value */
            P[i][0] = (i+P[i][1]*999) * CurrentPosition[i] % Seed
 
            P[i][2] = 0
 
            /* Normalize*/
           P[i][0]=(P[i][0]-0.5)*2
           P[i][1]=(P[i][1]-0.5)*2
 
 
                                }
 
    result.Points=P;
    return result;
}
PreviewAttachmentSize
JS_PseudoRandom_V3.qtz3.95 KB