46
関数型プログラミング入門 for Matlabユーザー 丸田 一郎

関数型プログラミング入門 for Matlab ユーザー

Embed Size (px)

Citation preview

Page 1: 関数型プログラミング入門 for Matlab ユーザー

関数型プログラミング入門for Matlabユーザー

丸田 一郎

Page 2: 関数型プログラミング入門 for Matlab ユーザー

アメリカで滞在していた研究室にて…

学生「何か手っ取り早くプログラミングが上達するチュートリアルやってくださいよ」

○「Functional Programming とかどう?」学生「Function ならみんな知ってますよ~

他のネタがいいです」○「(これは教えがいがありそうやで…)」

という感じのいきさつで,一晩で準備したスライドの日本語訳がこれです.過度な期待はしないでください.

Page 3: 関数型プログラミング入門 for Matlab ユーザー

このチュートリアルのねらい

対象• Matlab初級者の大学生/大学院生/研究者

目標• 関数型プログラミングをちょろっと勉強して

日々のコーディングを効率的にする

Page 4: 関数型プログラミング入門 for Matlab ユーザー

関数型プログラミング(FP)って何?

「関数を組み合わせて処理を記述する」プログラミングパラダイムです

このチュートリアルでは,「関数を組み合わせて処理を記述する」うえで有用な機能・テクニックと,そのメリットについて例を挙げて説明します.

最初のトピックは「無名関数」です

Page 5: 関数型プログラミング入門 for Matlab ユーザー

そもそも無名関数(とかFP)って勉強する価値あるの?

高確率でペイすると思いますその根拠は…

Q

A

To Be Continued

Page 6: 関数型プログラミング入門 for Matlab ユーザー

メジャー&保守的な言語 偉大な祖先1958 Lisp1967 Simula1972 C1983 C++1995 ⋮ Java2011 C++11 ⋮

2014 C++14 Java 8

クラスの導入(オブジェクト指向)

無名関数の導入(関数型プログラミング)

C++ と Java が無名関数を最近導入関数型プログラミングの鍵となる機能

Page 7: 関数型プログラミング入門 for Matlab ユーザー

• C++ と Java が無名関数を最近導入• 他の人気言語はとっくの昔に導入• 他の関数型プログラミング由来の機能を

取り入れる言語も多い

無名関数(関数型プログラミング)の有用性は広く認められていると考えられる

Page 8: 関数型プログラミング入門 for Matlab ユーザー

というわけで,無名関数の使用例をみてみよう!

ここで考える例題𝑦𝑦 = 𝑓𝑓 𝑥𝑥 = 𝑥𝑥3 − 𝑥𝑥 のグラフを−1.2 ≤ 𝑥𝑥 ≤ 1.2の範囲で描け!

𝑥𝑥

𝑦𝑦𝑦𝑦 = 𝑓𝑓(𝑥𝑥)

←たぶんこんな感じTo Be Continued

Page 9: 関数型プログラミング入門 for Matlab ユーザー

-1 -0.5 0 0.5 1-0.6

-0.4

-0.2

0

0.2

0.4

0.6

x = -1.2:0.02:1.2; → x=[-1.20, -1.18,…, 1.20]y = x.^3 - x; → y=[-0.53, -0.46,…, 0.53]plot( x, y) → 配列のデータから描画

Matlabでグラフを描く普通のやり方

x = first:step:lastfirstから始まってstep刻みでlastまで続く配列(ベクトル)ができますy = x.^3 - x.^は要素ごとにべき乗を行う演算子です.減算はデフォルトでベクトルに対応しています.

Matlab を知らない人に…

Page 10: 関数型プログラミング入門 for Matlab ユーザー

-1 -0.5 0 0.5 1-0.6

-0.4

-0.2

0

0.2

0.4

0.6

無名関数を使う例f = @(x) x^3 - x; % fは関数xrng = [-1.2, 1.2]; % 描画範囲の[下限,上限]fplot(f,xrng) % 関数と範囲指定から描画

@(x) x^3 - x

Matlab の無名関数

x の関数 返り値は𝑥𝑥3 − 𝑥𝑥

という構文です

Page 11: 関数型プログラミング入門 for Matlab ユーザー

f = @(x) x^3 - x;fplot(f, xrng)

A 一行で書くとわかりやすいかも

f なんていらんかったんや!

Q どこが無名なの?

fplot( @(x) x^3-x, xrng)

名前っぽくね?

Page 12: 関数型プログラミング入門 for Matlab ユーザー

パッと見は些末な機能…だけど関数型プログラミングの鍵

