gravatar
alpar (Alpar Juttner)
alpar@cs.elte.hu
A better way of generating pareto distr, and swap its parameters. - Pareto distribution is now generated as a composition of a Gamma and an exponential one - Similarly to gamma() and weibull(), the shape parameter became the first one.
0 1 0
default
1 file changed with 3 insertions and 7 deletions:
↑ Collapse diff ↑
Show white space 384 line context
... ...
@@ -609,269 +609,265 @@
609 609

	
610 610
    /// \brief Returns a random real number from the range [0, 1)
611 611
    ///
612 612
    /// It returns a random double from the range [0, 1).
613 613
    double operator()() {
614 614
      return real<double>();
615 615
    }
616 616

	
617 617
    /// \brief Returns a random real number from the range [0, b)
618 618
    ///
619 619
    /// It returns a random real number from the range [0, b).
620 620
    template <typename Number>
621 621
    Number operator()(Number b) { 
622 622
      return real<Number>() * b; 
623 623
    }
624 624

	
625 625
    /// \brief Returns a random real number from the range [a, b)
626 626
    ///
627 627
    /// It returns a random real number from the range [a, b).
628 628
    template <typename Number>
629 629
    Number operator()(Number a, Number b) { 
630 630
      return real<Number>() * (b - a) + a; 
631 631
    }
632 632

	
633 633
    /// \brief Returns a random integer from a range
634 634
    ///
635 635
    /// It returns a random integer from the range {0, 1, ..., b - 1}.
636 636
    template <typename Number>
637 637
    Number integer(Number b) {
638 638
      return _random_bits::Mapping<Number, Word>::map(core, b);
639 639
    }
640 640

	
641 641
    /// \brief Returns a random integer from a range
642 642
    ///
643 643
    /// It returns a random integer from the range {a, a + 1, ..., b - 1}.
644 644
    template <typename Number>
645 645
    Number integer(Number a, Number b) {
646 646
      return _random_bits::Mapping<Number, Word>::map(core, b - a) + a;
647 647
    }
648 648

	
649 649
    /// \brief Returns a random integer from a range
650 650
    ///
651 651
    /// It returns a random integer from the range {0, 1, ..., b - 1}.
652 652
    template <typename Number>
653 653
    Number operator[](Number b) {
654 654
      return _random_bits::Mapping<Number, Word>::map(core, b);
655 655
    }
656 656

	
657 657
    /// \brief Returns a random non-negative integer
658 658
    ///
659 659
    /// It returns a random non-negative integer uniformly from the
660 660
    /// whole range of the current \c Number type.  The default result
661 661
    /// type of this function is unsigned int.
662 662
    template <typename Number>
663 663
    Number uinteger() {
664 664
      return _random_bits::IntConversion<Number, Word>::convert(core);
665 665
    }
666 666

	
667 667
    unsigned int uinteger() {
668 668
      return uinteger<unsigned int>();
669 669
    }
670 670

	
671 671
    /// \brief Returns a random integer
672 672
    ///
673 673
    /// It returns a random integer uniformly from the whole range of
674 674
    /// the current \c Number type. The default result type of this
675 675
    /// function is int.
676 676
    template <typename Number>
677 677
    Number integer() {
678 678
      static const int nb = std::numeric_limits<Number>::digits + 
679 679
        (std::numeric_limits<Number>::is_signed ? 1 : 0);
680 680
      return _random_bits::IntConversion<Number, Word, nb>::convert(core);
681 681
    }
682 682

	
683 683
    int integer() {
684 684
      return integer<int>();
685 685
    }
686 686
    
687 687
    /// \brief Returns a random bool
688 688
    ///
689 689
    /// It returns a random bool. The generator holds a buffer for
690 690
    /// random bits. Every time when it become empty the generator makes
691 691
    /// a new random word and fill the buffer up.
692 692
    bool boolean() {
693 693
      return bool_producer.convert(core);
694 694
    }
695 695

	
696 696
    ///\name Nonuniform distributions
697 697
    ///
698 698
    
699 699
    ///@{
700 700
    
701 701
    /// \brief Returns a random bool
702 702
    ///
703 703
    /// It returns a random bool with given probability of true result
704 704
    bool boolean(double p) {
705 705
      return operator()() < p;
706 706
    }
707 707

	
708 708
    /// Standard Gauss distribution
709 709

	
710 710
    /// Standard Gauss distribution.
711 711
    /// \note The Cartesian form of the Box-Muller
712 712
    /// transformation is used to generate a random normal distribution.
713 713
    /// \todo Consider using the "ziggurat" method instead.
714 714
    double gauss() 
715 715
    {
716 716
      double V1,V2,S;
717 717
      do {
718 718
	V1=2*real<double>()-1;
719 719
	V2=2*real<double>()-1;
720 720
	S=V1*V1+V2*V2;
721 721
      } while(S>=1);
722 722
      return std::sqrt(-2*std::log(S)/S)*V1;
723 723
    }
724 724
    /// Gauss distribution with given mean and standard deviation
725 725

	
726 726
    /// \sa gauss()
727 727
    ///
728 728
    double gauss(double mean,double std_dev)
729 729
    {
730 730
      return gauss()*std_dev+mean;
731 731
    }
732 732

	
733 733
    /// Exponential distribution with given mean
734 734

	
735 735
    /// This function generates an exponential distribution random number
736 736
    /// with mean <tt>1/lambda</tt>.
737 737
    ///
738 738
    double exponential(double lambda=1.0)
739 739
    {
740 740
      return -std::log(1.0-real<double>())/lambda;
741 741
    }
