计算的跟踪
Mathematica 运行的标准方式是将任何表达式看作输入,计算它们的值并给出结果. 为了观察 Mathematica 的运行过程,不仅需要知道运行结果,还要知道中间的计算步骤.
| Trace[expr] | 产生在 expr 计算过程中使用的表达式列表 |
| Trace[expr,form] | 仅包括与模式 form 匹配的表达式 |
跟踪表达式的计算.
立即求出

的结果

.
| Out[1]= |  |
在加法前计算

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

过程中的
所有 中间表达式. 结果相当复杂.
| Out[5]= |  |
此处仅显示了形如

的中间表达式.
| Out[6]= |  |
| Out[7]= |  |
Trace[expr, form] 仅选择出 expr 计算过程中与模式 form 匹配的那些表达式.
需要跟踪
等函数的调用情况时,就可以用 Trace 去挑选出形如
的表达式. 也可以用模式
去选出具有某一自变量的调用.
典型的 Mathematica 程序不仅有"函数调用",如
,而且有变量赋值、控制结构等语句. 这些语句都被看作为表达式,所以,能在 Trace 中选出任何 Mathematica 程序元素. 例如,模式
可以选出对符号
的所有赋值.
显示了对

的赋值序列.
| Out[8]= |  |
Trace[expr, form] 能选出 expr 计算过程中出现的表达式. 这些表达式不必直接出现在给出的 expr 形式中. 它们也有可能在 expr 计算的部分过程中被调用的时候出现.
查看

计算过程中产生的表达式.
| Out[10]= |  |
用 Trace 可以监视自定义函数和 Mathematica 内部函数计算的中间步骤. 而且,Mathematica 内部函数的中间步骤序列与 Mathematica 具体版本的实现和优化细节有关.
使用 Trace 的一些方式.
Trace 函数的返回值是一个列表,它反映了 Mathematica 的计算过程. 在这个列表中的表达式按照计算过程中产生的顺序排列. 大部分情况下,Trace 返回的列表具有嵌套结构,这反映了计算过程中的"结构".
其基本思想是,在 Trace 返回值列表中的子列表代表一个 Mathematica 表达式的计算序列. 这个序列的不同元素代表同一表达式的不同形式. 通常一个表达式的计算涉及到几个其它表达式的计算. 每个计算对应于由 Trace 返回的结构中的一个子列.
| Out[11]= |  |
| Out[12]= |  |
在

化简过程中产生的序列反映这个计算链中的元素.
| Out[13]= |  |
函数

的每个变量有一个计算链,这些链由子列给出.
| Out[14]= |  |
| Out[15]= |  |
| Out[16]= |  |
在 Mathematica 表达式的计算中有两种情况需辅助计算. 第一种情况是要计算该表达式所包含的一些子表达式,第二种情况在表达式计算中有一些规则,这些规则又要求计算其它一些表达式. 这两种辅助计算都反映在 Trace 返回值的子列中.
这是由

和

的变量的计算所产生的子计算.
| Out[17]= |  |

的计算涉及到与该条件有关的子计算.
| Out[19]= |  |
在跟踪由递推定义的函数计算时,就会得到嵌套列表. 其原因是函数的形式在递推过程中反复出现.
例如,当定义
时,计算
时产生表达式
,其中
是一个子表达式.
这是计算

时产生的嵌套子列.
| Out[20]= |  |
由定义

可作为
fp[n] 的值来得到.
子表达式中不出现
fp[n],因此没有子列表生成.
| Out[22]= |  |
| Out[24]= |  |
显示在

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

匹配的中间表达式.
| Out[26]= |  |
显示使用所有与符号

有关的变换规则的计算.
| Out[27]= |  |
这是

函数的规则.
跟踪

的计算过程,显示与

有关的所有变量.
| Out[29]= |  |
关闭某些形式内部的跟踪.
Trace[expr, form] 跟踪计算 expr 过程任何点产生的与 form 匹配的表达式. 有时候,也需要跟踪在计算 expr.
通过设置 TraceOn->oform,就可以仅跟踪与 oform 匹配的表达式计算. 同样,通过设置 TraceOff->oform,就可以不用跟踪与 oform 匹配的表达式计算.
| Out[30]= |  |
仅显示

计算过程中的步骤.
| Out[31]= |  |
仅显示不在

计算过程中的步骤.
| Out[32]= |  |
| Trace[expr,lhs->rhs] | 找出在 expr 计算过程中遇到的与 lhs 匹配的所有表达式,并用 rhs 替换它们 |
将规则运用到计算过程中遇到的表达式.
令
Trace 仅给出计算

过程中所用到的

