gravatar
kpeter (Peter Kovacs)
kpeter@inf.elte.hu
Minor doc improvements
0 1 0
default
1 file changed with 9 insertions and 23 deletions:
↑ Collapse diff ↑
Ignore white space 192 line context
... ...
@@ -447,603 +447,589 @@
447 447
      }
448 448
    };
449 449

	
450 450
    template <typename Word>
451 451
    struct BoolConversion {
452 452
      static bool convert(RandomCore<Word>& rnd) {
453 453
        return (rnd() & 1) == 1;
454 454
      }
455 455
    };
456 456

	
457 457
    template <typename Word>
458 458
    struct BoolProducer {
459 459
      Word buffer;
460 460
      int num;
461 461

	
462 462
      BoolProducer() : num(0) {}
463 463

	
464 464
      bool convert(RandomCore<Word>& rnd) {
465 465
        if (num == 0) {
466 466
          buffer = rnd();
467 467
          num = RandomTraits<Word>::bits;
468 468
        }
469 469
        bool r = (buffer & 1);
470 470
        buffer >>= 1;
471 471
        --num;
472 472
        return r;
473 473
      }
474 474
    };
475 475

	
476 476
  }
477 477

	
478 478
  /// \ingroup misc
479 479
  ///
480 480
  /// \brief Mersenne Twister random number generator
481 481
  ///
482 482
  /// The Mersenne Twister is a twisted generalized feedback
483 483
  /// shift-register generator of Matsumoto and Nishimura. The period
484 484
  /// of this generator is \f$ 2^{19937} - 1 \f$ and it is
485 485
  /// equi-distributed in 623 dimensions for 32-bit numbers. The time
486 486
  /// performance of this generator is comparable to the commonly used
487 487
  /// generators.
488 488
  ///
489 489
  /// This implementation is specialized for both 32-bit and 64-bit
490 490
  /// architectures. The generators differ sligthly in the
491 491
  /// initialization and generation phase so they produce two
492 492
  /// completly different sequences.
493 493
  ///
494 494
  /// The generator gives back random numbers of serveral types. To
495 495
  /// get a random number from a range of a floating point type you
496 496
  /// can use one form of the \c operator() or the \c real() member
497 497
  /// function. If you want to get random number from the {0, 1, ...,
498 498
  /// n-1} integer range use the \c operator[] or the \c integer()
499 499
  /// method. And to get random number from the whole range of an
500 500
  /// integer type you can use the argumentless \c integer() or \c
501 501
  /// uinteger() functions. After all you can get random bool with
502 502
  /// equal chance of true and false or given probability of true
503 503
  /// result with the \c boolean() member functions.
504 504
  ///
505 505
  ///\code
506 506
  /// // The commented code is identical to the other
507 507
  /// double a = rnd();                     // [0.0, 1.0)
508 508
  /// // double a = rnd.real();             // [0.0, 1.0)
509 509
  /// double b = rnd(100.0);                // [0.0, 100.0)
510 510
  /// // double b = rnd.real(100.0);        // [0.0, 100.0)
511 511
  /// double c = rnd(1.0, 2.0);             // [1.0, 2.0)
512 512
  /// // double c = rnd.real(1.0, 2.0);     // [1.0, 2.0)
513 513
  /// int d = rnd[100000];                  // 0..99999
514 514
  /// // int d = rnd.integer(100000);       // 0..99999
515 515
  /// int e = rnd[6] + 1;                   // 1..6
516 516
  /// // int e = rnd.integer(1, 1 + 6);     // 1..6
517 517
  /// int b = rnd.uinteger<int>();          // 0 .. 2^31 - 1
518 518
  /// int c = rnd.integer<int>();           // - 2^31 .. 2^31 - 1
519 519
  /// bool g = rnd.boolean();               // P(g = true) = 0.5
520 520
  /// bool h = rnd.boolean(0.8);            // P(h = true) = 0.8
