Clojure与F#中的符号数学计算

时间:2010-10-03 23:45:12

标签: f# clojure symbolic-math

我遇到了以下F#样本,发现它很有趣。

http://www.codeproject.com/KB/net-languages/SymbolicCalcInFS.aspx

Clojure是否有语言/图书馆设施可以轻松完成这样的事情?如果能让事情变得更容易,可以强制使用波兰语表示公式。

谢谢,如果有问题,请告诉我。

6 个答案:

答案 0 :(得分:6)

我对Clojure知之甚少,但至少有一些指示。

使F#代码更好的关键特性是代数数据类型上的模式匹配。代数数据类型例如是Expression类型的声明(用于表示数学表达式),模式匹配是match构造,用于在实现简化时检查各种已知情况或分化。

我不认为Clojure对模式匹配有任何内置支持,但它可以作为库实现。一个看起来很有趣的库是patter-match module(在Clojars中)。这是一个使用它的例子to implement algebraic evaluator(这与F#文章非常接近)。

F#文章中出现的另一件事是活动模式(允许您声明和重用模式)。我不认为有一个Clojure库,但考虑到语言的灵活性,也应该可以实现它们(但是,它们在F#文章中并不是真正必要的)

答案 1 :(得分:6)

Lisp在符号计算方面有着悠久的历史。见Peter Norvig的the AI case study book。 Lisp提供了许多很棒的语言功能来抽象符号上的常见操作。有时您可以编写非常简洁的代码(比F#更简洁/更简洁)。

像F#这样的静态语言具有强类型系统和对数据类型的方便模式匹配。编译器可以找到类型系统捕获的错误,例如没有考虑一个特例。考虑使用数据的类型也可以减少运行时错误的可能性。 F#中的类型推断也使F#代码非常简洁。

答案 2 :(得分:4)

符号差异化是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)))))) 

答案 3 :(得分:2)

我没有尝试过,但Clojuratica看起来非常有趣。

答案 4 :(得分:1)

好吧,现在Clojure提供了强大的模式匹配库:

  1. matchure:https://github.com/dcolthorp/matchure
  2. 匹配:https://github.com/swannodette/match

答案 5 :(得分:0)

是的,您现在描述的系统现在存在于Clojure中!正是格里·苏斯曼(Gerry Sussman)的同伴系统 - 和智慧的SICM(经典力学的结构和解释)一书。对于Clojure,它被命名为 sicmutils ,并由Colin Smith移植。

我已在其他地方简要描述过它 - https://stackoverflow.com/a/41646455/4070712 - 但简而言之,肯定是你提到的F#文章提到的四件事,即

  1. 分化:
  2. 简化代数表达式
  3. 格式
  4. 解析表达
  5. 以及更多......

    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
    

    NB。支持两种类型的向量," up" " down"以适应协变和逆变表达

    2)简化表达:哦,是的......

    > (def unity (+ (square sin) (square cos)))
    > (unity 'x)   ==> 1 ;; yes we can deal with symbols
    

    3)格式化:表达式可以在TeX中呈现,以获得漂亮的显示效果。 我不能在这里轻松地展示这一点,但目前枫树风格的笔记本/工作服正在开发中,使用Clojure" Gorilla"

    4)解析:显然。表达式和函数之间的转换是系统的核心部分。

    看看https://github.com/littleredcomputer/sicmutils。你甚至不需要Clojure来运行它,你可以使用提供的Java jar文件。