Sunday, June 30, 2013

Задача о неподвижной точке функции

Число x называется неподвижной точкой (fixed point) функции f, если оно удовлетворяет равенству:

f(x)=x

В sicp предлагается следующий алгоритм решения данной задачи. Для некоторой функций f можно найти неподвижную точку, многократно вычисляя f(от предыдущего значения функции) до тех пор, пока изменение значения превышает условную пороговую величину(заданную точность):

f(x),f(f(x)),f(f(f (x))),...

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

(defn fixed-point [f guess]
  (defn close-enough? [v1 v2]
    (< (abs (- v1 v2)) 0.00001))
  (let [next (f guess)]
    (if
      (close-enough? guess next)
      next
      (recur f next))))

Для примера вычислим приближенное значение неподвижной точки функции косинуса:

(ns sicp.clojure.topic-1-3-4
  (:use [clojure.contrib.generic.math-functions :only [cos]]))
...
(fixed-point cos 1.0) ; -> 0.7390822985224024

Как можно заметить, данный способ имеет ряд недостатков. Если попытаться вычислить значение для функции kx+b, например, вот так:

=> (fixed-point (fn[x] (+ 0.5 (* 2 x))) 1)

То интерпретатор уходит в глубокое раздумье. Я подвожу к тому, что неплохо бы подумать об альтернативном способе. В прошлый раз мы решали задачу нахождения корней уравнения. Допустим у нас есть некая процедура half-interval-method трех аргументов - функция и границы интервала, умеющая находить корни уравнения вида f(x)=0. Тогда для нахождения неподвижной точки нужно решить:

f(x)-x=0

Выглядеть это будет так(код half-interval-method я приводить не буду, его можно посмотреть в предыдущем посте):

(defn fixed-point [f x1 x2]
  (half-interval-method (fn[x] (- (f x) x)) x1 x2))

Ну и на последок:

(fixed-point cos 0.0 1.0)
0.7390899658203125

...
(fixed-point (fn[x] (+ 0.5 (* 2 x))) -3 3)
-0.5000152587890625

No comments:

Post a Comment