POV-Ray : Newsgroups : povray.binaries.images : Toward a less-lame rand() function. Server Time
31 Jul 2024 16:21:34 EDT (-0400)
  Toward a less-lame rand() function. (Message 1 to 10 of 29)  
Goto Latest 10 Messages Next 10 Messages >>>
From: gregjohn
Subject: Toward a less-lame rand() function.
Date: 15 May 2009 07:55:00
Message: <web.4a0d5729a7098c1c34d207310@news.povray.org>
The neatly ordered, predictable pattern of red dots in the top half of the image
are generated with povray's rand() function.  They demonstrate what you get if
you cause a monotonic increase in the seed value.  Once I had a project
"ruined" by this predictable pattern because I was exploring some parameter
space via use of the #declare RSEED=seed(frame_number).

The green dots below represent my best attempt so far to create something worthy
of the title "random function".   It requires one first to set an "aseed" value
between 0 and 1, but this aseed *may* increase monotonically, like #declare
aseed=(frame_number+0.1)/(final_frame+0.1);

#macro randoo()
#declare aseed=pi/(aseed)+pi/(1+aseed);
#declare aseed=aseed*10000-int(10000*aseed);
(aseed)
#end


And here is the complete (mess!) of code that generated my image:

#include"transforms.inc"

#macro Reorient(Axis1,Axis2)//john vansickle
                #local vX1=vnormalize(Axis1);
                #local vX2=vnormalize(Axis2);
                #local vY=vnormalize(vcross(vX1,vX2));
                #local vZ1=vnormalize(vcross(vX1,vY));
                #local vZ2=vnormalize(vcross(vX2,vY));
                matrix < vX1.x, vY.x,vZ1.x, vX1.y,vY.y,vZ1.y, vX1.z,vY.z, vZ1.z,
0,0,0 >
                matrix < vX2.x,vX2.y,vX2.z,  vY.x,vY.y, vY.z, vZ2.x,vZ2.y,vZ2.z,
0,0,0 >
              #end

#declare iwih=image_width/image_height;

#declare camang=45;

#declare camloke=-100*z;
#declare azee=0.5*iwih/tan(camang/2*pi/180);

#declare camlook_at=0;
#declare seedirn= camlook_at-camloke+0.000001;
#declare cameratransform=transform{ Reorient (z,seedirn*<1,0,1.001>)
Reorient(seedirn*<1,0,1.001>,seedirn) translate camloke}

camera {
  direction z*azee
  up y
  right     x*image_width/image_height
  transform{cameratransform}
 }

#declare RRR=seed(frame_number);   //standard way of declaring a seed
#declare aseed=0.335;//mod((frame_number+1)/100,1);

#macro randoo()                     //a new, truly random number generator.
#declare aseed=pi/(aseed)+pi/(1+aseed);
#declare aseed=aseed*10000-int(10000*aseed);
(aseed)
#end

#declare a=randoo();
#declare nmax=3980;
#declare oldway_oldend=rand(RRR);
#declare newway_oldend=randoo();//rand(aseed2);


#declare n=0;
#while(n<nmax)

#declare RRR=seed(n);
#declare aseed=mod((n+1)/nmax,1);


#declare oldway_newend =rand(RRR);
#declare newway_newend=randoo();

sphere{<iwih*(n+1)/nmax-iwih/2,0.5*(oldway_newend),azee>
,0.005
 pigment{red 1}finish{ambient rgb 1}
 transform{cameratransform}
 }

sphere{<iwih*(n+1)/nmax-iwih/2,0.5*(newway_newend)-0.5,azee>
,0.005
 pigment{green 0.5}finish{ambient rgb 1}
 transform{cameratransform}
 }

#declare oldway_oldend=oldway_newend;
#declare newway_oldend=newway_newend;

#declare n=n+1;
#end

box{<-iwih/2,-0.5,azee+1>,<iwih/2,0.5,azee+0.051> pigment{rgb 1}finish{ambient
rgb 1}
 transform{cameratransform}}


Post a reply to this message


Attachments:
Download 'zrandtest11.png' (137 KB)

Preview of image 'zrandtest11.png'
zrandtest11.png


 

