此为 Mathematica 4 文档,内容基于更早版本的 Wolfram 语言
查看最新文档(版本11.1)

2.5.10 计算的跟踪

Mathematica 运行的标准方式是将任何表达式看作输入,计算它们的值 并给出结果. 为了观察 Mathematica 的运行过程,不仅需要知道运行结果, 还要知道中间的计算步骤.

跟踪表达式的计算

立即求出 1+1 的结果 2

在加法前计算 2^3

每个子表达式的计算显示在不同的子列中

Trace[expr] 给出 expr 计算过程中涉及的所有中间表达式. 除过特别简单的情形,所产生的这些中间表达式非常多,这使 Trace 的返回值不容易理解. Trace[expr, form] 可以滤掉一部分 Trace 所记录的表达式,仅保存与模式 form 匹配的那一部分表达式.

阶乘函数的递推定义

这里给出了计算 fac[3] 过程中的所有中间表达式,结果相当复杂

此处仅显示了形如 fac[n_] 的表达式

Trace 中可以任意指定模式

Trace[expr, form] 仅选择出 expr 计算过程中与模式 form ꪧ匹配的那些表达式.
需要跟踪 fac 等函数的调用情况时,就可以用 Trace 去挑选出形如 fac[n_] 的表达式,也可以用模式 f[n_, 2] 去选出具有某一自变量的调用.
典型的 Mathematica 程序不仅有函数调用,而且有变量赋值, 控制结构等语句. 这些语句都被看作为表达式,所以能在 Trace 中用模式选出任何语句. 例如,模式 k = _ 可以选出对k的所有赋值.

显示了对 k 的赋值序列

Trace[expr, form] 能选出 expr 计算过程中出现的表达式,也包括 expr 计算中所有调用的函数的计算过程中出现的那些表达式.

定义一个函数

查看 h 计算过程中产生的表达式

Trace 可以监视自定义函数和内部函数计算的中间步骤,且内部函数 的中间步骤序列与 Mathematica 的版本有关.

使用Trace的一些方式

Trace 函数的返回值是一个列表,它反映了Mathematica 的计算过程, 在这个列表中的表达式按照计算过程中产生的顺序排列. 大部分情况下, Trace 返回值列表且有嵌套结构,这反映了计算过程中的结构. 在 Trace 返回值列表中的子列表代表一个 Mathematica 表达式的计算序列,这个序列 的不同元素代表同一表达式的不同形式.通常一个表达式的计算涉及到几个其它 表达式的计算. 每个计算对应于列表中的一个子列.

这里给出一个赋值序列

这里产生一个反映 a[i] 变换序列的计算链

y+x+y 化简过程中产生的序列反映这个计算链中的元素

函数 f 的每个变量有一个计算链,这些链由子列给出

每个子表达式的计算链在不同的子列中给出

跟踪一个嵌套表达式给出了一个嵌套列表

Mathematica 表达式的计算中有两种情况需辅助计算,第一种情况是 要计算该表达式所包含的一些子表达式,第二种情况在表达式计算中有一些 规则,这些规则又要求计算其它一些表达式. 这两种辅助计算都反映在 Trace 返回值的子列中.

这是由 fg 的变量的计算所产生的子计算

附加了一个条件的函数

fe[6] 的计算涉及到与该条件有关的子计算

在跟踪由递推定义的函数计算时,就会得到嵌套列表. 其原因是函数的形式在递 推过程中反复出现. 例如当定义 fac[n_] := n fac[n-1] 时,计算 fac[6] 时产生表达式 6fac[5], 其中 fac[5]是一个子表达式.

这是计算 fac 时产生的嵌套子列

由定义 fp[n-1] 可作为 fp[n] 的值来得到

子表达式中不出现 fp[n] ,因此没有子列表生成

这里给出 Fibonacci 数的递推定义

这里给出递推结束的条件

显示在 fib[5] 递推计算中的所有步骤

