SlideShare a Scribd company logo
1 of 27
Download to read offline
Lisp でやる記号微分って何?
渡邉慶一
Osaka, Japan
2018 年 6 月 23 日
[1/ 27]
⽬次
1 記号微分
記号微分のご紹介
記号微分処理ってどんな感じなの?
記号微分は何をしているか
記号微分手続きの説明
式の簡単化
べき乗の微分の処理を追加する
まとめ
2 数式処理ソフト:Maxima
3 iPad の MathStudio の紹介
4 SICP の紹介
[2/ 27]
記号微分とは
数値計算ではない
数式を扱う (数式を微分します)
記号を扱う (変数ですね。Lisp のシンボルを扱います)
今日やる微分は高校の微分
微分というかパターンの操作なので、話は難しくない
定数を微分すると 0 になる
x を x で微分すると 1 になる。3x を x で微分すると 3 になる
y = x2 を x で微分すると y = 2x になる
こんなルールに基いたパターンの置き換えの話です
詳しくは後に出てくる関数定義で
[3/ 27]
一番のポイント
数式を S 式で書くことにするよ
これがものすごく大きなポイントですね
いろいろ楽になります
まず字句解析が不要
それに操作に Lisp の関数がそのまま使える
中置式に変換するのはそれはそれでおもしろい
やるなら TEX の数式表記に直すとかどうでしょう
でも S 式のほうがいいですよね
[4/ 27]
お断わり
プログラム例は SICP のものを使ってます
『SICP 非公式日本語版 翻訳改訂版』
「2.3.2 例: 記号微分」(156 ページ〜162 ページ)
http://vocrf.net/docs_ja/jsicp.pdf
多少変更はしています
なので Common Lisp ではなく Scheme です (処理系は Gauche です)
でも簡単な作りなので、キーワードが多少違うだけです
この例では 2 つの項の式しか微分できません
多項式を扱うのは練習問題になってます (練習問題 2.57)
[5/ 27]
ちょっと実感をつかんでみましょう
記号微分する関数の本体です
(define (deriv exp var)
(cond (( number? exp) 0) ;; 数 値 ?
(( variable? exp) ;; 変 数 ?
(if (same-variable? exp var) 1 0)) ;; 同 じ 変 数 ?
(( sum? exp) ;; 和 の 微 分 再 帰 し て い ま す
(make-sum (deriv (addend exp) var)
(deriv (augend exp) var )))
(( product? exp) ;; 積 の 微 分 こ れ も 再 帰 し て い ま す
(make-sum
(make-product (multiplier exp)
(deriv (multiplicand exp) var))
(make-product (deriv (multiplier exp) var)
(multiplicand exp ))))
(else ;; そ れ 以 外 は エ ラ ー で す
(error "unknown␣expression␣type␣--␣DERIV" exp ))))
[6/ 27]
こんな感じで動作します (1)
gosh > (load "./ deriv.scm")
#t
gosh > (deriv ’(+ x 3) ’x)
1 ;; f (x) = x + 3 を x で 微 分 す る と 1
gosh > (deriv ’(* x y) ’x)
y ;; f (x) = xy を x で 微 分 す る と y
gosh > (deriv ’(* x y) ’y)
x ;; f (y) = xy を y で 微 分 す る と x
deriv 関数は何で微分するとか知らなくって、引数の記号で微分できると
ころがおもしろくないですか?
[7/ 27]
記号微分・記号計算のポイント
記号を記号として扱う
単なる文字列ではない
変数でもない
データに対する名前ではない
見た⽬がメモリに存在、オブジェクト
見た⽬ (=そういう名前) で参照できる「実体」がメモリにある
記号で微分・計算するので、記号を変更しても大丈夫
Lisp 以外の言語でこれを実装するとしたらどのようにやったらい
いか?
[8/ 27]
Lisp における記号微分とは
Lisp の力を発揮
他の言語だと面倒
字句解析してオブジェクトを作る
それは Lisp ですよね
Lisp はさすがに記号の処理は得意だね
微妙に再帰も使っていますね
SICP 以外の入門書では見たことがない
『Land of Lisp』にはないようだ
『初めての人のための LISP』にもな
かったと思います
『実用 Common Lisp』の第 8 章にあ
るようです
税込 9,936 円。高いね。著者の Peter Norvig さんは現在 Google の研究開発本部長。
さすが Lisper!
[9/ 27]
記号微分処理の概要:再掲
記号微分する関数の本体です
(define (deriv exp var)
(cond (( number? exp) 0) ;; 数 値 ?
(( variable? exp) ;; 変 数 ?
(if (same-variable? exp var) 1 0)) ;; 同 じ 変 数 ?
(( sum? exp) ;; 和 の 微 分 再 帰 し て い ま す
(make-sum (deriv (addend exp) var)
(deriv (augend exp) var )))
(( product? exp) ;; 積 の 微 分 こ れ も 再 帰 し て い ま す
(make-sum
(make-product (multiplier exp)
(deriv (multiplicand exp) var))
(make-product (deriv (multiplier exp) var)
(multiplicand exp ))))
(else ;; そ れ 以 外 は エ ラ ー で す
(error "unknown␣expression␣type␣--␣DERIV" exp ))))
[10/ 27]
手続きの説明 (1)
• 変数は記号である。基本述語 symbol? で識別する。
(define (variable? x) (symbol? x))
• ⼆つの変数は、それらを表現する記号が eq? であれば等しい。
(define (same-variable? v1 v2)
(and (variable? v1) (variable? v2)
(eq? v1 v2)))
• 和と積は、リストとして構築する。
(define (make-sum a1 a2) (list ’+ a1 a2))
(define (make-product m1 m2) (list ’* m1 m2))
基本的な考えはこれなんですが、これだと式をあまり簡約してくれませ
ん。たとえば make-sum で a1 が x、a2 が 0 のときは (+ x 0) となって
しまいます。そこは x という表示でいいわけで、その改良版を後で載せ
ます。
[11/ 27]
手続きの説明 (2)
• 和は、最初の要素が記号 + であるリストである。
(define (sum? x)
(and (pair? x) (eq? (car x) ’+)))
• 加数は、和のリストの⼆つ⽬の項である。
(define (addend s) (cadr s))
• 被加数は、和のリストの三つ⽬の項である。
(define (augend s) (caddr s))
例
(+ x 3)
この場合だと、先頭が+で、2 番⽬が x で、3 番⽬が 3 ということです。
[12/ 27]
手続きの説明 (3)
• 積は、最初の要素が記号 * であるリストである。
(define (product? x)
(and (pair? x) (eq? (car x) ’*)))
• 乗数は、積のリストの⼆つ⽬の項である。
(define (multiplier p) (cadr p))
• 被乗数は、積のリストの三つ⽬の項である。
(define (multiplicand p) (caddr p))
例
(* (* x y) (+ x 3))
この場合だと、先頭が*で、2 番⽬が (* x y) で、3 番⽬が (+ x 3) とい
うことです。
[13/ 27]
こんな感じで動作します (2)
改良前の構築手続きで f (x) = xy(x + 3) を x で微分するとどうなるかと
いうと...
gosh > (deriv ’(* (* x y) (+ x 3)) ’x)
(+ (* (* x y) (+ 1 0))
(* (+ (* x 0) (* 1 y)) (+ x 3)))
なんだかよくわかりません。でも和の微分と積の微分がわかれば一応
ちゃんとやっているんだということがわかります。
公式
和の微分の公式 {f (x) + g(x)} = f (x) + g (x)
公式
積の微分の公式 {f (x)g(x)} = f (x)g(x) + f (x)g (x)
[14/ 27]
こんな感じで動作します (3)
f (x) = xy、g(x) = x + 3 とすると、f (x) = y、g (x) = 1 となります。
したがって、{f (x)g(x)} = y × (x + 3) + xy × 1 です。
ここでもう一回さっきの実行結果を見てみるとわかります。
gosh > (deriv ’(* (* x y) (+ x 3)) ’x)
(+ (* (* x y) (+ 1 0))
(* (+ (* x 0) (* 1 y)) (+ x 3)))
g (x) が x の微分と 3 の微分の和で (+ 1 0) と書かれているんですね。
f (x) は xy をまた積の微分しているんです。x × y + x × y になるので、
(+ (* x 0) (* 1 y)) になってます。(y = 0、x = 1 です。)
[15/ 27]
和と積の構築手続きの改良版を使うと
和と積の構築手続きの改良版を使うと
gosh > (deriv ’(* (* x y) (+ x 3)) ’x)
(+ (* x y) (* y (+ x 3)))
と少しましになります。それでもなんか変な感じなので、付け足しの説
明をします。
f (x) = xy(x + 3) を x で微分すると
df (x)
dx = xy + y(x + 3) になります。
というのが上の手続きの結果です。
元の式を展開してから微分してみましょう。
xy(x + 3) を展開すると x2y + 3xy になります。これを x で微分すると
2xy + 3y です。
このほうがわかりやすいですよね。でもこの式は xy + y(x + 3) と書け
ます。
だから deriv 関数はちゃんと微分しているんです。
実は微分よりも式を簡単に (人間にわかりやすく) するのが難しいという
ことです。
[16/ 27]
和の構築手続きの改良版
(define (make-sum a1 a2)
(cond (( =number? a1 0) a2)
(( =number? a2 0) a1)
((and (number? a1) (number? a2))
(+ a1 a2))
(else (list ’+ a1 a2 ))))
こんな感じでどちらかが 0 だったら、もう片方を返します。
両方とも数だったら、計算しちゃいます。
どちらも変数 (シンボル) だったら、S 式の数式表現を作って返します。
あと、数値の時だけ、等しいかどうか調べる述語を使ってます。
(define (=number? exp num)
(and (number? exp) (= exp num )))
[17/ 27]
積の構築手続きの改良版
(define (make-product m1 m2)
(cond ((or (=number? m1 0) (=number? m2 0))
0)
(( =number? m1 1) m2)
(( =number? m2 1) m1)
((and (number? m1) (number? m2))
(* m1 m2))
(else (list ’* m1 m2 ))))
これも和のほうと考えは同じです。どちらかが 0 だったら、もう 0 を返
していいですよね。
あとはどっちかが 1 だったら、もう片方を返すし、どちらも数だったら
計算しちゃいます。
どっちも変数 (シンボル) のときには、S 式の数式表現を作って返します。
[18/ 27]
べき乗の微分を追加する (1)
SICP の練習問題 2.56 にあるのですが、べき乗の微分を追加してみま
しょう
(ax を x で微分するのではなく、xn を x で微分するやつです)
公式
べき乗の微分の公式 (xn) = nxn−1
べき乗の演算子を「**」にします。
(define (exponentiation? exp) ;; 先 頭 が **
(and (pair? exp) (eq? (car exp) ’**)))
(define (make-exponent a1 a2)
(cond (( =number? a1 0) 1) ;; 簡 単 化 規 則 (1)
(( =number? a2 1) a1);; 簡 単 化 規 則 (2)
(else (list ’** a1 a2 ))))
[19/ 27]
べき乗の微分を追加する (2)
(define (exponent exp) ;; 指 数 部 を 取 り 出 す
(caddr exp))
(define (base exp) ;; 基 数 部 を 取 り 出 す
(cadr exp))
あとは deriv 関数に以下の処理を加えます。
(( exponentiation? exp)
(make-product
(make-product
(exponent exp) ;; 指 数 部 (n) が 前 に 出 る
(make-exponent
(base exp)
(- (exponent exp) 1))) ;; 指 数 部 は 1 を 引 く
(deriv (base exp) var ))) ;; 基 数 部 も 微 分
[20/ 27]
べき乗の微分を追加する (3)
べき乗の処理を加えた deriv 関数
(define (deriv exp var)
(cond (( number? exp) 0) ;; 数 値 ?
(( variable? exp) ;; 変 数 ?
(if (same-variable? exp var) 1 0)) ;; 同 じ 変 数 ?
(( sum? exp) ;; 和 の 微 分 再 帰 し て い ま す
(make-sum (deriv (addend exp) var)
(deriv (augend exp) var )))
(( product? exp) ;; 積 の 微 分 こ れ も 再 帰 し て い ま す
(make-sum
(make-product (multiplier exp)
(deriv (multiplicand exp) var))
(make-product (deriv (multiplier exp) var)
(multiplicand exp ))))
(( exponentiation? exp) ;; べ き 乗 の 処 理
(make-product
(make-product
(exponent exp) ;; 指 数 部 (n) が 前 に 出 る
( make-exponent (base exp)
(- (exponent exp) 1))) ;; 指 数 部 は 1 を 引 く
(deriv (base exp) var ))) ;; 基 数 部 も 微 分
(else ;; そ れ 以 外 は エ ラ ー で す
(error "unknown␣expression␣type␣--␣DERIV" exp ))))
こんなの括弧が見えなくなれば python ですよね
もう皆さんはだいぶ括弧が見えなくなっていますよね
[21/ 27]
べき乗の微分の実行結果
gosh > (deriv ’(** x 2) ’x)
(* 2 x) ;; f (x) = x2 を 微 分 す る と 、
df (x)
dx = 2x
gosh > (deriv ’(** x 3) ’x)
(* 3 (** x 2)) ;; f (x) = x3 を 微 分 す る と 、
df (x)
dx = 3x2
[22/ 27]
まとめ
記号微分は Lisp だと原理的にはこんなに簡単
べき乗のサポートでもわかるとおり、SICP のプログラミングプロセ
スは抽象化がメイン
抽象化を進めた関数でプログラミングをしておくと拡張がきれい
抽象化は非常に強力な考え方で、SICP でマスターできるとてもよい
もの
抽象化は SICP を勉強しなくてもマスターしたほうがいい
しかし記号微分の拡張というのは、ある程度の範囲に収まるからき
れいに書けたのかもしれない (顧客要望でとんでもない拡張をする必
要はたぶんない)
結局きれいなプログラムというのはその問題をよくわかっている、
あるいはとんでもない要望がない、からできるものではないか?
[23/ 27]
Maxima と Common Lisp と iMaxima(1)
Maxima は有名な数式処理ソフト
(Common Lisp で書かれています)
iMaxima は Emacs 用のモード
出力を LATEX に通して画像にしている
のできれい
入力は Maxima のまま
数値計算もグラフも使える
電卓を使うのをやめて、Maxima か表
計算ソフトを使おう
計算式は一部「計算機基礎 A - Maxima
入門 (2)」より引用しました。
iMaxima
http://www.cc.kyoto-su.
ac.jp/~mtkg/lecture/comp_
A/2012/maxima_02.html
[24/ 27]
Maxima と Common Lisp と iMaxima(2)
iMaxima
コンソールの Maxima
これは iMaxima の機能ではなく、
Maxima 自体の機能だと思います
が、gnuplot に通してグラフも描
画できます。
-8
-6 -4
-2
	0
	2
	4
	6
	8 -8
