Esempio n. 1
0
def normal_01_cdf_inverse(p):

    #*****************************************************************************80
    #
    ## NORMAL_01_CDF_INVERSE inverts the standard normal CDF.
    #
    #  Discussion:
    #
    #    The result is accurate to about 1 part in 10^16.
    #
    #  Licensing:
    #
    #    This code is distributed under the GNU LGPL license.
    #
    #  Modified:
    #
    #    15 February 2015
    #
    #  Author:
    #
    #    Original FORTRAN77 version by Michael Wichura.
    #    Python version by John Burkardt.
    #
    #  Reference:
    #
    #    Michael Wichura,
    #    The Percentage Points of the Normal Distribution,
    #    Algorithm AS 241,
    #    Applied Statistics,
    #    Volume 37, Number 3, pages 477-484, 1988.
    #
    #  Parameters:
    #
    #    Input, real P, the value of the cumulative probability
    #    densitity function.  0 < P < 1.  If P is not in this range, an "infinite"
    #    result is returned.
    #
    #    Output, real VALUE, the normal deviate value with the
    #    property that the probability of a standard normal deviate being
    #    less than or equal to the value is P.
    #
    import numpy as np
    from r8_huge import r8_huge
    from r8poly_value_horner import r8poly_value_horner

    a = np.array ( (\
          3.3871328727963666080,      1.3314166789178437745e+2, \
          1.9715909503065514427e+3,   1.3731693765509461125e+4, \
          4.5921953931549871457e+4,   6.7265770927008700853e+4, \
          3.3430575583588128105e+4,   2.5090809287301226727e+3 ))

    b = np.array ( (\
          1.0,                        4.2313330701600911252e+1, \
          6.8718700749205790830e+2,   5.3941960214247511077e+3, \
          2.1213794301586595867e+4,   3.9307895800092710610e+4, \
          2.8729085735721942674e+4,   5.2264952788528545610e+3 ))

    c = np.array ( (\
          1.42343711074968357734,     4.63033784615654529590, \
          5.76949722146069140550,     3.64784832476320460504, \
          1.27045825245236838258,     2.41780725177450611770e-1, \
          2.27238449892691845833e-2,  7.74545014278341407640e-4 ))

    const1 = 0.180625

    const2 = 1.6

    d = np.array ( (\
          1.0,                        2.05319162663775882187,    \
          1.67638483018380384940,     6.89767334985100004550e-1, \
          1.48103976427480074590e-1,  1.51986665636164571966e-2, \
          5.47593808499534494600e-4,  1.05075007164441684324e-9 ))

    e = np.array ( (\
          6.65790464350110377720,     5.46378491116411436990,    \
          1.78482653991729133580,     2.96560571828504891230e-1, \
          2.65321895265761230930e-2,  1.24266094738807843860e-3, \
          2.71155556874348757815e-5,  2.01033439929228813265e-7 ))

    f = np.array ( (\
          1.0,               5.99832206555887937690e-1, \
          1.36929880922735805310e-1,  1.48753612908506148525e-2, \
          7.86869131145613259100e-4,  1.84631831751005468180e-5, \
          1.42151175831644588870e-7,  2.04426310338993978564e-15 ))

    split1 = 0.425
    split2 = 5.0

    if (p <= 0.0):
        value = -r8_huge()
        return value

    if (1.0 <= p):
        value = r8_huge()
        return value

    q = p - 0.5

    if (abs(q) <= split1):

        r = const1 - q * q
        value = q * r8poly_value_horner ( 7, a, r ) \
                  / r8poly_value_horner ( 7, b, r )

    else:

        if (q < 0.0):
            r = p
        else:
            r = 1.0 - p

        if (r <= 0.0):

            value = r8_huge()

        else:

            r = np.sqrt(-np.log(r))

            if (r <= split2):

                r = r - const2
                value = r8poly_value_horner ( 7, c, r ) \
                      / r8poly_value_horner ( 7, d, r )

            else:

                r = r - split2
                value = r8poly_value_horner ( 7, e, r ) \
                      / r8poly_value_horner ( 7, f, r )

        if (q < 0.0):
            value = -value

    return value
def normal_01_cdf_inverse ( p ):

