Open Axiom

作者:Joey Bernard

Linux 用户可以使用几种计算机代数系统。我甚至在本专栏中介绍过其中几个,但在本期中,我将讨论 OpenAxiom。OpenAxiom 实际上是 Axiom 的一个分支。Axiom 最初是在 IBM 以 ScratchPad 的名称开发的。开发始于 1971 年,因此 Axiom 和我一样古老,几乎和我一样聪明。在 1990 年代,它被出售给了 Numerical Algorithms Group (NAG)。2001 年,NAG 将其从商业销售中移除,并作为自由软件发布。从那时起,它分叉为 OpenAxiom 和 FriCAS。Axiom 仍然可用。该系统在 Richard Jenks 和 Robert Sutor 合著的著作 AXIOM: the Scientific Computation System 中进行了规范。这本书可以在线获取,网址为 http://wiki.axiom-developer.org/axiom-website/hyperdoc/axbook/book-contents.xhtml,它构成了 OpenAxiom 的核心文档。

大多数 Linux 发行版应该都有 OpenAxiom 的软件包。例如,对于基于 Debian 的发行版,您可以使用以下命令安装 OpenAxiom:


sudo apt-get install openaxiom

如果您想从源代码构建 OpenAxiom,您需要安装 Lisp 引擎。Linux 上有几种可供选择,例如 CLisp 或 GNU Common Lisp。构建过程很简单:


./configure; make; make install

要使用 OpenAxiom,只需在命令行中执行 open-axiom。这将为您提供一个交互式的 OpenAxiom 会话。如果您有一个命令脚本想要作为一个完整的单元运行,您可以使用以下命令:


open-axiom --script myfile.input

其中文件 "myfile.input" 包含要执行的 OpenAxiom 命令。

那么,您实际上可以用 OpenAxiom 做什么呢?OpenAxiom 有许多不同的数据类型。有代数类型(如多项式、矩阵和幂级数)和数据结构(如列表和字典)。您可以将它们组合成任何合理的组合,例如矩阵的多项式或多项式的矩阵。这些数据类型由 OpenAxiom 中的程序定义。这些数据类型程序还包括可以应用于特定数据类型的操作。整个系统在设计上是多态的。您还可以通过编写自己的数据类型程序来扩展整个数据类型系统。还有大量不同的数值类型来处理几乎任何类型的运算。

OpenAxiom 最简单的用途是作为计算器。例如,您可以使用以下命令找到 1.2 的余弦值:


cos(1.2)

这将为您提供默认情况下保留 20 位数字的结果。您可以使用 digits() 函数更改使用的位数。OpenAxiom 还会给出答案的类型。这在您进行更多实验性计算以检查您的工作时非常有用。在上面的示例中,类型将是 Float。如果您尝试这个:


4/6

结果是 2/3,您将看到一个新的类型 Fraction Integer。如果您以前使用过像 Maple 这样的商业系统,这应该很熟悉。

OpenAxiom 具有数据类型,可以尝试将结果保持为精确值。如果您有理由使用特定类型,您可以使用 :: 运算符进行转换。因此,您可以重做上面的除法,并将答案作为浮点数得到,使用:


(4/6)::Float

它甚至可以反向计算,并使用以下命令计算与给定浮点数最接近的分数:


%::Fraction Integer

% 字符指的是您最近计算的结果。由于各种舍入误差,从该命令获得的答案可能与原始分数不符。

有一些函数允许您处理数字的各个部分。您可以 round()truncate() 浮点数。您甚至可以使用 fractionPart() 仅获取小数部分。

OpenAxiom 中一个稍微独特的特性是一组测试函数。您可以使用函数 odd?()even?() 检查奇偶性。您甚至可以使用 prime?() 检查数字是否为素数。当然,您仍然拥有所有标准函数,如三角函数,以及标准运算符,如加法和乘法。

OpenAxiom 也处理通用表达式。为了使用它们,您需要将它们分配给变量名。赋值运算符是 :=。需要记住的一件事是,此运算符将执行右侧的内容,并将结果分配给左侧的名称。这可能不是您想要发生的事情。如果是这样,您可以使用延迟赋值运算符 ==。假设您想要计算一些数字的平方。您可以使用以下命令创建一个表达式:


xSquared := x**2

为了使用此表达式,您需要使用 eval 函数:


eval(xSquared, x=4)

您的表达式中也可以有多个参数。假设您想要计算面积。您可以使用类似这样的东西:


xyArea := x * y eval(xyArea, [x=2, y=10])

我想在本文中介绍的最后一个功能是 OpenAxiom 如何处理数据结构。最基本的数据结构是列表。OpenAxiom 中的列表是同质的,因此所有元素都需要是相同的数据类型。您可以通过将逗号分隔的组放在方括号中直接定义列表,例如:


[1,2,3,4]

这可以使用 list 函数等效地完成:


list(1,2,3,4)

您可以使用 append 函数将两个列表放在一起:


append([1,2],[3,4])

如果您想在列表的前面添加一个元素,可以使用 cons 函数:


cons(1, [2,3,4])

列表寻址借用了 Lisp 中的概念。因此,获取元素最基本的寻址函数是函数 firstrest。使用上面基本列表,函数:


first([1,2,3,4])

将返回数字 1,函数:


rest([1,2,3,4])

将返回列表 [2,3,4]。使用这些函数和循环的创造性使用,您可以获取给定列表中的任何元素。但是,这非常不方便,因此 OpenAxiom 提供了更简单的接口。如果您已将上面的列表分配给变量 mylist,则可以使用以下命令获取第三个元素:


mylist.3

或者,等效地:


mylist(3)

这些索引值是基于 1 的,而不是像 C 语言中基于 0 的索引。

一种非常独特的可用列表类型是无限列表。假设您想要一个包含所有整数的列表。您可以使用以下命令执行此操作:


myints := [i for i in 1..]

此列表将包含所有可能的整数,并且仅在您需要该值时才计算它们。您可以有更复杂的示例,例如素数列表:


myprimes := [i for i in 1.. | prime?(i)]

列表的一个问题是访问时间取决于列表的大小。访问列表的最后一个元素会因列表的大小而异。这是因为列表的长度可能会有所不同。如果您的代码处理长度不会改变的列表,则可以使用数组来提高性能。您可以使用以下函数创建一个一维数组:


oneDimensionalArray([2,3,4,5])

这会分配一个固定的内存区域来存储数据,并且访问时间现在变得均匀,而与列表的大小无关。数组也用作字符串和向量的基础数据结构。您甚至可以创建一个位数据结构。您可以使用以下命令创建一组八个 1 位:


bits(8,true)

通过这种方式,您可以开始进行一些相当抽象的计算工作。

正如您所看到的,OpenAxiom 及其变体是非常强大的科学计算系统。我在这里只介绍了可用的非常基本的功能,但这应该让您对您可以做什么有所了解。在不久的将来,我计划再次研究 OpenAxiom,看看有哪些更高级的技术是可能的,包括编写您自己的函数和程序。

加载 Disqus 评论