-6
-4
-2
	0
	2
	4
	6
	8
-0.4
-0.2
	0
	0.2
	0.4
	0.6
	0.8
	1
sin(sqrt(y2
+x2
))/sqrt(y2
+x2
)
x
y
z
例は「数式処理ソフト Maxima」
http://www.kn-makkun.com/
MakkunWp/maxima.html より引用
しました。
[25/ 27]
iPad の MathStudio の紹介
iPhone/iPad に MathStudio という数学アプリがあります
もちろん微分もできます グラフも描画できます。おもし
ろいのはグリグリ動かせるんで
すよね
[26/ 27]
SICP
すばらしい教科書・入門書
日本語の翻訳もいいのが手に入る
http://vocrf.net/docs_ja/jsicp.pdf
練習問題を解かないと価値がすごく下
がる
時間のあるとき (大学生のときとかね)
にやっといたほうがいい本だと思い
ます
[27/ 27]

More Related Content

What's hot

tcolorboxによる装飾表現(TeXユーザの集い2015)
tcolorboxによる装飾表現(TeXユーザの集い2015)tcolorboxによる装飾表現(TeXユーザの集い2015)
tcolorboxによる装飾表現(TeXユーザの集い2015)TeXmedicine
 
マルチコアを用いた画像処理
マルチコアを用いた画像処理マルチコアを用いた画像処理
マルチコアを用いた画像処理Norishige Fukushima
 