#*****************************************************************************80
#
## NORMAL_01_CDF_INVERSE inverts the standard normal CDF.
#
#  Discussion:
#
#    The result is accurate to about 1 part in 10^16.
#
#  Licensing:
#
#    This code is distributed under the GNU LGPL license.
#
#  Modified:
#
#    15 February 2015
#
#  Author:
#
#    Original FORTRAN77 version by Michael Wichura.
#    Python version by John Burkardt.
#
#  Reference:
#
#    Michael Wichura,
#    The Percentage Points of the Normal Distribution,
#    Algorithm AS 241,
#    Applied Statistics,
#    Volume 37, Number 3, pages 477-484, 1988.
#
#  Parameters:
#
#    Input, real P, the value of the cumulative probability 
#    densitity function.  0 < P < 1.  If P is not in this range, an "infinite"
#    result is returned.
#
#    Output, real VALUE, the normal deviate value with the 
#    property that the probability of a standard normal deviate being 
#    less than or equal to the value is P.
#
  import numpy as np
  from r8_huge import r8_huge
  from r8poly_value_horner import r8poly_value_horner

  a = np.array ( (\
        3.3871328727963666080,      1.3314166789178437745e+2, \
        1.9715909503065514427e+3,   1.3731693765509461125e+4, \
        4.5921953931549871457e+4,   6.7265770927008700853e+4, \
        3.3430575583588128105e+4,   2.5090809287301226727e+3 ))

  b = np.array ( (\
        1.0,                        4.2313330701600911252e+1, \
        6.8718700749205790830e+2,   5.3941960214247511077e+3, \
        2.1213794301586595867e+4,   3.9307895800092710610e+4, \
        2.8729085735721942674e+4,   5.2264952788528545610e+3 ))

  c = np.array ( (\
        1.42343711074968357734,     4.63033784615654529590, \
        5.76949722146069140550,     3.64784832476320460504, \
        1.27045825245236838258,     2.41780725177450611770e-1, \
        2.27238449892691845833e-2,  7.74545014278341407640e-4 ))

  const1 = 0.180625

  const2 = 1.6

  d = np.array ( (\
        1.0,                        2.05319162663775882187,    \
        1.67638483018380384940,     6.89767334985100004550e-1, \
        1.48103976427480074590e-1,  1.51986665636164571966e-2, \
        5.47593808499534494600e-4,  1.05075007164441684324e-9 ))

  e = np.array ( (\
        6.65790464350110377720,     5.46378491116411436990,    \
        1.78482653991729133580,     2.96560571828504891230e-1, \
        2.65321895265761230930e-2,  1.24266094738807843860e-3, \
        2.71155556874348757815e-5,  2.01033439929228813265e-7 ))

  f = np.array ( (\
        1.0,               5.99832206555887937690e-1, \
        1.36929880922735805310e-1,  1.48753612908506148525e-2, \
        7.86869131145613259100e-4,  1.84631831751005468180e-5, \
        1.42151175831644588870e-7,  2.04426310338993978564e-15 ))

  split1 = 0.425
  split2 = 5.0

  if ( p <= 0.0 ):
    value = - r8_huge ( )
    return value
 
  if ( 1.0 <= p ):
    value = r8_huge ( )
    return value

  q = p - 0.5

  if ( abs ( q ) <= split1 ):

    r = const1 - q * q
    value = q * r8poly_value_horner ( 7, a, r ) \
              / r8poly_value_horner ( 7, b, r )

  else:

    if ( q < 0.0 ):
      r = p
    else:
      r = 1.0 - p

    if ( r <= 0.0 ):

      value = r8_huge ( )

    else:

      r = np.sqrt ( - np.log ( r ) )

      if ( r <= split2 ):

        r = r - const2
        value = r8poly_value_horner ( 7, c, r ) \
              / r8poly_value_horner ( 7, d, r )

      else:

        r = r - split2
        value = r8poly_value_horner ( 7, e, r ) \
              / r8poly_value_horner ( 7, f, r )

    if ( q < 0.0 ):
      value = - value

  return value
def truncated_normal_rule ( *args ):

