最適化式の静的解析
静的解析とは
静的解析は、関数を解析し、効率的にコード化できる規則性の有無を探すプロセスです。特に、fcn2optimexpr は、for ループを効率的に符号化しようとするために静的解析を実行します。これを行うために、fcn2optimexpr ではループが別個の関数内になければなりません。入れ子形式の for ループは 1 つの関数内に入れることができます。例静的解析のための for ループの作成では、for ループを別個の関数に容易に変換する方法を示します。例静的解析のための for ループの制約の変換では、別個の関数の制約に for ループを作成する方法を示します。
静的解析の一環として、どの関数が数値データのみで動作するか、およびどれが最適化変数に依存するかを特定します。最適化変数に依存しない関数の場合、fcn2optimexpr はサポートされていない関数を自動的にラップし、関数の残りの部分が自動微分を利用できるようにします。このサポートされていない関数をラップしたものは、最適化変数に関してゼロ勾配をもつと仮定されます。たとえば、関数 ceil はサポートされていません (最適化変数および式でサポートされる演算を参照してください)。ただし、次の関数では、ceil が最適化変数ではなくループ変数のみで動作するため、fcn2optimexpr は自動微分をサポートする式を返します。
function [expr, val] = forloop(x, y) N = numel(y); expr = y + 2; val = zeros(N,1); for i = 1:N val(i) = ceil(sqrt(i+1)); expr(i) = expr(i) + val(i)*x; end end
静的解析の制限
静的解析は次をサポートしていません。
cell 配列
セル インデックス付け
ドット インデックス付け
無名関数
break、continue、およびreturnステートメントクラス
入れ子関数
グローバル変数
永続変数
名前と値の引数
parforswitchステートメントtry-catchブロックwhileステートメントifステートメントstring インデックス付け
非数値のループ範囲
複数の左辺への代入 — 静的解析は、次のような複数の左辺を含む代入をサポートしていません。
[a,b] = peaks(5);
ループ内で縮小または拡大する式 — 静的解析は、式の大きさを変化させる
forループをサポートしていません。すべての式を事前に割り当てることをお勧めします。たとえば、次のループは静的解析でサポートされていません。for i = 1:10 x = [x fun(i)]; % x grows by concatenation end %% temp = x.^2; for i = 1:N temp(i+1) = temp(i) + x.*i; % temp grows by indexing end %% for i = 2:N expr(2:i) = expr(1:i-1) - i*x^2; % Vectors 2:i and 1:i-1 change size at each iteration end %% for i = N:-1:1 expr(i) = []; % expr shrinks at each iteration end
静的解析は、main 関数によって呼び出されるサブ関数には適用されません。静的解析では、サブ関数をそのまま使用できる場合もありますが、サブ関数をソフトウェアでブラック ボックスとしてラップすることが必要になる場合もあります。この要件は、一般に、サブ関数でインデックス付けを使用しており、式のサイズが変わる可能性がある場合に当てはまります。
たとえば、同じ式を評価する 2 つの手法について考えてみます。1 つはサブ関数でインデックス付けを使用する手法で、したがって静的解析は使用できません。もう 1 つは main 関数でインデックス付けを使用する手法であり、静的解析を使用します。
N = 5000; q = optimvar("q",5,N); tic ceqstat1 = fcn2optimexpr(@nonlconNotUseStatic,q,N); out1 = evaluate(ceqstat1,s); tocElapsed time is 32.319667 seconds.
tic ceqstat2 = fcn2optimexpr(@nonlconUseStatic,q,N); out2 = evaluate(ceqstat2,s); toc
Elapsed time is 10.332486 seconds.
function dyneval = nonlconUseStatic(q,N) dyneval = zeros(2,N,"like",q); for i = 1:N tmp = q(:,i); tmp2 = sin(tmp([1 5])); dyneval(:,i) = tmp2; end end function dyneval = nonlconNotUseStatic(q, N) dyneval = zeros(2,N,"like",q); for i = 1:N dyneval(:,i) = myfun(q(:,i)); end end function y = myfun(x) y = sin(x([1 5])); end
静的解析を使用した手法の方がはるかに高速に実行されます。
また、静的解析では計算をしない関数を無視することができます。アルゴリズムにはこのような特徴があるため、次のような結果になります。
pauseステートメントは無視されます。結果に影響しないグローバル変数は無視される可能性があります。たとえば、グローバル変数を使用して関数の実行回数をカウントすると、誤った回数を得る場合があります。
randまたはrngの呼び出しが関数に含まれている場合、関数は 1 回目のみ呼び出しを実行すると考えられますが、その後の呼び出しでは乱数ストリームが設定されません。plotを呼び出しても、すべての反復で Figure が更新されない場合があります。matファイルまたはテキスト ファイルへのデータの保存は、すべての反復で実行されない場合があります。
計算をしない関数が想定したとおりに動作するには、fcn2optimexpr の Analysis 名前と値の引数を "off" に設定します。