521 521
  ///\endcode
522 522
  ///
523 523
  /// LEMON provides a global instance of the random number
524 524
  /// generator which name is \ref lemon::rnd "rnd". Usually it is a
525 525
  /// good programming convenience to use this global generator to get
526 526
  /// random numbers.
527 527
  class Random {
528 528
  private:
529 529

	
530 530
    // Architecture word
531 531
    typedef unsigned long Word;
532 532

	
533 533
    _random_bits::RandomCore<Word> core;
534 534
    _random_bits::BoolProducer<Word> bool_producer;
535 535

	
536 536

	
537 537
  public:
538 538

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

	
543
    ///\name Initialization
544
    ///
545
    /// @{
546

	
547 543
    /// \brief Default constructor
548 544
    ///
549 545
    /// Constructor with constant seeding.
550 546
    Random() { core.initState(); }
551 547

	
552 548
    /// \brief Constructor with seed
553 549
    ///
554 550
    /// Constructor with seed. The current number type will be converted
555 551
    /// to the architecture word type.
556 552
    template <typename Number>
557 553
    Random(Number seed) {
558 554
      _random_bits::Initializer<Number, Word>::init(core, seed);
559 555
    }
560 556

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

	
572 568
    /// \brief Copy constructor
573 569
    ///
574 570
    /// Copy constructor. The generated sequence will be identical to
575 571
    /// the other sequence. It can be used to save the current state
576 572
    /// of the generator and later use it to generate the same
577 573
    /// sequence.
578 574
    Random(const Random& other) {
579 575
      core.copyState(other.core);
580 576
    }
581 577

	
582 578
    /// \brief Assign operator
583 579
    ///
584 580
    /// Assign operator. The generated sequence will be identical to
585 581
    /// the other sequence. It can be used to save the current state
586 582
    /// of the generator and later use it to generate the same
587 583
    /// sequence.
588 584
    Random& operator=(const Random& other) {
589 585
      if (&other != this) {
590 586
        core.copyState(other.core);
591 587
      }
592 588
      return *this;
593 589
    }
594 590

	
595 591
    /// \brief Seeding random sequence
596 592
    ///
597 593
    /// Seeding the random sequence. The current number type will be
598 594
    /// converted to the architecture word type.
599 595
    template <typename Number>
600 596
    void seed(Number seed) {
601 597
      _random_bits::Initializer<Number, Word>::init(core, seed);
602 598
    }
603 599

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

	
615 611
    /// \brief Seeding from file or from process id and time
616 612
    ///
617 613
    /// By default, this function calls the \c seedFromFile() member
618 614
    /// function with the <tt>/dev/urandom</tt> file. If it does not success,
619 615
    /// it uses the \c seedFromTime().
620 616
    /// \return Currently always true.
621 617
    bool seed() {
622 618
#ifndef WIN32
623 619
      if (seedFromFile("/dev/urandom", 0)) return true;
624 620
#endif
625 621
      if (seedFromTime()) return true;
626 622
      return false;
627 623
    }
628 624

	
629 625
    /// \brief Seeding from file
630 626
    ///
631 627
    /// Seeding the random sequence from file. The linux kernel has two
632 628
    /// devices, <tt>/dev/random</tt> and <tt>/dev/urandom</tt> which
633 629
    /// could give good seed values for pseudo random generators (The
634 630
    /// difference between two devices is that the <tt>random</tt> may
635 631
    /// block the reading operation while the kernel can give good
636 632
    /// source of randomness, while the <tt>urandom</tt> does not
637 633
    /// block the input, but it could give back bytes with worse
638 634
    /// entropy).
639 635
    /// \param file The source file
640 636
    /// \param offset The offset, from the file read.
641 637
    /// \return True when the seeding successes.
642 638
#ifndef WIN32
643 639
    bool seedFromFile(const std::string& file = "/dev/urandom", int offset = 0)
644 640
#else
645 641
    bool seedFromFile(const std::string& file = "", int offset = 0)
646 642
#endif
647 643
    {
648 644
      std::ifstream rs(file.c_str());
649 645
      const int size = 4;
650 646
      Word buf[size];
651 647
      if (offset != 0 && !rs.seekg(offset)) return false;
652 648
      if (!rs.read(reinterpret_cast<char*>(buf), sizeof(buf))) return false;
653 649
      seed(buf, buf + size);
654 650
      return true;
655 651
    }
656 652

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

	
676 672
    /// @}
677 673

	
678 674
    ///\name Uniform distributions
679 675
    ///
680 676
    /// @{
681 677

	
682 678
    /// \brief Returns a random real number from the range [0, 1)
683 679
    ///
684 680
    /// It returns a random real number from the range [0, 1). The
685 681
    /// default Number type is \c double.
686 682
    template <typename Number>
687 683
    Number real() {
688 684
      return _random_bits::RealConversion<Number, Word>::convert(core);
689 685
    }
690 686

	
691 687
    double real() {
692 688
      return real<double>();
693 689
    }
694 690

	
695 691
    /// \brief Returns a random real number the range [0, b)
696 692
    ///
697 693
    /// It returns a random real number from the range [0, b).
698 694
    template <typename Number>
699 695
    Number real(Number b) {
700 696
      return real<Number>() * b;
701 697
    }
702 698

	
703 699
    /// \brief Returns a random real number from the range [a, b)
704 700
    ///
705 701
    /// It returns a random real number from the range [a, b).
706 702
    template <typename Number>
707 703
    Number real(Number a, Number b) {
708 704
      return real<Number>() * (b - a) + a;
709 705
    }
710 706

	
711
    /// @}
712

	
713
    ///\name Uniform distributions
714
    ///
715
    /// @{
716

	
717 707
    /// \brief Returns a random real number from the range [0, 1)
718 708
    ///
719 709
    /// It returns a random double from the range [0, 1).
720 710
    double operator()() {
721 711
      return real<double>();
722 712
    }
723 713

	
724 714
    /// \brief Returns a random real number from the range [0, b)
725 715
    ///
726 716
    /// It returns a random real number from the range [0, b).
727 717
    template <typename Number>
728 718
    Number operator()(Number b) {
729 719
      return real<Number>() * b;
730 720
    }
731 721

	
732 722
    /// \brief Returns a random real number from the range [a, b)
733 723
    ///
734 724
    /// It returns a random real number from the range [a, b).
735 725
    template <typename Number>
736 726
    Number operator()(Number a, Number b) {
737 727
      return real<Number>() * (b - a) + a;
738 728
    }
739 729

	
740 730
    /// \brief Returns a random integer from a range
741 731
    ///
742 732
    /// It returns a random integer from the range {0, 1, ..., b - 1}.
743 733
    template <typename Number>
744 734
    Number integer(Number b) {
745 735
      return _random_bits::Mapping<Number, Word>::map(core, b);
746 736
    }
747 737

	
748 738
    /// \brief Returns a random integer from a range
749 739
    ///
750 740
    /// It returns a random integer from the range {a, a + 1, ..., b - 1}.
751 741
    template <typename Number>
752 742
    Number integer(Number a, Number b) {
753 743
      return _random_bits::Mapping<Number, Word>::map(core, b - a) + a;
754 744
    }
755 745

	
756 746
    /// \brief Returns a random integer from a range
757 747
    ///
758 748
    /// It returns a random integer from the range {0, 1, ..., b - 1}.
759 749
    template <typename Number>
760 750
    Number operator[](Number b) {
761 751
      return _random_bits::Mapping<Number, Word>::map(core, b);
762 752
    }
763 753

	
764 754
    /// \brief Returns a random non-negative integer
765 755
    ///
766 756
    /// It returns a random non-negative integer uniformly from the
767 757
    /// whole range of the current \c Number type. The default result
768 758
    /// type of this function is <tt>unsigned int</tt>.
769 759
    template <typename Number>
770 760
    Number uinteger() {
771 761
      return _random_bits::IntConversion<Number, Word>::convert(core);
772 762
    }
773 763

	
774
    /// @}
775

	
776 764
    unsigned int uinteger() {
777 765
      return uinteger<unsigned int>();
778 766
    }
779 767

	
780 768
    /// \brief Returns a random integer
781 769
    ///
782 770
    /// It returns a random integer uniformly from the whole range of
783 771
    /// the current \c Number type. The default result type of this
784 772
    /// function is \c int.
785 773
    template <typename Number>
786 774
    Number integer() {
787 775
      static const int nb = std::numeric_limits<Number>::digits +
788 776
        (std::numeric_limits<Number>::is_signed ? 1 : 0);
789 777
      return _random_bits::IntConversion<Number, Word, nb>::convert(core);
790 778
    }
791 779

	
792 780
    int integer() {
793 781
      return integer<int>();
794 782
    }
795 783

	
796 784
    /// \brief Returns a random bool
797 785
    ///
798 786
    /// It returns a random bool. The generator holds a buffer for
799 787
    /// random bits. Every time when it become empty the generator makes
800 788
    /// a new random word and fill the buffer up.
801 789
    bool boolean() {
802 790
      return bool_producer.convert(core);
803 791
    }
804 792

	
805 793
    /// @}
806 794

	
807 795
    ///\name Non-uniform distributions
808 796
    ///
809

	
810 797
    ///@{
811 798

	
812
    /// \brief Returns a random bool
799
    /// \brief Returns a random bool with given probability of true result.
813 800
    ///
814 801
    /// It returns a random bool with given probability of true result.
815 802
    bool boolean(double p) {
816 803
      return operator()() < p;
817 804
    }
818 805

	
819
    /// Standard Gauss distribution
806
    /// Standard normal (Gauss) distribution
820 807

	
821
    /// Standard Gauss distribution.
808
    /// Standard normal (Gauss) distribution.
822 809
    /// \note The Cartesian form of the Box-Muller
823 810
    /// transformation is used to generate a random normal distribution.
824 811
    double gauss()
825 812
    {
826 813
      double V1,V2,S;
827 814
      do {
828 815
        V1=2*real<double>()-1;
829 816
        V2=2*real<double>()-1;
830 817
        S=V1*V1+V2*V2;
831 818
      } while(S>=1);
832 819
      return std::sqrt(-2*std::log(S)/S)*V1;
833 820
    }
834
    /// Gauss distribution with given mean and standard deviation
821
    /// Normal (Gauss) distribution with given mean and standard deviation
835 822

	
836
    /// Gauss distribution with given mean and standard deviation.
823
    /// Normal (Gauss) distribution with given mean and standard deviation.
837 824
    /// \sa gauss()
838 825
    double gauss(double mean,double std_dev)
839 826
    {
840 827
      return gauss()*std_dev+mean;
841 828
    }
842 829

	
843 830
    /// Lognormal distribution
844 831

	
845 832
    /// Lognormal distribution. The parameters are the mean and the standard
846 833
    /// deviation of <tt>exp(X)</tt>.
847 834
    ///
848 835
    double lognormal(double n_mean,double n_std_dev)
849 836
    {
850 837
      return std::exp(gauss(n_mean,n_std_dev));
851 838
    }
852 839
    /// Lognormal distribution
853 840

	
854 841
    /// Lognormal distribution. The parameter is an <tt>std::pair</tt> of
855 842
    /// the mean and the standard deviation of <tt>exp(X)</tt>.
856 843
    ///
857 844
    double lognormal(const std::pair<double,double> &params)
858 845
    {
859 846
      return std::exp(gauss(params.first,params.second));
860 847
    }
861 848
    /// Compute the lognormal parameters from mean and standard deviation
862 849

	
863 850
    /// This function computes the lognormal parameters from mean and
864 851
    /// standard deviation. The return value can direcly be passed to
865 852
    /// lognormal().
866 853
    std::pair<double,double> lognormalParamsFromMD(double mean,
867
						   double std_dev)
854
                                                   double std_dev)
