使用工具、提示和技巧
OEIS背景下的SAGE
获取软件
http://www.sagemath.org/
浏览文档
搜索文档,参考,oeis模块
修剪序列。
历史上,OEIS条目有3个术语行,总字符数(包括符号)。今天,建议提交给OEIS的“DATA”字段的长度为260个字符。功能下面将给定的列表修剪到这个长度。
定义OEIStrim(L):n=0长度=0T=[]对于l中的l:s=1,如果l<0,否则为0leng=leng+s+len(str(l))如果长度>260:断开长度+=2T附加(l)n+=1打印n,“术语”返回T
示例用法:OEIStrim([(-n)^n代表n in(0..100)])
使用OEIS界面
在Sage中,您可以使用内置斯隆。Axxxxx的功能。例如,快速实现A102467号是
定义为_A102467(n):return bool(斯隆)。A001221号(n) <>1和斯隆。A001222号(n) <>2)定义A102467_列表(n):如果是_A102467(k),则返回[(1..n)中k的k
Sage计算的“sloane”序列的功能已记录在案在这里. 如果您想知道这些函数是如何实现的,请查看github在这里(Jaap Spies编写了大部分序列)。
备忘录
在Sage中,通过应用记忆装饰器激活记忆将“CachedFunction”添加到函数。我们的第一个示例是lame:阶乘函数。
@缓存函数定义f(x):如果x>1,则返回x*f(x-1),否则返回1对于(0..9)中的i:打印f(i)
现在如果你计算f(1000),你不仅执行了1000乘法运算,但也建立了一个可容纳1000个大小的缓存整数。如果随后不在进一步计算中使用这些值这是对资源的巨大浪费。因此,这是一个潜在的误导示例(取自维基). 动态编程技术不能替代好的算法。如果你想知道如何高效计算阶乘函数在这里.
如果只需要对值进行循环,则经济的方法是使用发电机(这不需要内部记忆表)。
定义F(最大值):n=0f=1当n<=最大值时:产量fn+=1f*=n对于f(9)中的f:打印f
一个比阶乘更有意义的记忆用法示例函数由指数变换提供:
def-exptrans(s):@缓存函数定义g(n):如果n>0,则返回加法(二项式(n-1,k-1)*s(k)*g(n-k)for k in(1..n)),否则为1返回g
指数变换将序列s映射到序列t。例如s是常数序列1。
定义s(n):返回1t=出口[(0..9)中n的t(n)]
输出>[1、1、2、5、15、52、203、877、4140、21147]
或者让s是常数序列-1。
定义s(n):返回-1t=出口[(0..9)中n的t(n)]
输出>[1,-1,0,1,1,-2,-9,-9、50、267]
表达这一点的一种更简洁的形式是使用lambda表示法,它创建一个可调用的Python函数,将m发送到1。
A000110号=exptrans(λm:1)[A000110号(n) 对于n in(0..9)]
输出>[1、1、2、5、15、52、203、877、4140、21147]
或更短:
[(0..9)中n的exptrans(λm:1)(n)]
可以找到更多指数变换的例子在这里.
展平迭代
一个经常需要的实用函数是“扁平化”。
def展平(I):L=[]对于i中的i:如果hasattr(i,“iter_”):L.extend(展平(i))其他:L.附录(i)返回L
示例用途是压平按类型给定的标尺(请参见威克曼统治者).
科学的格式
任意精度(MPFR)实数的打印例程。
定义SciFormat(f,n):s=f.str()t=“”计数=0w=真对于c in s:如果c<>‘e’和w:如果计数<n+2:t+=c计数+=1其他:t+=cw=假返回t#例如:b=2.2379923576571269975e4767529对于(0..20)中的i:打印SciFormat(b,i)
示例用法见伯努利数的渐近性其中仅显示渐近近似值的有效位数。
标杆管理
让我们用它们的生成函数来计算贝尔数。。。
定义A000110_list(n):R.<t>=PowerSeriesRing(QQ,default_prec=n+1)G=exp(exp(t)-1)return G.ogf().padded_list()
…以及数据库中给出的实现,A000110号 :
定义A000110_列表(m):A=[0,i在范围(0,m)内]A[0]=1R=[1,1]对于范围(1,m)内的n:A[n]=A[0]对于范围(n,0,-1)中的k:A[k-1]+=A[k]R追加(A[0])返回R
时间安排:
时间a=A000110_列表(1000)
时间:CPU 4.31秒,墙:5.56秒(在生成函数的情况下)
时间:CPU 0.99秒,墙壁:1.35秒(在OEIS实施的情况下)
因此,OEIS的实施速度是实施速度的4倍基于生成函数;-)
弗雷德里克·约翰逊在mpmath中实现了贝尔数。他写在他的博客:“我为计算大贝尔数B做了一些基准测试n个, 而且这种方法似乎比其他系统使用的速度快得多。“所以让我们看看他的实现。
从mpmath导入*定义bellexact(n,x=1):mp.prec=20大小=int(log(bell(n,x),2))+10mp.prec=大小返回int(钟形(n,x)+0.5)定义A000110_list(n):return[(0..n)中k的bellexact(k)]时间a=A000110_列表(1000)
时间:CPU 19.69秒,墙壁:27.72秒
当然,约翰逊的算法针对单个评估进行了优化,而不是用于计算值列表。然而,该示例显示了Phython是多么容易库可以在Sage中使用,如本例所示mpmath(数学).
尽管如此,我们还有另一种方法可以用Sage计算贝尔数:expnums!(E.T.贝尔的论文标题为“指数”。)
时间a=扩展(1001,1)
时间:CPU 0.10秒,墙壁:0.19秒
这位圣人班(作家尼克·亚历山大)无疑是赢家。另一方面,我们的实现是普通的Python脚本,而“expnums”函数是基于代码编译的论超高速MPIR公司(前GMP)库。
还有另一个计算贝尔数的功能,在类sage.combinat.combinet,称为bell_number,用于包装间隙是贝尔。
定义A000110_list(n):return[(0..n)中k的bell_number(k)]时间a=A000110_列表(1000)
这次我们得等三分钟以上!秒表上说
时间:CPU 5.25秒,墙壁:182.39秒
好吧,与我们花了大约一秒钟才闪亮的小10字线相比
总之,这些示例表明Sage是一个提供执行任务的多种方法。其次OEIS应该有两种实现:一种是计算序列和另一个序列来计算值列表[a0,a1,a2,…,an]高效。
在本地使用数据库
函数SloaneEncyclopedia.install()安装本地数据库。这些文件是stripped.gz和names.gz. 每隔一段时间只调用此函数一次就足以更新它。为此,请以SloaneEncyclopedia.install(overwrite=True)的形式使用它。更多信息在这里.
斯隆百科全书安装()
出于各种原因,我发现包装库函数SloaneEncyclopedia.find()如下所示:
定义OEIS_ID(T,num):#T是以列表形式给出的序列,以供识别。#num是要返回的可能匹配项的数量。如果长度(T)<3:返回[]S=T[1:分钟(长度(T),20)]R=SloaneEncyclopedia.find(S,num)如果R==[]:U=过滤器(λz:z!=0,S)模型U[0]R=SloaneEncyclopedia.find(U,num)A=[r[0]代表r中的r]s=[]对于a中的a:sa=str(a)L=“A000000元“[0:7-len(sa)]s.附加(L+sa)返回s
示例调用:
OEIS_ID([1,2,3,4,5,6,7,8,9,10],4)
输出>['A000027号', 'A000401号', 'A000926号', 'A001477号']
例如,我在计算正定二次型.
使用Pari
在Sage中使用已发布的Pari脚本很容易。例如,考虑计算阿贝尔群(C_2)^n的子群个数。
在>gp.read(get_remote_file('http://www.cse.sc.edu/~maxal/gpscripts/nsg.gp'))
out>尝试加载远程文件:http://www.cse.sc.edu/~maxal/gpscripts/nsg.gp正在加载:[.]
in>[gp('numsubgp(2,向量(%d,i,1))'%(n))用于n in(0..9)]
输出>[1、2、5、16、67、374、2825、29212、417199、8283458]
这是A006116号。您无需安装Pari即可完成此操作。Pari安装自动与Sage一起工作,无需再做任何事。
我们还可以为此编写一个小包装器函数:
定义A006116号(n) :""" 交换群子群个数公式的实现鉴于G.A Miller的论文“关于阿贝尔群的子群”,《数学年鉴》,第二辑。,第6卷,第1期(1904年10月),第1-6页(c) 2007年Max Alekseyev"""gp.read(获取远程文件('http://home.gwu.edu/~maxal/gpscripts/nsg.gp'))返回gp('numsubgrp(2,向量(%d,i,1))'%(n))
此方法的一个缺点是您必须联机才能使用此功能。然而,您可以进一步推进,并将代码直接合并到包装纸&只要你不侵犯版权。下一个示例演示了如何操作。
在>gp.read(get_remote_file('http://luschny.de/hacking/gp/A094348号.gp'))
out>尝试加载远程文件:http://luschny.de/hacking/gp/A094348号.gp(加仑)正在加载:[.]
in>gp('A094348号')
输出>(lim)->本地(n,i,R,A,len,count,change,high);R=矢量(500);A=矢量(50\);A[1]=1;A[2]=2;A[3]=4;A[4]=6;A[5]=12;计数=5;高=0;n=12;而(n<=li\m、 d=除数(n);len=长度(d);变化=0;对于(i=1,min(len,high),如果(R[i]>\d[i],R[i]=d[i]:;变化=1));如果(len>high,对于(i=high+1,len,R[i]=d[i]);高(hig)\h=长度);if(更改,计数++;A[计数]=n);n+=12;);向量(count,i,A[i])
现在可以将代码复制到包装器中。只需替换代码依据“A094348号(lim)=“。
定义A094348号(限制):gp('A094348号(lim)=局部(n,i,R,A,len,count,change,high)\R=矢量(500);A=矢量(50);A[1]=1;A[2]=2;A[3]=4;A[4]=6;A[5]=12\计数=5;高=0;n=12;而(n<=lim,d=除数(n);len=长度(d)\变化=0;对于(i=1,min(len,high),如果(R[i]>d[i],R[i]=d[i]:变化=1)\如果(len>high,对于(i=high+1,len,R[i]=d[i]);高=len)\if(更改,计数++;A[计数]=n);n+=12;);向量(count,i,A[i])')返回gp('A094348号(%d)'%(lim))
打电话A094348号(7207200)稍后返回
[1, 2, 4, 6, 12, 24, 36, 48, 60, 72, 120, 180, 240, 360, 420, 720, 840,1260, 1680, 2520, 5040, 7560, 10080, 15120, 20160, 25200, 27720, 30240,45360, 50400, 55440, 83160, 110880, 166320, 221760, 277200, 332640,360360、498960、554400、665280、720720、1081080、1441440、2162160、,2882880, 3603600, 4324320, 6486480, 7207200]
严格地说,包装是没有必要的。“gp.read(…)”之后例如,您可以调用gp('A094348号(2000)’)。但封装调用是一种良好的软件实践。圣人说话Python和Sage所依赖的所有层都应该封装。所以当你决定某天实施A094348号在Python中或基于不同的库,只有一个位置您必须更改内容,而不是在整个代码中进行更改。
附带说明:马修·范德马斯特A094348号是一个非常有趣的序列。请参见David Wasserman的评论。可以在上找到更复杂的Pari脚本seqcomp系列还有一个讨论A094348的一个好算法?.
在云中计算,在网上发布。
去SMC公司(圣人数学云)创建一个帐户(免费),您可以立即开始计算没有安装任何软件。SMC上预装了许多不同的格式。因此,您不仅可以使用Sage笔记本,还可以使用IPython笔记本我最近更喜欢这样。要在IPython笔记本中使用Sage,您只需在IP-notebook的开头包含命令“%load_ext-sage”一次。例如,我在完美和最佳的标尺只是一个Sage笔记本导出到Html,相应的IP笔记本可以浏览在这里和已下载在这里.
更多信息和帮助可以在这里找到山艾素-云-帮助在这里:云朵.