グラフィカルモデル入門
グラフィカルモデル入門グラフィカルモデル入門
グラフィカルモデル入門Kawamoto_Kazuhiko
 
情報抽出入門 〜非構造化データを構造化させる技術〜
情報抽出入門 〜非構造化データを構造化させる技術〜情報抽出入門 〜非構造化データを構造化させる技術〜
情報抽出入門 〜非構造化データを構造化させる技術〜Yuya Unno
 
大規模な組合せ最適化問題に対する発見的解法
大規模な組合せ最適化問題に対する発見的解法大規模な組合せ最適化問題に対する発見的解法
大規模な組合せ最適化問題に対する発見的解法Shunji Umetani
 
組み込みでこそC++を使う10の理由
組み込みでこそC++を使う10の理由組み込みでこそC++を使う10の理由
組み込みでこそC++を使う10の理由kikairoya
 
CUDAのアセンブリ言語基礎のまとめ PTXとSASSの概説
CUDAのアセンブリ言語基礎のまとめ PTXとSASSの概説CUDAのアセンブリ言語基礎のまとめ PTXとSASSの概説
CUDAのアセンブリ言語基礎のまとめ PTXとSASSの概説Takateru Yamagishi
 
オブジェクト指向できていますか?
オブジェクト指向できていますか?オブジェクト指向できていますか?
オブジェクト指向できていますか?Moriharu Ohzu
 