Mathematica 表达式计算的每一步可以看作一个变换规则的使用. 正如 2.4.10 中所述,Mathematica 中的规则与特定符号或标志相联系. 可以用 Trace[expr, f] 去观察与符号f相联系的变换规则作用于 expr 的计算步骤,在这种情况下,Trace 不仅给出了使用每个规则的表达式序列,而且给出了使用这些规则的结果. Trace[expr, form] 一般选出计算 expr 的所有步骤其中 form 与要计算的表达式匹配,或与所使用的规则相联系的标志匹配.

跟踪与特定标志联系的计算

仅显示与 fac[_] 匹配的中间表 达式

显示使用所有与 fac 有关的变换规则的计算

这是 log 函数的规则

跟踪 log[a b c d] 的计算过程,显示与 log 有关的所有变量

跟踪一些形式内部的转向

Trace[expr, form] 跟踪在计算 expr 过程任何点产生的与 form 匹配的表达式,也需跟踪在计算 expr 过程的某一部分产生的表达式. 通过设置 TraceOn -> oform 就可以仅跟踪与 oform 匹配的表达式计算,同样 TraceOff -> oform 就不跟踪这些计算.

显示计算的所有步骤

仅显示 fac 计算过程中的步骤

仅显示不在 fac 计算过程中的步骤

将规则运用到计算过程中遇到的表达式

Trace 仅给出计算 fib[5] 过程中所用到的 fib 的变量

Mathematica 函数 Trace 的返回值仅是一个标准的 Mathematica 表达式, 它可以由其它函数调用,这是 Trace 函数的一个强大功能. 但要注意 Trace 将列表中产生的所有表达式用 HoldForm 封装起来使其不计算. HoldForm 不在 Mathematica 标准输出中显示,但它仍在表达式的内部结构中存在.

这显示了计算过程中中间步骤的表达式

这些表达式用 HoldForm 封装,使得它们不被计算

Out[35]//InputForm=

Mathematica 的标准输出中, 有些难以区别哪些列表是与

Trace 的返回结构相关,哪些是正在计算的表达式这里的输入解决了上面的二义性问题

Out[37]//InputForm=

Trace 中使用变换规则时,在用 HoldForm 封装之前先计算结果

在复杂的计算中,由 Trace 返回的列表结构可能是相当复杂的. 当使用 Trace[expr, form] 时,Trace 给出仅与模式 form 匹配的表达式列表. 不管给出的是什么模式,列表的结构是相同的.

这里显示在 fib[3] 计算中出现 的所有 fib[_]

这里仅显示了fib[1],但列表的结构与 fib[_] 的相同

可选项 TraceDepth -> n 使 Trace 仅跟踪到嵌套列表中的第 n 层, 用这种方式能观察到计算过程中的主要步骤,而忽然略一些细节. 用 TraceDepthTraceOff 可以不跟踪计算过程中的一些步骤, 使 Trace 的运行加快.

这里仅显示了嵌套列表中前 2

跟踪层次的限制

Trace[expr, form] 得到计算 expr 过程中与 form 匹配的所有 表达式列表,还需要观察这些表达式的结果时,可以在 Trace 中设置可选项 TraceForward->True.

这里不仅显示了与 fac[_] 匹配 的 表达式,而且给出了它们的计算结果

Trace[expr, form] 能得到计算链中间的表达式,设置 TraceForward->True 可以令 Trace 包含计算链末尾的表达式. 设置TraceForward->All 可使 Trace 显示计算链中出现与 expr 匹配的表达式之后的所有表达式.

TraceForward -> All 来包含计算链中与 fac[_] 匹配后 的所有元素

通过设置 TraceForward,就可以在计算过程中有效地观察到某一特定表达式的计算. 有时不需要知道某一表达式的计算,而是关心它的生成过程,这 可以用可选项 TraceBackward 来实现. TraceBackward 显示一个计算链中某特定表达式之前的情况.

这里表示 120 来源于 fac[10] 的计算中对 fac[5] 的计算

