我遇到了以下 F# 示例,发现它很有趣。
http://www.codeproject.com/KB/net-languages/SymbolicCalcInFS.aspx
Clojure 是否有语言/库工具可以轻松地做这样的事情?可以对公式强制使用波兰表示法,如果这会使事情变得更容易。
谢谢,如果有问题请告诉我。
我遇到了以下 F# 示例,发现它很有趣。
http://www.codeproject.com/KB/net-languages/SymbolicCalcInFS.aspx
Clojure 是否有语言/库工具可以轻松地做这样的事情?可以对公式强制使用波兰表示法,如果这会使事情变得更容易。
谢谢,如果有问题请告诉我。
Lisp 在符号计算方面有着悠久的历史。请参阅Peter Norvig的 AI 案例研究书。Lisp 提供了很多很棒的语言特性来抽象符号上的常用操作。有时您可以编写非常简洁的代码(比 F# 更简洁/简短)。
像 F# 这样的静态语言具有强大的类型系统和方便的数据类型模式匹配。编译器可以发现类型系统捕获的错误,例如没有考虑一种特殊情况。考虑数据的类型也可以减少运行时错误的机会。F# 中的类型推断也使得 F# 代码非常简洁。
我对 Clojure 了解不多,但至少这里有一些指针。
使 F# 代码良好的关键特性是代数数据类型的模式匹配。例如,代数数据类型是类型的声明(用于表示数学表达式),模式匹配是用于在实现简化或微分时检查各种已知情况的构造。Expression
match
我不认为 Clojure 有任何对模式匹配的内置支持,但它可以作为一个库来实现。一个看起来很有趣的库是模式匹配模块(在 Clojars 中)。这是一个使用它来实现代数求值器的示例(与 F# 文章非常接近)。
F# 文章中出现的另一件事是活动模式(它允许您声明和重用模式)。我不认为有一个 Clojure 库可以做到这一点,但考虑到语言的灵活性,应该也可以实现它们(但是,在 F# 文章中它们并不是真正必要的)
符号微分是 lisp 的首批应用之一!
我写了一篇关于一个简单的符号微分器的博文。它只处理 + 和 *,但它很容易扩展。
这是我在伦敦的一次会议上向初学者介绍 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))))))
我没试过,但Clojuratica看起来很有趣。
好吧,现在 Clojure 提供了强大的模式匹配库:
是的,像您描述的系统现在存在于 Clojure 上!它是 Gerry Sussman 的伴侣系统,他的 -and Wisdom 的 - SICM(经典力学的结构和解释)一书。对于 Clojure,它被命名为sicmutils,并由 Colin Smith 移植。
我已经在别处简要描述了它 - https://stackoverflow.com/a/41646455/4070712 - 但简而言之,是的,它确实做了你 F# 文章提到的四件事,即。
还有很多很多...
1)微分(支持全偏微分)
> (defn ff [x y] (* (expt x 3)(expt y 5)))
> ((D ff) 'x 'y) ==> (down (* 3 (expt x 2) (expt y 5)) (* 5 (expt x 3) (expt y 4)))
> ;; i.e. vector of results wrt to both variables
注意。支持两种类型的向量,“向上”和“向下”以适应协变和逆变表达式
2)表达式的简化:哦,是的......
> (def unity (+ (square sin) (square cos)))
> (unity 'x) ==> 1 ;; yes we can deal with symbols
3) 格式化:表达式可以在 TeX 中呈现,以便显示美观。我不能在这里简单地展示这一点,但目前正在开发 Maple 风格的笔记本/workshhet,使用 Clojure 的“Gorilla”
4)解析:显然。表达式和函数之间的转换是系统的核心部分。
看看https://github.com/littleredcomputer/sicmutils。你甚至不需要 Clojure 来运行它,你可以使用提供的 Java jar 文件。