Date Редакция Категория sci Теги matlab

Передача параметров в решатель

Допустим, нам нужно решить кубическое уравнение 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