代码之家  ›  专栏  ›  技术社区  ›  Hamish Grubijan

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

  •  4
  • Hamish Grubijan  · 技术社区  · 15 年前

    我发现下面的F样本很有趣。

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

    Clojure是否有语言/图书馆设施,可以轻松完成类似的工作?如果这使事情变得容易,那么强制公式使用波兰符号是可以的。

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

    6 回复  |  直到 9 年前
        1
  •  6
  •   Yin Zhu    15 年前

    Lisp在符号计算方面有着悠久的历史。见 the AI case study book 彼得·诺维格。Lisp提供了许多很好的语言特性来抽象符号上的常见操作。有时,您可以编写真正简洁的代码(比f更简洁/简短)。

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

        2
  •  6
  •   Tomas Petricek    15 年前

    我对clojure不太了解,但至少这里有一些建议。

    使F代码更漂亮的关键特性是 模式匹配 代数数据类型 . 代数数据类型是 Expression 类型(用于表示数学表达式)和模式匹配是 match 构造,用于在实现简化或差异化时检查各种已知情况。

    我不认为Clojure有任何内置的模式匹配支持,但是它可以作为一个库来实现。一个看起来很有趣的图书馆是 patter-match module (在克洛贾尔语中)。下面是一个使用它的示例 to implement algebraic evaluator (非常接近F条款)。

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

        3
  •  4
  •   John Lawrence Aspden    15 年前

    符号分化是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)))))) 
    
        4
  •  2
  •   Arthur Edelstein    15 年前

    我没试过,但是 Clojuratica 看起来很有趣。

        5
  •  1
  •   Fabien Todescato    14 年前

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

    1. 匹配: https://github.com/dcolthorp/matchure
    2. 匹配: https://github.com/swannodette/match
        6
  •  0
  •   Community Mohan Dere    9 年前

    是的,像你描述的那样的系统现在存在于Clojure上!这正是格里·苏斯曼在《经典力学的结构与解释》一书中的伴奏体系。对于Clojure,它被命名为 锡克分子 由科林·史密斯移植。

    我在别处简单地描述过- https://stackoverflow.com/a/41646455/4070712 -但简而言之,是的,它确实做到了你文章提到的四件事,即。

    1. 区别:
    2. 代数表达式的简化
    3. 格式化
    4. 解析表达式

    还有更多…

    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呈现,以实现美观的显示。 我不能在这里轻松展示这个,但目前正在开发一个枫木风格的笔记本/工作包,使用Clojure的“Gorilla”。

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

    看看 https://github.com/littleredcomputer/sicmutils . 您甚至不需要CuljEube来运行它,您可以使用所提供的JavaJAR文件。