Mathematica学习笔记·三
Mathematica第二原理:计算即重写
根据上节笔记中的开头,我简单说明了下模式匹配,这节笔记我将会记录一下规则带入相关内容
重写规则
所谓重写,即是将匹配成功的模式改写成为其他形式
而Mathematica就是由一大堆重写规则组成的
重写规则的一般形式是:
- (模式)(重写符号)(重写结果)
其中重写符号有四种:
- -> 规则(Rule)
- :> 规则延迟(RuleDelayed)
- = 赋值(Set)
- := 设置延迟(SetDelayed)
规则与规则延迟是一种较为安全的重写机制,因为只有在你应用它们的时候它们才起作用
而赋值和设置延迟则是添加到系统内部的一种重写规则,一旦添加进去就立刻起作用,并且永远存在,除非你手动移除它们,而常见的移除相关函数如下:
- Unset[f] 去掉函数(或符号) f 定义的任何规则,符号是英文等号+英文句号,即 =.
- Clear[f] 清除函数(或符号) f 的值或定义
- ClearAll[f] 清除函数(或符号) f 相关联的所有的值、定义、属性、信息或缺省值
- Remove[f] 彻底去除函数(或符号) f ,使得Wolfram语言无法再识别
替换规则
提到替换规则,我们则需要知道一些常用函数,如下所示:
- Replace[expr,rules,levelspec] 将 expr 中指定的层数 levelspec (默认是所有层)用 rules 进行替换
- ReplaceAll[expr,rules] 将 expr 尽可能的用 rules 进行替换,符号是英文正斜杠+英文句号,即 /.
- ReplaceRepeated[expr,rules] 将 expr 用 rules 重复替换至不再改变,符号是两个英文正斜杠+英文句号,即 //.
- ReplacePart[expr,{{i1,j1,...}->new1,...}] 将 newn 替换 expr 中位置是 {in,jn,...} 处的元素
- ReplaceList[expr,rules,n] 将 expr 用 rules 替换的所有可能的结果用列表表示出来,列表中最多有 n 个结果(默认是所有结果)
(实际上就是Replace各种形式的变种,ReplacePart就是Replace加上Map或者MapAt,其他的也都差不多)
值得一提的是:在Wolfram语言中,对规则命名后,就可以像操作符号表达式一样对一组规则进行操作
定义规则
替换运算将规则作用于一个表达式,但经常需要在可能的情况下自动使用变换规则,这可以通过对Wolfram语言表达式和模式赋值来实现,赋值表明适当形式的表达式出现时就使用规则,如:
- expr /. lhs->rhs 将规则用于一个表达式
- lhs = rhs 赋值使规则可能时立即使用
除模块(Module) 和块(Block) 等一些内部结构外,在Wolfram语言中的所有赋值都是永久的,若没有清除或改写他们,在Wolfram语言的同一个进程中所有赋值保持不变,赋值的永久性意味着使用时要特别慎重,一个在使用Wolfram语言时,常犯的错误是在后面使用x时忘记或误用了前面x的赋值,为了减少这一错误,可能时尽量避免赋值而用替换运算等,也可以在任务完成后立即使用Unset(即符号=.) 或Clear去清除所赋的值
在Wolfram语言编程中,经常需要不断改变一些变量的值,Wolfram语言在一些常用情况提供了通过增量修改变量的方法:
- i++ i加1
- i-- i减1
- ++i 先给i加1
- --i 先给i减1
- i+=di i加di
- i-=di i减di
- i*=di i乘以di
- i/=di i除以di
如果需要同时对几个变量赋值,也有如下方法:
- x=y=value 对x和y赋同一值
- {x,y}={value1,value2} 对x和y赋不同的值
- {x,y}={y,x} 交换x和y的值
在Wolfram语言编程时,通过逐步增加元素的方法来构造一个集合石十分方便的,这可以用前加于(PrependTo) 和附加(AppendTo) 来实现:
- PrependTo[v,elem] v前加元素elem
- AppendTo[v,elem] v后加元素elem
- v={v,elem} 构造一个包含elem的嵌套列表
在多种计算中,需要建立包含一列带标号的表达式的阵列,在Wolfram语言中得到的阵列的一种途径是定义列表,你可以定义一个列表,如a={x,y,z,…},然后就可以用a[[i]] 来调用它的元素或用a[[i]]=value来修改它,这一方式的缺陷时必须给出它所有的元素,定义阵列的一个简便方法时在需要时给出它的一些元素,这可以通过定义表达式如a[i] 来实现,可以把a[i]当作一个带索引或带下标的变量:
- a[i]=value 增加变量或改动变量的值
- a[i] 调用变量
- a[i]=. 删除变量
- ?a 显示定义过的值
- Clear[a] 清除定义过的值
- Table[a[i],{i,1,n}] 或 Array[a,n] 转换为一个列表List操作带标号的变量
在表达式a[i]中,i并不一定要是整数,事实上,Wolfram语言允许它是任意表达式,通过使用符号性的标号,可以在Wolfram语言中构造一些简单的数据库等
定义函数
定义函数表明当Wolfram语言遇到与模式相匹配的表达式时,它将用函数来代替该表达式
- f[x] = value 对指定表达式x的定义
- f[x_] = value 对任何涉及到x的表达式的定义
定义f[x]可以看作对阵列f的元素赋值,定义f[x_]可以看作对一个具有任意标号的阵列的一系列元素赋值,事实上,可以把函数看作具有任意变动标号的元素的阵列
从数学的观点看,f是一个映射,当定义f[1]和f[2]等时,就是给出其定义域中离散点的像,而f[x_]是给出f在一连续流点集上的像
Wolfram语言允许我们对任何表达式或模式定义变换规则,可以将具体表达式的定义与像等的定义相结合
许多数学函数可以通过将特定和一般定义相结合的方式给出,例如阶乘函数,在Wolfram语言中已经给出了这一函数n!,但可以用Wolfram语言的定义自行建立这个函数
定义顺序
在Wolfram系统中给出一系列定义时,一部分总是比另一部分更一般一些,Wolfram系统中的原则是:一般定义在特殊定义之后使用。 这意味着,规则的特例总是在一般情况之前使用。
这种行为对于定义函数节中给出的函数特别重要,不管输入方式如何,Wolfram系统总是把特殊规则放在一般规则之前,这意味着,当Wolfram系统在计算具有一般规则和特殊规则的表达式时,先测试特殊规则,当它不能用时,再使用一般规则。
Wolfram系统总是将特殊规则放在一般规则之前
Wolfram系统中定义的处理:
如果Wolfram系统不遵循上述原则,则特殊规则将会被一般规则所屏蔽。尽管在许多情况下,Wolfram系统能判断哪一个规则更一般一些,但总有些例外,例如在含有两个ReplaceAll (即/;) 的规则中,就无法确定那一个更一般,事实上也没有明确的顺序,在顺序不清楚时,Wolfram系统总是按照输入顺序保存规则
定义形式
Wolfram语言中有两种赋值形式:立即赋值和延迟赋值,其主要区别是什么时候计算右式的值,立即赋值是在赋值时立即计算,而延迟赋值在赋值时并不计算右式,而是在需要右式的值时才进行计算
- lhs = rhs (立即赋值) 赋值时立即计算 rhs
- lhs := rhs (延迟赋值) 每次需要 lhs 时计算 rhs
同样的,Wolfram语言中也有两种变换规则形式:立即变换和延迟变换
- lhs -> rhs 给出规则后就计算 rhs
- lhs :> rhs 使用规则时计算 rhs
在用SetDelayed(即:=) 定义的函数中,调用时函数的值就会被反复计算,但一些计算中,需要将同一组函数使用多次,这时就可以让Wolfram语言记住这些函数值以节省时间,接下来给出定义这种函数的方法:
- f[x_] := f[x] = rhs 定义一个保存已有值的函数
注:关于记住函数值这里存在一个权衡,在记住了一些函数值时,查找就比计算快,但这需要占用内存。通常当重复计算的代价很大时保存函数值,且需要保存的函数不宜太多。
定义关联
在Wolfram语言中,f[args]=rhs
和f[args]:=rhs
会将对象f
和你的定义相关联,也就是说,当输入?f
时,就会显示该定义,一般我们把符号f
作为标头的表达式称为f
的下值(downvalue)
Wolfram语言也支持上值(upvalue),上值可以把不直接作为表头的符号与定义相关联,同样的,我们可以将任意赋值和符号相关联
- f[args] := rhs 定义 f 的下值
- f[g[args],…] ^:= rhs 定义 g 的上值
- f /: lhs = rhs 将 rhs 赋给 lhs,并将赋值和符号 f 相关联
示例如下:
- f[g] ^= value 让赋值与 g 相关联而不是与 f 相关联
- f[g[args]] ^= value 同上
- f[g] ^:= value 让延迟赋值与 g 相关联
- f[g[args]] ^:= value 同上
- f[arg1,arg2,…] ^= value 让赋值与所有 argi 的标头相关联
- f[…] := rhs f 的下值
- f /: f[g[…]][…] := rhs f 的下值
- g /: f[…,g,…] := rhs g 的上值
- g /: f[…,g[…],…] := rhs g 的上值
上值的典型用法是建立特定对象的属性数据库,使用上值可以把对象的定义与所关心的相关联,而不是与你指定的属性相关联
文章于2024.9.2编写,2024.10.22完成
(2024.11.1添加图片,怎么少前1就这么没了啊,成天💊,结果真💊了)