From: Warp
Subject: Re: Toward a less-lame rand() function.
Date: 15 May 2009 12:13:24
Message: <4a0d94a4$1@news.povray.org>
gregjohn wrote:
> The neatly ordered, predictable pattern of red dots in the top half of the image
> are generated with povray's rand() function.  They demonstrate what you get if
> you cause a monotonic increase in the seed value.  Once I had a project
> "ruined" by this predictable pattern because I was exploring some parameter
> space via use of the #declare RSEED=seed(frame_number).
> 
> The green dots below represent my best attempt so far to create something worthy
> of the title "random function".   It requires one first to set an "aseed" value
> between 0 and 1, but this aseed *may* increase monotonically, like #declare
> aseed=(frame_number+0.1)/(final_frame+0.1);

  The reason why you get regular patterns is because POV-Ray uses a
simple linear congruential generator as its RNG, which has this precise
flaw. LCGs are very poor-quality RNGs.

  You can try shuffling the results of the LGC around by adding
additional "garbage" to the result, but the quality of the results will
not increase. The only thing you will achieve is that in a particular
case where the original values presented regular patterns, it will stop
doing that. However, in a different case it will most probably show the
regular patterns again (because the quality of the randomness has not
increased).

  One solution would be if a new, higher-quality RNG was added to
POV-Ray internally. Perhaps it could be used with a different keyword
(such as seed2() and rand2()).


Post a reply to this message

From: Edouard
Subject: Re: Toward a less-lame rand() function.
Date: 16 May 2009 06:55:01
Message: <web.4a0e9b562a89ae6db1aa47b00@news.povray.org>
"gregjohn" <pte### [at] yahoocom> wrote:
> The neatly ordered, predictable pattern of red dots in the top half of the image
> are generated with povray's rand() function.  They demonstrate what you get if
> you cause a monotonic increase in the seed value.  Once I had a project
> "ruined" by this predictable pattern because I was exploring some parameter
> space via use of the #declare RSEED=seed(frame_number).
>
> The green dots below represent my best attempt so far to create something worthy
> of the title "random function".   It requires one first to set an "aseed" value
> between 0 and 1, but this aseed *may* increase monotonically, like #declare
> aseed=(frame_number+0.1)/(final_frame+0.1);

This was the problem I found with my stochastic rig - esp because I was seeding
each frame's RNG with frame_number. I wrote some (non-mathematically-robust)
functions to increase the quality of the random numbers I was using for a few
key parameters. They helped for my code, but I don't really know if they were
increasing the randomness, or just hiding the problems from my uses. I've seen
papers about how to create high-quality random numbers from poor-quality RNGs,
but I'm not mathematically adept enough to understand them...

In the end I found myself using halton sequences more and more - they are
decidedly non-random, but what I was really using the RNG for was to create low
discrepancy samples, and the halton sequence seemed better than a RNG for that
purpose.

A (ever-so slightly buggy) version of both a RNG massager, and a halton sequence
generator are both in my 35m Camera macros I posted a few months back.

Cheers,
Edouard.


Post a reply to this message

From: Larry Hudson
Subject: Re: Toward a less-lame rand() function.
Date: 16 May 2009 20:28:43
Message: <4a0f5a3b$1@news.povray.org>
gregjohn wrote:
> The neatly ordered, predictable pattern of red dots in the top half of the image
> are generated with povray's rand() function.  They demonstrate what you get if
> you cause a monotonic increase in the seed value.  Once I had a project
> "ruined" by this predictable pattern because I was exploring some parameter
> space via use of the #declare RSEED=seed(frame_number).
> 
The key to using a RNG is that it should be seeded once and ONLY once, 
before the RNG is used the first time.  That starts up a sequence of 
random numbers.  Then each time the RNG is called it gives you the next 
(pseudo) random number in the sequence.  If you try to seed it each 
time, you're not using a random sequence, it depends on however your 
seqence of seeds is defined.

Now, this can be a problem in POV-Ray animations because each frame is 
essentially created from scratch.  There's no built-in way to continue 
the RNG sequence between frames.  One possible approach is to save a 
final random number to a file and use that as the seed for the next 
frame.  But in a single, non-amimated image, don't use more than one 
initial seed.

Of course, since POV-Ray allows multiple random streams, this means that 
each one should be only seeded once -- and generally a different seed 
for each.

      -=- Larry -=-


Post a reply to this message