这里显示了与产生 120 有关的计算链

TraceForwardTraceBackward 可以使我们观察计算链中一个表达式前后的情形, 有时还需要观察包含某一特定表达式的计算链,可以用 TraceAbove 来完成这一任务. 可选项 TraceAbove->TrueTrace 包含相关计算链的首尾表达式. TraceAbove->All Trace 包含这个计算链中的所有表达式.

这里包含了 120 计算链中的首尾表达式

显示计算 fib[5] 过程中生成 fib[2] 的所有方式

跟踪表中可选项的设置

Trace[expr, ... ] 工作的基本方式是截取 expr 计算过程中所遇到的每一个表达式,然后用各种判据去确定是否记录该表达式. Trace 一般在函数变量计算完成后截取表达式,通过使用可选项 TraceOriginal->True 能使 Trace 跟踪函数变量计算之前的表达式.

这里包括了变量计算前后与 fac[_] 匹配的表达式

Trace 得到的列表结构中一般仅包含非平凡计算链中的表达式, 例如单个符号自身的计算不包括在内. 但设置了 TraceOriginal->True 后, Trace 就跟踪计算过程中的每一个表达式,包括平凡计算链中的表达式.

这里 Trace 跟踪所有表达式,包括平凡计算链内的表达式

Trace的附加可选项

当使用 Trace 去考察程序的执行时必然涉及到局部变量的处理. Mathematica 中的 Module 等产生一些新符号来表示局部变量. 于是,即使在原代码中变量名为 x, 在执行过程中会被重命名为 x$nnn 等.
根据 Trace[expr, form] 的设置规律,出现在 form 中的 x 将与 expr 执行中出现的所有形如 x$nnn 的符号相匹配. 例如,Trace[expr, x = _] 可以跟踪原程序中所有变量 (全局或局部) x 的赋值过程.

禁止与局部变量匹配

有时仅需要跟踪全局变量 x 不跟踪名为 x 的局部变量,这可以通过设置可选项 MatchLocalNames -> False 来实现.

跟踪所有名为 x$nnn 变量的赋值

仅对全局变量 x 的赋值进行跟踪

Trace 函数进行彻底的计算,返回值是代表这个计算过程的结构. 在很长的计算中,有必要跟踪计算进程. 函数 TracePrintTrace 相似,但 它显示所遇到的表达式,而不像Trace 哪样保存这些表达式去产生一个结构.

显示在 fib[3] 计算中出现的表达式

TracePrint 显示的表达式序列与 Trace 返回的列表结构中的表达式序列相对应, TracePrint 输出中的缩进形式与 Trace 列表结构中的嵌套相对应.在 TracePrint 中也可以使用 Trace 的可选项 TraceOn, TraceOff TraceForward, 但由于 TracePrint 随着进程产生输出,所以它不能用可选项 TraceBackward. 另外,总是把 TracePrint 设置为 TraceOriginal->True.

跟踪计算函数

fac[10] 的计算过程中出现 fac[5] 时显示一个对话

在对话中通过查看 "stack" 就可以发现在何处

从对话中返回,给出 fac[10] 的计算结果

函数 TraceDialog 可以暂停计算,并对当时环境进行处理.例如得到 计算过程中中间变量的值,甚至重新设置它们的值. 当然还有许多辅助 作用,大部分都与模式或模块有关.
TraceDialog 的功能是在一个表达式列中调用 Dialog 函数,Dialog 函数 将在 2.13.2 节仔细讨论.在调用 Dialog 时就开始了一个具有自已输入和输出 列的 Mathematica 辅助进程.
跟踪计算时,一般需要对所得到的表达式运用一个任意函数. TraceScan[f, expr, ... ]f 作用于所出现的每个表达式上,用HoldForm 封装的表达式不计算.
TraceScan[f, expr, ... ] 中,f 在表达式被计算之前作用于该表达式,而 TraceScan[f, expr, patt, fp] 在计算之前作用于 f,而在计算之后作用于 fp.