15

简短版本:我对一些 Clojure 代码感兴趣,它允许我指定 x 的转换(例如排列、旋转),在这种转换下,函数 f(x) 的值是不变的,这样我就可以有效地生成 x 的序列满足 r = f(x)。Clojure 的计算机代数是否有一些发展?对于(一个微不足道的)示例

(defn #^{:domain #{3 4 7} 
         :range #{0,1,2}
         :invariance-group :full} 
          f [x]  (- x x))

我可以调用 (preimage f #{0}),它会有效地返回 #{3 4 7}。自然,它也能够正确地注释 codomain。有什么建议么?

更长的版本:我有一个特定的问题让我有兴趣了解有关 Clojure 计算机代数的开发。谁能指出我这样的项目?我的具体问题涉及找到满足 F(x) = r 的所有单词组合,其中 F 是排名函数,ra 是正整数。在我的特殊情况下, f 可以计算为总和

F(x) = f(x[0]) + f(x[1]) + ... f(x[N-1])

此外,我有一组不相交的集合 S = {s_i},使得 f(a)=f(b) for a,b in s, s in S. 所以生成所有 x 的策略使得 F(x) = r 应该依赖于 F 的这种因式分解和每个 s_i 下 f 的不变性。换句话说,我计算了包含 S 元素总和为 r 的站点的所有排列,并将它们与每个 s_i 中元素的所有组合组成。这在以下情况下非常草率地完成:

(use 'clojure.contrib.combinatorics)
(use 'clojure.contrib.seq-utils)


(defn expand-counter [c]
 (flatten (for [m c] (let [x (m 0) y (m 1)] (repeat y x)))))

(defn partition-by-rank-sum [A N f r]
  (let [M (group-by f A)
    image-A (set (keys M))
    ;integer-partition computes restricted integer partitions,
    ;returning a multiset as key value pairs
    rank-partitions (integer-partition r (disj image-A 0))
    ]
    (apply concat (for [part rank-partitions]
        (let [k (- N (reduce + (vals part)))
          rank-map (if (pos? k) (assoc part 0 k) part) 
          all-buckets (lex-permutations (expand-counter rank-map))
          ]
          (apply concat (for [bucket all-buckets]
        (let [val-bucket (map M bucket)
              filled-buckets (apply cartesian-product val-bucket)]
          (map vec filled-buckets)))))))))

这完成了工作,但错过了潜在的画面。例如,如果关联操作是乘积而不是总和,我将不得不重写部分。

4

3 回答 3

5

下面的系统还不支持组合数学,尽管添加它们并不费力,但已经存在大量好的代码,这可能是一个很好的移植它的平台,因为基础非常健全。我希望简短的插件在这里不是不合适的,这是我所知道的唯一一个严重的 Clojure CAS,但是,嘿,什么系统......

=======

Gerry Sussman 的scmutils系统被移植到 Clojure可能会让本主题的读者感兴趣。这是一个非常先进的 CAS,提供诸如自动微分、文字函数等功能,非常类似于Maple。它在麻省理工学院用于动力学和微分几何的高级程序,以及相当多的电气工程材料。它也是 Sussman&Wisdom 的SICPSICM(经典力学的结构和解释)的“续集”(LOL)中使用的系统。虽然最初是一个 Scheme 程序,但这不是直接翻译,而是为了利用 Clojure 的最佳特性而进行的彻底重写。它被命名为sicmutils, 既是为了纪念原著,也是为了纪念这本书。这项出色的工作是 Colin Smith 的作品,您可以在https://github.com/littleredcomputer/sicmutils找到它。

我相信这可以构成一个惊人的 Clojure 计算机代数系统的基础,与其他任何可用的东西竞争。尽管它是一个巨大的野兽,正如你可以想象的那样,还有大量的东西需要移植,但基础知识已经差不多了,系统会区分,并且可以很好地处理字面量和字面量函数。这是一项正在进行的工作。该系统还使用了 Sussman 倡导的“通用”方法,从而可以将操作应用于函数,从而创建一个极大的抽象来简化符号。

这是一个品尝者:

> (def unity (+ (square sin) (square cos)))
> (unity 2.0)  ==>  1.0
> (unity 'x)   ==> 1 ;; yes we can deal with symbols
> (def zero (D unity))  ;; Let's differentiate
> (zero 2.0)   ==> 0

SicmUtils 引入了两种新的向量类型“向上”和“向下”(称为“结构”),它们的工作方式与您期望的向量非常相似,但具有一些特殊的数学(协变、逆变)属性,以及一些编程属性,在它们是可执行的!

> (def fnvec (up sin cos tan))  => fnvec
> (fnvec 1)   ==> (up 0.8414709848078965 0.5403023058681398 1.5574077246549023)
> ;; differentiated
> ((D fnvec) 1)  ==>  (up 0.5403023058681398 -0.8414709848078965 3.425518820814759) 
> ;; derivative with symbolic argument
> ((D fnvec) 'θ) ==> (up (cos θ) (* -1 (sin θ)) (/ 1 (expt (cos θ) 2)))  

完全支持偏微分

> (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

该系统还支持 TeX 输出、多项式分解和许多其他好东西。然而,许多可以轻松实施的东西并不是纯粹因为缺乏人力资源而完成的。图形输出和“记事本/工作表”界面(使用 Clojure 的 Gorilla)也正在开发中。

我希望这已经在某种程度上激发了您的胃口,足以让您访问该网站并试一试。你甚至不需要 Clojure,你可以从提供的 jar 文件中运行它。

于 2017-01-14T03:17:02.660 回答
2

Clojuretica 是 Clojure 和 Mathematica 之间的接口:

http://clojuratica.weebly.com/

另请参阅Clojuratica 的作者的此邮件列表帖子。

虽然不是 CAS,但 Incanter也有几个非常好的功能,可能是构建您自己的想法的一个很好的参考/基础。

关于“例如,如果关联操作是乘积而不是总和,我将不得不重写部分。” : 如果你相应地构造你的代码,你不能通过使用高阶函数并传入关联操作来完成吗?想想map-reduce。

于 2010-10-19T12:24:28.207 回答
1

我不知道有任何用 Clojure 编写的计算机代数系统。但是,对于我相当简单的数学需求,我发现使用用 lisp 编写的Maxima通常很有用。可以使用 s 表达式或更高级别的表示与 Maxima 进行交互,这非常方便。Maxima 还具有一些基本的组合函数,这可能是您正在寻找的。

如果您一心想要使用 Clojure,那么短期内,在 Maxima 和 Clojure 之间来回传输数据可能会帮助您实现目标。

从长远来看,我很想看看你的想法!

于 2010-10-19T08:06:41.880 回答