Обратите внимание, что метод Ньютона-Рафсона определяет корни функции.Т.е. у вас должна быть функция f (x) такая, что f (x) = 0 при желаемом решении.
В этом случае вы можете определить f as
f (x) = Время (x) - t
, где t - желаемое время.Тогда по второй фундаментальной теореме исчисления
f '(x) = 1 / Velocity (x)
С этими определенными функциями реализация становится довольно простой!
Сначала мы определим простую функцию Ньютона-Рафсона, которая принимает анонимные функции в качестве аргументов ( f и f '), а также первоначальное предположение x0 .
function x = newton_method(f, df, x0)
MAX_ITER = 100;
EPSILON = 1e-5;
x = x0;
fx = f(x);
iter = 0;
while abs(fx) > EPSILON && iter <= MAX_ITER
x = x - fx / df(x);
fx = f(x);
iter = iter + 1;
end
end
Затем мы можем вызвать нашу функцию следующим образом
t_given = 0.3; % e.g. we want to determine distance after 0.3 hours.
n = 180;
route = 'test.mat';
f = @(x) time_to_destination(x, route, n) - t_given;
df = @(x) 1/velocity(x, route);
distance_guess = 50;
distance = newton_method(f, df, distance_guess);
Результат
>> distance
distance = 25.5877
Кроме того, я переписал ваши time_to_destination
иvelocity
работает следующим образом.Эта версия time_to_destination
использует все доступные данные для более точной оценки интеграла.При использовании этих функций метод, по-видимому, сходится быстрее.
function t = time_to_destination(x, d, v)
% x is scalar value of destination distance
% d and v are arrays containing measured distance and velocity
% Assumes d is strictly increasing and d(1) <= x <= d(end)
idx = d < x;
if ~any(idx)
t = 0;
return;
end
v1 = interp1(d, v, x);
t = trapz([d(idx); x], 1./[v(idx); v1]);
end
function v = velocity(x, d, v)
v = interp1(d, v, x);
end
Использование этих новых функций требует незначительного изменения определений анонимных функций.
t_given = 0.3; % e.g. we want to determine distance after 0.3 hours.
load('test.mat');
f = @(x) time_to_destination(x, distance_km, speed_kmph) - t_given;
df = @(x) 1/velocity(x, distance_km, speed_kmph);
distance_guess = 50;
distance = newton_method(f, df, distance_guess);
Поскольку интеграл оценивается болееточно решение немного отличается
>> distance
distance = 25.7771
Редактировать
Обновленное условие остановки может быть реализовано как незначительное изменение функции newton_method
.Мы не должны ожидать, что ошибка правила трапеции обнулится, поэтому я опускаю это.
function x = newton_method(f, df, x0)
MAX_ITER = 100;
TOL = 1e-5;
x = x0;
iter = 0;
dx = inf;
while dx > TOL && iter <= MAX_ITER
x_prev = x;
x = x - f(x) / df(x);
dx = abs(x - x_prev);
iter = iter + 1;
end
end
Чтобы проверить наш ответ, мы можем построить график зависимости времени от расстояния и убедиться, что наша оценка падает на кривой.
...
distance = newton_method(f, df, distance_guess);
load('test.mat');
t = zeros(size(distance_km));
for idx = 1:numel(distance_km)
t(idx) = time_to_destination(distance_km(idx), distance_km, speed_kmph);
end
plot(t, distance_km); hold on;
plot([t(1) t(end)], [distance distance], 'r');
plot([t_given t_given], [distance_km(1) distance_km(end)], 'r');
xlabel('time');
ylabel('distance');
axis tight;
![enter image description here](https://i.stack.imgur.com/ZAqvK.png)