ラムダ計算入門
ラムダ計算入門ラムダ計算入門
ラムダ計算入門Eita Sugimoto
 
Python 学習教材
Python 学習教材Python 学習教材
Python 学習教材Jun MITANI
 
データ解析14 ナイーブベイズ
データ解析14 ナイーブベイズデータ解析14 ナイーブベイズ
データ解析14 ナイーブベイズHirotaka Hachiya
 
Transformerを雰囲気で理解する
Transformerを雰囲気で理解するTransformerを雰囲気で理解する
Transformerを雰囲気で理解するAtsukiYamaguchi1
 
Tensor コアを使った PyTorch の高速化
Tensor コアを使った PyTorch の高速化Tensor コアを使った PyTorch の高速化
Tensor コアを使った PyTorch の高速化Yusuke Fujimoto
 
僕がつくった 70個のうちの48個のWebサービス達
僕がつくった 70個のうちの48個のWebサービス達僕がつくった 70個のうちの48個のWebサービス達
僕がつくった 70個のうちの48個のWebサービス達Yusuke Wada
 
「日本語LaTeX」が多すぎる件について
「日本語LaTeX」が多すぎる件について「日本語LaTeX」が多すぎる件について
「日本語LaTeX」が多すぎる件についてTakayuki Yato
 
形態素解析の過去・現在・未来
形態素解析の過去・現在・未来形態素解析の過去・現在・未来
形態素解析の過去・現在・未来Preferred Networks
 
constexpr関数はコンパイル時処理。これはいい。実行時が霞んで見える。cpuの嬌声が聞こえてきそうだ
constexpr関数はコンパイル時処理。これはいい。実行時が霞んで見える。cpuの嬌声が聞こえてきそうだconstexpr関数はコンパイル時処理。これはいい。実行時が霞んで見える。cpuの嬌声が聞こえてきそうだ
constexpr関数はコンパイル時処理。これはいい。実行時が霞んで見える。cpuの嬌声が聞こえてきそうだGenya Murakami
 

What's hot (20)

tcolorboxによる装飾表現(TeXユーザの集い2015)
tcolorboxによる装飾表現(TeXユーザの集い2015)tcolorboxによる装飾表現(TeXユーザの集い2015)
tcolorboxによる装飾表現(TeXユーザの集い2015)
 
マルチコアを用いた画像処理
マルチコアを用いた画像処理マルチコアを用いた画像処理
マルチコアを用いた画像処理
 
NumPy闇入門
NumPy闇入門NumPy闇入門
NumPy闇入門
 
グラフィカルモデル入門
グラフィカルモデル入門グラフィカルモデル入門
グラフィカルモデル入門
 
情報抽出入門 〜非構造化データを構造化させる技術〜
情報抽出入門 〜非構造化データを構造化させる技術〜情報抽出入門 〜非構造化データを構造化させる技術〜
情報抽出入門 〜非構造化データを構造化させる技術〜
 
大規模な組合せ最適化問題に対する発見的解法
大規模な組合せ最適化問題に対する発見的解法大規模な組合せ最適化問題に対する発見的解法
大規模な組合せ最適化問題に対する発見的解法
 
組み込みでこそC++を使う10の理由
組み込みでこそC++を使う10の理由組み込みでこそC++を使う10の理由
組み込みでこそC++を使う10の理由
 
プログラムを高速化する話
プログラムを高速化する話プログラムを高速化する話
プログラムを高速化する話
 
CUDAのアセンブリ言語基礎のまとめ PTXとSASSの概説
CUDAのアセンブリ言語基礎のまとめ PTXとSASSの概説CUDAのアセンブリ言語基礎のまとめ PTXとSASSの概説
CUDAのアセンブリ言語基礎のまとめ PTXとSASSの概説
 
オブジェクト指向できていますか?
オブジェクト指向できていますか?オブジェクト指向できていますか?
オブジェクト指向できていますか?
 
ラムダ計算入門
ラムダ計算入門ラムダ計算入門
ラムダ計算入門
 
Python 学習教材
Python 学習教材Python 学習教材
Python 学習教材
 