868 855
    {
869 856
      double fr=std_dev/mean;
870 857
      fr*=fr;
871 858
      double lg=std::log(1+fr);
872 859
      return std::pair<double,double>(std::log(mean)-lg/2.0,std::sqrt(lg));
873 860
    }
874 861
    /// Lognormal distribution with given mean and standard deviation
875
    
862

	
876 863
    /// Lognormal distribution with given mean and standard deviation.
877 864
    ///
878 865
    double lognormalMD(double mean,double std_dev)
879 866
    {
880 867
      return lognormal(lognormalParamsFromMD(mean,std_dev));
881 868
    }
882
    
869

	
883 870
    /// Exponential distribution with given mean
884 871

	
885 872
    /// This function generates an exponential distribution random number
886 873
    /// with mean <tt>1/lambda</tt>.
887 874
    ///
888 875
    double exponential(double lambda=1.0)
889 876
    {
890 877
      return -std::log(1.0-real<double>())/lambda;
891 878
    }
892 879

	
893 880
    /// Gamma distribution with given integer shape
894 881

	
895 882
    /// This function generates a gamma distribution random number.
896 883
    ///
897 884
    ///\param k shape parameter (<tt>k>0</tt> integer)
898 885
    double gamma(int k)
899 886
    {
900 887
      double s = 0;
901 888
      for(int i=0;i<k;i++) s-=std::log(1.0-real<double>());
902 889
      return s;
903 890
    }