高階関数を使うときに超便利だから

無名関数 = 🍜🍜 即席で作れる使い捨ての関数

fplot( @(x) x^3-x, xrng)

なんで?

To Be Continued

Page 13: 関数型プログラミング入門 for Matlab ユーザー

高階関数とは?引数 → 返り値

関数function

Data → Data

高階関数higher order function

Function → DataData → FunctionFunction → Function

汎関数functional

※ 数学ではこのクラスを特に functional と呼ぶが,functional programming の由来では無いっぽい

Function → Data

関数型プログラミングでは高階関数を駆使する

Page 14: 関数型プログラミング入門 for Matlab ユーザー

引数plot( x, y) Datafplot( f, xrng) Function

高階関数を使うとハイレベルなアルゴリズムを容易に使いまわすことができる

⇒ fplot が如何にハイレベルか見てみよう

←高階関数

高階関数の例

←ただの関数

Page 15: 関数型プログラミング入門 for Matlab ユーザー

-1 -0.5 0 0.5 1-0.6

-0.4

-0.2

0

0.2

0.4

0.6

ただの関数 plot(x,y) の結果(拡大)

16

まぁ普通ですね

Page 16: 関数型プログラミング入門 for Matlab ユーザー

-1 -0.5 0 0.5 1-0.6

-0.4

-0.2

0

0.2

0.4

0.6高階関数 fplot(f,xrng) の結果(拡大)

17

密適応ステップ!

Page 17: 関数型プログラミング入門 for Matlab ユーザー

18

描画する関数 f の形状に応じて適応的にステップ幅を調節しながらプロットする

fplot(f,xrng)

高階関数として実装することで,そこそこ高度なアルゴリズムを簡単かつ自然に使いまわせている点に注目

Page 18: 関数型プログラミング入門 for Matlab ユーザー

まとめ (3/5)関数型プログラミング 関数を組み合わせて処理を記述するプログラミング

パラダイム無名関数 即席で作れる使い捨ての関数高階関数 引数や返値として関数をとる関数 高度なアルゴリズムを再利用容易な形で実装する際

に便利 New

Page 19: 関数型プログラミング入門 for Matlab ユーザー

一見地味な無名関数だが高階関数を使う上では必要不可欠

例題を通して確認

To Be Continued

Page 20: 関数型プログラミング入門 for Matlab ユーザー

例題 マサチューセッツ湾交通局(MBTA)提供リアルタイムデータの可視化

バス・電車の位置情報をリアルタイムで提供!

Page 21: 関数型プログラミング入門 for Matlab ユーザー

車両位置可視化プログラムを作りたい

MBTAからのデータ取得・解釈 かっこいい可視化

• ややこしい• 面倒くさい• 誰が作っても一緒

プログラムを2つの関数に分けることにしてみよう

• かっこいい• 個性を発揮できる部分

Page 22: 関数型プログラミング入門 for Matlab ユーザー

parse_mbta_feed(visualizer)

MBTAからのデータ取得・解釈部分⇒ データの取得と解釈を行う

高階関数として実装

MBTAのサーバーにアクセスし車両情報 (車両ID,x座標,y座標) を取得する度に,引数で指定された関数 visualizer(id,x,y) を呼び出す.

Page 23: 関数型プログラミング入門 for Matlab ユーザー

id x yGreen-E 234222.4 899242.8Orange 231959.8 894831.3Orange 231900.0 894700.1Red 240703.5 889367.2:

parse_mbta_feed(...@(id,x,y) fprintf('%s\t%f\t%f\n',id,x,y));

🍜🍜 文字列で出力する可視化関数

可視化その1 ターミナルに文字列でテスト出力

ボストンの地下鉄はRed Line, Blue Line…と色で呼ばれているちなみにバスには番号が振られている

↓実行結果

退屈な部分の動作を確認!

Page 24: 関数型プログラミング入門 for Matlab ユーザー

1

1

1

10

11

111

39

39

504 5560

608

69

7

742749

749751

88

9

92

93Blue

CR-Fairmount

CR-FitchburgCR-Lowell

Green-B

Green-B

Green-B

n-B

Green-B

Green-C

Green-C

Green-C

Green-C

Green-D

Green-D

Green-D

Green-D

Green-D

Green-E

Green-E

Green-E

Green-E

Green-E

Orange

Orange

Orange

Red

Red

Red

可視化その2 地図上にテスト出力parse_mbta_feed(...

@(id,x,y) text( x, y, id, 'Color', [1,1,1]));🍜🍜グラフィカルな可視化関数,車両位置にIDを表示

