Пример #1
0
    def _median_(self, func, xmin, xmax, *args):

        ## need to know the integral
        from ostap.math.integral import Integral

        iint = Integral(func, xmin, err=False, args=args)
        half = 2.0 / iint(xmax)

        ifun = lambda x: iint(x) * half - 1.0

        from ostap.math.rootfinder import findroot

        ## @see https://en.wikipedia.org/wiki/Median#Inequality_relating_means_and_medians
        try:
            meanv = Mean.__call__(self, func, *args)
            sigma = RMS.__call__(self, func, *args)
            import math
            xmn = meanv - 2 * sigma  ## use 2 instead of 1
            xmx = meanv + 2 * sigma  ## use 2 instead of 1
            #
            if isinstance(xmin, float): xmn = max(xmn, xmin)
            if isinstance(xmax, float): xmx = min(xmx, xmax)
            #
            result = findroot(ifun, xmn, xmx)
        except:
            result = findroot(ifun, xmin, xmax)

        return result
Пример #2
0
    def __call__(self, func, mode=None, *args):
        ##

        ## mode is specified
        if isinstance ( mode , float )        and \
           self.xmin < mode < self.xmax       and \
           func ( self.xmin ) < func ( mode ) and \
           func ( self.xmax ) < func ( mode ) :
            m0 = mode
        else:
            ## mode needs to be calculated
            m0 = Mode.__call__(self, func, *args)

        ## function  value at the maximum
        v0 = float(func(m0, *args))

        ## half height
        vheight = 1.0 * v0 * self._hfactor

        ifun = lambda x, *a: float(func(x, *a)) - vheight

        from ostap.math.rootfinder import findroot
        x1 = findroot(ifun, self.xmin, m0, args=args)
        x2 = findroot(ifun, m0, self.xmax, args=args)

        return x1, x2
Пример #3
0
    def __call__(self, func, *args):

        ## additional arguments
        args = args if args else self.args

        #
        ## define integration rules
        #
        if hasattr(func, 'integral'):
            _integral_ = lambda f, low, high: f.integral(low, high, *args)
        else:
            from ostap.math.integral import integral
            _integral_ = lambda f, low, high: integral(f, low, high, *args)

        #
        ## xmin/max
        #
        xmin, xmax = self.xmin, self.xmax

        #
        ## calculate x0 as "mean"-value
        #
        x0 = self.x0
        if x0 is None:
            if hasattr(func, 'mean'): x0 = func.mean()
            else:
                m = Mean(xmin, xmax, False)
                x0 = m(func, *args)

        #
        ## check validity of x0
        #
        if not xmin <= x0 <= xmax:
            raise AttributeError("Invalid x0 value %s<=%s<=%s" %
                                 (xmin, x0, xmax))

        #
        ## get the normalization
        #
        norm = _integral_(func, xmin, xmax)
        if 0 >= norm:
            raise AttributeError("Normalization integral is not positive %s" %
                                 norm)

        #
        ## Equation:  ifun(x) \equiv \int_{x0-x}^{x0+x}f(t)dt - N*prob = 0
        #
        yval = self.prob * norm

        def ifun(x):
            if 0 >= x: return -yval
            return _integral_(func, max(xmin, x0 - x), min(xmax,
                                                           x0 + x)) - yval

        from ostap.math.rootfinder import findroot
        s = findroot(ifun, 0, max(xmax - x0, x0 - xmin))

        from ostap.math.ve import VE
        return VE(x0, s * s)
Пример #4
0
    def __call__(self, func, *args):
        ##

        ## get the position of the mode
        m0 = Mode.__call__(self, func, *args)

        ## function  value at the maximum
        v0 = func(m0, *args)

        ## half height
        vheight = 1.0 * v0 * self._hfactor

        ifun = lambda x, *a: float(func(x, *a)) - vheight

        from ostap.math.rootfinder import findroot
        x1 = findroot(ifun, self.xmin, m0, args=args)
        x2 = findroot(ifun, m0, self.xmax, args=args)

        return x1, x2
Пример #5
0
def test_root_sin():

    fun = lambda x: -1.00 * math.sin(0.5 * (x - 1.0))
    der1 = lambda x: -0.50 * math.cos(0.5 * (x - 1.0))
    der2 = lambda x: +0.25 * math.sin(0.5 * (x - 1.0))

    logger.info(
        'sin/Halley:  %.15g\n%s' %
        find_root(fun, -0.5, 2.5, deriv1=der1, deriv2=der2, full_output=True))
    logger.info('sin/Newton:  %.15g\n%s' %
                find_root(fun, -0.5, 2.5, deriv2=der1, full_output=True))
    logger.info('sin/Plain :  %.15g\n%s' %
                find_root(fun, -0.5, 2.5, full_output=True))
    logger.info('sin/Brent :  %.15g\n%s' %
                findroot(fun, -0.5, 2.5, full_output=True))