904 891

	
905 892
    /// Gamma distribution with given shape and scale parameter
906 893

	
907 894
    /// This function generates a gamma distribution random number.
908 895
    ///
909 896
    ///\param k shape parameter (<tt>k>0</tt>)
910 897
    ///\param theta scale parameter
911 898
    ///
912 899
    double gamma(double k,double theta=1.0)
913 900
    {
914 901
      double xi,nu;
915 902
      const double delta = k-std::floor(k);
916 903
      const double v0=E/(E-delta);
917 904
      do {
918 905
        double V0=1.0-real<double>();
919 906
        double V1=1.0-real<double>();
920 907
        double V2=1.0-real<double>();
921 908
        if(V2<=v0)
922 909
          {
923 910
            xi=std::pow(V1,1.0/delta);
924 911
            nu=V0*std::pow(xi,delta-1.0);
925 912
          }
926 913
        else
927 914
          {
928 915
            xi=1.0-std::log(V1);
929 916
            nu=V0*std::exp(-xi);
930 917
          }
931 918
      } while(nu>std::pow(xi,delta-1.0)*std::exp(-xi));
932 919
      return theta*(xi+gamma(int(std::floor(k))));
933 920
    }
934 921

	
935 922
    /// Weibull distribution
936 923

	
937 924
    /// This function generates a Weibull distribution random number.