データ解析14 ナイーブベイズ
データ解析14 ナイーブベイズデータ解析14 ナイーブベイズ
データ解析14 ナイーブベイズ
 
Transformerを雰囲気で理解する
Transformerを雰囲気で理解するTransformerを雰囲気で理解する
Transformerを雰囲気で理解する
 
Tensor コアを使った PyTorch の高速化
Tensor コアを使った PyTorch の高速化Tensor コアを使った PyTorch の高速化
Tensor コアを使った PyTorch の高速化
 
BERT+XLNet+RoBERTa
BERT+XLNet+RoBERTaBERT+XLNet+RoBERTa
BERT+XLNet+RoBERTa
 
僕がつくった 70個のうちの48個のWebサービス達
僕がつくった 70個のうちの48個のWebサービス達僕がつくった 70個のうちの48個のWebサービス達
僕がつくった 70個のうちの48個のWebサービス達
 
「日本語LaTeX」が多すぎる件について
「日本語LaTeX」が多すぎる件について「日本語LaTeX」が多すぎる件について
「日本語LaTeX」が多すぎる件について
 
形態素解析の過去・現在・未来
形態素解析の過去・現在・未来形態素解析の過去・現在・未来
形態素解析の過去・現在・未来
 
constexpr関数はコンパイル時処理。これはいい。実行時が霞んで見える。cpuの嬌声が聞こえてきそうだ
constexpr関数はコンパイル時処理。これはいい。実行時が霞んで見える。cpuの嬌声が聞こえてきそうだconstexpr関数はコンパイル時処理。これはいい。実行時が霞んで見える。cpuの嬌声が聞こえてきそうだ
constexpr関数はコンパイル時処理。これはいい。実行時が霞んで見える。cpuの嬌声が聞こえてきそうだ
 

Similar to Lispでやる記号微分

モナドハンズオン前座
モナドハンズオン前座モナドハンズオン前座
モナドハンズオン前座bleis tift
 
VBAで数値計算 03 数式実装パターン
VBAで数値計算 03 数式実装パターンVBAで数値計算 03 数式実装パターン
VBAで数値計算 03 数式実装パターンKatsuhiro Morishita
 
2011年11月11日
2011年11月11日2011年11月11日
2011年11月11日nukaemon
 
数式をnumpyに落としこむコツ
数式をnumpyに落としこむコツ数式をnumpyに落としこむコツ
数式をnumpyに落としこむコツShuyo Nakatani
 
関数型言語&形式的手法セミナー(3)
関数型言語&形式的手法セミナー(3)関数型言語&形式的手法セミナー(3)
関数型言語&形式的手法セミナー(3)啓 小笠原
 
化学科自主ゼミ1
化学科自主ゼミ1化学科自主ゼミ1
化学科自主ゼミ1Hiroki Sato
 
(define)なしで再帰関数を定義する
(define)なしで再帰関数を定義する(define)なしで再帰関数を定義する
(define)なしで再帰関数を定義するblackenedgold
 
Lisp tutorial for Pythonista : Day 2
Lisp tutorial for Pythonista : Day 2Lisp tutorial for Pythonista : Day 2
Lisp tutorial for Pythonista : Day 2Ransui Iso
 
kagamicomput201707
kagamicomput201707kagamicomput201707
kagamicomput201707swkagami
 
Material
MaterialMaterial
Material_TUNE_
 
関数型都市忘年会『はじめての函数型プログラミング』
関数型都市忘年会『はじめての函数型プログラミング』関数型都市忘年会『はじめての函数型プログラミング』
関数型都市忘年会『はじめての函数型プログラミング』Kenta USAMI
 
JSX / Haxe / TypeScript
JSX / Haxe / TypeScriptJSX / Haxe / TypeScript
JSX / Haxe / TypeScriptbleis tift
 
データとは何か
データとは何かデータとは何か
データとは何かKenta Suzuki
 
命令プログラミングから関数プログラミングへ
命令プログラミングから関数プログラミングへ命令プログラミングから関数プログラミングへ
命令プログラミングから関数プログラミングへNaoki Kitora
 
Java数値(浮動小数点)課題勉強会
Java数値(浮動小数点)課題勉強会Java数値(浮動小数点)課題勉強会
Java数値(浮動小数点)課題勉強会Tetsuya Yoshida
 
言語処理系入門€5
言語処理系入門€5言語処理系入門€5
言語処理系入門€5Kenta Hattori
 
プログラミング
プログラミングプログラミング
プログラミングsaireya _
 
kagami_comput2015_7
kagami_comput2015_7kagami_comput2015_7
kagami_comput2015_7swkagami
 

Similar to Lispでやる記号微分 (20)

たのしい関数型
たのしい関数型たのしい関数型
たのしい関数型
 
モナドハンズオン前座
モナドハンズオン前座モナドハンズオン前座
モナドハンズオン前座
 
VBAで数値計算 03 数式実装パターン
VBAで数値計算 03 数式実装パターンVBAで数値計算 03 数式実装パターン
VBAで数値計算 03 数式実装パターン
 
2011年11月11日
2011年11月11日2011年11月11日
2011年11月11日
 
数式をnumpyに落としこむコツ
数式をnumpyに落としこむコツ数式をnumpyに落としこむコツ
数式をnumpyに落としこむコツ
 
関数型言語&形式的手法セミナー(3)
関数型言語&形式的手法セミナー(3)関数型言語&形式的手法セミナー(3)
関数型言語&形式的手法セミナー(3)
 
化学科自主ゼミ1
化学科自主ゼミ1化学科自主ゼミ1
化学科自主ゼミ1
 
(define)なしで再帰関数を定義する
(define)なしで再帰関数を定義する(define)なしで再帰関数を定義する
(define)なしで再帰関数を定義する
 
Lisp tutorial for Pythonista : Day 2
Lisp tutorial for Pythonista : Day 2Lisp tutorial for Pythonista : Day 2
Lisp tutorial for Pythonista : Day 2
 
kagamicomput201707
kagamicomput201707kagamicomput201707
kagamicomput201707
 
Material
MaterialMaterial
Material
 
関数型都市忘年会『はじめての函数型プログラミング』
関数型都市忘年会『はじめての函数型プログラミング』関数型都市忘年会『はじめての函数型プログラミング』
関数型都市忘年会『はじめての函数型プログラミング』
 
#6:実数と繰り返し
#6:実数と繰り返し#6:実数と繰り返し
#6:実数と繰り返し
 
JSX / Haxe / TypeScript
JSX / Haxe / TypeScriptJSX / Haxe / TypeScript
JSX / Haxe / TypeScript
 
データとは何か
データとは何かデータとは何か
データとは何か
 
命令プログラミングから関数プログラミングへ
命令プログラミングから関数プログラミングへ命令プログラミングから関数プログラミングへ
命令プログラミングから関数プログラミングへ
 
Java数値(浮動小数点)課題勉強会
Java数値(浮動小数点)課題勉強会Java数値(浮動小数点)課題勉強会
Java数値(浮動小数点)課題勉強会
 
言語処理系入門€5
言語処理系入門€5言語処理系入門€5
言語処理系入門€5
 
プログラミング
プログラミングプログラミング
プログラミング
 
kagami_comput2015_7
kagami_comput2015_7kagami_comput2015_7
kagami_comput2015_7
 

