|
RDF、SPARQL及凡此种种! \) u; \5 x! {5 C! O5 g
世界知识的最佳表示方式是什么?自古以来,哲学家(和其他人)一直对此争论不休。有时人们说逻辑是关键,有时说是数学,而有时又说是关系数据库。但现在我们至少有一个坚定的共识:一切都可以通过计算来表示。这是一个伟大的想法,从某种意义上说,这使得我们使用Wolfram语言所做的一切成为可能。 ; V7 A/ r6 Z% y6 E# G- H1 U
但是,是否存在一些通用的计算子集可用于表示至少某些类型的知识?我们在Wolfram知识库中广泛使用的是实体(“纽约市”),属性(“人口”)及其值(“860万人”)的概念。当然,这样的三元组并不代表世界上的所有知识(“明天火星的位置将在哪里?”)。但是当谈到不同事物的“静态”知识时,这是一个不错的开端。
" @( X0 O. L0 I: Q那么如何将这类知识表示形式化呢?答案之一是通过图形数据库。与许多“语义网”项目一致,在版本12.0中,我们使用RDF支持图形数据库,并使用SPARQL对它们进行查询。在RDF中,中心对象是IRI(“国际化资源标识符”),它可以表示实体或属性。然后,“triplestore”由三元组(“主语”,“谓词”,“对象”)组成,每个三元组中的每个元素都是IRI(或文字,例如数字)。然后可以将整个对象视为图形数据库或图形存储(数学上称为超图)。(它是超图因为谓词“边”也可以是别处的顶点。) ) _* I5 C( k! y
您可以像构建EntityStore一样构建自己的RDFStore。事实上,您可以像查询RDFStore一样使用SPARQL查询任何Wolfram语言的EntityStore。由于Wolfram知识库的实体属性部分可以视为实体存储,因此您也可以对它进行查询。这是一个例子。国家-城市列表实体{Entity["Country"],Entity["City"]}实际上代表RDF存储。然后SPARQLSelect是一个操作此存储的运算符。它的作用是尝试找到符合要求的三元组,并使用“SPARQL变量”x的特定值:
/ ~) \& m, b I% p" X! q* e8 v: R
2 s4 c3 p {6 F3 Q! U4 i% i' O当然,在Wolfram语言中还有一种更简单的方法:
" \. s4 D( X1 H$ u) a8 R
1 Y) J+ R% [. n. P3 M# P' d# n
但SPARQL可以让你做更多酷炫的事情,比如询问把美国与墨西哥联系起来的属性有哪些:
0 i+ H4 ?% U" W" o8 N7 ?7 X5 t8 X% B! I: x) d( Q/ Q3 b
或者从葡萄牙到德国是否存一条基于国家边境关系的路径:
2 _+ }: i6 ?- N6 }* o/ }3 H/ r5 ]2 H
- c; N K: m- V. H
原则上您可以将SPARQL查询写作字符串(就像您可以写SQL字符串)。我们在版本12.0中所做的是引入SPARQL的符号表示,允许对表示本身进行计算。例如,可以轻松地自动生成复杂的SPARQL查询。(这样做尤为重要,因为实际的SPARQL查询本身就有一种变得冗长笨重的习惯。) 6 Z0 W7 C6 W5 D
但有没有野生的RDF存储?长期以来,人们一直希望网络的大部分内容最终会被标记的足以“变成语义”,从而成为一个巨大的RDF存储。如果发生这种情况当然会很棒,但到目前为止它肯定还没有发生。尽管如此,还是有一些公共RDF存储,以及机构内部的一些RDF存储,而版本12.0中的新功能令我们处于一个独特的位置,可以与这些RDF存储一起做很多有趣的事情。 - a# ~2 Z8 `2 n6 E' D2 Q3 C3 h- b. ]
数值优化
3 _( O a+ K: `7 S* l* [数学工业应用中一个及其常见的问题形式是:“如果必须满足某些约束,什么配置可以最小化成本(或最大化收益)?”半个多世纪以前,发明了所谓的单纯形算法,用于求解这类问题的线性版本,其中目标函数(成本,支付)和约束都是问题中变量的线性函数。到了20世纪80年代,人们发明了更有效的(“内部点”)方法,而对此我们已经在Wolfram语言中进行了长期的“线性编程”。
% [3 Q& `( E. J3 E而对于非线性问题,一般情况下可以使用像NMinimize这样的函数,这类函数是非常先进的。但这确实是一个难题。然而几年前,人们认识到,即使在非线性优化问题中,也存在一类所谓的凸优化问题,这些问题实际上可以像线性问题一样有效地求解。(“凸”意味着目标和约束都只涉及凸函数,因此当接近极值时,没有任何东西可以“摆动”,并且不存在任何不是全局最小值的局部最小值。) 5 z' `! F4 \7 e6 V
在版本12.0中,我们现在已经为所有凸优化的标准类提供了强大的求解功能。这是一个简单的案例,涉及使用几个线性约束的最小化二次形式:
& E9 g2 q, Y& S# i
% V( a" a1 [& }6 y+ b, W在版本11.3中,NMinimize已经能够求解此特定问题: ) k9 U# _/ }' t% D, @8 J( E1 B
2 B+ q: b2 k* l5 x: u1 o
但如果变量更多,则旧的NMinimize会很快陷入困境。但在版本12.0中,QuadraticOptimization能继续正常工作,最多可达十万多个变量,超过十万个约束(只要它们相当稀疏)。
1 x+ \$ G9 Z& q/ L! Q在版本12.0中,我们已经得到了像“原始凸优化”函数,如SemidefiniteOptimization(处理线性矩阵不等式)和ConicOptimization(处理线性向量不等式)。但像NMinimize和FindMinimum这样的函数也会对何时通过转换为凸优化形式来有效地解决问题进行自动识别。 0 A) n/ N8 j! o# Z9 r
如何设置凸优化问题?较大的问题将涉及对整个向量或变量矩阵的约束。在版本12.0中,我们现在可以使用VectorGreaterEqual(输入为≥)等函数来立即表示这些函数。
) p) J2 S' T5 p非线性有限元分析 . f( | D, n/ ?0 |
偏微分方程很难求解。30多年来,我们一直在研究开发更高级更通用的求解方法。我们在1991年首次在版本2中引入了NDSolve(用于ODE)。到20世纪90年代中期,我们有了首个(1+1维)数值偏微分方程。2003年,我们引入了强大的模块化框架来处理数值微分方程。但就PDE而言,我们基本上只停留在简单的矩形区域内。要突破这个极限,需要构建我们在第10版中引入的整个计算几何系统。随后,我们发布了第一个有限元PDE求解器。在第11版中,我们将其推广到本征问题。
" v$ O) n3 e2 p4 c, _- D而今天,我们在第12版中实现了另一个重大的推广:非线性有限元分析。有限元分析涉及将区域分解成小的离散三角形、四面体等,其中原始PDE可以通过大量耦合方程来近似。当原始PDE为线性时,这些方程也将是线性的,这正是人们谈论“有限元分析”时所考虑的典型情况。 9 w6 M+ ^! `& d7 @: x( }
但是,有许多具有实际重要性的偏微分方法并不是线性的。要解决这些问题,需要进行非线性有限元分析,而这正是版本12.0版的新功能。 1 O+ f9 m" R0 E; `7 K! `
举例说,这是求解一个非线性PDE所要做的事情,该非线性PDF描述的是2D最小表面(例如理想化的肥皂膜,此处这里是环形的)的高度,具有(Dirichlet)边界条件,使其在边上做正弦曲线摆动(就像肥皂膜悬挂在电线上):
9 T, Z& _3 ^5 t+ W$ e+ c
/ ?+ S3 k; N# \. ^0 B
在我的电脑上,只需要四分之一秒就可解出这个方程,并获得插值函数。以下是表示解决方案的插值函数图:
; q. b( C& x0 q- A2 ~% U" A }) H \0 b# c
新型高级编译器 6 z; y. x8 s% V, K! _6 `2 |
多年来,我们为优化Wolfram语言程序的执行投入了大量的人力物力。早在1989年,我们就开始对高效虚拟机的指令自动编译简单的机器精度数值计算(事实上,原始代码是我本人亲自编写的)。多年来,我们将编译器功能不断扩展,但它总是局限于比较简单的程序。
f5 _( I& ~. _& N/ @在版本12.0中,我们向前迈进了一大步,我们发布的是一个全新的、功能更强大的编译器的第一个版本,为此我们已经奋斗了多年。这个编译器能够处理的程序范围更广泛(包括复杂的功能结构和控制流程),并且它也不再是编译到虚拟机,而是直接编译为优化的本机机器代码。
R% L+ ] E# i8 g" {% u# o5 x在版本12.0中,我们仍然考虑新的编译器试验。但它在迅速发展壮大,必将对Wolfram语言的效率产生巨大影响。在版本12.0中,我们只是公开了新编译器的“套件表单”,具有特定的编译功能。今后,我们会逐步让编译器的运行变得越来越自动化,用机器学习等手段搞清楚何时值得花时间去做编译,以及去做什么级别的编译。 6 O/ X: K1 e7 S; m& O
在技术层面,12.0版编译器基于LLVM,并通过生成LLVM代码,链接Wolfram语言内核本身使用的同一低级运行时库,并调回完整的Wolfram语言内核来实现运行时库中不存在的功能。
3 Q. j/ l3 ?5 E W2 T这是在新编译器的当前版本中编译纯函数的基本方法:
% i$ X/ q1 Q/ v X% M' ~
' x# I) H8 W7 Z8 ^
生成的编译代码函数就像原始函数一样工作,但速度更快:
6 b9 o" g) {8 t- A' j; G
1 V! @( f; E# [/ T, _3 |% b使FunctionCompile产生速度更快的函数的一个重要原因是,你要对将获得的参数类型做出假设。我们支持许多基本类型(如“Integer32”和“Real64”)。但是当使用FunctionCompile时,您将提交特定的参数类型,因此更加简化的代码才得以生成。
J( p8 @/ O7 v, j* L6 N: V新编译器的许多复杂性与推断在程序执行中将生成什么类型的数据有关。(这要涉及到许多图论和其他算法,当然编译器的所有元编程都是用Wolfram语言完成的。) 9 x/ H! a* H) b4 a4 i R' t! ]
这个例子涉及类型推断(fib的类型被推断为“Integer64”->“Integer64”:返回整数的整数函数): 5 r3 P$ x0 [* e( a. @1 t
在我的电脑上,cf[25]的运行速度比未编译函数快约300倍。(当然,当编译版本的输出不是“Integer64”类型时,编译版本会失败,但标准的Wolfram语言版本继续正常工作。) Q, s M4 m- S8 D% M3 b! t2 |9 X$ Q
编译器已经可以处理数百个Wolfram语言编程基元,适当地跟踪生成的类型,并生成直接实现这些基元的代码。然而有时候人们在Wolfram语言中使用复杂的函数时,并不希望生成自己编译的代码,而只是想要调用Wolfram语言内核来实现这些函数。在版本12.0中,可以使用KernelFunction实现:
& m" s0 Q4 {# O9 H9 J
现在假设有一个已编译的代码函数。人们可以用它来做什么?首先可以在Wolfram语言中运行它,也可以将其存储稍后再运行。对于特定的处理器架构(例如64位x86),任何特定编译已经完成,但CompiledCodeFunction会自动保留足够的信息,以便在需要时为不同的架构进行额外的编译。
9 }$ k# F/ p* L8 y2 S; j8 V但是给定一个CompiledCodeFunction,一个有趣的新可能性是可以直接生成甚至可以在Wolfram语言环境之外运行的代码。(我们的旧编译器具有CCodeGenerate包,它在简单的情况下提供了略微类似的功能,尽管那时依赖于C编译器精巧的工具链等。) 1 q3 ^. _# J: Y3 e F/ D
以下是如何导出原始LLVM代码(注意尾递归优化是自动完成的,并注意最后的符号函数和编译器选项): % S) ~7 w/ G* z# O
6 u! S: ^9 D/ _+ I
如果使用的是 FunctionCompileExportLibrary,则得到一个库文件:在Mac上是.dylib,在Windows上是.dll,在Linux上是.so。它可以通过执行LibraryFunctionLoad在Wolfram语言中使用,也可以用于外部程序。
+ [: }/ L& z# S- e. A% Y3 s决定新编译器通用性的主要因素之一是其类型系统的丰富性。现在编译器支持14种原子类型(例如“Boolean”,“Integer8”,“Complex64”等)。它也支持类型结构如“PackedArray”,也就是说,例如TypeSpecifier [“PackedArray”] [“Real64”,2]对应于64位实数的秩为2的堆积阵列。 + m' U1 p% i% I8 U7 m3 t) j
在Wolfram语言的内部实现中(顺便说一句,它本身主要使用Wolfram语言),我们早已拥有存储数组的一套优化方法。在版本12.0中,我们将其公开为NumericArray。与普通的Wolfram语言结构不同,您必须详细指定NumericArray应该如何存储数据。但它的工作方式极其优雅和优化: % w4 \+ y. v# J1 p
% e% A8 y# {0 r( o. r/ d: [ C
2 C, ] Y5 ^" m6 G& N4 k
) u4 K0 ^6 h& F3 n
调用Python及其它语言 2 j& t0 Y6 ^+ u: |; s# E
在版本11.2中,我们引入了ExternalEvaluate,它允许您在Wolfram语言中使用Python和JavaScript等语言进行计算(在Python中,“^”表示BitXor):
: X8 p# b5 a' g0 \0 k( ?
7 g' R8 k* l+ k# D$ H在版本12.0中,我们进一步强化了这种整合。例如,在外部语言字符串中,您可以使用<*... *>提供待运算的Wolfram语言代码:
/ [1 V* ] i3 F% t
这也适用于外部语言单元:2 j" F) x) ~, G3 Z4 O' W; V
4 |( |( m; E% B2 W, q: |
当然,Python不是Wolfram语言,所以很多时候不起作用:( Q, |, q! D+ L: l% _& V. `
4 S2 d( g% A D7 ]0 E但是ExternalEvaluate至少可以从Python返回许多类型的数据,包括列表(作为List),字典(作为Association),图像(作为Image),日期(作为DateObject),NumPy数组(作为NumericArray)和pandas数据集(作为TimeSeries,DataSet等)。(ExternalEvaluate也可以返回ExternalObject,它基本上可以控制发送回Python的对象。)
: I6 {; i) e7 r5 f j+ R' D9 R您也可以直接使用外部函数(这个略显古怪的命名ord基本上是ToCharacterCode的Python模拟): ) Y0 H# l$ {7 Q1 _) J
8 D" R, A$ K# L4 ?( h
/ r6 S4 _' }( Y1 j6 O6 q8 f' i
这是一个Python纯函数在Wolfram语言中的符号式表示:
. J- O/ ?' x2 y
+ ~& g5 N; `; m" h( Z% {6 p
从Python或其它地方调用Wolfram语言
; u& L% e e7 M4 R: k/ K6 p" }: s! r如何访问Wolfram语言?有很多方法。可以直接在笔记本中使用,可以调用它的API在云端执行,或者可以在命令行shell中使用WolframScript。WolframScript可以针对本地Wolfram引擎运行,也可以针对云中的Wolfram引擎运行。它允许您直接提供执行代码:
4 Y2 Z: ^5 C# h& B! Y7 L- D
! ?7 e9 g+ L$ v: V4 H$ L* B允许您执行函数定义之类的操作,例如使用文件中的代码:' `0 p6 m s5 G0 r! ~7 S" n3 c
: p/ d! u' _9 ^
7 U7 ]0 _, g4 b2 H随着版本12.0的发布,我们同时发布了第一个全新的Wolfram Language Client Library(Wolfram语言客户端库),用于Python。该库的基本理念是让Python程序可以轻松调用Wolfram语言。(值得指出的是,我们拥有C语言客户端库已经至少30年了,它就是现在大家知道的WSTP。) 7 h7 F% \ Y1 x* ^, a
语言客户端库的工作方式因语言而异。对于作为一种解释性语言(实际上是早期Wolfram语言的历史)的Python来说,这一点非常简单。在设置库并启动会话(本地或在云中)之后,您可以只执行Wolfram语言代码并将结果返回到Python:
# _9 U5 m4 Y+ u! K6 `, n4 @
$ K6 u* z6 A; j( ]还可以直接访问Wolfram语言函数(作为ExternalFunction的一种逆操作):
0 J+ B/ p H) q- `- t3 v1 v$ Q: S9 ~; @6 w5 J
可以直接与pandas结构,NumPy数组等进行交互。实际上,您可以将整个Wolfram语言视为可以从Python访问的巨型库。当然了,您也可以直接使用优美的Wolfram语言,如果需要的话,还可以创建外部API。
3 v# j/ F& A f0 A# gWolfram “Super Shell” + N8 R3 q; h: @( B
使用Wolfram语言的一个特点是,它可以让您尽可能不被计算机系统细节以及文件和进程等内容烦扰。但有时候人们希望在系统级别工作。对于比较简单的任务,可以使用操作系统GUI。但是对于更复杂的任务呢?在过去,我经常使用Unixshell。但是很长一段时间以来,我反而使用了Wolfram语言。
/ {2 W' p# K% i6 b" H将所有内容都放在笔记本中当然非常方便,能够以编程方式使用FileNames(ls)、FindList(grep)、SystemProcessData(ps)、RemoteRunProcess(ssh)和FileSystemScan等函数非常棒。在版本12.0中,我们对Wolfram语言作为“超级shell”使用提供了更多函数以支持。
' ?! N$ v- N+ |Remotefile用于符号式表示远程文件(必要时需身份验证),你可以在CopyFile等函数中立即使用。FileConvert用于不同格式文件的直接转换。
4 V; y# ^$ r1 W7 {" j1 B1 \' O; \/ W如果想要进一步了解,这里是你如何追踪用于读取Wolfram.com使用的端口80和443上的所有数据包: $ G8 m7 F. b n8 A- d( F9 m
6 M7 r3 ]% G" L8 U) Y0 k* O' p$ ~7 X操纵Web 浏览器 + q A: b5 H+ { j( U
很久以来,在Wolfram语言内部与Web服务器交互很容易,方法是使用URLExecute和HTTPRequest等函数,以及$Cookies等。但在版本12.0中,我们添加了一些新功能:用Wolfram语言控制Web浏览器,并通过编程来对其掌控。最直接的事情就是获取在Web浏览器中一个网站的样子:
7 z7 c) l" \4 }8 ^" ^! v/ o6 P
- _8 `# I$ b9 p7 w+ x$ n
结果是一个图像,我们可以用于进行以下计算:
4 T; W4 ~; [- L: Y: D+ y
/ d0 Y; z# B* Z; Z+ [- T# G
要做更具体的事情,我们必须启动浏览器会话(目前支持Firefox和Chrome):
; k1 r" k8 i2 w4 ^5 x) @5 a. V
/ ~# D1 U9 i0 j$ X! ]) n. q
- @1 L }9 s/ b, w屏幕上会立即出现一个空白的浏览器窗口。现在我们可以使用WebExecute打开一个网页:
$ d1 l! e8 ^9 W
' q5 X4 h, _# s2 X/ y8 o
2 c4 u$ X- a7 b1 T# n现在页面已经打开,我们可以运行很多命令。单击包含文本“Programming Lab”的第一个超链接:0 c, O; ?1 W) t! i0 u3 q
0 Z4 W& P& h3 c7 H6 ]
% ~2 V, I) p4 s6 U+ ~这将返回我们所到达页面的标题:
3 U6 G+ j& ~9 Z2 ?; M1 N
9 i, J+ i1 _* j8 V `. m您可以键入字段,运行JavaScript,并且可以通过Web浏览器手动执行几乎任何操作。毋庸置疑,在我们公司内部,该技术的一个版本已被我们使用多年,来对我们的各种网站和网络服务进行测试。但在版本12.0中,呈献给您的是一个更加流畅和通用的版本。 5 [1 g3 C& Z) J, O4 l4 |6 d
独立的微控制器
4 k- {/ q0 z6 G/ H$ [# {今天,世界上微控制器的数量可能是普通计算机数量的10倍,它们在没有任何通用操作系统的情况下运行着特定计算,而成本可能只有几美分到几美元。一台中型轿车上微处理器的数量大概为30个。
! t' C6 o' d7 d: g; U在版本12.0中,我们为Wolfram语言引入了一个微控制器套件,它允许您提供符号规范,从而自动生成和部署代码以在微控制器中自主运行。在典型的设置中,微控制器不断对来自传感器的数据进行计算,并实时向执行器发出信号。最常见的计算类型是控制理论和信号处理中的有效计算。 6 _4 m: R2 Z. O
很久以来,我们就对在Wolfram语言中进行控制理论和信号处理提供广泛深入的支持。而现在,我们可以把该语言指定的任何内容取出并将其作为嵌入式代码下载到独立微控制器,以实现在任何地方(设备、物联网等)的部署。
) r1 R# v" B+ t% T# b/ w% \2 W例如,以下是生成模拟信号处理滤波器的符号表示: 1 p) I" ?: ?7 T- E9 N: }3 V8 N
9 F( h* S- N; M3 U+ f5 E4 o
此过滤器可以直接在Wolfram语言中使用,比如使用RecurrenceFilter将其应用于音频信号。我们还可以绘制频率响应:
4 F0 \, f& E/ d1 J
`* C& t/ q, }% t; C要在微控制器中部署该滤波器,首先必须从这个连续时间表示中推导出离散时间近似,它可以在微控制器中以紧密循环(此处为每0.1秒)运行:
5 u! y8 J& ~; }+ n4 v# u" r
! p/ Q" e, E* r
0 t5 ^! ^# L7 q0 c7 d- D
D' U. l8 O9 S( l* j$ F
现在一切就绪,可以使用微控制器套件将其实际部署到微控制器上。该套件支持超过一百种不同类型的微控制器。以下是如何将过滤器部署到一个已连接到计算机上串行端口的Arduino Uno:
; {4 i: R/ O; Q/ C8 \) H
+ w: X* y7 _4 C) d
1 I( t% p8 _4 P, h# p. @& Y
MicrocontrollerEmbedCode的工作原理是生成适当的C类源代码,为想要的微控制器架构进行编译,然后通过其所谓的编程器将其部署到微控制器。这是在这种特定情况下生成的实际源代码:# e$ w7 `5 r9 k" f: q9 T. z
( J4 U* b/ q$ f7 F: } d现在我们就有了一个运行Butterworth滤波器的微处理器,可用于任何地方: D3 }) \' T' A& o4 @6 v. L: d
3 A/ \' M( S: c4 J' V
如果我们想检查它到底在做什么,可以使用DeviceOpen将它连接回Wolfram语言来打开它的串口,并从中读取和写入。 " ~ _( j8 T N1 ]+ O+ I) r
与Unity世界的链接
G& @5 _4 Q0 M$ HWolfram语言和视频游戏之间有什么关系?多年来,Wolfram语言一直工作在游戏开发众多方面(模拟策略,创建几何,分析结果,等等)的幕后。但近年来,我们开始致力于在Wolfram语言和Unity游戏环境之间建立更紧密的链接,在版本12.0中我们发布了这个链接的第一个版本。
2 t" F1 }' K5 v0 t简单地说,基本方案是让Unity与Wolfram语言一起运行,然后设置双向通信,允许交换对象和命令,底层机理则非常复杂,但结果是实现了Wolfram语言和Unity的优势互补。 * w5 T" d% j# U, w1 y W9 c* ]
这将设置链接,然后在Unity中启动一个新项目: 0 D! a+ Z) U. \' k! C
! |0 S1 [- w4 { B! @4 H
1 t5 N4 i5 M$ K) r5 `. }
现在创建一些复杂的形状:
0 F% _5 x3 H4 Q- G1 a0 m. C+ J' n4 A6 X$ K9 u( L9 \! q7 x
然后只需要一个命令就可以将它作为一个名为“thingoid”的对象放入Unity游戏中:
& \5 i' o6 C# U
4 L0 R$ l" G- R _$ x% f
Wolfram语言内部存在对象的符号表示,而UnityLink现提供数百种用于操作此类对象的函数,并且同时在Unity和Wolfram语言中进行版本维护。
: k# v( G1 N& Y& u- a8 N. O$ @& T人们可以从Wolfram语言中取出对象并立即将其置于Unity中,无论它是几何、图像、音频、地理地形、分子结构或3D解剖学对象,这是非常了不起的。同样了不起的是,这类对象可以通过游戏物理学或用户操作在Unity游戏中被操纵。(最终,我们可以期待类似Manipulate的功能,其中控件不仅仅是滑块和事物,而是复杂的游戏片段。) 6 S+ Q' T+ T; }
将Wolfram语言生成的内容放入虚拟现实的实验,我们自20世纪90年代初就在做了。但是到了现代,Unity已成为设置VR/ AR环境的事实标准。现在通过UnityLink可以直接将Wolfram语言的内容放入任何现代XR环境中。
5 @# [8 C9 r6 g6 JWolfram语言可用来准备Unity游戏的原材料,但在Unity游戏内部,UnityLink基本上只允许插入Wolfram语言代码,该代码可在游戏过程中在本地计算机上或通过WolframCloud中的API执行。这使得在游戏中放入钩子(Hooks)变得简单,从而游戏可以发送“遥测”(比如WolframData Drop)以进行Wolfram语言分析。(也可以编写游戏运行的脚本,这对游戏测试非常有用。) 1 u8 }0 J2 o# _, Q' p6 `3 M8 n
" ]# r! `% Y8 {
% T t4 M. c* Q1 J6 |UnityLink并不简单:它包含600多个函数。但是通过这些功能,人们可以访问Unity的几乎所有功能,并设置几乎任何可以想象的游戏。 ; o0 [+ a- _7 H: g
机器学习仿真环境 / Z4 i* D5 Q r/ g- B8 q4 Z
在对机器学习进行强化时,拥有一个可操纵的外部环境是至关重要的。例如,用ServiceExecute调用API(发布推文或进行交易的效果怎样?),用DeviceExecute启动实际设备(向左转动机器人)并从传感器获取数据(机器人是否倒下?)。 + C8 Q# G1 j9 v5 U! o
但是出于许多目的,人们想要拥有的却是一个模拟的外部环境。在某种程度上,纯Wolfram语言已经做到了这一点,例如提供对丰富“计算世界”的访问,这个“计算世界”里充满了可修改的程序和方程(元胞自动机,微分方程,......)。并且是的,在这个计算世界中的万物可以通过现实世界来告知,比如海洋、化学品或山脉的现实属性等。
6 [/ j! i6 T6 ?1 |/ l但是对于我们现代人通常学习的、充满工程结构的环境呢?SystemModel可以非常方便地访问许多真实的工程系统。通过UnityLink,我们可以期待访问丰富的基于游戏的仿真世界。
' O' l7 [' U) P1 r# |但作为第一步,在版本12.0中,我们建立了与一些简单游戏(特别是来自OpenAI“gym”)的连接。界面与现实世界中的交互很相似,游戏像“设备”一样被访问(有时需要适当进行开源安装):
: D6 g0 ?) x! M ]: W; j% b2 G3 V
. |$ ]: D6 J9 r4 Z
' \: K5 C2 u% Y- B6 g; m- ~: ?我们可以读取游戏状态:
, C1 {" }% p8 @) }
2 m% B, n3 u1 Z
6 ~: A+ l8 S! h; E. L# Z) `- l% |将它显示为图像:
8 O! w$ ^7 [7 Z( H: y! h+ i
6 ^: |/ U) a: B( H, [0 ?
通过一点点努力,我们可以提取游戏中的100个随机动作(总是检查我们有没有“玩完”),然后显示观察到的游戏状态的特征空间图:
/ f2 X, T- k) o$ Y8 Y0 i
& F f0 U3 |3 a$ W) P2 m
区块链(和CryptoKitty)计算 ! S4 P J( W! V7 w
我们与区块链的第一个连接从版本11.3就开始了。版本12.0增加了许多新的特性和功能,其中最显著的大概要数写入公共区块链以及从中读取的能力。(我们还为Wolfram Cloud用户提供了自己的WolframBlockchain。)我们目前支持比特币、以太坊和ARK 区块链,包括主网和测试网(并且我们有自己的节点直接连接到这些区块链)。
, y" |% L! j! |# C6 y% n版本11.3允许从区块链中原始读取交易。版本12.0在此基础上添加了一层分析。因此,您可以在以太坊区块链上请求“CK”(即CryptoKitties)代币(Token)的摘要:
8 i2 x& X9 O& ]7 B: N% V3 g2 r
4 a4 U* F6 D# ~1 f. j9 f/ K可以快速查看历史记录中的所有代币交易,并制作一个关于不同代币活跃程度的文字云:$ _& C9 X7 @$ v2 ?& ^4 `+ s7 \* A$ Y
, m4 D @- C6 E
但是做我们自己的交易会怎样呢?假设我们想要使用比特币ATM(比方说,位于我附近的百吉饼商店中那台(注:参见https://coinatmradar.com/)将现金转移到一个比特币地址。首先我们创建加密密钥(务必记牢我们的私钥):
/ f( G9 e! v) x8 S
$ X8 R2 E( U8 c1 Y$ J2 `9 S8 {
接下来,必须使用公钥并从中生成比特币地址:
; F7 Q1 T5 S4 S+ s, H# l! W2 j
& ` k& |$ t& T2 ~+ _# v7 p
从那里生成一个二维码,就可以去ATM了:0 L1 \9 Q5 T1 E# }
3 v f F7 r6 F' H) i
但如果我们想要自己写入区块链呢?在这里,我们将使用比特币测试网(所以并没真正花钱)。这显示了我们之前做过的交易,包括0.0002比特币,即20,000satoshi(中本聪):
- [( ~2 t) R' q+ y
9 k5 S+ U. v+ r, F+ D) T) ^* T3 f
# Y( l: W1 h) O( U( p- U: g3 }/ V现在我们可以设置一个获取此输出的交易,例如,向两个地址各发送8000个satoshi(就像ATM交易一样定义):
0 P* i! c+ R4 e2 T8 x: u
: q( n* \7 _1 d9 D- O% T$ O现在,我们就得到了一个区块链交易对象,这将提供一个费用(显示为红色,因为它是你将花费的“实际资金”),从剩余所有加密货币(此处为4000satoshi)转给愿意将该交易放入区块链的矿工。但在我们提交此交易(“真正花钱”)之前,我们必须用我们的私钥对其进行签名:
, e1 m, k, I8 n' Q$ a
; T ^3 m9 G- F- X& w# K3 \
最后,只需应用BlockchainTransactionSubmit,就可将交易提交到区块链上:
3 d) W3 z( \5 G$ r- ~5 h" y
0 W3 I% p+ [- s这是它的交易ID:- ~1 @- A- y& }6 m: H
2 i1 _7 d% P4 e! I7 B8 r0 M
如果是立即查询此交易,会收到该交易不在区块链中的消息:
* E8 e7 F! ]2 }% O
6 k7 N( C7 f2 z/ F
- m. [- E# i0 |, V9 w* ]( C I: F如果你准备好了,可以在主网上进行真实的交易,使用的函数与上面完全相同。您也可以购买CryptoKitties等产品。像BlockchainContractValue 这样的函数可以用于任何智能合约(目前只限以太坊),并且设置为立即理解ERC-20和ERC-721代币。 $ ^% k" J2 b9 ~4 O* j' E
普通加密功能 4 q/ d' Y( W$ i3 _8 N
和区块链打交道涉及大量加密功能,其中一些是版本12.0中的新功能(特别是处理椭圆曲线)。版本12.0还扩展了非区块链加密功能。例如,我们现在有了直接处理数字签名的函数。这将使用上面的私钥创建数字签名:
" z4 g2 c: G/ M. p5 i
* o, T; f& v' [# C/ o现在任何人都可以使用相应的公钥验证消息:
# Y/ i( Z, l1 ~# ^4 g0 q( ]
& z$ ^2 |1 L( ?9 |+ O
! P% l# O# m0 q* a: w
3 x' [2 v# l% E9 A2 R$ s0 b" g* L" O" J+ l* X1 c @- T( a: Q
这是派生密钥的一个版本,适用于各种身份验证方案:/ M$ W9 C1 V' h! b6 D7 t5 A! q
" W! v2 ?6 h. ^1 J+ Z" @
与金融数据源连接 ' D$ o/ l1 m- _7 a9 K( [& B* o
Wolfram知识库包含各种金融数据。通常有一个金融实体(如股票),然后有一个属性(如价格)。以下是Apple股票价格的完整日常历史记录(它在对数尺度上最令人印象深刻):
0 C8 |3 G8 |: x: [ \Wolfram知识库中的金融数据可以从Wolfram语言中直接获取,该金融数据库不断更新,但并不是实时的(大多有15分钟延迟),并且不会呈现许多金融交易者需要的所有细节。因此,对于专业的金融用途,我们开发了 Wolfram Finance Platform。在版本12.0中,可以直接访问Bloomberg和路透社的金融数据源。 8 P0 { s- M' u# K5 v
Wolfram语言中具有与Bloomberg和路透社连接的架构,但必须拥有Wolfram Finance Platform及相应的Bloomberg或Reuters订阅才会被激活,这是我们构建Wolfram语言的方式。假设你有这些服务,下面连接到彭博终端(BloombergTerminal)服务:
" o5 H, w: [5 L' _* J! E! i4 q& n3 v2 s& \$ c5 H ]
由彭博终端负责的所有金融工具现在都可以作为Wolfram语言中的实体使用:6 ]; u6 H5 C2 O( \
! ^$ p7 U5 b2 n% m' v1 b8 i现在我们可以询问该实体的属性:
- t' C, [% b6 X0 n6 s8 q共有超过6万个实体可从彭博终端访问:
5 t$ R% x, j) Z4 I. v9 [3 J) Z9 y' _+ b1 |) n+ M7 @5 ?4 Y, }2 ?6 U& B
8 F, ^1 m3 s" V; o5 g. u) o+ u这里有5个随机示例(是的,看上去很详细;这些名字来自Bloomberg而不是我们):
2 G8 E8 u, M8 w2 R2 a: ?
2 d7 C; v/ G& n6 |6 }我们支持Bloomberg Terminal服务,BloombergData License服务和Reuters Elektron服务。人们现在可以执行相当复杂的任务,比如设置一个连续的任务来异步接收数据,并在每次有新的数据进入时调用“Handler函数”:
9 w7 x5 h' r F! w4 t/ t1 p7 [! X" F
软件工程和平台更新
9 c$ n4 t: \- y9 D, n/ f/ X# p关于Wolfram语言中的新函数和新功能我已经谈了很多。但是Wolfram语言的底层架构进展如何呢?在这方面,我们也一直在不懈努力。例如,从版本11.3到版本12.0,我们已设法修复了近8000个错误,使Wolfram语言的很多方面变得更快更鲁棒。总的来说,我们一直在强化系统的软件工程,例如将初始下载大小降低近10%(在已经添加了所有功能的情况下)。(我们还做了很多事情,比如改进从云中预取知识库元素的预测,使得您在需要类似数据时,它很可能已经缓存在到了您的计算机上。)
}) T/ P" u+ v9 d% o; M8 n多年来,操作系统不断升级,为了利用其最新功能,应用程序也必须随之更新,这一直是计算领域发展的一大特点。针对Mac笔记本界面的重大更新,我们已经倾注了几年心血,最终在版本12.0中成型。作为更新的一部分,我们对20多年来开发和完善的大量代码进行了重写与重构,但结果是在版本12.0中,Mac上我们系统的所有内容都完全是64位,并使用最新的Cocoa API。这意味着笔记本前端速度明显更快,并且还可以超出之前的2GB内存限制。
5 F% ?* O0 l7 r1 t6 S% ^对Linux平台也有更新,现在笔记本界面完全支持Qt 5,它允许所有渲染操作“无头”地进行,无需任何X服务器,这大大简化了Wolfram Engine在云端的部署。(对于Windows系统,版本12.0还尚未实现的高dpi支持,但很快就会到来。) 4 V8 n+ `8 R3 A) f. \5 R8 x$ f
Wolfram Cloud的开发在某些方面与Wolfram语言和Wolfram Desktop应用程序的开发是分开的(尽管为了内部兼容性,我们在两个环境中同时发布了12.0版本)。但是自从版本11.3于去年发布以来,WolframCloud取得了巨大的进步。
$ Y3 C, h' |! y: {; T# @* J特别值得一提的是,云笔记本现在支持更多的界面元素(包括如嵌入式网站和视频,这甚至在台式机笔记本中尚不可用),并且其稳健性和速度大大提高。(使我们的整个笔记本界面在Web浏览器中工作并非易事,甚至可以称为软件工程的一大壮举。在版本12.0中还有一些非常复杂的策略,用于维护一致的快速加载缓存,以及完整的符号DOM表示。) 5 C! v0 d4 T! [0 A1 z
在版本12.0中,现在只需一个简单的菜单项(文件>发布到云...)即可将任何笔记本发布到云端。一旦笔记本发布了,世界上任何人都可以与之互动,并制作自己的副本,从而进行编辑。
) ^6 p# i+ }: x/ g/ W云技术已经深入到Wolfram语言的方方面面。除了与云知识库的无缝集成,与区块链连接的功能之外,还有一些便利功能,例如Send To ...通过电子邮件发送任何笔记本,如果没有直接的电子邮件服务器连接,则使用云。 & k2 J5 z7 z4 S6 {. X1 G0 \
还有很多
. J4 G/ X$ N U& I( ]尽管我已经写了这么多,但还远远不能详尽版本12的所有新功能。与我们团队的其他成员一起,我已经在版本12.0上努力工作很久了,但是讲到这些新功能还是让人激动不已。 W5 }1 K1 v% [
版本间的连贯一致性(Coherency)至关重要,这也令我们倾注了大量心血。我们所添加的所有内容都经过精心设计,使之与已经存在的内容保持一致。从30多年前Wolfram语言的第一个版本开始,我们一直遵循相同的核心原则,这也正是我们在保持长期兼容性的同时仍能不断成长的原因之一。
$ B) J6 d/ A! O对于每个新版本,如何确定功能开发的优先顺序总是一件困难的事,但我对我们为版本12.0做出的选择非常满意。在过去的一年里,我做过很多场讲座,在谈到将要出现的功能时,我惊讶于自己多少次说到这一句:“好吧,碰巧这将是版本12.0的一部分!”
$ G( w( Y8 F+ F$ T) ^0 Q% ^6 n) y% p我个人一直在使用版本12.0的内部测试版,对它的许多新功能都已经了如指掌,并且受益良多。所以我很高兴今天终于到来,12.0的正式版本发布了,任何人都能够和我一样,随时随地使用它。 . u; D9 d6 a# C+ h5 m
/ M4 V# _$ }( h- [4 g* p. f% w
^# @5 u# B, E. v) Q 8 V9 M! F$ l% T5 A
# |% P4 i7 J1 i3 A1 Z4 s% ?$ _ |