Changeset c8a5446 in tol
- Timestamp:
- Mar 30, 2012, 9:19:20 AM (15 years ago)
- Branches:
- 1941-docker-image-to-test, devel, master
- Children:
- 6768766
- Parents:
- 7427dd4c
- Location:
- tol
- Files:
-
- 3 edited
-
bmath/bprdist/prd.cpp (modified) (1 diff)
-
bmath/bprdist/tol_bprdist.h (modified) (1 diff)
-
btol/vmatrix_type/vmat_stats.cpp (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
tol/bmath/bprdist/prd.cpp
r7427dd4c rc8a5446 893 893 894 894 //-------------------------------------------------------------------- 895 BDat BTruncatedNormalDist::Random01( 896 BDat lower_, BDat upper_, BDat borderDistance_) 897 //-------------------------------------------------------------------- 898 { 899 double lower = lower_.Value(); 900 double upper = upper_.Value(); 901 double borderDistance = borderDistance_.Value(); 902 double negInf = BDat::NegInf(); 903 double posInf = BDat::PosInf(); 904 double tn; 905 if((lower>negInf)||(upper<posInf)) 906 { 907 //Checking different cases 908 //lower = 66.8902; upper = posInf; 909 //upper = -66.8902; lower = negInf; 910 911 //A continuación se generará una N(0,1) truncada estrictamente en el 912 //interior del intevalo de dominio abierto (lower, upper) para evitar 913 //problemas numéricos de frontera. 914 915 //Máximo valor absoluto para el que se usará la distribución N(0,1) 916 double K = 6; 917 //La probabilidad de estar una N(0,1) fuera del intervalo [-K,K] es 918 //con K=6 es p=1.973175400848959e-009 ~ 1 entre 500 mil millones, por lo que 919 //es despreciable cualquier valor fuera del mismo y nos evitamos problemas 920 //numéricos, pues tanto la cumulativa como su inversa funcionan bien 921 //en este intervalo pero empiezan a fallar a partir de K=8. 922 //Quizás podría ponerse K=7 pero se toma K=6 por dar un margen y porque 923 //la pérdida de precisión es irrelevante tan lejos de la moda. 924 //Fuera de ahí la distribución se aproximará por la raíz cuadrada de una 925 //uniforme en el dominio reducido interior al original de tal forma que 926 //el que el cociente de verosimilitudes entre los extremos sea menor o 927 //igual a 100, pues en ese rango resulta una buena aproximación de la 928 //normal truncada y es al mismo tiempo tratable numéricamente. 929 // 930 //El cociente de densidades entre dos puntos x,y ~ N(0,1) es 931 // 932 // f(x)/f(y) = Exp(-0.5*(x^2-y^2)) 933 // 934 //Si queremos un punto y que sea h veces menos probable que x entonces 935 // 936 // Log(h) = -0.5*(x^2-y^2) 937 // y^2 = x^2 + 2*Log(h) 938 // 939 //Estas operaciones no comportan riesgos numéricos incluso para valores 940 //muy grandes. 941 double lowMrg = lower; 942 double uppMrg = upper; 943 if(lowMrg>K) 944 { 945 if(uppMrg>=2*lowMrg) { uppMrg=2*lowMrg; } 946 //Si todo el dominio está por encima de K tomamos como nuevos límites 947 //tentativos los puntos con densidad 1.1 y 110 veces las del límite inferior. 948 //De esta forma el nuevo límite inferior es por construcción 100 veces más 949 //probable que el superior 950 double lowMrg_ = sqrt(pow(lowMrg,2) + 2.0 * log( 1.1) ); 951 double uppMrg_ = sqrt(pow(lowMrg,2) + 2.0 * log(110.0) ); 952 //Si los límites tentativos se salen del dominio hay que meterlos dentro 953 if(lowMrg_>=upper) 954 { 955 lowMrg = 0.99*lowMrg+0.01*uppMrg; 956 uppMrg = 0.99*uppMrg+0.01*lowMrg; 957 } 958 else 959 { 960 lowMrg = lowMrg_; 961 if(uppMrg_>=upper) 962 { 963 uppMrg = 0.99*uppMrg+0.01*lowMrg; 964 } 965 else 966 { 967 uppMrg = uppMrg_; 968 } 969 } 970 //Tomamos un r uniforme 971 double r = BUniformDist::Random01().Value(); 972 //y calculamos su raíz cuadrada como valor de ponderación de los límites 973 //para forzar puntos más cercanos al nuevo límite inferior. 974 double u = sqrt(r); 975 tn = u*lowMrg + (1.0-u)*uppMrg; 976 if((tn<=lower) ||(tn>=upper)) 977 { 978 Warning(BText("(I) TruncStdGaussian [Case C.1] ")<< 979 " domain:["<<lower<<","<<upper<<"] -> "<< 980 " interior domain: ["<<lowMrg<<","<<uppMrg<<"] -> "<<tn); 981 return(-1); 982 } 983 } 984 else if(upper<-K) 985 { 986 if(lowMrg<=2*uppMrg) { lowMrg=2*uppMrg; } 987 //Si todo el dominio está por debajo de -K tomamos como nuevos límites 988 //tentativos los puntos con densidad 1.1 y 110 veces las del límite superior. 989 //De esta forma el nuevo límite superior es por construcción 100 veces más 990 //probable que el inferior 991 double uppMrg_ = -sqrt(pow(uppMrg,2) + 2.0 * log( 1.1) ); 992 double lowMrg_ = -sqrt(pow(uppMrg,2) + 2.0 * log(110.0) ); 993 //Si los límites tentativos se salen del dominio hay que meterlos dentro 994 if(uppMrg_<=lower) 995 { 996 lowMrg = 0.99*lowMrg+0.01*uppMrg; 997 uppMrg = 0.99*uppMrg+0.01*lowMrg; 998 } 999 else 1000 { 1001 uppMrg = uppMrg_; 1002 if(lowMrg_<=lower) 1003 { 1004 lowMrg = 0.99*lowMrg+0.01*uppMrg; 1005 } 1006 else 1007 { 1008 lowMrg = lowMrg_; 1009 } 1010 } 1011 //Tomamos un r uniforme 1012 double r = BUniformDist::Random01().Value(); 1013 //y calculamos su raíz cuadrada como valor de ponderación de los límites 1014 //para forzar puntos más cercanos al nuevo límite inferior. 1015 double u = sqrt(r); 1016 tn = u*uppMrg + (1.0-u)*lowMrg; 1017 if((tn<=lower) ||(tn>=upper)) 1018 { 1019 Warning(BText("(I) TruncStdGaussian [Case C.2] ") << 1020 " domain:["<<lower<<","<<upper<<"] -> "<< 1021 " interior domain: ["<<lowMrg<<","<<uppMrg<<"] -> "<<tn); 1022 return(-1); 1023 } 1024 } 1025 else 1026 { 1027 //Si alguno de los límites cae fuera de [-K,K] hacemos la intersección 1028 if(lower<-K) { lowMrg=-K; } 1029 if(upper>+K) { uppMrg=+K; } 1030 BNormalDist u01(0,1); 1031 //Calculamos los cuantiles de la N(0,1) en los extremos 1032 double lowF01 = u01.Dist(lowMrg).Value(); 1033 double uppF01 = u01.Dist(uppMrg).Value(); 1034 //Calculamos el desplazamiento en la métrica probabilística 1035 double difF01 = borderDistance*(uppF01-lowF01); 1036 //Desplazamos los límites hacia el interior 1037 double lowF01_ = lowF01+difF01; 1038 double uppF01_ = uppF01-difF01; 1039 //Tomamos un r uniforme 1040 double r = BUniformDist::Random01().Value(); 1041 //Tomamos un u normal truncado en el dominio interior 1042 double u = r*uppF01_ + (1.0-r)*lowF01_; 1043 //Volvemos a la métrica normalizada 1044 tn = u01.Inverse(u).Value(); 1045 if((tn<=lower) ||(tn>=upper)) 1046 { 1047 Warning(BText("(I) TruncStdGaussian [Case C.1] ")<< 1048 " domain:["<<lower<<","<<upper<<"] -> "<< 1049 " Prob domain["<<lowF01<<","<<uppF01<<"] -> "<< 1050 " Prob interior domain["<<lowF01_<<","<<uppF01_<<"] -> "<<tn); 1051 return(-1); 1052 } 1053 } 1054 } 1055 else 1056 { 1057 tn = BNormalDist::Random01().Value(); 1058 if((tn<=lower) ||(tn>=upper)) 1059 { 1060 Warning(BText("(I) TruncStdGaussian [Case D] ")<< 1061 I2("(empty interval", 1062 "(intervalo vacio")+" ["+BDat(lower).Format("%.16lg")+","+ 1063 BDat(upper).Format("%.16lg")+"])"); 1064 } 1065 } 1066 return(tn); 1067 } 1068 1069 //-------------------------------------------------------------------- 1070 BDat BTruncatedNormalDist::Random() 1071 //-------------------------------------------------------------------- 1072 { 1073 BDat nu = normal_.Nu(); 1074 BDat sigma = normal_.Sigma(); 1075 BDat lower = (A_-nu)/sigma; 1076 BDat upper = (B_-nu)/sigma; 1077 BDat borderDistance = DEpsilon(); 1078 BDat tn01 = Random01(lower,upper,borderDistance); 1079 BDat tn = sigma*tn01+nu; 1080 return(tn); 1081 } 1082 1083 //-------------------------------------------------------------------- 895 1084 BClosestInsideDist::BClosestInsideDist(BDat A, BDat B, BDat nu) 896 1085 //-------------------------------------------------------------------- -
tol/bmath/bprdist/tol_bprdist.h
r7427dd4c rc8a5446 315 315 BProbDist& NonTruncated() { return(normal_); } 316 316 317 static BDat Random01(BDat lower, BDat upper, BDat borderDistance); 318 BDat Random(); 319 317 320 BDat Average (); 318 321 BDat Varianze (); -
tol/btol/vmatrix_type/vmat_stats.cpp
r7427dd4c rc8a5446 681 681 } 682 682 # ifdef USE_BTruncatedNormalDist 683 else if((lower>negInf)||(upper<posInf)) 684 { 685 //Checking different cases 686 //lower = 66.8902; upper = posInf; 687 //upper = -66.8902; lower = negInf; 688 689 //A continuación se generará una N(0,1) truncada estrictamente en el 690 //interior del intevalo de dominio abierto (lower, upper) para evitar 691 //problemas numéricos de frontera. 692 693 //Máximo valor absoluto para el que se usará la distribución N(0,1) 694 double K = 6; 695 //La probabilidad de estar una N(0,1) fuera del intervalo [-K,K] es 696 //con K=6 es p=1.973175400848959e-009 ~ 1 entre 500 mil millones, por lo que 697 //es despreciable cualquier valor fuera del mismo y nos evitamos problemas 698 //numéricos, pues tanto la cumulativa como su inversa funcionan bien 699 //en este intervalo pero empiezan a fallar a partir de K=8. 700 //Quizás podría ponerse K=7 pero se toma K=6 por dar un margen y porque 701 //la pérdida de precisión es irrelevante tan lejos de la moda. 702 //Fuera de ahí la distribución se aproximará por la raíz cuadrada de una 703 //uniforme en el dominio reducido interior al original de tal forma que 704 //el que el cociente de verosimilitudes entre los extremos sea menor o 705 //igual a 100, pues en ese rango resulta una buena aproximación de la 706 //normal truncada y es al mismo tiempo tratable numéricamente. 707 // 708 //El cociente de densidades entre dos puntos x,y ~ N(0,1) es 709 // 710 // f(x)/f(y) = Exp(-0.5*(x^2-y^2)) 711 // 712 //Si queremos un punto y que sea h veces menos probable que x entonces 713 // 714 // Log(h) = -0.5*(x^2-y^2) 715 // y^2 = x^2 + 2*Log(h) 716 // 717 //Estas operaciones no comportan riesgos numéricos incluso para valores 718 //muy grandes. 719 double lowMrg = lower; 720 double uppMrg = upper; 721 if(lowMrg>K) 722 { 723 if(uppMrg>=2*lowMrg) { uppMrg=2*lowMrg; } 724 //Si todo el dominio está por encima de K tomamos como nuevos límites 725 //tentativos los puntos con densidad 1.1 y 110 veces las del límite inferior. 726 //De esta forma el nuevo límite inferior es por construcción 100 veces más 727 //probable que el superior 728 double lowMrg_ = sqrt(pow(lowMrg,2) + 2.0 * log( 1.1) ); 729 double uppMrg_ = sqrt(pow(lowMrg,2) + 2.0 * log(110.0) ); 730 //Si los límites tentativos se salen del dominio hay que meterlos dentro 731 if(lowMrg_>=upper) 732 { 733 lowMrg = 0.99*lowMrg+0.01*uppMrg; 734 uppMrg = 0.99*uppMrg+0.01*lowMrg; 735 } 736 else 737 { 738 lowMrg = lowMrg_; 739 if(uppMrg_>=upper) 740 { 741 uppMrg = 0.99*uppMrg+0.01*lowMrg; 742 } 743 else 744 { 745 uppMrg = uppMrg_; 746 } 747 } 748 //Tomamos un r uniforme 749 double r = BUniformDist::Random01().Value(); 750 //y calculamos su raíz cuadrada como valor de ponderación de los límites 751 //para forzar puntos más cercanos al nuevo límite inferior. 752 double u = sqrt(r); 753 zj = u*lowMrg + (1.0-u)*uppMrg; 754 if((zj<=lower) ||(zj>=upper)) 755 { 756 warn_cannot_apply("(I) TruncStdGaussian [Case C.1] ", 757 BText(" j=")<<j<< 758 " domain:["<<lower<<","<<upper<<"] -> "<< 759 " interior domain: ["<<lowMrg<<","<<uppMrg<<"] -> "<<zj,z); 760 return(-1); 761 } 762 } 763 else if(upper<-K) 764 { 765 if(lowMrg<=2*uppMrg) { lowMrg=2*uppMrg; } 766 //Si todo el dominio está por debajo de -K tomamos como nuevos límites 767 //tentativos los puntos con densidad 1.1 y 110 veces las del límite superior. 768 //De esta forma el nuevo límite superior es por construcción 100 veces más 769 //probable que el inferior 770 double uppMrg_ = -sqrt(pow(uppMrg,2) + 2.0 * log( 1.1) ); 771 double lowMrg_ = -sqrt(pow(uppMrg,2) + 2.0 * log(110.0) ); 772 //Si los límites tentativos se salen del dominio hay que meterlos dentro 773 if(uppMrg_<=lower) 774 { 775 lowMrg = 0.99*lowMrg+0.01*uppMrg; 776 uppMrg = 0.99*uppMrg+0.01*lowMrg; 777 } 778 else 779 { 780 uppMrg = uppMrg_; 781 if(lowMrg_<=lower) 782 { 783 lowMrg = 0.99*lowMrg+0.01*uppMrg; 784 } 785 else 786 { 787 lowMrg = lowMrg_; 788 } 789 } 790 //Tomamos un r uniforme 791 double r = BUniformDist::Random01().Value(); 792 //y calculamos su raíz cuadrada como valor de ponderación de los límites 793 //para forzar puntos más cercanos al nuevo límite inferior. 794 double u = sqrt(r); 795 zj = u*uppMrg + (1.0-u)*lowMrg; 796 if((zj<=lower) ||(zj>=upper)) 797 { 798 warn_cannot_apply("(I) TruncStdGaussian [Case C.2] ", 799 BText(" j=")<<j<< 800 " domain:["<<lower<<","<<upper<<"] -> "<< 801 " interior domain: ["<<lowMrg<<","<<uppMrg<<"] -> "<<zj,z); 802 return(-1); 803 } 804 } 805 else 806 { 807 //Si alguno de los límites cae fuera de [-K,K] hacemos la intersección 808 if(lower<-K) { lowMrg=-K; } 809 if(upper>+K) { uppMrg=+K; } 810 BNormalDist u01(0,1); 811 //Calculamos los cuantiles de la N(0,1) en los extremos 812 double lowF01 = u01.Dist(lowMrg).Value(); 813 double uppF01 = u01.Dist(uppMrg).Value(); 814 //Calculamos el desplazamiento en la métrica probabilística 815 double difF01 = borderDistance*(uppF01-lowF01); 816 //Desplazamos los límites hacia el interior 817 double lowF01_ = lowF01+difF01; 818 double uppF01_ = uppF01-difF01; 819 //Tomamos un r uniforme 820 double r = BUniformDist::Random01().Value(); 821 //Tomamos un u normal truncado en el dominio interior 822 double u = r*uppF01_ + (1.0-r)*lowF01_; 823 //Volvemos a la métrica normalizada 824 zj = u01.Inverse(u).Value(); 825 if((zj<=lower) ||(zj>=upper)) 826 { 827 warn_cannot_apply("(I) TruncStdGaussian [Case C.1] ", 828 BText(" j=")<<j<< 829 " domain:["<<lower<<","<<upper<<"] -> "<< 830 " Prob domain["<<lowF01<<","<<uppF01<<"] -> "<< 831 " Prob interior domain["<<lowF01_<<","<<uppF01_<<"] -> "<<zj,z); 832 return(-1); 833 } 834 } 835 } 836 else 837 { 838 zj = BNormalDist::Random01().Value(); 839 if((zj<=lower) ||(zj>=upper)) 840 { 841 warn_cannot_apply("(I) TruncStdGaussian [Case D] ", 842 I2("(empty interval", 843 "(intervalo vacio")+" ["+BDat(lower).Format("%.16lg")+","+ 844 BDat(upper).Format("%.16lg")+"])",z); 845 } 846 } 847 848 683 zj = BTruncatedNormalDist::Random01(lower, upper, borderDistance).Value(); 849 684 # else 850 685 zj = gsl_rtabnorm_combo(getGslRng(), 0.0, 1.0,
Note: See TracChangeset
for help on using the changeset viewer.
