Wting обратная функция, используя метод деления пополам в логарифмическом времени выполнения

Я пытаюсь написать функцию, которая может взять любую функцию и вернуть параметр, который, если поместить в функцию, вернет ответ, близкий к 0 (близко к эпсилону), функция будет выглядеть примерно так:

def solve(f, x0=-10000, x1=10000, epsilon=EPSILON):

x0, x1 - диапазон, в котором нужно искать ответ. я также знаю, что она применима только к функции, которая может быть как положительной, так и отрицательной (например, f(X) = x^2+1 не является хорошей функцией для решения).

Я нашел здесь ответ методом бисекции

def solve(f, x0=-10000, x1=10000, epsilon=EPSILON):
""" return the solution to f in the range between x0 and x1\
use an algorithm to check if a solution can be found so f(x)<epsilon
iterates in a while loop until either a solution is found or if the abs
the value of the midpoint is smaller than epsilon (return None)"""

# make sure the function is in the type that can be solved 
if (f(x1) * f(x0)) >= 0:
    return None

while True:
    mid = (x0 + x1) / 2
    sol = f(mid)
    if abs(sol) < epsilon:
        return mid
    if mid == 0 or (abs(f(x1) - f(x0)) / 2) < epsilon:
        return None
    elif sol * f(x0) < 0:
        x1 = mid
    elif sol * f(x1) < 0:
        x0 = mid

редактировать: пока все хорошо. теперь у меня есть основная функция, которую мне нужно написать - функция, которая дает уважаемое значение для функции. сама функция получает функцию, которая должна быть обращена, и эпсилон, к которому ответ должен быть близок.

например, для f (x) = x + 2 я хочу, чтобы inverse_func (f (100)) возвращал 100. У меня есть подсказка, что я могу использовать функцию prev, которую я показал. Я попробовал сделать так:

def inverse(g, epsilon=EPSILON):
"""return f s.t. f(g(x)) = x"""

def ret_function(x):
    return find_x(x, g, epsilon)

return ret_function


def find_x(x, g, epsilon):
    x0, x1 = -10000, 1001
    g_sol = x
    sent_epsilone = EPSILON
    while True:
        def f(x):
            g_val = g(x)
            ans = g_sol - g_val
            return ans

        sol = solve(f, x0, x1, sent_epsilone)
        if sol == None:
            pass
        else:
            return sol
        x0, x1 = x0 * 10, x1 * 10

то, что я пытался дать "решить" функцию, чтобы решить проблему для меня. Я даю ему функцию, которая вычисляет заданное значение из f (x) минус значение, которое должна найти функция решения.

например, для f(x) = x+2, то вызов

minus_func = обратный (g (100)) = обратный (102) print (minus_func) должен вернуться

100, потому что функция внутри "решить" - это 102-f(x), и, конечно, "решить" может найти правильное значение для этого.

и я попробовал это в своем коде, и он работает нормально, но не достаточно хорошо. для некоторых функций работает нормально. но для других это не работает вообще. для функций:

math.e**x
x**-3

и, вероятно, другие, это не работает. У кого-нибудь есть идеи, как это решить?.

PS - я пишу код на Python, поэтому было бы здорово, если ответ также на Python. но все остальное в порядке (я знаю также Java и все, что объяснит логику, конечно, здорово)

Спасибо!

2 ответа

Состояние

if mid == 0 or (abs(f(x1) - f(x0)) / 2) < epsilon:
    return None

не имеет смысла. Почему 0 исключено как возможный корень? При начальных значениях по умолчанию метод потерпит неудачу в первом цикле. И если значения функции настолько близки, они либо имеют один и тот же знак, который был исключен, либо они представляют корень функции, поскольку оба значения достаточно малы.

Следует заменить отсутствующим

if abs(x1-x0) < epsilon:
    return mid

Попробуйте эту реализацию бинарного поиска:

def solve(f, x0=-10000, x1=10000, epsilon=EPSILON):
    if f(x0) * f(x1) > 0:  # predicate of binary search
        return None

    while x1 - x0 > epsilon:  # while search interval is bigger than EPS
        mid = (x0 + x1) / 2  # take middle of interval
        sol = f(mid)  # take function value in mid point
        if sol * f(x0) > 0:  # one of roots is located in [mid, x1] interval
            x0 = mid
        else:  # one of roots is located in [x0, mid] interval
            x1 = mid
    return (x0 + x1) / 2

Не стесняйтесь задавать вопросы об этом.

Другие вопросы по тегам