gravatar
deba@inf.elte.hu
deba@inf.elte.hu
Seeding from file source or from pid and time (ticket #19)
0 1 0
default
1 file changed with 83 insertions and 0 deletions:
↑ Collapse diff ↑
Ignore white space 96 line context
... ...
@@ -21,100 +21,110 @@
21 21
 * Generator of Matsumoto and Nishimura.
22 22
 *
23 23
 * See the appropriate copyright notice below.
24 24
 * 
25 25
 * Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
26 26
 * All rights reserved.                          
27 27
 *
28 28
 * Redistribution and use in source and binary forms, with or without
29 29
 * modification, are permitted provided that the following conditions
30 30
 * are met:
31 31
 *
32 32
 * 1. Redistributions of source code must retain the above copyright
33 33
 *    notice, this list of conditions and the following disclaimer.
34 34
 *
35 35
 * 2. Redistributions in binary form must reproduce the above copyright
36 36
 *    notice, this list of conditions and the following disclaimer in the
37 37
 *    documentation and/or other materials provided with the distribution.
38 38
 *
39 39
 * 3. The names of its contributors may not be used to endorse or promote 
40 40
 *    products derived from this software without specific prior written 
41 41
 *    permission.
42 42
 *
43 43
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
44 44
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
45 45
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
46 46
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
47 47
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
48 48
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
49 49
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
50 50
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
51 51
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
52 52
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
53 53
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
54 54
 * OF THE POSSIBILITY OF SUCH DAMAGE.
55 55
 *
56 56
 *
57 57
 * Any feedback is very welcome.
58 58
 * http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/emt.html
59 59
 * email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space)
60 60
 */
