シンボリック関数を関数ハンドルに直して、arrayfunを適用する

arrayfunの使い方 - ハリ・セルダンになりたくて(はてダから移行中)

Matlabのシンボリック式を無名関数(関数ハンドル)に変換する関数 - ハリ・セルダンになりたくて(はてダから移行中)

の合わせ技。

sf(x,y)というシンボリック関数があった場合、それにarrayfunを適用するには関数ハンドル(無名関数)に変換する必要がある。手順は以下の通り。

arrayfun(sf, [1 2], [3 4])

はエラーになる。
hf = matlabFunction(sf)
arrayfun(hf, [1 2], [3 4])

ある数字の繰り返しである行列を作成するのに効率的方法は?

たとえば、7が単に並んだ列ベクトルをつくるとき、Matlabで一番効率的な方法はなにか?

 

tic; repmat(7, 1000000,1); toc;
経過時間は 0.006551 秒です。
tic; ones(1000000,1) * 7; toc;
経過時間は 0.008067 秒です。

 

repmatの方が微妙に早い?のか?

arrayfunの使い方

Matlabに詳しい人には当たり前の話だと思うがarrayfunの使い方を自分用にメモ(Rではapply系の関数に該当するのがarrayfun、cellfun、bsxfunだと思えばいいのかな・・・):

 

plusFun = @(x, y) x + 2 * y
plusFun(1,2)
arrayfun(plusFun, [1 2], [3 4])
arrayfun(plusFun, [1; 2], [3; 4])

 

GPUのあるPCでPCTを契約していると、GPU arrayfunを使うと高速化できるそうです。

[参考]

jp.mathworks.com

jp.mathworks.com

 

Symbolic mathで微分演算子っぽいものを作る

Symbolic mathで微分演算子っぽいものを作ることができる。なんの役に立つか不明だが、面白い機能なので覚書。

 

[問題の定式化]

2回微分可能な関数 u(x)について以下の簡単な常微分方程式を考える。

 \frac{d^2 u }{d x^2} + \rho u + x = 0

微分演算子 Dを以下のように定義する。

 D =  \frac{d^2 }{d x^2} + \rho

微分演算子 Dを使えば、常微分方程式は以下のように簡単に表記できる。

 D u + x = 0 

 

関数の定義:

function [DD] = diffOperator(funcArray, vars, params)

rho = params.rho;

xx = vars.xx;

DD = diff(funcArray, xx, 2) + rho * funcArray;

end

 

使い方:

% 関数を特定した場合の使い方

syms xx;

params.rho = 1.5;

vars.xx = xx;

uu(xx) = xx^2; 

func = symfun(uu(xx), xx);

diffOperator(func, vars, params)

 

% 関数が一般形の場合の使い方

clear uu;

syms uu(xx);

func = symfun(uu(xx), xx);

 

diffOperator(func, vars, params)

 

 

Symbolic mathではシンボリック関数の配列が作成できる。微分もできる。

使い方次第だと思うが、面白い機能なので覚書。

 

シンボリック関数はsymfunで作ることができる(フォーマルなやり方)。簡易なやり方としてsym f(x,y)のようにすることもできる(xxとyyは自動生成される)。

 

syms phi1(xx) phi2(xx);

phi1(xx) = xx;
phi2(xx) = xx^2;

funcArray = symfun([1, phi1(xx), phi2(xx)], xx);

 

funcArray(xx) = [ 1, xx, xx^2] 

 

使い方:funcArray(2)とするとans = [ 1, 2, 4]が返ってくる。

 

補足:2変数関数にもできる

clear;

syms phi1(xx, yy) phi2(xx, yy);  % xxとyyは自動生成される

phi1(xx, yy) = xx*yy;
phi2(xx, yy) = xx^2 * yy^2;

funcArray = symfun([1, phi1(xx, yy), phi2(xx, yy)], [xx, yy]);

 

funcArray(xx, yy) = [ 1, xx*yy, xx^2*yy^2] 

 

 使い方:funcArray(2, 2)とするとans = [ 1, 4, 16]が返ってくる。

 

さらにその「シンボリック関数の配列」を(まるで普通の関数のように)微分することもできる。

chebVec(x, y) = chebyshevT([0, 1, 2], x) .* chebyshevT([0, 1, 2], y)

chebVec(x, y)  = [ 1, x*y, (2*x^2 - 1)*(2*y^2 - 1)]

diff(chebVec, x)

ans(x, y) = [ 0, y, 4*x*(2*y^2 - 1)]

 

公式ページのマニュアルだと少しわかりにくい。

参考:

jp.mathworks.com

jp.mathworks.com

 

シンボリック式・シンボリック関数はstringで文字列に変換できる

何に役立つのか分からないが、面白い機能なので覚書(この機能はMatlabドキュメントに載っていないようなので)。

 

syms xx yy;

% シンボリック式はstringで文字列に変換できる
string(xx + yy)

% シンボリック関数もstringで文字列に変換できる
testFun = @(xx, yy) xx + yy;

string(testFun(xx, yy))

 

なお、普通のMatlab関数をstringで文字列に変換・・・はできない模様。

Matlabのシンボリック式を無名関数(関数ハンドル)に変換する関数

Matlabのsymbolic math toolboxを使わない人にとってはどうでもいい話題ですが、シンボリック式を最適化しようとして少し困ったので、覚書。

 

Matlabのシンボリック式またはシンボリック関数を無名関数(関数ハンドル)に変換する関数が存在する。使い方はこんな感じ(↓)

ht = matlabFunction(r)

 

詳しくは

https://jp.mathworks.com/help/symbolic/matlabfunction.html