#*****************************************************************************80
#
## MAIN is the main program for TRUNCATED_NORMAL_RULE.
#
#  Discussion:
#
#    This program computes a truncated normal quadrature rule
#    and writes it to a file.
#
#    The user specifies:
#    * option: 0/1/2/3 for none, lower, upper, double truncation.
#    * N, the number of points in the rule
#    * MU, the mean of the original normal distribution
#    * SIGMA, the standard deviation of the original normal distribution,
#    * A, the left endpoint (for options 1 or 3)
#    * B, the right endpoint (for options 2 or 3)
#    * HEADER, the root name of the output files.
#
#  Licensing:
#
#    This code is distributed under the GNU LGPL license.
#
#  Modified:
#
#    23 March 2015
#
#  Author:
#
#    John Burkardt
#
  import numpy as np
  from moment_method              import moment_method
  from normal_ms_moment           import normal_ms_moments
  from r8_huge                    import r8_huge
  from rule_write                 import rule_write
  from sys                        import exit
  from truncated_normal_a_moment  import truncated_normal_a_moments
  from truncated_normal_ab_moment import truncated_normal_ab_moments
  from truncated_normal_b_moment  import truncated_normal_b_moments

  print ''
  print 'TRUNCATED_NORMAL_RULE'
  print '  Python version'
  print ''
  print '  For the (truncated) Gaussian probability density function'
  print '    pdf(x) = exp(-0.5*((x-MU)/SIGMA)^2) / SIGMA / sqrt ( 2 * pi )'
  print '  compute an N-point quadrature rule for approximating'
  print '    Integral ( A <= x <= B ) f(x) pdf(x) dx'
  print ''
  print '  The value of OPTION determines the truncation interval [A,B]:'
  print '  0: (-oo,+oo)'
  print '  1: [A,+oo)'
  print '  2: (-oo,B]'
  print '  3: [A,B]'
  print ''
  print '  The user specifies OPTION, N, MU, SIGMA, A, B and FILENAME.'
  print ''
  print '  HEADER is used to generate 3 files:'
  print ''
  print '    header_w.txt - the weight file'
  print '    header_x.txt - the abscissa file.'
  print '    header_r.txt - the region file, listing A and B.'

  argument_count = ( len ( args ) )

  iarg = 0
#
#  Get OPTION.
#
  if ( argument_count < iarg + 1 ):
    option = eval ( input ( '  Enter OPTION, 0/1/2/3:  ' ) )
  else:
    option = args[iarg]
    iarg = iarg + 1

  if ( option < 0 or 3 < option ):
    print ''
    print 'TRUNCATED_NORMAL_RULE - Fatal error!'
    print '  0 <= OPTION <= 3 was required.'
    exit ( 'TRUNCATED_NORMAL_RULE - Fatal error!' )
#
#  Get N.
#
  if ( argument_count < iarg + 1 ):
    n = eval ( input ( '  Enter the rule order N:  ' ) )
  else:
    n = args[iarg]
    iarg = iarg + 1
#
#  Get MU.
#
  if ( argument_count < iarg + 1 ):
    mu = eval ( input ( '  Enter MU, the mean value of the normal distribution:  ' ) )
  else:
    mu = args[iarg]
    iarg = iarg + 1
#
#  Get SIGMA.
#
  if ( argument_count < iarg + 1 ):
    sigma = eval ( input ( '  Enter SIGMA, the standard deviation:  ' ) )
  else:
    sigma = args[iarg]
    iarg = iarg + 1
#
#  Get A.
#
  if ( option == 1 or option == 3 ):
    if ( argument_count < iarg + 1 ):
      a = eval ( input ( '  Enter the left endpoint A:  ' ) )
    else:
      a = args[iarg]
      iarg = iarg + 1
  else:
    a = - r8_huge ( )
#
#  Get B.
#
  if ( option == 2 or option == 3 ):
    if ( argument_count < iarg + 1 ):
      b = eval ( input ( '  Enter the right endpoint B:  ' ) )
    else:
      b = args[iarg]
      iarg = iarg + 1
  else:
    b = r8_huge ( )
#
#  Get HEADER.
#
  if ( argument_count < iarg + 1 ):
    print ''
    print '  HEADER is the "root name" of the quadrature files.'
    header = input ( '  Enter HEADER as a quoted string:  ' )
  else:
    header = args[iarg]
    iarg = iarg + 1
#
#  Input summary.
#
  print ''
  print '  OPTION = %d' % ( option )
  print '  N = %d' % ( n )
  print '  MU = %g' % ( mu )
  print '  SIGMA = %g' % ( sigma )
  if ( option == 1 or option == 3 ):
    print '  A = %g' % ( a )
  else:
    print '  A = -oo'

  if ( option == 2 or option == 3 ):
    print '  B = %g' % ( b )
  else:
    print '  B = +oo'

  print '  HEADER = "%s"' % ( header )
#
#  Compute the moments.
#
  if ( option == 0 ):
    moment = normal_ms_moments ( 2 * n + 1, mu, sigma )
  elif ( option == 1 ):
    moment = truncated_normal_a_moments ( 2 * n + 1, mu, sigma, a )
  elif ( option == 2 ):
    moment = truncated_normal_b_moments ( 2 * n + 1, mu, sigma, b )
  elif ( option == 3 ):
    moment = truncated_normal_ab_moments ( 2 * n + 1, mu, sigma, a, b )
#
#  Compute the rule.
#
  x, w = moment_method ( n, moment )

  r = np.array ( [ [ a ], [ b ] ] )
#
#  Write the rule.
#
  rule_write ( n, header, x, w, r )
#
#  Terminate.
#
  print ''
  print 'TRUNCATED_NORMAL_RULE:'
  print '  Normal end of execution.'

  return