Mathematica 9 is now available

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.



Any questions about topics on this page? Click here to get an individual response.Buy NowMore Information
THIS IS DOCUMENTATION FOR AN OBSOLETE PRODUCT.
SEE THE DOCUMENTATION CENTER FOR THE LATEST INFORMATION.