TheSwamp

Code Red => AutoLISP (Vanilla / Visual) => Topic started by: irneb on May 25, 2012, 05:49:08 AM

Title: ==={Challenge}=== Random Numbers
Post by: irneb on May 25, 2012, 05:49:08 AM
Generally when searching for an AutoLisp PRNG you end up with something like this:
Code - Auto/Visual Lisp: [Select]
  1. (defun Random  (seed /)
  2.   (if (not seed)
  3.     (setq seed (if *random:seed*
  4.                  *random:seed*
  5.                  (setq *random:seed* (getvar "DATE"))))
  6.     (setq *random:seed* seed))
  7.   (setq seed          (rem (+ (* 25173 seed) 13849) 65536)
  8.         *random:seed* seed)
  9.   (/ seed 65536))
I was wondering if anyone's come across a more suitable random number generator. One alternative I've just realized is to make use of Microsoft's built-in CryptGenRandom function. This is used to generate the GUID numbers. So this might do - though it's a bit complex to make use of, since it needs to convert from hex to decimal:
Code - Auto/Visual Lisp: [Select]
  1. (defun GUID  (/ tl g)
  2.   (if (setq tl (vlax-get-or-create-object "Scriptlet.TypeLib"))
  3.     (progn (setq g (vlax-get tl 'Guid)) (vlax-release-object tl) (substr g 2 36))))
  4.  
  5. ;;; ---------------------------------------------------------------------------------------
  6. ;;; Convert a base into an integer
  7. ;;; ---------------------------------------------------------------------------------------
  8. (defun Base->Int  (s b / i m ex)
  9.   (or *digits* (setq *digits* (vl-string->list "0123456789ABCDEFGHIJKLMNOPQSTUVWXYZ")))
  10.   (setq m  (wcmatch s "-*")
  11.         s  (vl-string->list (vl-string-left-trim "-+" s))
  12.         i  0.0
  13.         ex 0)
  14.   (while s
  15.     (setq i (+ (* i b) (vl-position (car s) *digits*))
  16.           s (cdr s)))
  17.   (fix (if m
  18.          (- i)
  19.          i)))
  20.  
  21. (defun RandomFromGUID  (/ G a b)
  22.   (setq G (vl-string-translate "-" "3" (GUID))
  23.         a (float (Base->Int (substr G 1 18) 16))
  24.         b (float (Base->Int (substr G 19) 16))
  25.         G (/ a b))
  26.   (rem (/ G (expt 10. (fix (/ G 10)))) 1.))
Anyone got any other ideas?
Title: Re: ==={Challenge}=== Random Numbers
Post by: CAB on May 25, 2012, 07:44:52 AM
You probably saw all of these:

http://www.theswamp.org/index.php?topic=25248.msg303904#msg303904
http://www.theswamp.org/index.php?topic=2523.msg31984#msg31984
http://www.theswamp.org/index.php?topic=10883.msg137525#msg137525
Title: Re: ==={Challenge}=== Random Numbers
Post by: irneb on May 25, 2012, 08:31:33 AM
Yes, I've looked at some of those (and others as well). But they all use the Linear Concruential Generator (http://en.wikipedia.org/wiki/Linear_congruential_generator) method, which is not very "random" - at least not "crytographically" usable. Perhaps something like the Mersenne twister (http://en.wikipedia.org/wiki/Mersenne_twister), or some of the others: http://en.wikipedia.org/wiki/List_of_random_number_generators#Pseudorandom_number_generators_.28PRNGs.29

Or even trying to achieve a True Random Number Generator by linking to one of the entropy random number sites: http://en.wikipedia.org/wiki/List_of_random_number_generators#Random_Number_Servers

E.g. here's a "true" random number in the form of a 32bit hexadecimal code:
Code - Auto/Visual Lisp: [Select]
  1. (defun TrueRandom (/ fn f str hex)
  2.     "http://www.fourmilab.ch/cgi-bin/Hotbits?nbytes=4&fmt=hex" 'fn :vlax-true)
  3.   (if (setq f (open fn "r"))
  4.     (progn (while (and (not hex) (setq str (strcase (read-line f)))) (setq hex (wcmatch str "*<PRE>*")))
  5.       (setq hex (read-line f))
  6.       (close f)
  7.       (vl-file-delete fn)
  8.       hex)))
Title: Re: ==={Challenge}=== Random Numbers
Post by: JohnK on May 25, 2012, 08:36:59 AM
Random number generators was/is one Cornbread's favorite subjects. He posted on the subject several times here and I have one of the "weirder examples" in a misc code folder of mine.

Here is the URL I had with that code:
http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html

Here is the code I had (I'm sure I was just tinkering with some of his code so all credit should go to him and I'm sure I mucked up the code pretty bad so if you notice anything wonky, that's me).
Code - C++: [Select]
  1. #include <iostream>
  2. #include "stdio.h"
  3. #include "stdlib.h"
  4. #include "time.h"
  5. #include "string.h"
  6.  
  7. #define RAND_RANGE(__n, __min, __max, __tmax) \
  8.      (__n) = (__min) + (long) ((double) ( (double) (__max) - (__min) + 1.0) * ((__n) / ((__tmax) + 1.0)))
  9.  
  10. #define MT_RAND_MAX ((long) (0x7FFFFFFF))
  11.  
  12.  
  13. /* Period parameters */
  14. #define N 624
  15. #define M 397
  16. #define MATRIX_A 0x9908b0dfUL   /* constant vector a */
  17. #define UPPER_MASK 0x80000000UL /* most significant w-r bits */
  18. #define LOWER_MASK 0x7fffffffUL /* least significant r bits */
  19.  
  20. static unsigned long mt[N]; /* the array for the state vector  */
  21. static int mti=N+1; /* mti==N+1 means mt[N] is not initialized */
  22.  
  23. /* initializes mt[N] with a seed */
  24. void init_genrand(unsigned long s)
  25. {
  26.     mt[0]= s & 0xffffffffUL;
  27.     for (mti=1; mti<N; mti++) {
  28.         mt[mti] =
  29.             (1812433253UL * (mt[mti-1] ^ (mt[mti-1] >> 30)) + mti);
  30.         mt[mti] &= 0xffffffffUL;
  31.     }
  32. }
  33.  
  34. /* generates a random number on [0,0xffffffff]-interval */
  35. unsigned long genrand_int32(void)
  36. {
  37.     unsigned long y;
  38.     static unsigned long mag01[2]={0x0UL, MATRIX_A};
  39.     /* mag01[x] = x * MATRIX_A  for x=0,1 */
  40.  
  41.     if (mti >= N) { /* generate N words at one time */
  42.         int kk;
  43.  
  44.         if (mti == N+1)   /* if init_genrand() has not been called, */
  45.             init_genrand(5489UL); /* a default initial seed is used */
  46.  
  47.         for (kk=0;kk<N-M;kk++) {
  48.             y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
  49.             mt[kk] = mt[kk+M] ^ (y >> 1) ^ mag01[y & 0x1UL];
  50.         }
  51.         for (;kk<N-1;kk++) {
  52.             y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
  53.             mt[kk] = mt[kk+(M-N)] ^ (y >> 1) ^ mag01[y & 0x1UL];
  54.         }
  55.         y = (mt[N-1]&UPPER_MASK)|(mt[0]&LOWER_MASK);
  56.         mt[N-1] = mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1UL];
  57.  
  58.         mti = 0;
  59.     }
  60.  
  61.     y = mt[mti++];
  62.  
  63.     /* Tempering */
  64.     y ^= (y >> 11);
  65.     y ^= (y << 7) & 0x9d2c5680UL;
  66.     y ^= (y << 15) & 0xefc60000UL;
  67.     y ^= (y >> 18);
  68.  
  69.     return y;
  70. }
  71.  
  72. long random_mt_range(long min, long max)
  73. {
  74.         long retval = (long) (genrand_int32() >> 1);
  75.         RAND_RANGE(retval, min, max, MT_RAND_MAX);
  76.         return retval;
  77. }
  78.  
  79. int main(int argc, const char *argv[])
  80. {
  81.  
  82.     unsigned long seed, oldSeed;
  83.     for(int i = 0; i < 100; i++)
  84.     {
  85.         while(seed == oldSeed)
  86.             seed = (unsigned long)time(0) + (unsigned long)clock();
  87.  
  88.         init_genrand(seed);
  89. //        if ((i % 22) == 0)
  90.             std::cout << random_mt_range(0, 100) << '\n';
  91.         oldSeed = seed;
  92.     }
  93.  
  94.     return 0;
  95. }
  96.  
Title: Re: ==={Challenge}=== Random Numbers
Post by: JohnK on May 25, 2012, 08:39:46 AM
Ah, I just noticed your last post inerb. ...the code I posted above is using the Mersenne twister method.
Title: Re: ==={Challenge}=== Random Numbers
Post by: chlh_jd on May 25, 2012, 08:42:52 AM
I use these
Code: [Select]
;;;产生单个随机数
;;;Generate a single random number
;;;由时间产生随机自然数
;;;Random natural number by the time
;;;(GA-Random-Num 0 99)
(defun GA-Random-Num (Rmi Rma / mid is_go_on)
  (setq is_go_on T)
  (while (and is_go_on
      (setq mid (fix (rem (getvar "CPUTICKS") Rma)))
)
    (if (>= mid Rmi)
      (setq is_go_on NIL)
    )
  )
  mid
)
;;;产生随机-1~1小数
;;;Generate a random decimal from -1 to 1
;;;(GA-Random-1 0 1)
(defun GA-Random-1 (Rmi Rma / mid is_go_on)
  (setq is_go_on T)
  (while (and is_go_on
      (setq mid (rem (getvar "CPUTICKS") (* 2.0 pi)))
)
    (if (>= Rma (sin mid) Rmi)
      (setq is_go_on NIL)
    )
  )
  (sin mid)
)
;;;产生0~LIMA的整数随机数列
;;;generate a 0 ~ LIMA random sequence of integers
(defun GA-Random-Series (Lima / lst i mid)
  (setq lst nil
i   0
  )
  (repeat (1+ Lima)
    (setq mid (GA-Random-1 -1 1)
  lst (cons (cons i mid) lst)
  i   (1+ i)
    )
  )
  (setq lst (vl-sort lst
     (function (lambda (e1 e2)
(< (cdr e1) (cdr e2))
       )
     )
    )
  )
  (mapcar 'car lst)
)
Title: Re: ==={Challenge}=== Random Numbers
Post by: pBe on May 25, 2012, 09:07:19 AM
I guess another soure of "random" value would be MEMORY usage [Physcial /Kernel].  Thats the only other value i can think of thats constantly changing besides TIME of course.

You can try accessing that data byhowever you want. I'm not that that computer savvy enough to know how  :-D

Theres also another factor to throw in the process. Unique Values
Code - Auto/Visual Lisp: [Select]
  1.       (mapcar (function (lambda (l)
  2.                     (vl-string->list l)))
  3.                           (list (getvar 'Loginname)
  4.                                 (getvar '_PKSER)
  5.                                 (getenv "ComputerName")(getenv "UserName")
  6.                                 (getenv "UserProfile")) ))

And have a play on that too.

Hopefully i can write one later :)








Title: Re: ==={Challenge}=== Random Numbers
Post by: pkohut on May 25, 2012, 06:49:05 PM
Intel's new Ivy Bridge processors have the RdRand assembly instruction. A 3 Ghz processor will produce 3 gigabits of random 1's and 0's per second.
http://www.tested.com/news/2829-how-intel-is-solving-the-problems-with-random-number-generation

Intel has also introduced the Rdrand library for Windows and Linux for those without Ivy Bridge processors.
http://software.intel.com/en-us/articles/user-manual-for-the-rdrand-library-windows-version/

Title: Re: ==={Challenge}=== Random Numbers
Post by: irneb on May 26, 2012, 02:21:11 AM
That's a very good idea! Now to compile such into an ActiveX server / ARX so we can use it in AutoLisp!  ;)
Title: Re: ==={Challenge}=== Random Numbers
Post by: efernal on May 26, 2012, 07:33:09 AM
Code - Auto/Visual Lisp: [Select]
  1. (ATOI (SUBSTR (RTOS (GETVAR "date") 2 16) 9))
  2.  
  3.  
  4. (REPEAT 20 (PRINT (ATOI (SUBSTR (RTOS (GETVAR "date") 2 16) 9))))
  5. ;|
  6. 351318553
  7. 351318634
  8. 351318669
  9. 351318715
  10. 351318843
  11. 351318889
  12. 351318924
  13. 351319051
  14. 351319098
  15. 351319213
  16. 351319259
  17. 351319294
  18. 351319421
  19. 351319456
  20. 351319491
  21. 351319606
  22. 351319653
  23. 351319676
  24. 351319804
  25. 351319827
  26. |;
  27.  
  28.   (* (ATOI (SUBSTR (RTOS (GETVAR "date") 2 16) 11)) (ATOI (SUBSTR (RTOS (GETVAR "date") 2 16) 12)))
  29. )
  30.  
  31.  
  32. (REPEAT 20
  33.   (PRINT (ABS (* (ATOI (SUBSTR (RTOS (GETVAR "date") 2 16) 11))
  34.                  (ATOI (SUBSTR (RTOS (GETVAR "date") 2 16) 12))
  35.               )
  36.          )
  37.   )
  38. )
  39.  
  40. ;|
  41. 1183228528
  42. 261076604
  43. 44193545
  44. 418119265
  45. 694501865
  46. 1735021801
  47. 2108966657
  48. 1153565696
  49. 869030711
  50. 495066719
  51. 447991705
  52. 821970601
  53. 1106522596
  54. 2049626724
  55. 1863213135
  56. 1586777767
  57. 643627935
  58. 359051580
  59. 82603632
  60. 860589120
  61. |;
  62.  
  63.  
Title: Re: ==={Challenge}=== Random Numbers
Post by: pBe on May 27, 2012, 09:42:35 AM
Still havent found a way to read the physical/kennel memory usage.
Where avaialbe and system cache is constantly chaging.



Title: Re: ==={Challenge}=== Random Numbers
Post by: tomipac on April 06, 2020, 02:12:32 PM
Nice piece of code irneb!
One question, does this work as a normal GUID? I mean are the chances of generating the same line is the same as it "normally" would be?
Thanks!  :-)

[/code]I was wondering if anyone's come across a more suitable random number generator. One alternative I've just realized is to make use of Microsoft's built-in CryptGenRandom function. This is used to generate the GUID numbers. So this might do - though it's a bit complex to make use of, since it needs to convert from hex to decimal:
Code - Auto/Visual Lisp: [Select]
  1. (defun GUID  (/ tl g)
  2.   (if (setq tl (vlax-get-or-create-object "Scriptlet.TypeLib"))
  3.     (progn (setq g (vlax-get tl 'Guid)) (vlax-release-object tl) (substr g 2 36))))
  4.  
  5. ;;; ---------------------------------------------------------------------------------------
  6. ;;; Convert a base into an integer
  7. ;;; ---------------------------------------------------------------------------------------
  8. (defun Base->Int  (s b / i m ex)
  9.   (or *digits* (setq *digits* (vl-string->list "0123456789ABCDEFGHIJKLMNOPQSTUVWXYZ")))
  10.   (setq m  (wcmatch s "-*")
  11.         s  (vl-string->list (vl-string-left-trim "-+" s))
  12.         i  0.0
  13.         ex 0)
  14.   (while s
  15.     (setq i (+ (* i b) (vl-position (car s) *digits*))
  16.           s (cdr s)))
  17.   (fix (if m
  18.          (- i)
  19.          i)))
  20.  
  21. (defun RandomFromGUID  (/ G a b)
  22.   (setq G (vl-string-translate "-" "3" (GUID))
  23.         a (float (Base->Int (substr G 1 18) 16))
  24.         b (float (Base->Int (substr G 19) 16))
  25.         G (/ a b))
  26.   (rem (/ G (expt 10. (fix (/ G 10)))) 1.))
Anyone got any other ideas?
Title: Re: ==={Challenge}=== Random Numbers
Post by: JohnK on April 06, 2020, 02:24:17 PM
irneb's GUID code looks like the standard method for generating a GUID with windows typelib stuff to me. I would say `normal conditions' would apply.

Nice piece of code irneb!
One question, does this work as a normal GUID? I mean are the chances of generating the same line is the same as it "normally" would be?
Thanks!  :-)

[/code]I was wondering if anyone's come across a more suitable random number generator. One alternative I've just realized is to make use of Microsoft's built-in CryptGenRandom function. This is used to generate the GUID numbers. So this might do - though it's a bit complex to make use of, since it needs to convert from hex to decimal:
Code - Auto/Visual Lisp: [Select]
  1. (defun GUID  (/ tl g)
  2.   (if (setq tl (vlax-get-or-create-object "Scriptlet.TypeLib"))
  3.     (progn (setq g (vlax-get tl 'Guid)) (vlax-release-object tl) (substr g 2 36))))
  4.  
  5. ;;; ---------------------------------------------------------------------------------------
  6. ;;; Convert a base into an integer
  7. ;;; ---------------------------------------------------------------------------------------
  8. (defun Base->Int  (s b / i m ex)
  9.   (or *digits* (setq *digits* (vl-string->list "0123456789ABCDEFGHIJKLMNOPQSTUVWXYZ")))
  10.   (setq m  (wcmatch s "-*")
  11.         s  (vl-string->list (vl-string-left-trim "-+" s))
  12.         i  0.0
  13.         ex 0)
  14.   (while s
  15.     (setq i (+ (* i b) (vl-position (car s) *digits*))
  16.           s (cdr s)))
  17.   (fix (if m
  18.          (- i)
  19.          i)))
  20.  
  21. (defun RandomFromGUID  (/ G a b)
  22.   (setq G (vl-string-translate "-" "3" (GUID))
  23.         a (float (Base->Int (substr G 1 18) 16))
  24.         b (float (Base->Int (substr G 19) 16))
  25.         G (/ a b))
  26.   (rem (/ G (expt 10. (fix (/ G 10)))) 1.))
Anyone got any other ideas?
Title: Re: ==={Challenge}=== Random Numbers
Post by: ribarm on June 28, 2022, 12:04:42 AM
Here is something for playing regarding RND...

http://www.theswamp.org/index.php?topic=30434.msg610043#msg610043

@John
@Irneb
Beautiful attempts, but are they?