Пример #6
0
 def _solve_(func, fval, xmn, xmx, *args):
     ##
     if isequal(xmn, xmx): return xmn
     ##
     ifun = lambda x, *a: func(x, *a) - fval
     ##
     fmn = ifun(xmn)
     if iszero(ifun(xmn)): return xmn
     fmx = ifun(xmx)
     if iszero(ifun(xmx)): return xmx
     ##
     if 0 < fmx * fmn:  ## more or less arbitrary choice
         return xmx if abs(fmx) <= abs(fmn) else xmn
     #
     from ostap.math.rootfinder import findroot
     return findroot(ifun, xmn, xmx, args=args)
Пример #7
0
def test_root_mult():

    K = 1
    N = 2 * K + 1

    fun = lambda x: 1.0 * (x - 1.0)**N
    der1 = lambda x: 1.0 * N * (x - 1.0)**(N - 1)
    der2 = lambda x: 1.0 * N * (N - 1) * (x - 1.0)**(N - 2)

    logger.info('mult/Halley:  %.15g\n%s' % find_root(
        fun, -1, 10, deriv1=der1, deriv2=der2, full_output=True, disp=False))
    logger.info(
        'mult/Newton:  %.15g\n%s' %
        find_root(fun, -1, 10, deriv1=der1, full_output=True, disp=False))
    logger.info('mult/Plain :  %.15g\n%s' %
                find_root(fun, -1, 10, full_output=True, disp=False))
    logger.info('mult/Brent :  %.15g\n%s' %
                findroot(fun, -1, 10, full_output=True, disp=False))
Пример #8
0
    def __call__(self, func, *args):
        ##

        if 0.5 == self.Q: return Median.__call__(self, func, *args)
        elif 0.0 == self.Q: return self.xmin
        elif 1.0 == self.Q: return self.xmax

        ## need to know the integral
        from ostap.math.integral import IntegralCache
        iint = IntegralCache(func, self.xmin, err=False, args=args)
        quan = 1.0 / iint(self.xmax) / self.Q

        ifun = lambda x: iint(x) * quan - 1.0

        xmn = self.xmin
        xmx = self.xmax

        p = 0.5
        l = 0.5

        ## make some bracketing before next step
        while (not isinstance(xmn, float)) or (not isinstance(
                xmx, float)) or l > 0.1:

            l /= 2
            m = self._median_(func, xmn, xmx, *args)

            if self.Q < p:
                xmn = xmn
                xmx = float(m)
                p -= l
            elif self.Q > p:
                xmn = float(m)
                xmx = xmx
                p += l
            else:
                return m  ## RETURN

        ## finally, calculate quantile
        from ostap.math.rootfinder import findroot
        result = findroot(ifun, xmn, xmx)

        return result
Пример #9
0
    def __call__(self, func, *args):

        ## additional arguments
        args = args if args else self.args

        #
        ## define integration rules
        #
        if hasattr(func, 'integral'):
            _integral_ = lambda f, low, high: f.integral(low, high, *args)
        else:
            from ostap.math.integral import integral
            _integral_ = lambda f, low, high: integral(f, low, high, *args)

        #
        ## xmin/max
        #
        xmin, xmax = self.xmin, self.xmax

        #
        # calculate mode
        if hasattr(func, 'mode'): xmode = func.mode()
        else:
            md = Mode(xmin, xmax)
            xmode = md(func, *args)

        if not xmin <= xmode <= xmax:
            raise AttributeError("Invalid mode value %s<=%s<=%s" %
                                 (xmin, xmode, xmax))

        #
        ## get the normalization
        #
        norm = _integral_(func, xmin, xmax)
        if 0 >= norm:
            raise AttributeError("Normalization integral is not positive %s" %
                                 norm)

        normL = _integral_(func, xmin, xmode)
        normR = _integral_(func, xmode, xmax)

        from ostap.math.base import isequal, iszero

        ## solve equation f(x)=a
        def _solve_(func, fval, xmn, xmx, *args):
            ##
            if isequal(xmn, xmx): return xmn
            ##
            ifun = lambda x, *a: func(x, *a) - fval
            ##
            fmn = ifun(xmn)
            if iszero(ifun(xmn)): return xmn
            fmx = ifun(xmx)
            if iszero(ifun(xmx)): return xmx
            ##
            if 0 < fmx * fmn:  ## more or less arbitrary choice
                return xmx if abs(fmx) <= abs(fmn) else xmn
            #
            from ostap.math.rootfinder import findroot
            return findroot(ifun, xmn, xmx, args=args)

        yval = self.prob * norm
        fm = func(xmode)

        def iifun(f):

            if iszero(f): x1, x2 = xmin, xmax
            elif isequal(f, fm): return -yval
            else:
                x1 = _solve_(func, f, xmin, xmode)
                x2 = _solve_(func, f, xmode, xmax)

            return _integral_(func, x1, x2) - yval

        from ostap.math.rootfinder import findroot
        l = findroot(iifun, 0, func(xmode))
        x1 = _solve_(func, l, xmin, xmode)
        x2 = _solve_(func, l, xmode, xmax)

        return x1, x2
Пример #10
0
    def _solve_(self, func, fval, xmn, xmx, *args):

        ifun = lambda x, *a: func(x, *a) - fval

        from ostap.math.rootfinder import findroot
        return findroot(ifun, xmn, xmx, args=args)