2016-01-02 3 views
2

* Если вы делаете intro2cs в ЕУИ быть осторожным ... Я знаю, почему ты здесь *Попытка построить обратную функцию

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

Я написал кое-что, что даст мне x0, что делает f(x0)=0.

def solve(f, x0=-10000, x1=10000, epsilon=EPSILON): 
"""return the solution to f in the range between x0 and x1""" 

while x1-x0>EPSILON: 

    if (f(x0)*f((x1+x0)/2))<0: 
     x1=((x1+x0)/2) 
    elif (f(x0)*f((x1+x0)/2))>0: 
     x0=((x1+x0)/2) 
    elif (f(x0)*f(x1))==0: 
     if f(x0)==0: 
      return x0 
     else: 
      return x1 
if f(x0)*f(x1)<0: 
    return (x1+x0)/2 
else: 
    return None 

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

Любые идеи?

UPDATE: нормально, так что я пытался писать как @Spektre предложил и мне удастся:

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

    def helper(y): 
     x0=-2 
     x1=2 
     while x1<10000: 
      if solve((lambda x:g(x)-y),x0,x1,epsilon): 
       return solve((lambda x:g(x)-y),x0,x1,epsilon) 
      else: 
       x0=math.pow(x0,3) 
       x1=math.pow(x1,3) 
    return helper 
+0

Неэффективно выполнять одни и те же вызовы функций несколько раз; Python не будет оптимизировать их для вас. Вы можете получить некоторые идеи по улучшению кода из статьи Википедии по методу [bisection method] (https://en.wikipedia.org/wiki/Bisection_method). FWIW, чтобы выполнить инверсию функции, вы можете использовать метод Ньютона или тесно связанный [secant method] (https://en.wikipedia.org/wiki/Secant_method). –

+0

Для ускоренного использования в скобках используйте метод regula falsi - false position с модификацией Anti-stall от Illinois. Это намного быстрее, чем деление пополам и только умеренно медленнее, чем связанный с ним метод. – LutzL

ответ

1

без алгебраического выражения y=f(x)

Там нет никакого способа узнать фактическую x или y интервал.

Как упоминался вам необходимо непрерывное и однообразное интервал только

Так что, если вы не знаете его вы можете попытаться найти точки экстремума (где первый вывод проходить через нуль) с некоторым поиском с динамической стадией, зависящей от значение деривации (линейно или логарифмически), но всегда будет возникать риск отсутствия некоторых небольших ударов. Если вы создадите список этих точек, интервалы между ними должны быть монотонными. После этого, если функция x=g(y) является функцией, вы можете использовать двоичный поиск . Если имеются небольшие удары, то лучше approximation search.

Для функции несвязанных монотонной y=f(x)

вы можете изменить поиск приближения сверху ссылки на что-то вроде этого:

  1. первоначального предположения

    x0=0 
    

    нет мы можем обойтись без дополнительной информации о g,f. если x0=0 не является вариантом, используйте другое безопасное значение.

  2. обнаружения шага поиска dx

    dx=0.0001 // or dx=function(|f(x0),f(x0+0.0001)|) 
    if (|f(x0-dx)-y|<|f(x0+dx)-y|) dx=-dx; 
    

    так найти, какой путь ближе к решению. Константа 0.0001 должна быть выбрана каким-либо значимым образом. Слишком маленькая будет замедлять процесс слишком большой, будет скучать. Для динамического шага вы можете использовать величину первого вывода или расстояние до решения себя как dx=sign(dx)*abs(f(x)-y) и если dx==0 остановки ...

  3. поиска ближайшего матча

    while (|f(x0)-y|>|f(x0+dx)-y|) x0+=dx; 
    

    просто остановка на ближайший матче , Если вы хотите динамический шаг затем добавить также в dx=function(|f(x0),f(x0+0.0001)|) внутри цикла

  4. теперь вы связали поиск <x0-dx,x0+dx>

    так что вы можете использовать бинарный поиск Аппроксимация выше ссылке, как есть.

  5. если не достаточно близко, решения найдено

    тогда вы получили некоторые пропущенные удары или слишком большой шаг или начальная точка догадки экстремальной точка с symetric функции формы вызывая первоначальную оценку направления к сбою. Таким образом, вы можете изменить начальную константу x0.

+0

Привет Спектр! я сделал, как вы seggested и записал его и обновил его на question.thank вас. – limitless

0

Я хотел бы предложить работать на небольшом диапазоне первого, чем расширение его в геометрической прогрессии. Если вы используете диапазоны, такие как [-1, 1], [-2, 2], [-4, 4] и т. Д., Накладные расходы будут постоянными даже в худшем случае.

1

Я только что опубликовал пакет python, который делает это точно и должен пройти через многие из этих оговорок. Вы можете заимствовать некоторые идеи из него: https://pypi.python.org/pypi/pynverse

Это существенно ниже этой стратегии:

  1. Выяснить, если функция увеличения или уменьшения. Для этих двух опорных точек ref1 и ref2 необходимы:
    • В случае конечного интервала точки ref ref points равны 1/4 и 3/4 через интервал.
    • В бесконечном интервале работают любые два значения.
    • Если f (ref1) < f (ref2), функция увеличивается, в противном случае уменьшается.
  2. Вывести изображение функции в интервале.
    • Если указаны значения, то они используются.
    • В интервале с интервалом просто вычислите f (a) и f (b), где a и b - концы интервала.
    • В открытом интервале попробуйте рассчитать f (a) и f (b), если это работает, они используются, в противном случае это будет считаться (-Inf, Inf).
  3. Встроенный ограниченную функцию со следующими условиями:
    • bounded_f (х):
      • возврата -Inf если х ниже интервала, а F возрастает.
      • return + Inf, если x ниже интервала, и f уменьшается.
      • return + Inf, если x выше интервала, и f увеличивается.
      • return -Inf, если x выше интервала, а f уменьшается.
      • возврата F (X) в противном случае
  4. Если требуемое число у0 для обратной находится вне изображения, вызывает исключение.
  5. Найти корни для bounded_f (x) -y0, минимизируя (bounded_f (x) -y0) ** 2, используя метод Brent, убедившись, что алгоритм минимизации начинается в точке внутри исходного интервала, устанавливая ref1 , ref2 в виде скобок. Как только он выходит за пределы разрешенных интервалов, bounded_f возвращает бесконечность, заставляя алгоритм вернуться к поиску внутри интервала.
  6. Убедитесь, что решения точны и соответствуют f (x0) = y0 до некоторой желаемой точности, в противном случае возникает предупреждение.