Changeset abafec5 in tol


Ignore:
Timestamp:
Jan 13, 2011, 6:13:10 PM (16 years ago)
Author:
Víctor de Buen <vdebuen@…>
Branches:
1941-docker-image-to-test, devel, master
Children:
a419435
Parents:
e0b334d
Message:

Refs #975
New implementation of generic BDat BDiscreteDist::Inverse

git-svn-id: ​https://www.tol-project.org/svn/tolp/trunk@3040 be4846ae-f051-483a-831f-b64e7d08527f

File:
1 edited

Legend:

Unmodified
Added
Removed
  • tol/bmath/bprdist/prd.cpp

    re0b334d rabafec5  
    403403}
    404404
     405//--------------------------------------------------------------------
     406  BDat BDiscreteDist::Inverse (BDat prob, BDat tolerance)
     407//--------------------------------------------------------------------
     408{
     409  BText _MID = "BDiscreteDist::Inverse";
     410  if(wrongParameter_|| prob.IsUnknown()) { return(BDat::Unknown());}
     411  if(prob+1.0<1.0) { return(BDat::Unknown()); }
     412  if(prob-1.0>0.0) { return(BDat::Unknown()); }
     413  if(prob+1.0==1.0) { return(min_); }
     414  if(prob-1.0==0.0) { return(max_); }
     415  bool has_lower_bound = !min_.IsNegInf();
     416  bool has_upper_bound = !max_.IsPosInf();
     417  double a = min_.Value();
     418  double b = max_.Value();
     419  double pa = has_lower_bound ? Dist(a).Value() : 0;
     420  if(prob<=pa) { return(a); }
     421  double pb = 1.0;
     422  double h = 1.0;
     423  double h_factor = 10.0;
     424  if(!has_lower_bound || !has_upper_bound)
     425  {
     426    double avr = round(Average().Value());
     427    if(!IS_FINITE(avr))
     428    {
     429      Error(_MID+"Cannot handle with distribution which average is not finite.");
     430      return(BDat::Unknown());
     431    }
     432    double pdf_avr = Dist(avr).Value();
     433    if(prob+1==pdf_avr+1) {  return(avr); }
     434    else if(pdf_avr>prob)
     435    {
     436      b = avr;
     437      pb = pdf_avr;
     438      if(!has_lower_bound)
     439      {
     440        a = b;
     441        pa = pb;
     442      }
     443    }
     444    else // if(pdf_avr<prob)
     445    {
     446      a = avr;
     447      pa = pdf_avr;
     448      if(!has_upper_bound)
     449      {
     450        b = a;
     451        pb = pa;
     452      }
     453    }   
     454  };
     455  has_lower_bound = IS_FINITE(a)!=0;
     456  has_upper_bound = IS_FINITE(b)!=0;
     457  if(!has_lower_bound || !has_upper_bound)
     458  {
     459    Error(_MID+"Sorry, cannot find a finite searching interval for p="+prob);
     460    return(BDat::Unknown());
     461  }
     462  while(pa>prob)
     463  {
     464    a -= h;
     465    pa = Dist(a).Value();
     466    if(prob+1==pa+1) {  return(a); }
     467    h *= h_factor;
     468  }
     469  while(pb<prob)
     470  {
     471    b += h;
     472    pb = Dist(b).Value();
     473    if(prob+1==pb+1) {  return(b); }
     474    h *= h_factor;
     475  }
     476  double pa1 = (min_>=a-1)?0.0:Dist(a-1).Value();
     477  double pb1 =                 Dist(b-1).Value();
     478       if((pa1 < prob) && (prob <=pa)) {  return(a); }
     479  else if((pb1 < prob) && (prob <=pb)) {  return(b); }
     480
     481  if((a>=b)||(pa>=pb)||(pa>prob)||(pb<prob))
     482  {
     483    Error(_MID+"Sorry, cannot find a valid searching interval for p="+prob);
     484    return(BDat::Unknown());
     485  }
     486  double x;
     487  double px;
     488  double px1;
     489  while(a<b-1)
     490  {
     491    x = round((a+b)/2);
     492    px = Dist(x).Value();
     493    px1 = Dist(x-1).Value();
     494         if((px1 < prob) && (prob <=px)) {  return(x); }
     495    else if(prob> px1)                   {  a = x; pa = px; pa1 = px1; }
     496    else                                 {  b = x; pb = px; pb1 = px1; }
     497  }
     498       if((pa1 < prob) && (prob <= pa)) {  return(a); }
     499  else if((pb1 < prob) && (prob <= pb)) {  return(b); }
     500  else
     501  {
     502    Error(_MID+"Sorry, cannot find a valid searching interval for p="+prob);
     503    return(BDat::Unknown());
     504  }
     505
     506}
    405507
    406508//--------------------------------------------------------------------
    … …  
    20552157    return(BDat::Unknown());
    20562158}
     2159
    20572160
    20582161
    … …  
    24282531  double p, q, s, xlam, bound;
    24292532  int which, status;
    2430   s = (double) x.Value();
     2533  s = round((double) x.Value());
    24312534  xlam = (double) fi_.Value();
    24322535  which = 1;
    … …  
    24742577
    24752578//--------------------------------------------------------------------
    2476 BDat BPoissonDist::Inverse(BDat x, BDat tolerance)
    2477 
    2478 /*! Returns Inv(Sum{0..x}.Poisson(i,fi))
    2479  */
    2480 //--------------------------------------------------------------------
    2481 {
    2482 //return(BDiscreteDist::Inverse(x,tolerance));
    2483 
     2579BDat BPoissonDist::Inverse(BDat p, BDat tolerance)
     2580
     2581/*! Returns the maximum x matching Poisson(x,fi) <= p
     2582 */
     2583//--------------------------------------------------------------------
     2584{
     2585  return(BDiscreteDist::Inverse(p,tolerance));
     2586/*
    24842587  if(wrongParameter_|| x.IsUnknown()) { return(BDat::Unknown());}
     2588
     2589
    24852590  double p, q, s, xlam, bound=0.0;
    24862591  int which, status=0;
    … …  
    24932598  if(status==0)
    24942599  {
    2495           return(round(s));
     2600          return(s);
    24962601  }
    24972602  else if(status==1)
    24982603  {
    2499           return(0.0);
     2604    Warning(BText("[BPoissonDist::Dist] the answer of cdfpoi appears to be lower than lowest search bound ")+
     2605    "\n  p="+x.Name()+
     2606    "\n  s="+s+
     2607    "\n  status="+status+
     2608    "\n  bound="+bound);
     2609          return(s);
    25002610  }
    25012611  else if(status==2)
    25022612  {
     2613    Warning(BText("[BPoissonDist::Dist] the answer of cdfpoi appears to be higher than greatest search bound ")+
     2614    "\n  p="+x.Name()+
     2615    "\n  s="+s+
     2616    "\n  status="+status+
     2617    "\n  bound="+bound);
    25032618          return(BDat::PosInf());
    25042619  }
    … …  
    25072622    Error(BText("[BPoissonDist::Dist] cdfpoi fails at ")+
    25082623    "\n  p="+x.Name()+
     2624    "\n  s="+s+
    25092625    "\n  status="+status+
    25102626    "\n  bound="+bound);
Note: See TracChangeset for help on using the changeset viewer.