Page 25: 関数型プログラミング入門 for Matlab ユーザー

1

1

1

10

11

111

111

43

504

55

608

65

9

7070

741

749

751

8388

9

92

93

BB

CR-Fitchburg

CR-Kingston

CR-Lowell

CR-Newburyport

CR-Providence

CR-Providence

GG

GG

G

G

G

G

G

G

G

G

G

G

G

G

G

G

G

O

O

O

O

RR

R

可視化その3 本番用parse_mbta_feed(@visualizer);

より手の込んだ可視化を実現する通常の関数ももちろん作れる

Page 26: 関数型プログラミング入門 for Matlab ユーザー

この例題の教訓

parse_mbta_feed(...@(id,x,y) fprintf('%s\t%f\t%f\n',id,x,y));

fprintf と text は Matlab に元からある関数.そのままで parse_mbta_feed() の引数として使えるように設計されてはいない無名関数を使うことで出来合いの関数を自作のparse_mbta_feed() と簡単に組み合わせることができたのである!

parse_mbta_feed(...@(id,x,y) text( x, y, id, 'Color', [1,1,1]));

ターミナルへの出力

地図への出力

Page 27: 関数型プログラミング入門 for Matlab ユーザー

まとめ (4/5)関数型プログラミング 関数を組み合わせて処理を記述するプログラミング

パラダイム無名関数 即席で作れる使い捨ての関数 高階関数を組み合わせる際に便利高階関数 引数や返値として関数をとる関数 高度なアルゴリズムを再利用容易な形で実装する際

に便利

New

Page 28: 関数型プログラミング入門 for Matlab ユーザー

引数 返り値

関数 Data Data

高階関数Function DataData FunctionFunction Function

Q 関数を受け取って関数を返す関数とかほんとに要るんですか?

これ!

A 必要! 次の例で…To Be Continued

Page 29: 関数型プログラミング入門 for Matlab ユーザー

高校生用の例 数値微分とある関数の導関数がほしいけど計算するのがだるい諸般の事情で得られないとき(最適化でよくある)

←微分の定義

←こんなもんでええやろ(数値微分)

𝑓𝑓 𝑡𝑡 = limΔ𝑡𝑡→0

𝑓𝑓 𝑡𝑡 + Δ𝑡𝑡 − 𝑓𝑓 𝑡𝑡Δ𝑡𝑡

≃𝑓𝑓 𝑡𝑡 + 0.001 − 𝑓𝑓(𝑡𝑡)

0.001

ある関数 𝑓𝑓 が与えられたとき,その導関数を返す高階関数を作ってみよう

Page 30: 関数型プログラミング入門 for Matlab ユーザー

dt = 0.001;d = @(f) ( @(t) (f(t+dt)-f(t))/dt );

t の関数…を返す f の関数

例 数値微分に基づいて与えられた関数の導関数を生成する高階関数

Page 31: 関数型プログラミング入門 for Matlab ユーザー

f = @(t) sin(t);fplot( d(f), [0,2*pi])

使用例 𝑓𝑓 𝑡𝑡 = sin(𝑡𝑡)の微分をプロット

当然 cos(𝑡𝑡) になる

Page 32: 関数型プログラミング入門 for Matlab ユーザー

f = @(t) sin(t);fplot( d(d(f)), [0,2*pi])

使用例 𝑓𝑓 𝑡𝑡 = sin(𝑡𝑡)の2階微分をプロット

当然 −sin(𝑡𝑡) になる

Page 33: 関数型プログラミング入門 for Matlab ユーザー

f = @(t) sin(t);fplot( d(d(d(f))), [0,2*pi])

使用例 𝑓𝑓 𝑡𝑡 = sin(𝑡𝑡)の3階微分をプロット

当然 −cos(𝑡𝑡) になる

Page 34: 関数型プログラミング入門 for Matlab ユーザー

f = @(t) sin(t);fplot( d(d(d(d(f)))), [0,2*pi])

使用例 𝑓𝑓 𝑡𝑡 = sin(𝑡𝑡)の4階微分をプロット

当然 sin(𝑡𝑡) になる

Page 35: 関数型プログラミング入門 for Matlab ユーザー

f = @(t) sin(t);fplot( d(d(d(d(d(f))))), [0,2*pi])

使用例 𝑓𝑓 𝑡𝑡 = sin(𝑡𝑡)の5階微分をプロット

当然 cos(𝑡𝑡) になる…とは限らない!

Page 36: 関数型プログラミング入門 for Matlab ユーザー

大学生用の宿題• 5階微分の数値計算結果について論ぜよ

