MATLinkを使用してMathematicaからMATLABを呼び出す
MathematicaからMATLAB関数を直接呼び出して、2つのシステム間でデータと変数の交換を整理するにはどうすればよいですか?
これを行うために、 MATLink と呼ばれるクロスプラットフォームパッケージが あります。 これにより、MATLAB関数の呼び出しをMathematicaから直接整理し、システム間でさまざまなデータを簡単に転送できます。
少し説明します。
●インストール
まず、メインのMATLinkページに移動し、そこにある指示に従います。 最も簡単な方法は、アーカイブをダウンロードして、このフォルダーに解凍することです。
[1]で:=
SystemOpen@FileNameJoin[{$UserBaseDirectory, "Applications"}]
次に、メインページの「MATLABとのリンク」セクションの特定のオペレーティングシステムの指示に従います。
●MATLinkの使用
MATLinkは、次のコードでセルを計算することによりロードできます。
[2]で:=
Needs["MATLink`"]
そして、コマンドでMATLABを実行します:
[3]で:=
OpenMATLAB []
これにより、MATLABで新しいプロセスが開始され、Mathematicaとの対話が可能になります。
任意のMATLABコマンドを使用するには、 MEvaluateを使用します 。 データは文字列として送信されます。
例:
[4]で:=
MEvaluate["magic(4)"]
アウト[4] =
(* ==> ans = 16 2 3 13 5 11 10 8 9 7 6 12 4 14 15 1 *)
データをMATLABに転送するには、 MSetを使用する必要があります。
[5]で:=
MSet["x", Range[10]];MEvaluate["x"]
アウト[5] =
(* ==> x = 1 2 3 4 5 6 7 8 9 10 *)
データを取得するには、 MGetを使用します 。
[6]で:=
MGet["x"]
アウト[6] =
(* ==> {1., 2., 3., 4., 5., 6., 7., 8., 9., 10.} *)
スパース配列、構造体、セルなど、多数のデータ型がサポートされています。
MATLAB関数は、 MFunction関数を使用してMathematicaから直接呼び出すことができます。
[7]で:=
eig = MFunction["eig"]; eig[{{1, 2}, {3, 1}}]
アウト[7] =
(* ==> {{3.44949}, {-1.44949}} *)
ドキュメントでは、使用の機能およびその他の機能について詳しく読むことができます。
いくつかの簡単な例
まず、Mathematicaでは、MATLABロゴの表面を作成し、振動の周期を調整するマニピュレーターを追加します。
[8]で:=
Manipulate[ ListPlot3D@MFunction["membrane"][k], {k, 1, 12, 1} ]
アウト[8] =
MATLABから直接フラーレン構造(バッキーボール):
[9]で:=
AdjacencyGraph@Round@MFunction["bucky"][]
アウト[9] =
また、MATLABで使用される描画用の個別のスケーラブルウィンドウにMathematicaからのデータを表示するのも簡単です。
[9]で:=
mlf = LibraryFunctionLoad["demo_numerical", "mandelbrot", {Complex}, Integer]; mandel = Table[mlf[x + I y], {y, -1.25, 1.25, .002}, {x, -2., 0.5, .002}]; MFunction["image", "Output" -> False][mandel]
アウト[9] =
さらに複雑な例
以下の例は、MATLinkを使用した実際の問題の解決策を示しており、MATLABとMathematicaの最高品質を使用できます。
●高速ドロネー三角形分割
MathematicaはComputationalGeometryパッケージ内にDelaunayTriangulation関数を含んでいます(10番目のバージョンでは、このパッケージはカーネルに組み込まれ、現在この関数はDelaunayMeshと呼ばれ、最適化され、パフォーマンスはMATLABに劣りません-およそEd)。 (ただし、正確な演算の使用や共線点の操作など、独自の長所があります)。 これは、 ListDensityPlotが非常に非効率的に機能するという事実につながります(数千以上のポイントを構築するときに顕著になります)。 MATLinkを使用すると、MATLABのDelaunay関数を使用して、次のように特定のポイントセットのDelaunay三角形分割を計算できます。
[10]で:=
delaunay = Composition[Round, MFunction["delaunay"]];
Mathematicaシステムの関数は隣接する頂点のリストを返すので、MATLABの結果と比較するために結果を後処理する必要があります:
[11]で:=
Needs["ComputationalGeometry`"]; delaunayMma[points_] := Module[{tr, triples}, tr = DelaunayTriangulation[points]; triples = Flatten[ Function[{v, list}, Switch[Length[list], (* account for nodes with connectivity 2 or less *) 1, {}, 2, {Flatten[{v, list}]}, _, {v, ##}& @@@ Partition[list, 2, 1, {1, 1}]] ] @@@ tr, 1]; Cases[GatherBy[triples, Sort], a_ /; Length[a] == 3 :> a[[1]]] ]
通常、ポイントのランダムセットには一意のDelaunay三角形分割があるため、システムが同じ結果を生成することを確認する必要があります。
[12]で:=
pts = RandomVariate[NormalDistribution[], {100, 2}]; Sort[Sort /@ delaunay[pts]] === Sort[Sort /@ delaunayMma[pts]]
そして、以下で三角測量を構築します
[13]で:=
trianglesToLines[t_] := Union@Flatten[{{#1, #2}, {#2, #3}, {#1, #3}} & @@ Transpose[Sort /@ t], {{1, 3}, {2}}]; Graphics@GraphicsComplex[pts, Line@trianglesToLines@delaunay[pts]]
アウト[13]:=
ただし、 delaunayはDelaunayTriangulation (特に大きなデータセット)よりもはるかに高速であるという事実に加えて、 ListDensityPlot内で使用されるtriangulatorよりも高速です 。 したがって、MATLABのdelaunayを使用して、組み込み関数よりも高速なlistDensityPlotの独自のバージョンを開発できます。また、次のように大きなデータセットを処理することもできます。
[14]で:=
Options[listDensityPlot] = Options[Graphics] ~Join~ {ColorFunction -> Automatic, MeshStyle -> None, Frame -> True}; listDensityPlot[data_?MatrixQ, opt : OptionsPattern[]] := Module[{in, out, tri, colfun}, tri = delaunay[data[[All, 1;;2]]]; colfun = OptionValue[ColorFunction]; If[Not@MatchQ[colfun, _Symbol | _Function], Check[colfun = ColorData[colfun], colfun = Automatic]]; If[colfun === Automatic, colfun = ColorData["LakeColors"]]; Graphics[ GraphicsComplex[data[[All, 1;;2]], GraphicsGroup[{EdgeForm[OptionValue[MeshStyle]], Polygon[tri]}], VertexColors -> colfun /@ Rescale[data[[All, 3]]] ], Sequence @@ FilterRules[{opt}, Options[Graphics]], Method -> {"GridLinesInFront" -> True} ] ]
30,000ポイントの配列を使用して、関数を組み込み関数と比較しましょう。
[15]で:=
pts = RandomReal[{-1, 1}, {30000, 2}]; values = Sin[3 Sqrt[#1^2 + #2^2]] & @@@ pts;
[16]で:=
listDensityPlot[ArrayFlatten[{{pts, List /@ values}}], Frame -> True] // AbsoluteTiming
アウト[16] =
{0.409001, --Graphics--}
[17]で:=
ListDensityPlot[ArrayFlatten[{{pts, List /@ values}}]] // AbsoluteTiming
アウト[17] =
{12.416587, --Graphics--}
実行速度の違いは非常に重要であることが判明しました(30倍)。 数十万のポイントを処理するには、 ListDensityPlotはほとんど使用できませんが、 listDensityPlotは数秒しかかかりません。
MATLink速度の測定には、すべての時間を計算するAbsoluteTiming関数を使用する必要があることを考慮することも重要です。タイミングは、MATLABが費やした時間を測定せずに、MathematicaカーネルがCPUを使用した時間のみを測定します。
●信号処理ツールボックスを使用したオーディオデータのフィルタリング
ご存知のように、信号処理機能はMathematicaには9番目のバージョンまで存在していませんでしたが、機能と使いやすさの点でまだMATLABツールより劣っています。 Mathematicaのバージョン8があり、新しい関数がなく、オーディオファイルの周波数分析を行い、フィルタリングを実装するとします。 方法は次のとおりです。
[18]で:=
{data, fs} = {#[[1, 1, 1]], #[[1, 2]]} &@ExampleData[{"Sound", "Apollo13Problem"}]; spectrogram = MFunction["spectrogram", "Output" -> False]; (* Use MATLAB's spectrogram *) spectrogram[data, 1000, 0, 1024, fs]
明らかに、周波数は主に2.5 kHzを下回るため、MATLABでローパスフィルターを開発し、フィルター処理されたデータを返す補助関数を作成することもできます。
[19]で:=
MSet["fs", fs]; MEvaluate[" [z, p, k] = butter(6, 2.5e3/fs, 'low') ; [sos, g] = zp2sos(z, p, k) ; Hd = dfilt.df2tsos(sos, g) ; "] filter = MFunction["myfilt", "@(x)filter(Hd,x)"];
アウト[19] =
Mathematicaから直接データにフィルタリング関数を適用するためにすべてを準備しました。 この例は、機能のギャップを埋める方法を示しています。 したがって、Mathematicaでフィルタを設計するための時間(これは最も簡単なタスクではありません)とそれをデバッグするために何時間も節約できます。 バターワースフィルターのコードは、ファイルホスティングサービスまたはスタックオーバーフローから、以前に記述されたコードのフラグメントから、またはこの場合のようにドキュメントの例から、どこからでも取得できます。 現在のニーズに合わせてパラメーターをわずかに変更しましたが、この資料をMathematicaで操作できるようになりました。
最後の例として、フィルターを使用していくつかのデータを処理し、スペクトログラムを作成することを提案します。
[19]で:=
filteredData = filter@data; spectrogram[filteredData, 1000, 0, 1024, fs]
純粋に楽しみのために、フィルター処理されたオーディオファイルとオリジナルのオーディオファイルの両方を再生し、サウンドの違いを比較できます。
[20]で:=
ListPlay[data, SampleRate -> fs] ListPlay[filteredData, SampleRate -> fs]
MATLinkの作業で突然エラーや問題を見つけた場合は、GitHubまたはこの記事のオリジナルへのコメントで、電子メール(matlink.m@gmail.com)でそれらを報告してください。
追加
●NETLinkを使用してMathematicaからMATLABを呼び出す
MATLAB COMインターフェイスを使用して、WindowsオペレーティングシステムでNETLinkを使用してMATLABを呼び出す方法に関する簡単なメモ:
[21]で:=
Needs["NETLink`"] matlab = CreateCOMObject["matlab.application"]
アウト[21] =
«NETObject[COMInterface[MLApp.DIMLApp]]»
これで、MATLAB関数にアクセスできます。
[22]で:=
In[4]:= matlab@Execute["version"]
アウト[22] =
" ans = 7.9.0.529 (R2009b) "
[23]で:=
matlab@Execute["a=2"];matlab@Execute["a*2"]
アウト[23] =
" ans = 4 "
●式をMathematica構文からMATLAB構文に変換する
式をMathematicaからMATLABの同等物に変換するToMatlabというパッケージがあります。 以下に例を示します。
[24]で:=
<<ToMatlab` Expand[(x + Log@y)^5] // ToMatlab
アウト[24]:=
x.^5+5.*x.^4.*log(y)+10.*x.^3.*log(y).^2+10.*x.^2.*log(y).^3+5.* ... x.*log(y).^4+log(y).^5;
あなたは...を使用して式が非常に便利に壊れていることに気付くでしょう。
別のマトリックス変換の例を次に示します。
[25]で:=
RandomInteger[5, {5, 5}] // ToMatlab
アウト[25]:=
[5,0,5,3,4; 5,5,3,0,2; 1,4,4,4,4; 0,3,2,5,5; 4,5,5,1,1];
一般的な定義などは、MATLAB構文に変換できないことに注意してください。 もちろん、MATLABでサポートされていない構造は変換できません-たとえば、テンプレート式。
このパッケージをインストールするには、ToMatlab.mファイルをフォルダーに抽出するだけです。
[26]で:=
FileNameJoin[{$UserBaseDirectory, "Applications"}]
Wolframテクノロジーに関する質問については 、 info-russia @ wolfram.comに連絡してください