def gauss_cdf ( x , mu = 0.0 , sigma = 1.0 ) : """Standard gaussian CDF: >>> x,mu, sigma = .... >>> cdf = gauss_cdf ( x , mu , sigma ) """ y = VE ( x ) return _gauss_cdf_ ( y if 0 < y.cov2() else y.value () , mu , sigma )
def __call__(self, x, y, cxy=0): """Evaluate the function >>> func2 = lambda x,y : x*x + y*y >>> eval2 = Eval2VE ( func2 ) >>> x = VE(1,0.1**2) >>> y = VE(2,0.1**2) >>> print eval2(x,y) ## treat x,y as uncorrelated >>> print eval2(x,y, 0) ## ditto >>> print eval2(x,y,+1) ## treat x,y as 100% correlated >>> print eval2(x,y,-1) ## treat x,y as 100% anti-correlated """ assert isinstance ( cxy , num_types ) and \ ( abs ( cxy ) <= 1 or isequal ( abs ( cxy ) , 1 ) ) , \ 'Invalid correlation coefficient %s' % cxy x = VE(x) y = VE(y) xv = x.value() yv = y.value() val = self.func(xv, yv) xc2 = x.cov2() yc2 = y.cov2() x_plain = xc2 <= 0 or iszero(xc2) y_plain = yc2 <= 0 or iszero(yc2) # if x_plain and y_plain: return VE(val, 0) # ## here we need to calculate the uncertainties # dx = self.partial[0](xv, yv) if not x_plain else 0 dy = self.partial[1](xv, yv) if not y_plain else 0 # cov2 = dx * dx * xc2 + dy * dy * yc2 if cxy and xc2 and yc2: cov2 += 2 * cxy * dx * dy * math.sqrt(xc2 * yc2) return VE(val, cov2)
def __call__ ( self , args , cor = None ) : """Calcualte the value of the scalar function of N arguments with uncertainties and correlations >>> fun2 = lambda x , y : ... >>> fun2e = EvalNVEcor ( fun2 , 2 ) >>> cor = ... # 2x2 symmetric correlation matrix >>> x = ... >>> y = ... >>> result = fun2e ( (x,y) , cor ) ## """ n = self.N assert len ( args ) == n , 'Invalid argument size' ## get value of the function val = self.func ( *args ) c2 = 0 x = n * [ 0 ] ## argument g = n * [ 0 ] ## gradient for i in range ( n ) : xi = VE ( args[i] ) x [i] = x ci = xi.cov2() if ci < 0 or iszero ( ci ) : continue di = self.partial[i] ( *args ) if iszero ( di ) : continue ei = xi.error() g [i] = di e [i] = ei ## diagonal correlation coefficients are assumed to be 1 and ignored! c2 += ci * di * di for j in range ( i ) : xj = x [ j ] cj = xj.cov2 () if cj < 0 or iszero ( cj ) : continue dj = d [ j ] if iszero ( dj ) : continue ej = e [ j ] rij = self.__corr ( cor , i , j ) if cor else 0 assert -1 <= rij <= 1 or isequal ( abs ( rij ) , 1 ) ,\ 'Invalid correlaation coefficient (%d,%d)=%s ' % ( i , j , rij ) c2 += 2.0 * di * dj * rij * ei * ej return VE ( val , c2 )
def __call__(self, x, y, cxy=0): """Evaluate the function >>> func2 = lambda x,y : x*x + y*y >>> eval2 = Eval2VE ( func2 ) >>> x = VE(1,0.1**2) >>> y = VE(2,0.1**2) >>> print eval2(x,y) ## treat x,y as uncorrelated >>> print eval2(x,y, 0) ## ditto >>> print eval2(x,y,+1) ## treat x,y as 100% correlated >>> print eval2(x,y,-1) ## treat x,y as 100% anti-correlated """ ## evaluate the function val = self._value_(x, y) # x = VE(x) y = VE(y) # x_plain = x.cov2() <= 0 or iszero(x.cov2()) y_plain = y.cov2() <= 0 or iszero(y.cov2()) # if x_plain and y_plain: return VE(val, 0) # ## here we need to calculate the uncertainties # cov2 = 0.0 # fx = self.dFdX(x, y.value()) if not x_plain else 0 fy = self.dFdY(x.value(), y) if not y_plain else 0 # if not x_plain: cov2 += fx * fx * x.cov2() if not y_plain: cov2 += fy * fy * y.cov2() # if not x_plain and not y_plain: ## adjust the correlation coefficient: cxy = min(max(-1, cxy), 1) if not iszero(cxy): cov2 += 2 * cxy * fx * fy * x.error() * y.error() return VE(val, cov2)
def dFdY(self, x, y): """Get a partial derivatives d(func)/d(Y)""" y = VE(y) return self._partial_(self._dFdY, x, y.value(), y.cov2())
def dFdX(self, x, y): """Get a partial derivatives d(func)/d(X)""" x = VE(x) return self._partial_(self._dFdX, x.value(), y, x.cov2())