742 742

	
743 743
    /// Gamma distribution with given integer shape
744 744

	
745 745
    /// This function generates a gamma distribution random number.
746 746
    /// 
747 747
    ///\param k shape parameter (<tt>k>0</tt> integer)
748 748
    double gamma(int k) 
749 749
    {
750 750
      double s = 0;
751 751
      for(int i=0;i<k;i++) s-=std::log(1.0-real<double>());
752 752
      return s;
753 753
    }
754 754
    
755 755
    /// Gamma distribution with given shape and scale parameter
756 756

	
757 757
    /// This function generates a gamma distribution random number.
758 758
    /// 
759 759
    ///\param k shape parameter (<tt>k>0</tt>)
760 760
    ///\param theta scale parameter
761 761
    ///
762 762
    double gamma(double k,double theta=1.0)
763 763
    {
764 764
      double xi,nu;
765 765
      const double delta = k-std::floor(k);
766 766
      const double v0=M_E/(M_E-delta);
767 767
      do {
768 768
	double V0=1.0-real<double>();
769 769
	double V1=1.0-real<double>();
770 770
	double V2=1.0-real<double>();
771 771
	if(V2<=v0) 
772 772
	  {
773 773
	    xi=std::pow(V1,1.0/delta);
774 774
	    nu=V0*std::pow(xi,delta-1.0);
775 775
	  }
776 776
	else 
777 777
	  {
778 778
	    xi=1.0-std::log(V1);
779 779
	    nu=V0*std::exp(-xi);
780 780
	  }
781 781
      } while(nu>std::pow(xi,delta-1.0)*std::exp(-xi));
782 782
      return theta*(xi-gamma(int(std::floor(k))));
783 783
    }
784 784
    
785 785
    /// Weibull distribution
786 786

	
787 787
    /// This function generates a Weibull distribution random number.
788 788
    /// 
789 789
    ///\param k shape parameter (<tt>k>0</tt>)
790 790
    ///\param lambda scale parameter (<tt>lambda>0</tt>)
791 791
    ///
792 792
    double weibull(double k,double lambda)
793 793
    {
794 794
      return lambda*pow(-std::log(1.0-real<double>()),1.0/k);
795 795
    }  
796 796
      
797 797
    /// Pareto distribution
798 798

	
799 799
    /// This function generates a Pareto distribution random number.
800 800
    /// 
801
    ///\param k shape parameter (<tt>k>0</tt>)
801 802
    ///\param x_min location parameter (<tt>x_min>0</tt>)
802
    ///\param k shape parameter (<tt>k>0</tt>)
803 803
    ///
804
    ///\warning This function used inverse transform sampling, therefore may
805
    ///suffer from numerical unstability.
806
    ///
807
    ///\todo Implement a numerically stable method
808
    double pareto(double x_min,double k)
804
    double pareto(double k,double x_min)
809 805
    {
810
      return x_min*pow(1.0-real<double>(),1.0/k);
806
      return exponential(gamma(k,1.0/x_min));
811 807
    }  
812 808
      
813 809
    ///@}
814 810
    
815 811
    ///\name Two dimensional distributions
816 812
    ///
817 813

	
818 814
    ///@{
819 815
    
820 816
    /// Uniform distribution on the full unit circle.
821 817
    dim2::Point<double> disc() 
822 818
    {
823 819
      double V1,V2;
824 820
      do {
825 821
	V1=2*real<double>()-1;
826 822
	V2=2*real<double>()-1;
827 823
	
828 824
      } while(V1*V1+V2*V2>=1);
829 825
      return dim2::Point<double>(V1,V2);
830 826
    }
831 827
    /// A kind of two dimensional Gauss distribution
832 828

	
833 829
    /// This function provides a turning symmetric two-dimensional distribution.
834 830
    /// Both coordinates are of standard normal distribution, but they are not
835 831
    /// independent.
836 832
    ///
837 833
    /// \note The coordinates are the two random variables provided by
838 834
    /// the Box-Muller method.
839 835
    dim2::Point<double> gauss2()
840 836
    {
841 837
      double V1,V2,S;
842 838
      do {
843 839
	V1=2*real<double>()-1;
844 840
	V2=2*real<double>()-1;
845 841
	S=V1*V1+V2*V2;
846 842
      } while(S>=1);
847 843
      double W=std::sqrt(-2*std::log(S)/S);
848 844
      return dim2::Point<double>(W*V1,W*V2);
849 845
    }
850 846
    /// A kind of two dimensional exponential distribution
851 847

	
852 848
    /// This function provides a turning symmetric two-dimensional distribution.
853 849
    /// The x-coordinate is of conditionally exponential distribution
854 850
    /// with the condition that x is positive and y=0. If x is negative and 
855 851
    /// y=0 then, -x is of exponential distribution. The same is true for the
856 852
    /// y-coordinate.
857 853
    dim2::Point<double> exponential2() 
858 854
    {
859 855
      double V1,V2,S;
860 856
      do {
861 857
	V1=2*real<double>()-1;
862 858
	V2=2*real<double>()-1;
863 859
	S=V1*V1+V2*V2;
864 860
      } while(S>=1);
865 861
      double W=-std::log(S)/S;
866 862
      return dim2::Point<double>(W*V1,W*V2);
867 863
    }
868 864

	
869 865
    ///@}    
870 866
  };
871 867

	
872 868

	
873 869
  extern Random rnd;
874 870

	
875 871
}
876 872

	
877 873
#endif
0 comments (0 inline)