61 61

	
62 62
#ifndef LEMON_RANDOM_H
63 63
#define LEMON_RANDOM_H
64 64

	
65 65
#include <algorithm>
66 66
#include <iterator>
67 67
#include <vector>
68 68
#include <limits>
69
#include <fstream>
69 70

	
70 71
#include <lemon/math.h>
71 72
#include <lemon/dim2.h>
72 73

	
74
#ifndef WIN32
75
#include <sys/time.h>
76
#include <ctime>
77
#include <sys/types.h>
78
#include <unistd.h>
79
#else
80
#include <windows.h>
81
#endif
82

	
73 83
///\ingroup misc
74 84
///\file
75 85
///\brief Mersenne Twister random number generator
76 86

	
77 87
namespace lemon {
78 88

	
79 89
  namespace _random_bits {
80 90
    
81 91
    template <typename _Word, int _bits = std::numeric_limits<_Word>::digits>
82 92
    struct RandomTraits {};
83 93

	
84 94
    template <typename _Word>
85 95
    struct RandomTraits<_Word, 32> {
86 96

	
87 97
      typedef _Word Word;
88 98
      static const int bits = 32;
89 99

	
90 100
      static const int length = 624;
91 101
      static const int shift = 397;
92 102
      
93 103
      static const Word mul = 0x6c078965u;
94 104
      static const Word arrayInit = 0x012BD6AAu;
95 105
      static const Word arrayMul1 = 0x0019660Du;
96 106
      static const Word arrayMul2 = 0x5D588B65u;
97 107

	
98 108
      static const Word mask = 0x9908B0DFu;
99 109
      static const Word loMask = (1u << 31) - 1;
100 110
      static const Word hiMask = ~loMask;
101 111

	
102 112

	
103 113
      static Word tempering(Word rnd) {
104 114
        rnd ^= (rnd >> 11);
105 115
        rnd ^= (rnd << 7) & 0x9D2C5680u;
106 116
        rnd ^= (rnd << 15) & 0xEFC60000u;
107 117
        rnd ^= (rnd >> 18);
108 118
        return rnd;
109 119
      }
110 120

	
111 121
    };
112 122

	
113 123
    template <typename _Word>
114 124
    struct RandomTraits<_Word, 64> {
115 125

	
116 126
      typedef _Word Word;
117 127
      static const int bits = 64;
118 128

	
119 129
      static const int length = 312;
120 130
      static const int shift = 156;
... ...
@@ -481,164 +491,235 @@
481 491
  /// initialization and generation phase so they produce two
482 492
  /// completly different sequences.
483 493
  ///
484 494
  /// The generator gives back random numbers of serveral types. To
485 495
  /// get a random number from a range of a floating point type you
486 496
  /// can use one form of the \c operator() or the \c real() member
487 497
  /// function. If you want to get random number from the {0, 1, ...,
488 498
  /// n-1} integer range use the \c operator[] or the \c integer()
489 499
  /// method. And to get random number from the whole range of an
490 500
  /// integer type you can use the argumentless \c integer() or \c
491 501
  /// uinteger() functions. After all you can get random bool with
492 502
  /// equal chance of true and false or given probability of true
493 503
  /// result with the \c boolean() member functions.
494 504
  ///
495 505
  ///\code
496 506
  /// // The commented code is identical to the other
497 507
  /// double a = rnd();                     // [0.0, 1.0)
498 508
  /// // double a = rnd.real();             // [0.0, 1.0)
499 509
  /// double b = rnd(100.0);                // [0.0, 100.0)
500 510
  /// // double b = rnd.real(100.0);        // [0.0, 100.0)
501 511
  /// double c = rnd(1.0, 2.0);             // [1.0, 2.0)
502 512
  /// // double c = rnd.real(1.0, 2.0);     // [1.0, 2.0)
503 513
  /// int d = rnd[100000];                  // 0..99999
504 514
  /// // int d = rnd.integer(100000);       // 0..99999
505 515
  /// int e = rnd[6] + 1;                   // 1..6
506 516
  /// // int e = rnd.integer(1, 1 + 6);     // 1..6
507 517
  /// int b = rnd.uinteger<int>();          // 0 .. 2^31 - 1
508 518
  /// int c = rnd.integer<int>();           // - 2^31 .. 2^31 - 1
509 519
  /// bool g = rnd.boolean();               // P(g = true) = 0.5
510 520
  /// bool h = rnd.boolean(0.8);            // P(h = true) = 0.8
511 521
  ///\endcode
512 522
  ///
513 523
  /// LEMON provides a global instance of the random number
514 524
  /// generator which name is \ref lemon::rnd "rnd". Usually it is a
515 525
  /// good programming convenience to use this global generator to get
516 526
  /// random numbers.
517 527
  class Random {
518 528
  private:
519 529

	
520 530
    // Architecture word
521 531
    typedef unsigned long Word;
522 532
    
523 533
    _random_bits::RandomCore<Word> core;
524 534
    _random_bits::BoolProducer<Word> bool_producer;
525 535
    
526 536

	
527 537
  public:
528 538

	
539
    ///\name Initialization
540
    ///
541
    /// @{
542

	
529 543
    /// \brief Default constructor
530 544
    ///
531 545
    /// Constructor with constant seeding.
532 546
    Random() { core.initState(); }
533 547

	
534 548
    /// \brief Constructor with seed
535 549
    ///
536 550
    /// Constructor with seed. The current number type will be converted
537 551
    /// to the architecture word type.
538 552
    template <typename Number>
539 553
    Random(Number seed) { 
540 554
      _random_bits::Initializer<Number, Word>::init(core, seed);
541 555
    }
542 556

	
543 557
    /// \brief Constructor with array seeding
544 558
    ///
545 559
    /// Constructor with array seeding. The given range should contain
546 560
    /// any number type and the numbers will be converted to the
547 561
    /// architecture word type.
548 562
    template <typename Iterator>
549 563
    Random(Iterator begin, Iterator end) { 
550 564
      typedef typename std::iterator_traits<Iterator>::value_type Number;
551 565
      _random_bits::Initializer<Number, Word>::init(core, begin, end);
552 566
    }
553 567

	
554 568
    /// \brief Copy constructor
555 569
    ///
556 570
    /// Copy constructor. The generated sequence will be identical to
557 571
    /// the other sequence. It can be used to save the current state
558 572
    /// of the generator and later use it to generate the same
559 573
    /// sequence.
560 574
    Random(const Random& other) {
561 575
      core.copyState(other.core);
562 576
    }
563 577

	
564 578
    /// \brief Assign operator
565 579
    ///
566 580
    /// Assign operator. The generated sequence will be identical to
567 581
    /// the other sequence. It can be used to save the current state
568 582
    /// of the generator and later use it to generate the same
569 583
    /// sequence.
570 584
    Random& operator=(const Random& other) {
571 585
      if (&other != this) {
572 586
        core.copyState(other.core);
573 587
      }
574 588
      return *this;
575 589
    }
576 590

	
577 591
    /// \brief Seeding random sequence
578 592
    ///
579 593
    /// Seeding the random sequence. The current number type will be
580 594
    /// converted to the architecture word type.
581 595
    template <typename Number>
582 596
    void seed(Number seed) { 
583 597
      _random_bits::Initializer<Number, Word>::init(core, seed);
584 598
    }
585 599

	
586 600
    /// \brief Seeding random sequence
587 601
    ///
588 602
    /// Seeding the random sequence. The given range should contain
589 603
    /// any number type and the numbers will be converted to the
590 604
    /// architecture word type.
591 605
    template <typename Iterator>
592 606
    void seed(Iterator begin, Iterator end) { 
593 607
      typedef typename std::iterator_traits<Iterator>::value_type Number;
594 608
      _random_bits::Initializer<Number, Word>::init(core, begin, end);
595 609
    }
596 610

	
611
    /// \brief Seeding from file or from process id and time
612
    ///
613
    /// By default, this function calls the \c seedFromFile() member
614
    /// function with the <tt>/dev/urandom</tt> file. If it is not success,
615
    /// it uses the \c seedFromTime().
616
    /// \return Currently always true.
617
    bool seed() {
618
#ifndef WIN32
619
      if (seedFromFile("/dev/urandom", 0)) return true;
620
#endif
621
      if (seedFromTime()) return true;
622
      return false;
623
    }
624
    
625
    /// \brief Seeding from file
626
    ///
627
    /// Seeding the random sequence from file. The linux kernel has two
628
    /// devices, <tt>/dev/random</tt> and <tt>/dev/urandom</tt> which
629
    /// could give good seed values for pseudo random generators (The
630
    /// difference between two devices is that the <tt>random</tt> may
631
    /// block the reading operation while the kernel can give good
632
    /// source of randomness, while the <tt>urandom</tt> does not
633
    /// block the input, but it could give back bytes with worse
634
    /// entropy).
635
    /// \param file The source file
636
    /// \param offset The offset, from the file read.
637
    /// \return True when the seeding is success.
638
#ifndef WIN32
639
    bool seedFromFile(const std::string& file = "/dev/urandom", int offset = 0) 
640
#else
641
    bool seedFromFile(const std::string& file = "", int offset = 0) 
642
#endif
643
    {
644
      std::ifstream rs(file.c_str());
645
      const int size = 4;
646
      Word buf[size];
647
      if (offset != 0 && !rs.seekg(offset)) return false;
648
      if (!rs.read(reinterpret_cast<char*>(buf), sizeof(buf))) return false;
649
      seed(buf, buf + size);
650
      return true;
651
    }
652

	
653
    /// \brief Seding from process id and time
654
    ///
655
    /// Seding from process id and time. This function uses the
656
    /// current process id and the current time for initialize the
657
    /// random sequence.
658
    /// \return Currently always true.
659
    bool seedFromTime() { 	
660
#ifndef WIN32
661
      timeval tv;
662
      gettimeofday(&tv, 0);
663
      seed(getpid() + tv.tv_sec + tv.tv_usec);
664
#else
665
      FILETIME time;
666
      GetSystemTimeAsFileTime(&time);
667
      seed(GetCurrentProcessId() + time.dwHighDateTime + time.dwLowDateTime);
668
#endif
669
      return true;
670
    }
671

	
672
    /// @}
673

	
674
    ///\name Uniform distributions
675
    ///
676
    /// @{
677

	
597 678
    /// \brief Returns a random real number from the range [0, 1)
598 679
    ///
599 680
    /// It returns a random real number from the range [0, 1). The
600 681
    /// default Number type is \c double.
601 682
    template <typename Number>
602 683
    Number real() {
603 684
      return _random_bits::RealConversion<Number, Word>::convert(core);
604 685
    }
605 686

	
606 687
    double real() {
607 688
      return real<double>();
608 689
    }
609 690

	
610 691
    /// \brief Returns a random real number the range [0, b)
611 692
    ///
612 693
    /// It returns a random real number from the range [0, b).
613 694
    template <typename Number>
614 695
    Number real(Number b) { 
615 696
      return real<Number>() * b; 
616 697
    }
617 698

	
618 699
    /// \brief Returns a random real number from the range [a, b)
619 700
    ///
620 701
    /// It returns a random real number from the range [a, b).
621 702
    template <typename Number>
622 703
    Number real(Number a, Number b) { 
623 704
      return real<Number>() * (b - a) + a; 
624 705
    }
625 706

	
626 707
    /// \brief Returns a random real number from the range [0, 1)
627 708
    ///
628 709
    /// It returns a random double from the range [0, 1).
629 710
    double operator()() {
630 711
      return real<double>();
631 712
    }
632 713

	
633 714
    /// \brief Returns a random real number from the range [0, b)
634 715
    ///
635 716
    /// It returns a random real number from the range [0, b).
636 717
    template <typename Number>
637 718
    Number operator()(Number b) { 
638 719
      return real<Number>() * b; 
639 720
    }
640 721

	
641 722
    /// \brief Returns a random real number from the range [a, b)
642 723
    ///
643 724
    /// It returns a random real number from the range [a, b).
644 725
    template <typename Number>
... ...
@@ -664,96 +745,98 @@
664 745

	
665 746
    /// \brief Returns a random integer from a range
666 747
    ///
667 748
    /// It returns a random integer from the range {0, 1, ..., b - 1}.
668 749
    template <typename Number>
669 750
    Number operator[](Number b) {
670 751
      return _random_bits::Mapping<Number, Word>::map(core, b);
671 752
    }
672 753

	
673 754
    /// \brief Returns a random non-negative integer
674 755
    ///
675 756
    /// It returns a random non-negative integer uniformly from the
676 757
    /// whole range of the current \c Number type. The default result
677 758
    /// type of this function is <tt>unsigned int</tt>.
678 759
    template <typename Number>
679 760
    Number uinteger() {
680 761
      return _random_bits::IntConversion<Number, Word>::convert(core);
681 762
    }
682 763

	
683 764
    unsigned int uinteger() {
684 765
      return uinteger<unsigned int>();
685 766
    }
686 767

	
687 768
    /// \brief Returns a random integer
688 769
    ///
689 770
    /// It returns a random integer uniformly from the whole range of
690 771
    /// the current \c Number type. The default result type of this
691 772
    /// function is \c int.
692 773
    template <typename Number>
693 774
    Number integer() {
694 775
      static const int nb = std::numeric_limits<Number>::digits + 
695 776
        (std::numeric_limits<Number>::is_signed ? 1 : 0);
696 777
      return _random_bits::IntConversion<Number, Word, nb>::convert(core);
697 778
    }
698 779

	
699 780
    int integer() {
700 781
      return integer<int>();
701 782
    }
702 783
    
703 784
    /// \brief Returns a random bool
704 785
    ///
705 786
    /// It returns a random bool. The generator holds a buffer for
706 787
    /// random bits. Every time when it become empty the generator makes
707 788
    /// a new random word and fill the buffer up.
708 789
    bool boolean() {
709 790
      return bool_producer.convert(core);
710 791
    }
711 792

	
793
    /// @}
794

	
712 795
    ///\name Non-uniform distributions
713 796
    ///
714 797
    
715 798
    ///@{
716 799
    
717 800
    /// \brief Returns a random bool
718 801
    ///
719 802
    /// It returns a random bool with given probability of true result.
720 803
    bool boolean(double p) {
721 804
      return operator()() < p;
722 805
    }
723 806

	
724 807
    /// Standard Gauss distribution
725 808

	
726 809
    /// Standard Gauss distribution.
727 810
    /// \note The Cartesian form of the Box-Muller
728 811
    /// transformation is used to generate a random normal distribution.
729 812
    /// \todo Consider using the "ziggurat" method instead.
730 813
    double gauss() 
731 814
    {
732 815
      double V1,V2,S;
733 816
      do {
734 817
	V1=2*real<double>()-1;
735 818
	V2=2*real<double>()-1;
736 819
	S=V1*V1+V2*V2;
737 820
      } while(S>=1);
738 821
      return std::sqrt(-2*std::log(S)/S)*V1;
739 822
    }
740 823
    /// Gauss distribution with given mean and standard deviation
741 824

	
742 825
    /// Gauss distribution with given mean and standard deviation.
743 826
    /// \sa gauss()
744 827
    double gauss(double mean,double std_dev)
745 828
    {
746 829
      return gauss()*std_dev+mean;
747 830
    }
748 831

	
749 832
    /// Exponential distribution with given mean
750 833

	
751 834
    /// This function generates an exponential distribution random number
752 835
    /// with mean <tt>1/lambda</tt>.
753 836
    ///
754 837
    double exponential(double lambda=1.0)
755 838
    {
756 839
      return -std::log(1.0-real<double>())/lambda;
757 840
    }
758 841

	
759 842
    /// Gamma distribution with given integer shape
0 comments (0 inline)