Можно ли использовать анонимную функцию в качестве функции события при решении ОДУ в Matlab

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

opt = odeset('Events', @(t,y) (deal(y(end)-t^2,1,0)));
[T,Y] = ode45(@odefun,[tstart tend],y0,opt);

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


person The input-validating guy    schedule 19.02.2013    source источник


Ответы (3)


Кроме того (это очень поздно добавлять к этому, но это меня расстраивает). Вот решение с вложенными функциями:

function [ dealfunchandle ] = dealwithit( arrayfunc )
% Takes as input an event function of (t,z) that returns a 3 array (in same order as event syntax).

    function [a, b, c] = dealfunc(t,z)
       output = arrayfunc(t,z);
       a = output(:,1);
       b = output(:,2);
       c = output(:,3);
    end

dealfunchandle = @dealfunc;
end

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

arrayfunc = @(t,y) [y(1), 0, 1];
events = dealwithit(arrayfunc);

opts = odeset('Events', events);

А потом ode45 как обычно.

person corjos    schedule 01.11.2015

Я заметил этот пост в поисках ответа на тот же вопрос. Это означает, что для некоторых людей вопрос может быть по-прежнему актуален. Поскольку, наконец, я нашел решение самостоятельно, я хотел бы дать немного «устаревший» ответ.

На самом деле, да - это возможно, но не однозначно. Попробуй это:

evnt_fun = @(t, f)subsref({'какое-то условие остановки', 1, 0}, struct('type', '{}', 'subs', {{':'}}));

Я не могу полностью проверить обратную совместимость кода. Однако он работает с R2011 и более поздними версиями MATLAB.

person Jacek    schedule 06.03.2015

Нет, ты не можешь этого сделать. Анонимные функции в Matlab возвращают только одно значение.

Вместо этого вы можете определить тонкую оболочку вокруг deal и передать ее как дескриптор:

function [a b c] = wrapper(t,y)
    [a b c] = deal('some stop condition', 1, 0);
end

opt = odeset('Events', @wrapper);

[T, Y] = ode45(@odefun, [tstart tend], y0, opt);
person Chris Taylor    schedule 19.02.2013
comment
Дело в том, что я хотел бы избежать функции-оболочки. Используя сделку, вы МОЖЕТЕ заставить анонимную функцию возвращать три значения (поскольку сделка просто возвращает свои аргументы). Однако решатель ODE, по-видимому, ожидает разное количество возвращаемых значений, в то время как сделка должна точно соответствовать. - person The input-validating guy; 19.02.2013
comment
Вы совершенно правы. Я посмотрю еще раз, когда получу сдачу. Подозреваю, что это может быть связано с тем, что ode45 передает обработчику события переменное количество аргументов. - person Chris Taylor; 19.02.2013
comment
Я подозреваю, что это связано с тем, что функция оценивается с одним выходом в odeevents и с тройкой выходов в odezero. Однако количество выходных аргументов анонимной функции равно единице или трем, но она не может обрабатывать и то, и другое. - person embert; 23.11.2014