保存和读取个人的对象

假设你正在计算一个矩阵,或是模块化的符号空间,你想保存下来以后再用。 应该怎么做?计算机代数系统有以下几种方法保存个人的对象。

  1. 保存游戏: 仅仅支持保存和读取完整的会话(如,GAP,Magma)
  2. 统一的输入/输出:每一个对象都以可以读回来的方式打印(GP/PARI)。
  3. Eval: 在解释器中将它变成容易执行的代码(如,Singular, PARI)。

因为Sage使用的是Python,它用一种不同的方式实现,每一个对象都可以序列化,即,转换为字符串以便将来进行恢复。这跟PARI中统一I/O的想法是类似的,只是在屏幕输出时不那么复杂。保存和读取(在多数情况下)是自动进行的,不需要额外编程。这是Python从开始就支持的一个简单特性。

几乎所有的Sage对象x,都能用save(x, filename)以压缩格式保存到磁盘上(或x.save(filename))。读取时使用load(filename)

  1. sage: A = MatrixSpace(QQ,3)(range(9))^2
  2. sage: A
  3. [ 15 18 21]
  4. [ 42 54 66]
  5. [ 69 90 111]
  6. sage: save(A, 'A')

你现在可以退出Sage并重启。然后可以把A找回来:

  1. sage: A = load('A')
  2. sage: A
  3. [ 15 18 21]
  4. [ 42 54 66]
  5. [ 69 90 111]

对于其他更复杂的对象,如椭圆曲线,也可以这么做。所有与对象有关的数据都会保存下来。

  1. sage: E = EllipticCurve('11a')
  2. sage: v = E.anlist(100000) # 这里需要花点时间
  3. sage: save(E, 'E')
  4. sage: quit

保存下来的E有153KB,因为它保存了前100000个$a_n$.

  1. ~/tmp$ls -l E.sobj
  2. -rw-r--r-- 1 was was 153500 2006-01-28 19:23 E.sobj
  3. ~/tmp$sage[...]
  4. sage: E = load('E')
  5. sage: v = E.anlist(100000) # 很快!

(在Python中,保存和读取是使用cPickle模块实现的。特别的,一个Sage对象x可以通过cPickle.dumps(x, 2)保存。 注意2!)

Sage不能保存和读取其他计算机代数系统创建的个人对象,如,GAP,Singular,Maxima等。它们重载时标记为”无效”状态。在GAP中,虽然很多对象的输出是一种可重构的形式,但是很多却不行,所以不能用它们的输出结果重构。

  1. sage: a = gap(2)
  2. sage: a.save('a')
  3. sage: load('a')
  4. Traceback (most recent call last):
  5. ...
  6. ValueError: The session in which this object was defined is no longer
  7. running.

GP/PARI的对象可以保存和读取,因为他们的输出形式足以重构。

  1. sage: a = gp(2)
  2. sage: a.save('a')
  3. sage: load('a')
  4. 2

已保存的对象可以被不同的架构或操作系统的计算机读取,如,你可以在32位的OS X机上保存一个大的矩阵,并在64位的Linux机上重新读入,转为阶梯矩阵再移回去。多数情况下,你甚至可以使用不同版本的Sage读取已保存的对象,只要那个对象的代码差别不大。所有的属性与定义对象的类一起被保存下来(但不是源码)。如果那个类在新版的Sage中不存在,那么这个对象就不能在新版中被重新读取。但是你可以在老版本中读取,连同对象的字典(x.__dict__)一起保存,再在新版中打开。

保存为纯文本

你可以把对象保存为ASCII文本格式,只需简单的打开一个文件并将字符串写入(很多对象都可以这么做)。写完之后再关闭文件。

  1. sage: R.<x,y> = PolynomialRing(QQ,2)
  2. sage: f = (x+y)^7
  3. sage: o = open('file.txt','w')
  4. sage: o.write(str(f))
  5. sage: o.close()