Передача параметров в решатель
Допустим, нам нужно решить кубическое уравнение x^3 + b*x + c = 0 для различных значений коэффициентов b и c. Если b и c — константы, то достаточно написать обычную функцию
function y = cubicpoly(x)
y = x^3 + b*x + c;
а затем вызвать её из решателя fzero:
y = fzero(@cubicpoly, x0);
Однако в нашем случае b и c — параметры, которые нужно передать наряду с x в cubicpoly. Проблема в том, что решатель fzero не даёт нам инструментов для этого. Не получится сделать ни так:
y = fzero(@cubicpoly, x0, список_параметров);
ни так
function y = cubicpoly(x, список_параметров)
...
Как же быть?
1. Вложенные функции
Первый способ - "вложить" функцию cubicpoly вместе с решателем внутрь другой функции
function y = findzero(b, c, x0)
y = fzero(@cubicpoly, x0);
function y = cubicpoly(x)
y = x^3 + b*x + c;
end
end
Если раньше cubicpoly обладала отдельной областью памяти, то теперь она "со всеми потрохами" принадлежит области памяти своей функции-обёртки findzero. Соответственно, область видимости переменных b и c расширилась с cubicpoly до findzero, что даёт возможность изменять их, не меняя список аргументов cubicpoly.
2. Анонимные функции
Пусть у нас есть функция, в которую параметры b и c передаются через список аргументов:
function y = cubicpoly(x, b, c)
y = x^3 + b*x + c;
Использовать её в таком виде нельзя из-за требований, предъявляемых fzero (и действительно, как потом узнать, какой из массивов является массивом переменных?). Однако можно "замаскировать" её с помощью анонимной функции.
Пусть, для определенности, b = 2, а c = 3.5. Тогда
b = 2;
c = 3.5;
fun = @(x) cubicpoly(x, b, c);
x = fzero(fun, 0);
fun — анонимная функция аргумента x, которая "маскирует" функцию трёх аргументов cubicpoly, так что требования fzero будут выполнены.
Важный момент: если понадобится решить уравнение с новыми значениями параметров b и c, то недостаточно будет просто указать эти новые значения — нужно переопределить всю анонимную функцию. Например, так:
b = 4;
c = -1;
fzero(@(x) cubicpoly(x, b, c), 0)
Решатель fzero был выбран нами совершенно произвольно. Аналогичным образом можно передавать дополнительные параметры и в другие решатели.
Передача параметров из решателя
Покажем теперь как решается обратная задача — как получить параметры из решателя "сверх обычных". Проделаем это на примере решателя дифференциальных уравнений ode45.
Пусть задано дифференциальное уравнение y' = x + k*y, в котором k зависит от x и y: k = x^2 + y^2. Нам нужно не только решать это уравнение при заданных начальных условиях, но и получить результирующее значение k.
Запишем дифференциальное уравнение в виде функции:
function [dydx, k] = fun(x, y)
k = x.^2 + y.^2;
dydx = x + k.*y;
Особенность этой записи в том, что k присутствует в ней в качестве выходного параметра.
Решаем уравнение:
[X, Y] = ode45(@fun, [0 5], 1);
А затем получим значение k командой:
[dydx, k] = fun(X, Y);
Комментарии
comments powered by Disqus