From: Reactor
Subject: Re: Toward a less-lame rand() function.
Date: 17 May 2009 03:20:00
Message: <web.4a0fba322a89ae6db5db26f70@news.povray.org>
Larry Hudson <org### [at] yahoocom> wrote:
> gregjohn wrote:
> > The neatly ordered, predictable pattern of red dots in the top half of the image
> > are generated with povray's rand() function.  They demonstrate what you get if
> > you cause a monotonic increase in the seed value.  Once I had a project
> > "ruined" by this predictable pattern because I was exploring some parameter
> > space via use of the #declare RSEED=seed(frame_number).
> >
> The key to using a RNG is that it should be seeded once and ONLY once,
> before the RNG is used the first time.  That starts up a sequence of
> random numbers.  Then each time the RNG is called it gives you the next
> (pseudo) random number in the sequence.  If you try to seed it each
> time, you're not using a random sequence, it depends on however your
> seqence of seeds is defined.
>
> Now, this can be a problem in POV-Ray animations because each frame is
> essentially created from scratch.  There's no built-in way to continue
> the RNG sequence between frames.  One possible approach is to save a
> final random number to a file and use that as the seed for the next
> frame.  But in a single, non-amimated image, don't use more than one
> initial seed.
>
> Of course, since POV-Ray allows multiple random streams, this means that
> each one should be only seeded once -- and generally a different seed
> for each.
>
>       -=- Larry -=-

This sounds familiar ;)

The op may want to read this thread here:
http://news.povray.org/povray.general/thread/%3Cweb.497a1e5215dcf5ebf50167bc0%40news.povray.org%3E/?ttop=307384&toff=50
&mtop=300618

Of particular interest is this posting:
http://news.povray.org/povray.general/message/%3C497a49fd%241%40news.povray.org%3E/#%3C497a49fd%241%40news.povray.org%3
E
To make a long story short, one can use the frame number to iterate through the
stream, so that a "random" number is used for each frame.

That said, I would like to see a new, stronger rand function in a future
version.


-Reactor


Post a reply to this message

From: Warp
Subject: Re: Toward a less-lame rand() function.
Date: 17 May 2009 04:14:50
Message: <4a0fc77a@news.povray.org>
Larry Hudson wrote:
> The key to using a RNG is that it should be seeded once and ONLY once,
> before the RNG is used the first time.  That starts up a sequence of
> random numbers.  Then each time the RNG is called it gives you the next
> (pseudo) random number in the sequence.

  That won't help the regular patterns which appear in some situations
when using a LCG (which is a very poor-quality RNG). When or how often
you seed is not really the point.

> Now, this can be a problem in POV-Ray animations because each frame is
> essentially created from scratch.  There's no built-in way to continue
> the RNG sequence between frames.

  seed(frame_number) is a perfectly good way of using different random
streams at each frame. The quality of the randomness will neither
increase nor decrease by doing that. There will be no obvious pattern
caused by doing this.

  You are confusing "seed every time before calling rand()" with "seed
at the beginning of each frame" (using a value which varies at each
frame, eg. the frame number), which are completely different things. The
former is a bad idea, the latter is completely ok and won't result in
reduction of the quality of the randomness.

  Btw, I have suggested to the pov-team the implementation of
additional, higher-quality RNGs into povray, and they liked the idea. So
it may be possible that in a future beta we might have alternative,
better-quality RNGs (the current one will obviously be preserved for
backwards compatibility reasons; the new one can be used optionally). I
can't promise anything, though.


Post a reply to this message

From: gregjohn
Subject: Re: Toward a less-lame rand() function.
Date: 17 May 2009 08:10:00
Message: <web.4a0ffe3d2a89ae6d72e64ba0@news.povray.org>
Warp <war### [at] tagpovrayorg> wrote:
>
>   seed(frame_number) is a perfectly good way of using different random
> streams at each frame. The quality of the randomness will neither
> increase nor decrease by doing that. There will be no obvious pattern
> caused by doing this.
>

Unless I misunderstand what you're saying, I believe the exact opposite. I first
discovered the problem when using seed(frame_number) and saw a predictable,
linearly monotonous effect in rand().  I believe that's also exactly what I
showed in my red dot pattern.  The "n" is a placeholder for what you see across
multiple frame_number 's .


Post a reply to this message

From: Warp
Subject: Re: Toward a less-lame rand() function.
Date: 17 May 2009 10:32:25
Message: <4a101ff9$1@news.povray.org>
gregjohn wrote:
> Warp <war### [at] tagpovrayorg> wrote:
>>   seed(frame_number) is a perfectly good way of using different random
>> streams at each frame. The quality of the randomness will neither
>> increase nor decrease by doing that. There will be no obvious pattern
>> caused by doing this.
>>
> 
> Unless I misunderstand what you're saying, I believe the exact opposite. I first
> discovered the problem when using seed(frame_number) and saw a predictable,
> linearly monotonous effect in rand().  I believe that's also exactly what I
> showed in my red dot pattern.  The "n" is a placeholder for what you see across
> multiple frame_number 's .

  If you are getting a regular pattern inside one single frame, it's