Lispでやる記号微分

  • 3. 記号微分とは 数値計算ではない 数式を扱う (数式を微分します) 記号を扱う (変数ですね。Lisp のシンボルを扱います) 今日やる微分は高校の微分 微分というかパターンの操作なので、話は難しくない 定数を微分すると 0 になる x を x で微分すると 1 になる。3x を x で微分すると 3 になる y = x2 を x で微分すると y = 2x になる こんなルールに基いたパターンの置き換えの話です 詳しくは後に出てくる関数定義で [3/ 27]
  • 4. 一番のポイント 数式を S 式で書くことにするよ これがものすごく大きなポイントですね いろいろ楽になります まず字句解析が不要 それに操作に Lisp の関数がそのまま使える 中置式に変換するのはそれはそれでおもしろい やるなら TEX の数式表記に直すとかどうでしょう でも S 式のほうがいいですよね [4/ 27]
  • 5. お断わり プログラム例は SICP のものを使ってます 『SICP 非公式日本語版 翻訳改訂版』 「2.3.2 例: 記号微分」(156 ページ〜162 ページ) http://vocrf.net/docs_ja/jsicp.pdf 多少変更はしています なので Common Lisp ではなく Scheme です (処理系は Gauche です) でも簡単な作りなので、キーワードが多少違うだけです この例では 2 つの項の式しか微分できません 多項式を扱うのは練習問題になってます (練習問題 2.57) [5/ 27]
  • 6. ちょっと実感をつかんでみましょう 記号微分する関数の本体です (define (deriv exp var) (cond (( number? exp) 0) ;; 数 値 ? (( variable? exp) ;; 変 数 ? (if (same-variable? exp var) 1 0)) ;; 同 じ 変 数 ? (( sum? exp) ;; 和 の 微 分 再 帰 し て い ま す (make-sum (deriv (addend exp) var) (deriv (augend exp) var ))) (( product? exp) ;; 積 の 微 分 こ れ も 再 帰 し て い ま す (make-sum (make-product (multiplier exp) (deriv (multiplicand exp) var)) (make-product (deriv (multiplier exp) var) (multiplicand exp )))) (else ;; そ れ 以 外 は エ ラ ー で す (error "unknown␣expression␣type␣--␣DERIV" exp )))) [6/ 27]
  • 7. こんな感じで動作します (1) gosh > (load "./ deriv.scm") #t gosh > (deriv ’(+ x 3) ’x) 1 ;; f (x) = x + 3 を x で 微 分 す る と 1 gosh > (deriv ’(* x y) ’x) y ;; f (x) = xy を x で 微 分 す る と y gosh > (deriv ’(* x y) ’y) x ;; f (y) = xy を y で 微 分 す る と x deriv 関数は何で微分するとか知らなくって、引数の記号で微分できると ころがおもしろくないですか? [7/ 27]
  • 9. Lisp における記号微分とは Lisp の力を発揮 他の言語だと面倒 字句解析してオブジェクトを作る それは Lisp ですよね Lisp はさすがに記号の処理は得意だね 微妙に再帰も使っていますね SICP 以外の入門書では見たことがない 『Land of Lisp』にはないようだ 『初めての人のための LISP』にもな かったと思います 『実用 Common Lisp』の第 8 章にあ るようです 税込 9,936 円。高いね。著者の Peter Norvig さんは現在 Google の研究開発本部長。 さすが Lisper! [9/ 27]
  • 10. 記号微分処理の概要:再掲 記号微分する関数の本体です (define (deriv exp var) (cond (( number? exp) 0) ;; 数 値 ? (( variable? exp) ;; 変 数 ? (if (same-variable? exp var) 1 0)) ;; 同 じ 変 数 ? (( sum? exp) ;; 和 の 微 分 再 帰 し て い ま す (make-sum (deriv (addend exp) var) (deriv (augend exp) var ))) (( product? exp) ;; 積 の 微 分 こ れ も 再 帰 し て い ま す (make-sum (make-product (multiplier exp) (deriv (multiplicand exp) var)) (make-product (deriv (multiplier exp) var) (multiplicand exp )))) (else ;; そ れ 以 外 は エ ラ ー で す (error "unknown␣expression␣type␣--␣DERIV" exp )))) [10/ 27]
  • 11. 手続きの説明 (1) • 変数は記号である。基本述語 symbol? で識別する。 (define (variable? x) (symbol? x)) • ⼆つの変数は、それらを表現する記号が eq? であれば等しい。 (define (same-variable? v1 v2) (and (variable? v1) (variable? v2) (eq? v1 v2))) • 和と積は、リストとして構築する。 (define (make-sum a1 a2) (list ’+ a1 a2)) (define (make-product m1 m2) (list ’* m1 m2)) 基本的な考えはこれなんですが、これだと式をあまり簡約してくれませ ん。たとえば make-sum で a1 が x、a2 が 0 のときは (+ x 0) となって しまいます。そこは x という表示でいいわけで、その改良版を後で載せ ます。 [11/ 27]
  • 12. 手続きの説明 (2) • 和は、最初の要素が記号 + であるリストである。 (define (sum? x) (and (pair? x) (eq? (car x) ’+))) • 加数は、和のリストの⼆つ⽬の項である。 (define (addend s) (cadr s)) • 被加数は、和のリストの三つ⽬の項である。 (define (augend s) (caddr s)) 例 (+ x 3) この場合だと、先頭が+で、2 番⽬が x で、3 番⽬が 3 ということです。 [12/ 27]
  • 13. 手続きの説明 (3) • 積は、最初の要素が記号 * であるリストである。 (define (product? x) (and (pair? x) (eq? (car x) ’*))) • 乗数は、積のリストの⼆つ⽬の項である。 (define (multiplier p) (cadr p)) • 被乗数は、積のリストの三つ⽬の項である。 (define (multiplicand p) (caddr p)) 例 (* (* x y) (+ x 3)) この場合だと、先頭が*で、2 番⽬が (* x y) で、3 番⽬が (+ x 3) とい うことです。 [13/ 27]
  • 14. こんな感じで動作します (2) 改良前の構築手続きで f (x) = xy(x + 3) を x で微分するとどうなるかと いうと... gosh > (deriv ’(* (* x y) (+ x 3)) ’x) (+ (* (* x y) (+ 1 0)) (* (+ (* x 0) (* 1 y)) (+ x 3))) なんだかよくわかりません。でも和の微分と積の微分がわかれば一応 ちゃんとやっているんだということがわかります。 公式 和の微分の公式 {f (x) + g(x)} = f (x) + g (x) 公式 積の微分の公式 {f (x)g(x)} = f (x)g(x) + f (x)g (x) [14/ 27]
  • 15. こんな感じで動作します (3) f (x) = xy、g(x) = x + 3 とすると、f (x) = y、g (x) = 1 となります。 したがって、{f (x)g(x)} = y × (x + 3) + xy × 1 です。 ここでもう一回さっきの実行結果を見てみるとわかります。 gosh > (deriv ’(* (* x y) (+ x 3)) ’x) (+ (* (* x y) (+ 1 0)) (* (+ (* x 0) (* 1 y)) (+ x 3))) g (x) が x の微分と 3 の微分の和で (+ 1 0) と書かれているんですね。 f (x) は xy をまた積の微分しているんです。x × y + x × y になるので、 (+ (* x 0) (* 1 y)) になってます。(y = 0、x = 1 です。) [15/ 27]
  • 16. 和と積の構築手続きの改良版を使うと 和と積の構築手続きの改良版を使うと gosh > (deriv ’(* (* x y) (+ x 3)) ’x) (+ (* x y) (* y (+ x 3))) と少しましになります。それでもなんか変な感じなので、付け足しの説 明をします。 f (x) = xy(x + 3) を x で微分すると df (x) dx = xy + y(x + 3) になります。 というのが上の手続きの結果です。 元の式を展開してから微分してみましょう。 xy(x + 3) を展開すると x2y + 3xy になります。これを x で微分すると 2xy + 3y です。 このほうがわかりやすいですよね。でもこの式は xy + y(x + 3) と書け ます。 だから deriv 関数はちゃんと微分しているんです。 実は微分よりも式を簡単に (人間にわかりやすく) するのが難しいという ことです。 [16/ 27]
  • 17. 和の構築手続きの改良版 (define (make-sum a1 a2) (cond (( =number? a1 0) a2) (( =number? a2 0) a1) ((and (number? a1) (number? a2)) (+ a1 a2)) (else (list ’+ a1 a2 )))) こんな感じでどちらかが 0 だったら、もう片方を返します。 両方とも数だったら、計算しちゃいます。 どちらも変数 (シンボル) だったら、S 式の数式表現を作って返します。 あと、数値の時だけ、等しいかどうか調べる述語を使ってます。 (define (=number? exp num) (and (number? exp) (= exp num ))) [17/ 27]
  • 18. 積の構築手続きの改良版 (define (make-product m1 m2) (cond ((or (=number? m1 0) (=number? m2 0)) 0) (( =number? m1 1) m2) (( =number? m2 1) m1) ((and (number? m1) (number? m2)) (* m1 m2)) (else (list ’* m1 m2 )))) これも和のほうと考えは同じです。どちらかが 0 だったら、もう 0 を返 していいですよね。 あとはどっちかが 1 だったら、もう片方を返すし、どちらも数だったら 計算しちゃいます。 どっちも変数 (シンボル) のときには、S 式の数式表現を作って返します。 [18/ 27]
  • 19. べき乗の微分を追加する (1) SICP の練習問題 2.56 にあるのですが、べき乗の微分を追加してみま しょう (ax を x で微分するのではなく、xn を x で微分するやつです) 公式 べき乗の微分の公式 (xn) = nxn−1 べき乗の演算子を「**」にします。 (define (exponentiation? exp) ;; 先 頭 が ** (and (pair? exp) (eq? (car exp) ’**))) (define (make-exponent a1 a2) (cond (( =number? a1 0) 1) ;; 簡 単 化 規 則 (1) (( =number? a2 1) a1);; 簡 単 化 規 則 (2) (else (list ’** a1 a2 )))) [19/ 27]
  • 20. べき乗の微分を追加する (2) (define (exponent exp) ;; 指 数 部 を 取 り 出 す (caddr exp)) (define (base exp) ;; 基 数 部 を 取 り 出 す (cadr exp)) あとは deriv 関数に以下の処理を加えます。 (( exponentiation? exp) (make-product (make-product (exponent exp) ;; 指 数 部 (n) が 前 に 出 る (make-exponent (base exp) (- (exponent exp) 1))) ;; 指 数 部 は 1 を 引 く (deriv (base exp) var ))) ;; 基 数 部 も 微 分 [20/ 27]
  • 21. べき乗の微分を追加する (3) べき乗の処理を加えた deriv 関数 (define (deriv exp var) (cond (( number? exp) 0) ;; 数 値 ? (( variable? exp) ;; 変 数 ? (if (same-variable? exp var) 1 0)) ;; 同 じ 変 数 ? (( sum? exp) ;; 和 の 微 分 再 帰 し て い ま す (make-sum (deriv (addend exp) var) (deriv (augend exp) var ))) (( product? exp) ;; 積 の 微 分 こ れ も 再 帰 し て い ま す (make-sum (make-product (multiplier exp) (deriv (multiplicand exp) var)) (make-product (deriv (multiplier exp) var) (multiplicand exp )))) (( exponentiation? exp) ;; べ き 乗 の 処 理 (make-product (make-product (exponent exp) ;; 指 数 部 (n) が 前 に 出 る ( make-exponent (base exp) (- (exponent exp) 1))) ;; 指 数 部 は 1 を 引 く (deriv (base exp) var ))) ;; 基 数 部 も 微 分 (else ;; そ れ 以 外 は エ ラ ー で す (error "unknown␣expression␣type␣--␣DERIV" exp )))) こんなの括弧が見えなくなれば python ですよね もう皆さんはだいぶ括弧が見えなくなっていますよね [21/ 27]
  • 22. べき乗の微分の実行結果 gosh > (deriv ’(** x 2) ’x) (* 2 x) ;; f (x) = x2 を 微 分 す る と 、 df (x) dx = 2x gosh > (deriv ’(** x 3) ’x) (* 3 (** x 2)) ;; f (x) = x3 を 微 分 す る と 、 df (x) dx = 3x2 [22/ 27]
  • 23. まとめ 記号微分は Lisp だと原理的にはこんなに簡単 べき乗のサポートでもわかるとおり、SICP のプログラミングプロセ スは抽象化がメイン 抽象化を進めた関数でプログラミングをしておくと拡張がきれい 抽象化は非常に強力な考え方で、SICP でマスターできるとてもよい もの 抽象化は SICP を勉強しなくてもマスターしたほうがいい しかし記号微分の拡張というのは、ある程度の範囲に収まるからき れいに書けたのかもしれない (顧客要望でとんでもない拡張をする必 要はたぶんない) 結局きれいなプログラムというのはその問題をよくわかっている、 あるいはとんでもない要望がない、からできるものではないか? [23/ 27]
  • 24. Maxima と Common Lisp と iMaxima(1) Maxima は有名な数式処理ソフト (Common Lisp で書かれています) iMaxima は Emacs 用のモード 出力を LATEX に通して画像にしている のできれい 入力は Maxima のまま 数値計算もグラフも使える 電卓を使うのをやめて、Maxima か表 計算ソフトを使おう 計算式は一部「計算機基礎 A - Maxima 入門 (2)」より引用しました。 iMaxima http://www.cc.kyoto-su. ac.jp/~mtkg/lecture/comp_ A/2012/maxima_02.html [24/ 27]
  • 25. Maxima と Common Lisp と iMaxima(2) iMaxima コンソールの Maxima これは iMaxima の機能ではなく、 Maxima 自体の機能だと思います が、gnuplot に通してグラフも描 画できます。 -8 -6 -4 -2 0 2 4 6 8 -8 -6 -4 -2 0 2 4 6 8 -0.4 -0.2 0 0.2 0.4 0.6 0.8 1 sin(sqrt(y2 +x2 ))/sqrt(y2 +x2 ) x y z 例は「数式処理ソフト Maxima」 http://www.kn-makkun.com/ MakkunWp/maxima.html より引用 しました。 [25/ 27]
  • 26. iPad の MathStudio の紹介 iPhone/iPad に MathStudio という数学アプリがあります もちろん微分もできます グラフも描画できます。おもし ろいのはグリグリ動かせるんで すよね [26/ 27]