Changeset 8879ea8 in tol


Ignore:
Timestamp:
Mar 31, 2010, 4:02:06 PM (17 years ago)
Author:
Víctor de Buen <vdebuen@…>
Branches:
1941-docker-image-to-test, devel, master
Children:
acdac1ce
Parents:
69ee043
Message:

New built-in AsymptoticSampler1D to sample arbitrary scalar continuous distributions

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

File:
1 edited

Legend:

Unmodified
Added
Removed
  • tol/btol/real_type/datgrav.cpp

    r69ee043 r8879ea8  
    12871287//--------------------------------------------------------------------
    12881288{
    1289   contens_ = Pol(Arg(1)).StationaryValue();
     1289  contens_ = Pol(Arg(1)).StationaryValue(BFALSE);
    12901290}
    12911291
    … …  
    16951695}
    16961696
     1697struct AsymptoticSampler1D_SampleInfo
     1698{
     1699  double x;
     1700  double f;
     1701  double g;
     1702};
     1703
     1704//--------------------------------------------------------------------
     1705BInt AsymptoticSampler1D_cmp(const void* v1, const void* v2)
     1706//--------------------------------------------------------------------
     1707{
     1708  AsymptoticSampler1D_SampleInfo* u1 = (AsymptoticSampler1D_SampleInfo*)v1;
     1709  AsymptoticSampler1D_SampleInfo* u2 = (AsymptoticSampler1D_SampleInfo*)v2;
     1710  double dif = u1->f-u2->f;
     1711  return((dif<0)?-1:((dif>0)?+1:0));
     1712}
     1713
     1714//--------------------------------------------------------------------
     1715DeclareContensClass(BDat, BDatTemporary, BDatAsymptoticSampler1D);
     1716DefExtOpr(1, BDatAsymptoticSampler1D, "AsymptoticSampler1D", 3, 5,
     1717"Code Real Real Real Real",
     1718"(Code logDens, Real L, Real R [, Real numOfCandidates = 10, Real maxIter = 100])",
     1719"Este método consiste en una aproximación asintótica muy sencilla "
     1720"para simular realizaciones de una distribución de probabilidad con "
     1721"densidad arbitraria con dominio no necesariamente conexo dentro de un "
     1722"intervalo [L,R] orientativo:\n"
     1723" 1. Se toman secuencialmente valores x[k] uniformemente distribuidos en [L,R] \n"
     1724" 2. Se calcula el logaritmo de su densidad salvo una constante \n"
     1725"      f[k] = log(d(x[k]))+c \n"
     1726" 3. Se descartan los que den logaritmo de densidad -Inf, para forzar, densidad no nula, o sea, \n"
     1727"      d(x[k])>0 \n"
     1728" 4. Se para cuando se obtiene el número deseado de candidatos con densidad no nula o se supera el máximo de iteraciones\n"
     1729" 5. Se resta a cada uno el máximo de las f y se toma su exponencial \n"
     1730"      g[k] = Exp( f[k] - max{f[i]} ) \n"
     1731" 6. Se calcula el peso relativo w[k] de cada valor de forma proporcional a su densidad \n"
     1732"      w[k] = g[k] / Sum( g[i] ) \n"
     1733" 7. Se ordenan por densidad creciente \n"
     1734"      w(x[k])<=w(x[k+1]) \n"
     1735" 8. Se calculan los pesos acumulados \n"
     1736"      W(x[1]) = w(x[1]) \n"
     1737"      W(x[k+1])=W(x[k])+w(x[k+1]) \n"
     1738" 9. Se toma un valor p uniformemente distribuido en [0,1] \n"
     1739"10. Se elige el primer valor que supera o iguala a p en peso acumulado \n"
     1740"      W(x[k-1]) < p <= W(x[k]) \n"
     1741"\n"
     1742"Cuando n->Inf esto da simulación exacta, pero con valores de apenas n=10 nos "
     1743"da puede dar una buena aproximación si el intervalo es lo bastante denso como "
     1744"para que no se descarte la totalidad de los candidatos.",
     1745BOperClassify::Statistic_);
     1746void BDatAsymptoticSampler1D::CalcContens()
     1747//--------------------------------------------------------------------
     1748{
     1749  BCode& cod = Code(Arg(1));
     1750  double L = Real(Arg(2));
     1751  double R = Real(Arg(3));
     1752  int numOfCandidates = 10;
     1753  int maxIter = 100;
     1754  if(Arg(4)) { numOfCandidates = int(Real(Arg(4))); }
     1755  if(Arg(5)) { maxIter = int(Real(Arg(5))); }
     1756
     1757  BText english("In AsymptoticSampler1D, ");
     1758  BText spanish("En AsymptoticSampler1D, ");
     1759
     1760  if (!cod.Operator()) {
     1761    english += "invalid code argument";
     1762    spanish += "argumento código inválido";
     1763    Error(I2(english,spanish));
     1764    return;
     1765  }
     1766 
     1767  if (cod.Operator()->MinArg()!=1 &&
     1768      cod.Operator()->MaxArg()!=1) {
     1769    english += "invalid argument number for logf argument: should be 1";
     1770    spanish += "número de argumentos inválidos para argumento logf: debe ser 1";
     1771    Error(I2(english,spanish)); 
     1772    return;
     1773  }
     1774
     1775  /* check user function's grammar */
     1776  if (cod.Grammar() != GraReal()) {
     1777    english += "invalid type ";
     1778    english += cod.Grammar()->Name();
     1779    english += " for logf argument: should be Real";
     1780    spanish += " tipo inválido ";
     1781    spanish += cod.Grammar()->Name();
     1782    spanish += " para argumento logf: debe ser Real";
     1783    Error(I2(english,spanish));
     1784    return;
     1785  }
     1786
     1787  /* check grammar of user function's first argument */
     1788  if (cod.Operator()->GrammarForArg(1) != GraReal()) {
     1789    english += "invalid type ";
     1790    english += cod.Operator()->GrammarForArg(1)->Name();
     1791    english += " for first argument of logf argument: should be Real";
     1792    spanish += "tipo inválido ";
     1793    spanish += cod.Operator()->GrammarForArg(1)->Name();
     1794    spanish += " en el primer argumento del argumento logf: debe ser Real";
     1795    Error(I2(english,spanish));
     1796    return;
     1797  }
     1798  BUniformDist U(L,R);
     1799  BUniformDist U01(0,1);
     1800  BRRCode fun(cod);
     1801  BArray< AsymptoticSampler1D_SampleInfo > sample;
     1802  sample.AllocBuffer(numOfCandidates);
     1803  int i, k;
     1804  double x, f, g, w, f_max = BDat::NegInf(), g_sum = 0, W=0, p;
     1805  for(i=k=0; (i<maxIter)&&(k<numOfCandidates); i++)
     1806  {
     1807    x = U.Random().Value();
     1808    f = (fun[x]).Value();
     1809    if(f>BDat::NegInf())
     1810    {
     1811      if(f_max<f) { f_max = f; }
     1812      sample[k].x = x;
     1813      sample[k].f = f;
     1814      k++;
     1815    }
     1816  }
     1817  int n = k;
     1818  sample.ReallocBuffer(n);
     1819  sample.Sort(AsymptoticSampler1D_cmp);
     1820  for(k=0; k<n; k++)
     1821  {
     1822    g = exp(sample[k].f-f_max);
     1823    g_sum += g;
     1824    sample[k].g = g;
     1825  }
     1826  p = U01.Random().Value();
     1827  for(k=0; k<n; k++)
     1828  {
     1829    w = sample[k].g / g_sum;
     1830    W += w;
     1831    if(W>=p)
     1832    {
     1833      contens_ = sample[k].x;
     1834      return;
     1835    }
     1836  }
     1837  contens_ = BDat::Unknown();
     1838};
    16971839
    16981840//--------------------------------------------------------------------
Note: See TracChangeset for help on using the changeset viewer.