Mathematica学习笔记·三

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] 将 exprrules 重复替换不再改变,符号是两个英文正斜杠+英文句号,即 //.
  • ReplacePart[expr,{{i1,j1,...}->new1,...}] 将 newn 替换 expr 中位置是 {in,jn,...} 处的元素​
  • ReplaceList[expr,rules,n] 将 exprrules 替换的所有可能结果列表表示出来,列表中最多有 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]=rhsf[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就这么没了啊,成天💊,结果真💊了)

404小队.jpg

消息盒子

# 暂无消息 #

只显示最新10条未读和已读信息