Changeset 9f6ab11 in tol
- Timestamp:
- Nov 21, 2011, 11:22:05 AM (15 years ago)
- Branches:
- 1941-docker-image-to-test, devel, master
- Children:
- 11d9bec
- Parents:
- 9e93790
- Location:
- tol/btol/vmatrix_type
- Files:
-
- 3 edited
-
tol_bvmat.h (modified) (2 diffs)
-
vmat_stats.cpp (modified) (7 diffs)
-
vmatgra.cpp (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
tol/btol/vmatrix_type/tol_bvmat.h
r9e93790 r9f6ab11 544 544 double& upper); 545 545 void TruncStdGaussian(const BVMat& D, const BVMat& d_, 546 const BVMat& z0_, int ncol, int burnin);546 const BVMat& z0_, int ncol, int burnin, double borderDistance); 547 547 void Histogram(const BVMat& M, int parts); 548 548 void Histogram(const BVMat& M, int parts, double min, double max); … … 555 555 const BVMat& d, 556 556 BVMat& b, 557 BVMat& z); 557 BVMat& z, 558 double borderDistance); 558 559 void Histogram_bRd(const BVMat& M, int parts); 559 560 void Histogram_bRd(const BVMat& M, int parts, double min, double max); -
tol/btol/vmatrix_type/vmat_stats.cpp
r9e93790 r9f6ab11 573 573 } 574 574 //Std(BText("\nlower=")<<lower<<"\tupper="<<upper); 575 double length = lower-upper;575 double length = upper-lower; 576 576 int length_sign = gsl_fcmp(length+1.0,1.0,vmat_trunc_eps); 577 if(length_sign >=0)577 if(length_sign<=0) 578 578 { 579 579 if(length_sign==0) … … 597 597 const BVMat& d, 598 598 BVMat& b, 599 BVMat& z) 599 BVMat& z, 600 double borderDistance) 600 601 // Generates a set of standarized multinormal z constrained to 601 602 // D*z <= d … … 646 647 { 647 648 bx[i] += Dij*zj; 649 aux = bx[i]/Dij; 648 650 //Std(BText("\n D[")+i+","+j+"]="+BDat(Dij)+"\tz["+j+"]="+BDat(zj)+"\tb["+i+"]="+BDat(bx[i])+"\td["+i+"]="+BDat(dx[i])); 649 651 if(Dij_sign<0) 650 652 { 651 aux = bx[i]/Dij;652 653 if(lower<aux) { lower = aux; } 653 //Std(BText("\n aux=")+BDat(aux)+"\tlower="<<BDat(lower));654 654 } 655 655 else //if(Dij_sign>0) 656 656 { 657 aux = bx[i]/Dij;658 657 if(upper>aux) { upper = aux; } 659 //Std(BText("\n aux=")+BDat(aux)+"\tupper="<<BDat(upper));660 658 } 661 659 } 662 660 } 663 661 //Std(BText("\nlower=")<<BDat(lower)<<"\tupper="<<BDat(upper)); 664 double length = lower-upper; 665 int length_sign = gsl_fcmp(length+1.0,1.0, vmat_trunc_eps); 666 if(length_sign>=0) 667 { 668 if(length_sign==0) 662 double length = upper-lower; 663 if(fabs(length)<=1.E-8) 664 { 665 //Si el intervalo es cuasi-vacío estamos rondando la frontera pero 666 //el punto es prácticamente factible. 667 Std(BText("(I) TruncStdGaussian [Case A] ")<< 668 I2("(cuasi-empty interval", 669 "(intervalo cuasi-vacio")+" ["+BDat(lower).Format("%.16lg")+","+ 670 BDat(upper).Format("%.16lg")+"])"); 671 zj = (lower+upper)*0.5; 672 } 673 else if(length<0) 674 { 675 //Si el intervalo es vacío estamos fuera de la región factible 676 warn_cannot_apply("(I) TruncStdGaussian [Case B] ", 677 I2("(empty interval", 678 "(intervalo vacio")+" ["+BDat(lower).Format("%.16lg")+","+ 679 BDat(upper).Format("%.16lg")+"])",z); 680 return(-1); 681 } 682 # ifdef USE_BTruncatedNormalDist 683 else if((lower>negInf)||(upper<posInf)) 684 { 685 //A continuación se generará una N(0,1) truncada estrictamente en el 686 //interior del intevalo de dominio abierto (lower, upper) para evitar 687 //problemas numéricos de frontera. 688 689 //Máximo valor absoluto para el que se usará la distribución N(0,1) 690 double K = 6; 691 //La probabilidad de estar una N(0,1) fuera del intervalo [-K,K] es 692 //con K=6 es p=1.973175400848959e-009 ~ 1 entre 500 mil millones, por lo que 693 //es despreciable cualquier valor fuera del mismo y nos evitamos problemas 694 //numéricos, pues tanto la cumulativa como su inversa funcionan bien 695 //en este intervalo pero empiezan a fallar a partir de K=8. 696 //Quizás podría ponerse K=7 pero se toma K=6 por dar un margen y porque 697 //la pérdida de precisión es irrelevante tan lejos de la moda. 698 //Fuera de ahí la distribución se aproximará por la raíz cuadrada de una 699 //uniforme en el dominio reducido interior al original de tal forma que 700 //el que el cociente de verosimilitudes entre los extremos sea menor o 701 //igual a 100, pues en ese rango resulta una buena aproximación de la 702 //normal truncada y es al mismo tiempo tratable numéricamente. 703 // 704 //El cociente de densidades entre dos puntos x,y ~ N(0,1) es 705 // 706 // f(x)/f(y) = Exp(-0.5*(x^2-y^2)) 707 // 708 //Si queremos un punto y que sea h veces menos probable que x entonces 709 // 710 // Log(h) = -0.5*(x^2-y^2) 711 // y^2 = x^2 + 2*Log(h) 712 // 713 //Estas operaciones no comportan riesgos numéricos incluso para valores 714 //muy grandes. 715 double lowMrg = lower; 716 double uppMrg = upper; 717 if(lower>=K) 718 { 719 //Si todo el dominio está por encima de K tomamos como nuevos límites 720 //tentativos los puntos con densidad 1.1 y 110 veces las del límite inferior. 721 //De esta forma el nuevo límite inferior es por construcción 100 veces más 722 //probable que el superior 723 double lowMrg_ = sqrt(pow(lower,2) + 2.0 * log( 1.1) ); 724 double uppMrg_ = sqrt(pow(upper,2) + 2.0 * log(110.0) ); 725 //Si los límites tentativos se salen del dominio hay que meterlos dentro 726 if(lowMrg_>=upper) 727 { 728 lowMrg = 0.99*lower+0.01*upper; 729 uppMrg = 0.99*upper+0.01*lower; 730 } 731 else 732 { 733 lowMrg = lowMrg_; 734 if(uppMrg_>=upper) 735 { 736 uppMrg = 0.99*upper+0.01*lowMrg; 737 } 738 else 739 { 740 uppMrg = uppMrg_; 741 } 742 } 743 //Tomamos un r uniforme 744 double r = BUniformDist::Random01().Value(); 745 //y calculamos su raíz cuadrada como valor de ponderación de los límites 746 //para forzar puntos más cercanos al nuevo límite inferior. 747 double u = sqrt(r); 748 zj = u*lowMrg + (1.0-u)*uppMrg; 749 if((zj<=lower) ||(zj>=upper)) 750 { 751 warn_cannot_apply("(I) TruncStdGaussian [Case C.1] ", 752 BText(" j=")<<j<< 753 " domain:["<<lower<<","<<upper<<"] -> "<< 754 " interior domain: ["<<lowMrg<<","<<uppMrg<<"] -> "<<zj,z); 755 return(-1); 756 } 757 } 758 else if(upper<=-K) 669 759 { 670 lower = upper; 760 //Si todo el dominio está por debajo de -K tomamos como nuevos límites 761 //tentativos los puntos con densidad 1.1 y 110 veces las del límite superior. 762 //De esta forma el nuevo límite superior es por construcción 100 veces más 763 //probable que el inferior 764 double uppMrg_ = -sqrt(pow(upper,2) + 2.0 * log( 1.1) ); 765 double lowMrg_ = -sqrt(pow(lower,2) + 2.0 * log(110.0) ); 766 //Si los límites tentativos se salen del dominio hay que meterlos dentro 767 if(uppMrg_<=lower) 768 { 769 lowMrg = 0.99*lower+0.01*upper; 770 uppMrg = 0.99*upper+0.01*lower; 771 } 772 else 773 { 774 uppMrg = uppMrg_; 775 if(lowMrg_<=lower) 776 { 777 lowMrg = 0.99*lower+0.01*uppMrg; 778 } 779 else 780 { 781 lowMrg = lowMrg_; 782 } 783 } 784 //Tomamos un r uniforme 785 double r = BUniformDist::Random01().Value(); 786 //y calculamos su raíz cuadrada como valor de ponderación de los límites 787 //para forzar puntos más cercanos al nuevo límite inferior. 788 double u = sqrt(r); 789 zj = u*uppMrg + (1.0-u)*lowMrg; 790 if((zj<=lower) ||(zj>=upper)) 791 { 792 warn_cannot_apply("(I) TruncStdGaussian [Case C.2] ", 793 BText(" j=")<<j<< 794 " domain:["<<lower<<","<<upper<<"] -> "<< 795 " interior domain: ["<<lowMrg<<","<<uppMrg<<"] -> "<<zj,z); 796 return(-1); 797 } 671 798 } 672 799 else 673 800 { 674 warn_cannot_apply("(I) TruncStdGaussian", 801 //Si alguno de los límites cae fuera de [-K,K] hacemos la intersección 802 if(lower<-K) { lowMrg=-K; } 803 if(upper>+K) { uppMrg=+K; } 804 BNormalDist u01(0,1); 805 //Calculamos los cuantiles de la N(0,1) en los extremos 806 double lowF01 = u01.Dist(lowMrg).Value(); 807 double uppF01 = u01.Dist(uppMrg).Value(); 808 //Calculamos el desplazamiento en la métrica probabilística 809 double difF01 = borderDistance*(uppF01-lowF01); 810 //Desplazamos los límites hacia el interior 811 double lowF01_ = lowF01+difF01; 812 double uppF01_ = uppF01-difF01; 813 //Tomamos un r uniforme 814 double r = BUniformDist::Random01().Value(); 815 //Tomamos un u normal truncado en el dominio interior 816 double u = r*uppF01_ + (1.0-r)*lowF01_; 817 //Volvemos a la métrica normalizada 818 zj = u01.Inverse(u).Value(); 819 if((zj<=lower) ||(zj>=upper)) 820 { 821 warn_cannot_apply("(I) TruncStdGaussian [Case C.1] ", 822 BText(" j=")<<j<< 823 " domain:["<<lower<<","<<upper<<"] -> "<< 824 " Prob domain["<<lowF01<<","<<uppF01<<"] -> "<< 825 " Prob interior domain["<<lowF01_<<","<<uppF01_<<"] -> "<<zj,z); 826 return(-1); 827 } 828 } 829 } 830 else 831 { 832 zj = BNormalDist::Random01().Value(); 833 if((zj<=lower) ||(zj>=upper)) 834 { 835 warn_cannot_apply("(I) TruncStdGaussian [Case D] ", 675 836 I2("(empty interval", 676 837 "(intervalo vacio")+" ["+BDat(lower).Format("%.16lg")+","+ 677 838 BDat(upper).Format("%.16lg")+"])",z); 678 return(-1);679 839 } 680 840 } 681 # ifdef USE_BTruncatedNormalDist 682 if(lower==upper) 683 { 684 zj = lower; 685 } 686 else if((lower>negInf)||(upper<posInf)) 687 { 688 if((lower>10) || (upper<-10)) 689 { 690 double r = BUniformDist::Random01().Value(); 691 zj = r*lower+(1-r)*upper; 692 } 693 else 694 { 695 BTruncatedNormalDist tn(lower,upper); 696 zj = tn.Random().Value(); 697 assert((lower<=zj) && (zj<=upper)); 698 //Std(BText("\nBTruncatedNormalDist z[")+j+"]="+zj); 699 } 700 } 701 else 702 { 703 zx[j] = BNormalDist::Random01().Value(); 704 //Std(BText("\nBNormalDist z[")+j+"]="+zj); 705 } 841 842 706 843 # else 707 844 zj = gsl_rtabnorm_combo(getGslRng(), 0.0, 1.0, … … 731 868 //////////////////////////////////////////////////////////////////////////////// 732 869 void BVMat::TruncStdGaussian(const BVMat& D, const BVMat& d_, 733 const BVMat& z0, int ncol, int burnin) 870 const BVMat& z0, int ncol, int burnin, 871 double borderDistance) 734 872 //Matrix instances 735 873 //////////////////////////////////////////////////////////////////////////////// … … 768 906 return; 769 907 } 770 if(burnin< =0 ) { burnin = 1; }908 if(burnin<0 ) { burnin = 0; } 771 909 BVMat burn; 772 910 burn.Zeros(nrow, burnin, ESC_blasRdense); … … 779 917 for(k=0; k<burnin; k++, aux+=nrow) 780 918 { 781 if(trunc_std_gaussian(D, d, b, z )!=0) { return; }919 if(trunc_std_gaussian(D, d, b, z, borderDistance)!=0) { return; } 782 920 memcpy(aux, z.s_.blasRdense_->x, size_row); 783 921 } … … 785 923 for(k=0; k<ncol; k++, aux+=nrow) 786 924 { 787 if(trunc_std_gaussian(D, d, b, z )!=0) { return; }925 if(trunc_std_gaussian(D, d, b, z, borderDistance)!=0) { return; } 788 926 memcpy(aux, z.s_.blasRdense_->x, size_row); 789 927 } -
tol/btol/vmatrix_type/vmatgra.cpp
r9e93790 r9f6ab11 2511 2511 //-------------------------------------------------------------------- 2512 2512 DeclareContensClass(BVMat, BVMatTemporary, BVMatTruncStdGaussian); 2513 DefExtOpr(1, BVMatTruncStdGaussian, "TruncStdGaussian", 3, 5, 2514 "VMatrix VMatrix VMatrix Real Real", 2515 "(VMatrix D, VMatrix d, VMatrix z0 [, Real ncol=1, Real burnin=0])", 2513 DefExtOpr(1, BVMatTruncStdGaussian, "TruncStdGaussian", 3, 6, 2514 "VMatrix VMatrix VMatrix Real Real Real", 2515 "(VMatrix D, VMatrix d, VMatrix z0 " 2516 "[, Real ncol=1, Real burnin=0, Real borderDistance=0.001])", 2516 2517 I2("Creates a random virtual matrix X which ncol columns are distributed as " 2517 2518 "independent standard normal truncated into a polytope", … … 2541 2542 int ncol = 1; 2542 2543 int burn = 0; 2544 double borderDistance = 0.001; 2543 2545 if(Arg(4)) { ncol = (int)Real(Arg(4)); } 2544 2546 if(Arg(5)) { burn = (int)Real(Arg(5)); } 2545 contens_.TruncStdGaussian(D,d,z0,ncol,burn); 2547 if(Arg(6)) { burn = (int)Real(Arg(6)); } 2548 contens_.TruncStdGaussian(D,d,z0,ncol,burn,borderDistance); 2546 2549 assert(contens_.Check()); 2547 2550 }
Note: See TracChangeset
for help on using the changeset viewer.