938 925
    ///
939 926
    ///\param k shape parameter (<tt>k>0</tt>)
940 927
    ///\param lambda scale parameter (<tt>lambda>0</tt>)
941 928
    ///
942 929
    double weibull(double k,double lambda)
943 930
    {
944 931
      return lambda*pow(-std::log(1.0-real<double>()),1.0/k);
945 932
    }
946 933

	
947 934
    /// Pareto distribution
948 935

	
949 936
    /// This function generates a Pareto distribution random number.
950 937
    ///
951 938
    ///\param k shape parameter (<tt>k>0</tt>)
952 939
    ///\param x_min location parameter (<tt>x_min>0</tt>)
953 940
    ///
954 941
    double pareto(double k,double x_min)
955 942
    {
956 943
      return exponential(gamma(k,1.0/x_min))+x_min;
957 944
    }
958 945

	
959 946
    /// Poisson distribution
960 947

	
961 948
    /// This function generates a Poisson distribution random number with
962 949
    /// parameter \c lambda.
963 950
    ///
964 951
    /// The probability mass function of this distribusion is
965 952
    /// \f[ \frac{e^{-\lambda}\lambda^k}{k!} \f]
966 953
    /// \note The algorithm is taken from the book of Donald E. Knuth titled
967 954
    /// ''Seminumerical Algorithms'' (1969). Its running time is linear in the
