mirror of
https://github.com/SheffieldML/GPy.git
synced 2026-06-05 14:55:15 +02:00
Added missing files.
This commit is contained in:
parent
c800e0687f
commit
0509b6f9d0
6 changed files with 297 additions and 160 deletions
63
GPy/util/erfcx.py
Normal file
63
GPy/util/erfcx.py
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
## Copyright (C) 2010 Soren Hauberg
|
||||
##
|
||||
## Copyright James Hensman 2011
|
||||
##
|
||||
## This program is free software; you can redistribute it and/or modify it
|
||||
## under the terms of the GNU General Public License as published by
|
||||
## the Free Software Foundation; either version 3 of the License, or (at
|
||||
## your option) any later version.
|
||||
##
|
||||
## This program is distributed in the hope that it will be useful, but
|
||||
## WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
## General Public License for more details.
|
||||
##
|
||||
## You should have received a copy of the GNU General Public License
|
||||
## along with this program; see the file COPYING. If not, see
|
||||
## <http://www.gnu.org/licenses/>.
|
||||
|
||||
import numpy as np
|
||||
|
||||
def erfcx (arg):
|
||||
arg = np.atleast_1d(arg)
|
||||
assert(np.all(np.isreal(arg)),"erfcx: input must be real")
|
||||
|
||||
## Get precision dependent thresholds -- or not :p
|
||||
xneg = -26.628;
|
||||
xmax = 2.53e+307;
|
||||
|
||||
## Allocate output
|
||||
result = np.zeros (arg.shape)
|
||||
|
||||
## Find values where erfcx can be evaluated
|
||||
idx_neg = (arg < xneg);
|
||||
idx_max = (arg > xmax);
|
||||
idx = ~(idx_neg | idx_max);
|
||||
|
||||
arg = arg [idx];
|
||||
|
||||
## Perform the actual computation
|
||||
t = 3.97886080735226 / (np.abs (arg) + 3.97886080735226);
|
||||
u = t - 0.5;
|
||||
y = (((((((((u * 0.00127109764952614092 + 1.19314022838340944e-4) * u \
|
||||
- 0.003963850973605135) * u - 8.70779635317295828e-4) * u + \
|
||||
0.00773672528313526668) * u + 0.00383335126264887303) * u - \
|
||||
0.0127223813782122755) * u - 0.0133823644533460069) * u + \
|
||||
0.0161315329733252248) * u + 0.0390976845588484035) * u + \
|
||||
0.00249367200053503304;
|
||||
y = ((((((((((((y * u - 0.0838864557023001992) * u - \
|
||||
0.119463959964325415) * u + 0.0166207924969367356) * u + \
|
||||
0.357524274449531043) * u + 0.805276408752910567) * u + \
|
||||
1.18902982909273333) * u + 1.37040217682338167) * u + \
|
||||
1.31314653831023098) * u + 1.07925515155856677) * u + \
|
||||
0.774368199119538609) * u + 0.490165080585318424) * u + \
|
||||
0.275374741597376782) * t;
|
||||
|
||||
y [arg < 0] = 2 * np.exp (arg [arg < 0]**2) - y [arg < 0];
|
||||
|
||||
## Put the results back into something with the same size is the original input
|
||||
result [idx] = y;
|
||||
result [idx_neg] = np.inf;
|
||||
## result (idx_max) = 0; # not needed as we initialise with zeros
|
||||
return(result)
|
||||
|
||||
|
|
@ -18,54 +18,93 @@ def ln_diff_erfs(x1, x2, return_sign=False):
|
|||
:type x2: ndarray
|
||||
:return: tuple containing (log(abs(erf(x1) - erf(x2))), sign(erf(x1) - erf(x2)))
|
||||
|
||||
Based on MATLAB code that was written by Antti Honkela and modified by David Luengo, originally derived from code by Neil Lawrence.
|
||||
Based on MATLAB code that was written by Antti Honkela and modified by David Luengo and originally derived from code by Neil Lawrence.
|
||||
"""
|
||||
x1 = np.require(x1).real
|
||||
x2 = np.require(x2).real
|
||||
|
||||
v = np.zeros(np.max((x1.size, x2.size)))
|
||||
if x1.size==1:
|
||||
x1 = np.reshape(x1, (1, 1))
|
||||
if x2.size==1:
|
||||
x2 = np.reshape(x2, (1, 1))
|
||||
|
||||
if x1.shape==x2.shape:
|
||||
v = np.zeros_like(x1)
|
||||
else:
|
||||
if x1.size==1:
|
||||
v = np.zeros(x2.shape)
|
||||
elif x2.size==1:
|
||||
v = np.zeros(x1.shape)
|
||||
else:
|
||||
raise ValueError, "This function does not broadcast unless provided with a scalar."
|
||||
|
||||
# if numel(x1) == 1:
|
||||
# x1 = x1 * ones(size(x2))
|
||||
if x1.size == 1:
|
||||
x1 = np.tile(x1, x2.shape)
|
||||
|
||||
# if numel(x2) == 1:
|
||||
# x2 = x2 * ones(size(x1))
|
||||
if x2.size == 1:
|
||||
x2 = np.tile(x2, x1.shape)
|
||||
|
||||
sign = np.sign(x1 - x2)
|
||||
I = sign == -1
|
||||
swap = x1[I]
|
||||
x1[I] = x2[I]
|
||||
x2[I] = swap
|
||||
if x1.size == 1:
|
||||
if sign== -1:
|
||||
swap = x1
|
||||
x1 = x2
|
||||
x2 = swap
|
||||
else:
|
||||
I = sign == -1
|
||||
swap = x1[I]
|
||||
x1[I] = x2[I]
|
||||
x2[I] = swap
|
||||
|
||||
# TODO: switch off log of zero warnings.
|
||||
# Case 1: arguments of different sign, no problems with loss of accuracy
|
||||
I1 = np.logical_or(np.logical_and(x1>0, x2<0), np.logical_and(x2>0, x1<0)) # I1=(x1*x2)<0
|
||||
v[I1] = np.log( erf(x1[I1]) - erf(x2[I1]) )
|
||||
with np.errstate(divide='ignore'):
|
||||
# switch off log of zero warnings.
|
||||
|
||||
# Case 2: x1 = x2 so we have log of zero.
|
||||
I2 = (x1 == x2)
|
||||
v[I2] = -np.inf
|
||||
# Case 0: arguments of different sign, no problems with loss of accuracy
|
||||
I0 = np.logical_or(np.logical_and(x1>0, x2<0), np.logical_and(x2>0, x1<0)) # I1=(x1*x2)<0
|
||||
|
||||
# Case 3: Both arguments are non-negative
|
||||
I3 = np.logical_and(x1 > 0, np.logical_and(np.logical_not(I1),
|
||||
np.logical_not(I2)))
|
||||
v[I3] = np.log(erfcx(x2[I3])
|
||||
-erfcx(x1[I3])*np.exp(x2[I3]**2
|
||||
-x1[I3]**2)) - x2[I3]**2
|
||||
|
||||
# Case 4: Both arguments are non-positive
|
||||
I4 = np.logical_and(np.logical_and(np.logical_not(I1),
|
||||
np.logical_not(I2)),
|
||||
np.logical_not(I3))
|
||||
v[I4] = np.log(erfcx(-x1[I4])
|
||||
-erfcx(-x2[I4])*np.exp(x1[I4]**2
|
||||
-x2[I4]**2))-x1[I4]**2
|
||||
|
||||
# Case 1: x1 = x2 so we have log of zero.
|
||||
I1 = (x1 == x2)
|
||||
|
||||
# Case 2: Both arguments are non-negative
|
||||
I2 = np.logical_and(x1 > 0, np.logical_and(np.logical_not(I0),
|
||||
np.logical_not(I1)))
|
||||
# Case 3: Both arguments are non-positive
|
||||
I3 = np.logical_and(np.logical_and(np.logical_not(I0),
|
||||
np.logical_not(I1)),
|
||||
np.logical_not(I2))
|
||||
_x2 = x2.flatten()
|
||||
_x1 = x1.flatten()
|
||||
for group, flags in zip((0, 1, 2, 3), (I0, I1, I2, I3)):
|
||||
|
||||
if np.any(flags):
|
||||
if not x1.size==1:
|
||||
_x1 = x1[flags]
|
||||
if not x2.size==1:
|
||||
_x2 = x2[flags]
|
||||
if group==0:
|
||||
v[flags] = np.log( erf(_x1) - erf(_x2) )
|
||||
elif group==1:
|
||||
v[flags] = -np.inf
|
||||
elif group==2:
|
||||
v[flags] = np.log(erfcx(_x2)
|
||||
-erfcx(_x1)*np.exp(_x2**2
|
||||
-_x1**2)) - _x2**2
|
||||
elif group==3:
|
||||
v[flags] = np.log(erfcx(-_x1)
|
||||
-erfcx(-_x2)*np.exp(_x1**2
|
||||
-_x2**2))-_x1**2
|
||||
|
||||
# TODO: switch back on log of zero warnings.
|
||||
|
||||
if return_sign:
|
||||
return v, sign
|
||||
else:
|
||||
# Need to add in a complex part because argument is negative.
|
||||
v[I] += np.pi*1j
|
||||
if v.size==1:
|
||||
if sign==-1:
|
||||
v = v.view('complex64')
|
||||
v += np.pi*1j
|
||||
else:
|
||||
# Need to add in a complex part because argument is negative.
|
||||
v = v.view('complex64')
|
||||
v[I] += np.pi*1j
|
||||
|
||||
return v
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue