次のF#サンプルに出くわし、興味をそそられました。
http://www.codeproject.com/KB/net-languages/SymbolicCalcInFS.aspx
Clojureには、このようなことを簡単に行うための言語/ライブラリ機能がありますか?数式が簡単になる場合は、数式にポーランド記法を強制してもかまいません。
ありがとう、そして質問があれば私に知らせてください。
次のF#サンプルに出くわし、興味をそそられました。
http://www.codeproject.com/KB/net-languages/SymbolicCalcInFS.aspx
Clojureには、このようなことを簡単に行うための言語/ライブラリ機能がありますか?数式が簡単になる場合は、数式にポーランド記法を強制してもかまいません。
ありがとう、そして質問があれば私に知らせてください。
Lispは記号計算において長い歴史があります。PeterNorvigによるAIケーススタディブックを参照してください。Lispは、シンボルに対する一般的な操作を抽象化するための多くの優れた言語機能を提供します。本当に簡潔なコード(F#よりも簡潔/短い)を記述できる場合もあります。
F#のような静的言語には、強力な型システムとデータ型の便利なパターンマッチングがあります。コンパイラーは、型システムによってキャッチされたエラーを見つける可能性があります。たとえば、1つの特殊なケースを考慮していない場合などです。データの型について考えることで、ランタイムエラーの可能性を減らすこともできます。F#での型推論も、F#コードを非常に簡潔にします。
私は Clojure についてあまり知りませんが、少なくともいくつかの指針を示します。
F# コードを優れたものにする重要な機能は、代数データ型でのパターン マッチングです。代数データ型は、たとえば型の宣言(数式を表すために使用される) であり、パターン マッチングは、単純化または微分を実装するときにさまざまな既知のケースをチェックするために使用される構造です。Expression
match
Clojure にパターン マッチングのサポートが組み込まれているとは思いませんが、ライブラリとして実装できます。非常に興味深いライブラリの 1 つは、(Clojars の)パターン マッチ モジュールです。これを使用して代数エバリュエーターを実装する例を次に示します(これは F# の記事に非常に近いものです)。
F# の記事に登場するもう 1 つのことは、アクティブ パターン(パターンを宣言して再利用できるようにするもの) です。そのための Clojure ライブラリはないと思いますが、言語の柔軟性を考えると、それらも実装できるはずです (ただし、F# の記事ではそれほど必要ではありません)。
記号微分は、Lisp の最初のアプリケーションの 1 つです。
単純なシンボリック微分器についてのブログ投稿を作成しました。+ と * のみを扱いますが、簡単に拡張できます。
これは、ロンドンで開催された会議で初心者に clojure を紹介するために書いたシリーズの一部であり、clojure が独自のコードを操作するのがいかに簡単かを示すためのものでした。
もちろん、すばらしいことは、微分を行った後、コードをコンパイルできることです! したがって、ユーザー入力の差別化されたバージョン、または関数とその派生物などを生成するマクロを生成できます。
オリジナルはここにあり、構文が強調表示されています。
http://www.learningclojure.com/2010/02/clojure-dojo-4-symbolic-differentiation.html
しかし、ここにコードを投稿しましたので、ご覧ください。
;; The simplest possible symbolic differentiator
;; Functions to create and unpack additions like (+ 1 2)
(defn make-add [ a b ] (list '+ a b))
(defn addition? [x] (and (=(count x) 3) (= (first x) '+)))
(defn add1 [x] (second x))
(defn add2 [x] (second (rest x)))
;; Similar for multiplications (* 1 2)
(defn make-mul [ a b ] (list '* a b))
(defn multiplication? [x] (and (=(count x) 3) (= (first x) '*)))
(defn mul1 [x] (second x))
(defn mul2 [x] (second (rest x)))
;; Differentiation.
(defn deriv [exp var]
(cond (number? exp) 0 ;; d/dx c -> 0
(symbol? exp) (if (= exp var) 1 0) ;; d/dx x -> 1, d/dx y -> 0
(addition? exp) (make-add (deriv (add1 exp) var) (deriv (add2 exp) var)) ;; d/dx a+b -> d/dx a + d/dx b
(multiplication? exp) (make-add (make-mul (deriv (mul1 exp) var) (mul2 exp)) ;; d/dx a*b -> d/dx a * b + a * d/dx b
(make-mul (mul1 exp) (deriv (mul2 exp) var)))
:else :error))
;;an example of use: create the function x -> x^3 + 2x^2 + 1 and its derivative
(def poly '(+ (+ (* x (* x x)) (* 2 (* x x))) 1))
(defn poly->fnform [poly] (list 'fn '[x] poly))
(def polyfn (eval (poly->fnform poly)))
(def dpolyfn (eval (poly->fnform (deriv poly 'x))))
;;tests
(use 'clojure.test)
(deftest deriv-test
(testing "binary operators"
(is (= (let [m '(* a b)] [(multiplication? m) (make-mul (mul1 m) (mul2 m))]) [true '(* a b)]))
(is (= (let [m '(* a b)] [(addition? m) (make-add (add1 m) (add2 m))]) [false '(+ a b)])))
(testing "derivative function"
(is (= (deriv '0 'x) '0))
(is (= (deriv '1 'x) '0))
(is (= (deriv 'x 'x) '1))
(is (= (deriv 'y 'x) '0))
(is (= (deriv '(+ x x) 'x) '(+ 1 1)))
(is (= (deriv '(* x x) 'x) '(+ (* 1 x) (* x 1))))
(is (= (deriv '(* x x) 'y) '(+ (* 0 x) (* x 0))))
(is (= (deriv '(* x (* x x)) 'x) '(+ (* 1 (* x x)) (* x (+ (* 1 x) (* x 1)))))))
(testing "function creation: d/dx (x^3 + 2x^2 + 1) = 3x^2 + 4x "
(let [poly '(+ (+ (* x (* x x)) (* 2 (* x x))) 1)]
(is (= ((eval (poly->fnform poly)) 3) 46))
(is (= ((eval (poly->fnform (deriv poly 'x))) 3))))))
試したことはありませんが、Clojuratecaは非常に興味深いようです。
さて、Clojure は強力なパターン マッチング ライブラリを提供します。