968 955
    /// return value.
969 956

	
970 957
    int poisson(double lambda)
971 958
    {
972 959
      const double l = std::exp(-lambda);
973 960
      int k=0;
974 961
      double p = 1.0;
975 962
      do {
976 963
        k++;
977 964
        p*=real<double>();
978 965
      } while (p>=l);
979 966
      return k-1;
980 967
    }
981 968

	
982 969
    ///@}
983 970

	
984 971
    ///\name Two dimensional distributions
985 972
    ///
986

	
987 973
    ///@{
988 974

	
989 975
    /// Uniform distribution on the full unit circle
990 976

	
991 977
    /// Uniform distribution on the full unit circle.
992 978
    ///
993 979
    dim2::Point<double> disc()
994 980
    {
995 981
      double V1,V2;
996 982
      do {
997 983
        V1=2*real<double>()-1;
998 984
        V2=2*real<double>()-1;
999 985

	
1000 986
      } while(V1*V1+V2*V2>=1);
1001 987
      return dim2::Point<double>(V1,V2);
1002 988
    }
1003
    /// A kind of two dimensional Gauss distribution
989
    /// A kind of two dimensional normal (Gauss) distribution
1004 990

	
1005 991
    /// This function provides a turning symmetric two-dimensional distribution.
1006 992
    /// Both coordinates are of standard normal distribution, but they are not
1007 993
    /// independent.
1008 994
    ///
1009 995
    /// \note The coordinates are the two random variables provided by
1010 996
    /// the Box-Muller method.
1011 997
    dim2::Point<double> gauss2()
1012 998
    {
1013 999
      double V1,V2,S;
1014 1000
      do {
1015 1001
        V1=2*real<double>()-1;
1016 1002
        V2=2*real<double>()-1;
1017 1003
        S=V1*V1+V2*V2;
1018 1004
      } while(S>=1);
1019 1005
      double W=std::sqrt(-2*std::log(S)/S);
1020 1006
      return dim2::Point<double>(W*V1,W*V2);
1021 1007
    }
1022 1008
    /// A kind of two dimensional exponential distribution
1023 1009

	
1024 1010
    /// This function provides a turning symmetric two-dimensional distribution.
1025 1011
    /// The x-coordinate is of conditionally exponential distribution
1026 1012
    /// with the condition that x is positive and y=0. If x is negative and
1027 1013
    /// y=0 then, -x is of exponential distribution. The same is true for the
1028 1014
    /// y-coordinate.
1029 1015
    dim2::Point<double> exponential2()
1030 1016
    {
1031 1017
      double V1,V2,S;
1032 1018
      do {
1033 1019
        V1=2*real<double>()-1;
1034 1020
        V2=2*real<double>()-1;
1035 1021
        S=V1*V1+V2*V2;
1036 1022
      } while(S>=1);
1037 1023
      double W=-std::log(S)/S;
1038 1024
      return dim2::Point<double>(W*V1,W*V2);
1039 1025
    }
1040 1026

	
1041 1027
    ///@}
1042 1028
  };
1043 1029

	
1044 1030

	
1045 1031
  extern Random rnd;
1046 1032

	
1047 1033
}
1048 1034

	
1049 1035
#endif
0 comments (0 inline)