Page 37: 関数型プログラミング入門 for Matlab ユーザー

大学生用の例 常微分方程式の離散時間化

大抵の自然法則は常微分方程式で書かれているex. Van der Pole oscillator

𝑥𝑥1(𝑡𝑡)𝑥𝑥2(𝑡𝑡) =

𝑥𝑥2(𝑡𝑡)1 − 𝑥𝑥12 𝑡𝑡 𝑥𝑥2 𝑡𝑡 − 𝑥𝑥1 𝑡𝑡

��𝒙 𝑡𝑡 = 𝒇𝒇𝐂𝐂(𝒙𝒙 𝑡𝑡 )

でも差分方程式の方が扱いやすいこともある𝒙𝒙 𝑘𝑘 + 1 ℎ = 𝒇𝒇𝐃𝐃 𝒙𝒙 𝑘𝑘ℎ

お手軽に変換 𝒇𝒇𝐂𝐂 → 𝒇𝒇𝐃𝐃 する方法があると便利!( ℎ 時間刻み )

Page 38: 関数型プログラミング入門 for Matlab ユーザー

常微分方程式の離散化を行う高階関数

function [ fd ] = c2d_euler( fc, h )function x_new = proto_fd(x)x_new = x + h*fc(x);

endfd = @proto_fd;

End

与えられた 𝑓𝑓C と ℎ に基づいてオイラー法で計算を行う関数を…

← 返す!

Page 39: 関数型プログラミング入門 for Matlab ユーザー

常微分方程式版の van der Pole oscillatorfc = @(x) [x(2); (1-x(1)^2)*x(2)-x(1)];

差分方程式版の生成h = 0.2; % h:時間刻みfd = c2d_euler(fc,h); % 簡単!

確認のために 𝒙𝒙(𝒕𝒕) の軌道を計算N = 50; x = zeros(N,2);x(1,:) = [2,0]; % 初期状態

for k=1:N-1x(k+1,:) = fd(x(k,:)');

end 結果は次のスライド

使い方

Page 40: 関数型プログラミング入門 for Matlab ユーザー

0 2 4 6 8 10t

-2.5

-2

-1.5

-1

-0.5

0

0.5

1

1.5

2

2.5x1

ContinuousDiscrete誤差が大きい!

オイラー法はさすがに安直すぎた模様

常微分方程式��𝒙 𝒕𝒕 = 𝒇𝒇𝐂𝐂 𝒙𝒙 𝒕𝒕の解

得られた差分方程式𝑥𝑥 𝑘𝑘 + 1 ℎ = 𝑓𝑓D 𝑥𝑥 𝑘𝑘ℎ

によって計算された軌道

Page 41: 関数型プログラミング入門 for Matlab ユーザー

大学生の常識 ルンゲ=クッタ法に基づく実装function [ fd ] = c2d_rk4( fc, h )

function x_new = proto_fd(x)k1 = fc(x);k2 = fc(x+h/2*k1);k3 = fc(x+h/2*k2);k4 = fc(x+h*k3);x_new = x + h/6*(k1+2*k2+2*k3+k4);

endfd=@proto;

end

fd = c2d_rk4(fc,h); % fd = c2d_euler(fc,h); ← 使い方は一緒

Page 42: 関数型プログラミング入門 for Matlab ユーザー

0 2 4 6 8 10t

-2.5

-2

-1.5

-1

-0.5

0

0.5

1

1.5

2

2.5x1

ContinuousDiscrete完全に一致!

信頼と実績のルンゲ=クッタ法

Page 43: 関数型プログラミング入門 for Matlab ユーザー

離散化手法が高階関数として分離されているために,離散化手法の変更・修正・比較が容易になっている

Page 44: 関数型プログラミング入門 for Matlab ユーザー

まとめ関数型プログラミング 関数を組み合わせて処理を記述するプログラミング

パラダイム無名関数 即席で作れる使い捨ての関数 高階関数を組み合わせる際に便利高階関数 引数や返値として関数をとる関数 高度なアルゴリズムを再利用容易な形で実装する際

に便利To Be Continued第1部 今日から役立つFP / 完

Emphasized

Page 45: 関数型プログラミング入門 for Matlab ユーザー

第2部 関数の副作用と並列処理1. map 高階関数と並列化2. ループと再帰と並列化3. reduce 高階関数と並列化4. MapReduce

※ 準備期間が一晩だったので第2部のスライドは準備が間に合いませんでした

Page 46: 関数型プログラミング入門 for Matlab ユーザー

Special Thanks to Robust Systems Lab

Northeastern University