发现一个Trick,请来分析分析原理
进行如下替换操作a - b + (a - b) c /. a - b -> x结果是
(a - b) c + x
按照帮助 Applying Transformation Rules 条目的介绍,
The replacement expr/.rules tries each rule just once on each part of expr.
要想进行 重复迭代替换,需要这么做
a - b + (a - b) c //. a - b -> x
但问题来了,如下过程,
a + a b /. a -> x
倒是把a给全部替换掉了
那么这两个之间有什么本质区别呢?
我理解 /. 不进行迭代替换是为了避免这种情形
log /. log -> log + log
但我觉得最早那个表达式中,两个 a-b 是完全独立的,应该在第一次扫描是就匹配上的,所以应该都替换掉才合理,第二个 a-b 并不是在第一次替换的基础上生成的。
大家有什么看法呢? 本帖最后由 ggggwhw 于 2011-1-10 22:18 编辑
In:= (a + b - c) + (a - c) /. a - c -> x
Out= 2 a + b - 2 cIn:= (a + b - c) + (a - 2 c)*d /. a - c -> x
Out= b + (a - 2 c) d + xIn:= (a + b - c) + (a - c)*d /. a - c -> x
Out= b + (a - c) d + x
In:= (a + b - c) + (a - c) /. a - c -> x
Out= 2 a + b - 2 c
可见在替换之前,mathematica 应该是先进行了一些运算的. 2# ggggwhw
第三例中 a-c 分明被保留着且应该匹配 上面几例的形式类似但是他们的FullForm形式却能看出差别.
mathematica 会将你输入的表达式先改写成FullForm的形式,然后再进行替换,In:= (a b)^2 /. a b -> x
Out= a^2 b^2In:= (a b)^2 /. a^2 b^2 -> x
Out= x比如(ab)^2,
写成FullForm形式后,没有了小括号的概念,但是个有了复合函数的概念,在复合函数中逗号前后的多个量之间的关系是并列的,没有先后顺序.但是复合函数中的中括号决定了各个函数的优先级不同,
复合函数可以写成如下形式:
0,2,2,2,2],1],1,1,1,1]
其中0,1,2,3都表示第n层的复合函数字头,
/.a-b->x就是
第一步,看0[]是否和Plus]相同,若相同则替换,结束,若不相同,则进入下一步,
第二步,看多个1[]中是否有Plus],若有则替换,结束,若没有,则进入下一步,
第三步,看多个2[]中是否有Plus],若有则替换,结束,若没有,则进入下一步,
第四步,看多个3[]中是否有Plus],若有则替换,结束,若没有,则不替换,结束.
注意,在替换过程中,遇见了Plus],Plus,d],Plus],都会替换其中的Plus]的,但是遇见了Plus],Plus ,Times[-2, b] ],系统却无法识别. 本帖最后由 guocong89 于 2011-1-11 12:08 编辑
4# ggggwhw
那也就是说,/. 替换 是按照 语法树解析深度 执行的?
如果在一层上替换了,就不再进入下一层进行替换?a - b + (a - b) c // TreeForm
在第一层中匹配了 Plus那么第三层的就不再继续执行匹配替换了?
那么对于如下这个式子Hold // TreeForm执行替换Hold /. a -> x确实把所有层次的a都替换掉了。
这又怎么理解呢? 那么我想,mathematica 对待表达式和单个变量在替换时采取的是两种原则.
对于单个变量一次就替换完了,对于表达式一次替换一层. 本帖最后由 guocong89 于 2011-1-11 18:18 编辑
更诡异的是比较一下下面几个式子a^2 - Sin /. a^2 -> x
a b - Sin /. a b -> x
a/b - Sin /. a/b -> x
a + b - Sin /. a + b -> x
a - b - Sin /. a - b -> x从Attributes[{Plus, Times}]看不出来什么本质差别
最后这个测试也许能够说明点什么a b + Sin /. a b -> x
a b Sin /. a b -> x
(a + b) Sin /. a + b -> x
(a + b) + Sin /. a + b -> x输出x + Sin
x Sin
x Sin
x + Sin
也就是说mathematica 只认为在FullForm形式中,Times和Plus为一个层次,对于向Sin,Log,Power等复合函数所对应的层视而不见. 按深度替换,
Level
={}
exp/.a-b->sdfasdf
{}里面有几个a-b就替换几个a-b 9# HyperGroups
不对吧。。。
Level
a - b + (a - b) c + (a - b) d /. a - b -> x
输出
{a, -1, b, -b, a, -1, b, -b, a - b, c, (a - b) c, a, -1, b, -b,a - b, d, (a - b) d}(a - b) c + (a - b) d + x
恰恰相反,出现的a-b并没有替换,而是没有出现的被替换了
原因也可以理解。
Level是按照 Deep-First-Search 策略进行搜索的,返回表达式树的 按照 DFS 策略周游时 某个(或某些)深度层次上的子表达式。Level 和前面帖子里提到的 层 同一个概念。
所以 我就感觉很奇怪,a-b 明明就是 表达式的一个子树,为什么没有被替换呢?相反的,它按照Plus的flat特性,把本不是它的子树的 “首层a-b” 给替换掉了,所以感觉不符合逻辑,应该被修改掉。
突然发现刚刚的想法好弱智啊
本帖最后由 HyperGroups 于 2011-1-12 18:20 编辑10# guocong89
是嘛,看来还要再想想,刚好像测试了几个例子成功了嘛,哈哈
刚才的说法的确是愚蠢了,只是一个小范围的巧合
Level里就没有a-b
当然a-b/.a-b->x是能被替换的。 本帖最后由 HyperGroups 于 2011-1-12 18:29 编辑
。。。我在胡说八道了。。。呵呵,吃饭先。 12# HyperGroups
第0层就是表达式自己啊。。。 13# guocong89
回复这么快,哈哈,吃饭了先,晚上好好看看。 本帖最后由 HyperGroups 于 2011-1-12 21:08 编辑
一楼中
a - b + (a - b) c /. a - b -> x
这里第一个a-b 和 第二个 a-b似乎是不同的,之所以能替换到第一个是因为Plus的Flat属性,如果去掉这个属性,则替换后变成 a-b+xc,
a + a b /. a -> x 因为两个a同时被搜索到了,因此同时替换,替换一次,看起来像是替换了多次 15# HyperGroups
第一个替换没有什么疑问,我奇怪的是为什么第二个不替换。 现在回过头来看你10楼给出的反例。
Level
事实上Level是不会出现a-b的,如果把Plus的Flat属性去除,那么
a - b + (a - b) c /. a - b -> x
第一个a-b就不会被替换,
同样
a - b + (a - b) c + (a - b) d /. a - b -> x
第一个a-b就不会被替换,而第二个第三个a-b则被全部替换成
a-b+c x+ d x
因为Flat属性的影响。 16# guocong89
问题: a - b + (a - b) c + (a - b) d /. a - b -> x为什么只替换了第一个a - b到x?
这是符合ReplaceAll的函数说明的,只替换了一次就不再进行替换了。
但是为什么 {a, b, a, d, {{a}}} /.
a -> x就替换了一次但是两个a都替换成x了呢?首先肯定是做了一次替换,只是一下子在同一层Level[
expr, -1] 里找到两个匹配项。
第二个和第三个没被替换是因为第一个被替换了后按ReplaceAll的规则当然就不替换了,因为第二个和第三个还没有被找到。而去除Flat属性后\
就直接找到了后面的两个a - b,替换的效果就跟常量一样了。{a, b, c, a} /. a -> x
在5楼中的例子
Level, -1] 中出现的三个a也是这样被同时替换的。
而如果没有Flat属性,因为FullForm的形式就无法识别第一个a-b了,因此mathematica应该是首先识别这个,如果继续替换就没有了这种情况就继续搜索, 什么叫做 同时替换? 为什么可以同时找到a 却不能同时找到 a-b ?
更诡异的是7楼的最后几个测试。
这个测试表现出来的行为是,Plus与Times混合,Plus或者Times的匹配会完全被发现,如果是连加或者连乘,内层的匹配就失效了。 测试继续
Hold] /. a - b -> x
Hold[(a - b) (a - b) Sin] /. a - b -> x
Hold[(a - b + c) Sin] /. a - b -> x
Hold] /. a - b -> x
输出结果Hold + x]
Hold]
Hold[(c + x) Sin]
Hold + x]
页:
[1]
2