的变量.
| Out[33]= |  |
Mathematica 函数 Trace 的返回值基本上是一个标准的 Mathematica 表达式. 它可以由其它函数调用,这是 Trace 函数的一个强大功能. 但要注意,Trace 将列表中产生的所有表达式用 HoldForm 封装起来使其不计算. HoldForm 不在Mathematica 标准输出中显示,但它仍在表达式的内部结构中存在.
| Out[34]= |  |
Out[35]//InputForm= |
| |  |
在
Mathematica 的标准输出中,有些难以区别哪些列表是与
Trace 的返回结构相关,哪些是正在计算的表达式.
| Out[36]= |  |
Out[37]//InputForm= |
| |  |
| Out[38]= |  |
在复杂的计算中,由 Trace 返回的列表结构可能是相当复杂的. 当使用 Trace[expr, form] 时,Trace 给出仅与模式form 匹配的表达式列表. 不管给出的是什么模式,列表的结构是相同的.
这里显示在

计算中出现的所有

.
| Out[39]= |  |
这里仅显示了

,但列表的结构与

的相同.
| Out[40]= |  |
可选项 TraceDepth->n 使 Trace 仅跟踪到嵌套列表中的第 n 层. 用这种方式,能观察到计算过程中的主要步骤,而忽略一些细节. 用 TraceDepth 或 TraceOff 可以不跟踪计算过程中的一些步骤,使 Trace 的运行加快.
| Out[41]= |  |
跟踪层次的限制.
用 Trace[expr, form] 得到计算 expr 过程中与 form 匹配的所有表达式列表. 有时,不仅需要观察这些表达式,也需要通过这些表达式计算得到的结果. 这可以在 Trace 中设置可选项 TraceForward->True 来实现.
这里不仅显示了与

匹配的表达式,而且给出了它们的计算结果.
| Out[42]= |  |
用 Trace[expr, form] 能得到计算链中间的表达式,设置 TraceForward->True 可以令 Trace 包含计算链末尾的表达式. 设置 TraceForward->All 可使 Trace 显示计算链中出现与 form 匹配的表达式之后的所有表达式.
| Out[43]= |  |
通过设置 TraceForward,就可以在计算过程中有效地观察到某一特定表达式的计算. 有时不需要知道某一表达式的计算,而是关心它的生成过程. 这可以用可选项 TraceBackward 来实现. TraceBackward 显示一个计算链中某特定表达式之前的情况.
| Out[44]= |  |
这里显示了与产生

有关的计算链.
| Out[45]= |  |
TraceForward 和 TraceBackward 可以使我们观察计算链中一个表达式前后的情形,有时还需要观察包含某一特定表达式的计算链,可以用 TraceAbove 来完成这一任务. 可选项 TraceAbove->True 令 Trace 包含相关计算链的首尾表达式. 使用 TraceAbove->All 令 Trace 包含这个计算链中的所有表达式.
这里包含了

计算链中的首尾表达式.
| Out[46]= |  |
显示计算

过程中生成

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

匹配的表达式.
| Out[48]= |  |
Trace 得到的列表结构中一般仅包含非平凡计算链中的表达式,例如,单个符号自身的计算不包括在内. 但设置了TraceOriginal->True 之后,Trace 就跟踪计算过程中的每一个表达式,包括平凡计算链中的表达式.
这里
Trace 跟踪所有表达式,包括平凡计算链内的表达式.
| Out[49]= |  |
Trace 的附加可选项.
当使用 Trace 去考察程序的执行时必然涉及到局部变量的处理. 正如 "模块工作方式" 所述,Mathematica 中的Module 等产生一些新符号来表示局部变量. 于是,即使在原代码中变量名为
,在执行过程中会被重命名为
等.
跟踪 Trace[expr, form] 的设置规律,出现在 form 中的 x 将与 expr 执行中出现的所有形如
的符号相匹配. 例如,使用 Trace[expr, x=_] 可以跟踪原程序中所有变量(全局或局部)x 的赋值过程.
禁止与局部变量匹配.
有时,仅需要跟踪全局变量 x,不跟踪名为 x 的局部变量,这可以通过设置可选项 MatchLocalNames->False 来实现.
跟踪所有名为

变量的赋值.
| Out[50]= |  |
| Out[51]= |  |
Trace 函数进行彻底的计算,返回值是代表这个计算过程的结构. 在很长的计算中,有必要跟踪计算进程. 函数TracePrint 与 Trace 相似,但它显示所遇到的表达式,而不像 Trace 那样保存这些表达式去产生一个结构.
显示在

计算中出现的表达式.
| Out[52]= |  |
TracePrint 显示的表达式序列与 Trace 返回的列表结构中的表达式序列相对应. TracePrint 输出中的缩进形式与Trace 列表结构中的嵌套相对应. 在 TracePrint 中也可以使用 Trace 的可选项 TraceOn、TraceOff 和TraceForward. 但由于 TracePrint 随着进程产生输出,所以它不能用可选项 TraceBackward. 另外,总是把 TracePrint 设置成 TraceOriginal 值为 True.
跟踪计算函数.
在

的计算过程中出现

时显示一个对话.
| Out[53]= |  |
在对话中通过查看"stack"就可以发现当前在何处.
| Out[54]= |  |
从对话中返回,给出

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