Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Quickly finding the first point at which a function equals 0 using scipy.optimize

Basically, given a function that produces outputs like this for different parameters:

enter image description here

I want to quickly find the first x at which the function equals 0. So with parameters that produce the blue curve over x, I want to find x=134. For the green curve, I want to find x=56, etc.

I think the function will always be monotonically decreasing until it hits zero, but I'm not totally sure.

The function is not necessarily monotonically decreasing.

I am sure that it will only hit 0 once, and then remain zero.

Currently I'm brute-forcing it by iterating through x values until I hit zero, but I want something that will be better at making educated guesses (based on slope?) and iterating.

Ideally I want to use something already-baked (since 90% of programmers can't even write a binary search correctly), like something from scipy.optimize, but it seems like those all want to find either a global minimum or a zero-crossing.

(This function is sort of a distance_to_the_wall of the RGB cube for a given chroma in Lch color space (so basically building a "sanely clip to RGB" function), but since the mapping between IRGB and LCh can vary by library and with parameters like illuminant etc. I think it's best to just try a few values until the right one is found rather than trying to reverse-calculate the value directly?)

like image 468
endolith Avatar asked Apr 11 '13 23:04

endolith


People also ask

How do I speed up Scipy optimization?

Speed up your objective function. Reduce the number of design variables. Choose a better initial guess. Use parallel processing.

How does Scipy optimize minimize work?

SciPy optimize provides functions for minimizing (or maximizing) objective functions, possibly subject to constraints. It includes solvers for nonlinear problems (with support for both local and global optimization algorithms), linear programing, constrained and nonlinear least-squares, root finding, and curve fitting.

What is JAC in Scipy minimize?

jac : bool or callable, optional Jacobian (gradient) of objective function. Only for CG, BFGS, Newton-CG, L-BFGS-B, TNC, SLSQP, dogleg, trust-ncg. If jac is a Boolean and is True, fun is assumed to return the gradient along with the objective function.


2 Answers

Here is some code to flesh out @ExP's bisection/binary search answer:

def find_first_zero(func, min, max, tol=1e-3):
    min, max = float(min), float(max)
    assert (max + tol) > max
    while (max - min) > tol:
        mid = (min + max) / 2
        if func(mid) == 0:
            max = mid
        else:
            min = mid
    return max
like image 51
Bi Rico Avatar answered Sep 21 '22 07:09

Bi Rico


Try bisection: Check if it's 0 in the middle of your interval; if it is, continue on the left, otherwise, on the right. Do the same thing with the reduced interval recursively until you're close enough. This method is of complexity O(log n) compared to yours, which is O(n).

like image 20
Elmar Peise Avatar answered Sep 20 '22 07:09

Elmar Peise