certainly *not* because you did a "seed(frame_number)" at the beginning
of your scene.

  "seed(frame_number)" is not any more likely to produce regular
patterns than "seed(0)" (or any other value for that matter) is.

  The only difference between doing a "seed(0)" and a
"seed(frame_number)" is that in the former case you will always get the
same sequence of numbers for the frame, while in the latter case you
will get a different sequence for each frame (which is what you usually
want). The quality of the sequence will be the same in either case.

  It has been suggested that to get a different sequence of random
numbers for each frame in an animation, some kind of "seed" value should
be saved to a file and then in the next frame read and used as parameter
for seed(). However, this does not produce anything that the simple
"seed(frame_number)" wouldn't. It will not increase the quality of the
randomness, nor reduce the likelihood of regular patterns appearing in
certain situations.

  There's one situation where doing a "seed(frame_number)" might produce
"more" regular patterns than something else, and that's if the next
frame somehow remembers what was created in the previous frame. The
simplest case is that each frame executes a "seed(frame_number)", then
calls rand() once (or to create one object), and then the location of
this object is somehow stored in a file and read in the next frame.

  In this case the effect will be the same as if you had called
seed+rand repeatedly in a loop (giving seed() the loop counter).


Post a reply to this message

From: Kenneth
Subject: Re: Toward a less-lame rand() function.
Date: 17 May 2009 12:15:00
Message: <web.4a1036e82a89ae6df50167bc0@news.povray.org>
Warp <war### [at] tagpovrayorg> wrote:

>
>   If you are getting a regular pattern inside one single frame, it's
> certainly *not* because you did a "seed(frame_number)" at the beginning
> of your scene.
>
>   "seed(frame_number)" is not any more likely to produce regular
> patterns than "seed(0)" (or any other value for that matter) is.
>

I *think* you're correct in that, if there are *multiple* calls of rand() within
a single frame--using a single seed(frame_number)--then a pattern isn't
discernible. (I never actually did any definitive experiments to determine
that, though.) But of course it sounds logical.

However, if only ONE rand() value is called per frame, then a pattern is
definitely there as the animation progresses. So, extrapolating that to
multiple rand() calls per frame, there may (or may not) be patterns in *every*
rand() call--*from frame to frame.* Personally, I just don't know.

But as regards pulling just a single rand() per frame, I have to agree with
GregJohn.  Let me quote myself(!) from the above-mentioned newsgroup
post--about the core problem that prompted the post:

"...I *thought* that by simply throwing some multiplier value 'M'
at seed(M*clock) or seed(M*frame_number)--just one time in my POV scene, to use
for the entire animation--would give me 'obvious' random numbers from frame to
frame. Unfortunately, not so. There are, to my great surprise, clear
*almost*-repeating rand() patterns, no matter what seed values I use. And it
shows up quite quickly in animation--usually over 5 to 10 frames...."

"...It's especially obvious when using
strict integer multiples for M--3,6,9,12, for example. Actually, any multiple
of any integer. So simply using clock or frame_number to change the seed value
from frame to frame presents a problem, as they both count up linearly."

In other words, as frame_number progresses linearly, then seed(frame_number)
will start showing patterns quite quickly *from frame to frame.* Again, only IF
one rand() value is called per frame (or so it seems.)

In reality, these patterns are not *exact* duplicates, of course. Depending on
how (and for what) a single rand() value is used in a scene, any resulting
pattern may not even be visually apparent.

KW


Post a reply to this message

From: Darren New
Subject: Re: Toward a less-lame rand() function.
Date: 17 May 2009 12:40:31
Message: <4a103dff@news.povray.org>
Kenneth wrote:
> In other words, as frame_number progresses linearly, then seed(frame_number)
> will start showing patterns quite quickly *from frame to frame.* Again, only IF
> one rand() value is called per frame (or so it seems.)

If you have a known number of random numbers being used in each frame, you 
can seed once at frame 0, then on each subsequent frame, generate 
frame_number time known_random_number_count random numbers, and then pick up 
the stream from there. Use a while loop in SDL to generate calls to rand(), 
in other words.

There's no good reason to believe the first number you generate after 
seeding the RNG looks especially random for different seeds. It's the 
consecutive numbers from the same seed that are pseudo-random.

-- 
   Darren New, San Diego CA, USA (PST)
   There's no CD like OCD, there's no CD I knoooow!


Post a reply to this message

Goto Latest 10 Messages Next 10 Messages >>>

Copyright 2003-2023 Persistence of Vision Raytracer Pty. Ltd.