2016-02-28 2 views
0

Проблема, с которой я сталкиваюсь, - это тот, который я не смог преодолеть.MATLAB - работа с функциями, а не медленными символическими выражениями

Фактический код, который я запускаю, является слишком сложным, и поэтому я просто воспроизведу проблему здесь в более простых выражениях.

>> syms x 
>> T_m = [[exp(x), x^2];[x,sin(x)]]; 
>> sum_matrix = T_m(1,1) + T_m(1,2) + T_m(2,1) + T_m(2,2); 
>> main_func = matlabFunction(sum_matrix) 
main_func = 

    @(x)x+exp(x)+sin(x)+x.^2 

>> integrand = @(x) exp(-x) .* main_func(x); 
>> Q = integral(@(x) integrand(x), 0,2*pi); 

>> Q 
ans = 

    9.6677 

Основной вопрос, который я имею в моем фактического кода является использование

>> main_func = matlabFunction(sum_matrix) 

В этом примере линия проходит почти мгновенно. Функции, с которыми я имею дело, очень сложны, и эта строка кода занимает около 45 секунд для запуска, что смешно .. тем более, что я повторяю этот код еще 100 раз.

Я считаю, что решение должно работать исключительно с функциями, а не с символическими выражениями. Я еще не смог этого сделать, в основном потому, что не могу дважды индексировать матрицы (что-то похожее на линии T_m (x) (1,1), которое работает на многих языках, но не MATLAB).

Любое понимание оценено, спасибо!

+0

любая причина регулярная функция файла .m не работает? – user3528438

+0

Можете ли вы добавить акцент на свой вопрос? Обратите внимание, что matlabFunction() - это функция, встроенная в MATLAB. Все, что он делает, это преобразовать символические выражения в дескрипторы функций. – RRR

+0

Я имею в виду, вам действительно нужно динамически создавать функции? – user3528438

ответ

1

Одним из возможных вариантов было бы использовать массив ячеек функций, поскольку funcell{k1,k2}(3): действительный синтаксис. Однако использование ячеек также будет довольно медленным.

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

syms x; 
T_m = [[exp(x), x^2];[x,sin(x)]]; 
funT = matlabFunction(T_m); 
%// produces @(x)reshape([exp(x),x,x.^2,sin(x)],[2,2]) 

Вы можете использовать сумму этого количества в качестве новой анонимной функции,

main_func = @(x) sum(sum(funT(x))); 

, которые могли бы быть то же самое, что Troy Haskin suggested.

Основная причина, по которой я решил добавить ответ, - это также адрес your other, related question. Если вы хотите использовать отдельные элементы исходного массива функций, вы должны либо использовать массив ячеек для дескрипторов (тогда вам просто нужно получить доступ к funcell{k1,k2}(x)), либо, если окажется, что использование ячеек медленнее, чем ненужное вычисление полный массив, просто выбросить то, что вам не нужно:

id1 = eye(size(T_m,1))); %// for Kronecker delta, essentially 
id2 = eye(size(T_m,2))); %// same here 
T_m12 = @(x) id1(1,:)*funT(x)*id2(:,2); 

%// or even better, generally 
funT_m = @(x,k1,k2) id1(k1,:)*funT(x)*id2(:,k2); 

Чтобы завершить круг: если вы исходите из массива ячеек функции ручки, you can transform that to an array-valued function handle, которая действительно некрасиво и грязно, но не должен работать, если ваш функция - очень большой зверь (но in that case, all hope's lost anyway).

шлейф, просто для полноты картины: the answer to the suggested duplicate of your other question показывает вам, как вы можете присвоить в возвращаемом значение вызова функции без использования временного переменного. Основная проблема с этим подходом заключается в том, что он делает код невозможным для чтения людьми, но в остальном он является настолько низким, насколько это происходит с точки зрения эффективности.Если вы отчаянно, вы могли бы рассмотреть этот маршрут, а также (как это не включает в себя клетки, символической математикой, ни ненужный вектор-матрица-векторное произведение):

funT_m = @(x,k1,k2) subsref(funT(x),struct('type','()','subs',{{k1,k2}})); 

Но имейте в виду, что мы» все еще вычисляя полный массив в x, мы просто отбрасываем ненужные части как можно более эффективно.

Заключительное примечание: если вы в конце концов захотите интегрировать каждый элемент матрицы, который у вас есть, вы также должны рассмотреть возможность использования полной функции с массивом в integral с использованием пары значений параметра 'arrayvalued',true. Это сделает интеграцию медленнее, но вы можете вычислить интеграл от каждого матричного элемента одновременно, не отбрасывая никаких результатов.