mirror of
https://github.com/SheffieldML/GPy.git
synced 2026-05-21 14:05:14 +02:00
Added missing file.
This commit is contained in:
parent
a6c89b58f0
commit
c800e0687f
1 changed files with 71 additions and 0 deletions
71
GPy/util/ln_diff_erfs.py
Normal file
71
GPy/util/ln_diff_erfs.py
Normal file
|
|
@ -0,0 +1,71 @@
|
||||||
|
# Copyright (c) 2013, GPy authors (see AUTHORS.txt).
|
||||||
|
# Licensed under the BSD 3-clause license (see LICENSE.txt)
|
||||||
|
|
||||||
|
#Only works for scipy 0.12+
|
||||||
|
try:
|
||||||
|
from scipy.special import erfcx, erf
|
||||||
|
except ImportError:
|
||||||
|
from scipy.special import erf
|
||||||
|
from erfcx import erfcx
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
def ln_diff_erfs(x1, x2, return_sign=False):
|
||||||
|
"""Function for stably computing the log of difference of two erfs in a numerically stable manner.
|
||||||
|
:param x1 : argument of the positive erf
|
||||||
|
:type x1: ndarray
|
||||||
|
:param x2 : argument of the negative erf
|
||||||
|
: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.
|
||||||
|
"""
|
||||||
|
x1 = np.require(x1).real
|
||||||
|
x2 = np.require(x2).real
|
||||||
|
|
||||||
|
v = np.zeros(np.max((x1.size, x2.size)))
|
||||||
|
|
||||||
|
# if numel(x1) == 1:
|
||||||
|
# x1 = x1 * ones(size(x2))
|
||||||
|
|
||||||
|
# if numel(x2) == 1:
|
||||||
|
# x2 = x2 * ones(size(x1))
|
||||||
|
|
||||||
|
sign = np.sign(x1 - x2)
|
||||||
|
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]) )
|
||||||
|
|
||||||
|
# Case 2: x1 = x2 so we have log of zero.
|
||||||
|
I2 = (x1 == x2)
|
||||||
|
v[I2] = -np.inf
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue