美好的一天,
关于 Mathematica 中模式匹配和函数的性能的阅读thread我对Timo's idea关于优化表达式评估的印象非常深刻:
我偶尔会建造一个 发布所有功能的表格 需要并手动将它应用到我的 开始表达。这提供了一个 速度显着超过正常速度 评价与Mathematica无关 内置函数需要解析 反对我的表达。
如何构建这样的Dispatch
表?在哪些情况下会推荐这种方法?它是如何运作的?是否还有其他优化主循环的方法?
答案 0 :(得分:2)
要做到这一点,首先您需要能够计算符号的依赖关系。在Mathematica期刊的后期版本中有一个包可以做到这一点,现在免费在线。以下是网址:http://www.mathematica-journal.com/issue/v6i1/。请参阅“Power Programming:依赖性分析”一文。
这是一个有效的例子:
In[1]:= <<"/path/to/DEPEND.MA"
In[2]:= $ContextPath
Out[2]= {DependencyAnalysis`,PacletManager`,WebServices`,System`,Global`}
In[3]:= f[x_]:=x x
In[4]:= g[x_]:=x+1
In[5]:= h[x_]:=f[x]+g[x]
In[6]:= i[x_]:=f[g[x]]
In[7]:= DependsOn[g][[2]]
Out[7]= {Blank,Pattern,Plus,x}
In[8]:= DownValues@@@DependsOn[g][[2]]
Out[8]= {{},{},{},{}}
In[9]:= getDownValues[s_Symbol]:=DownValues[s]
In[10]:= getDownValues[s_HoldForm]:=getDownValues@@s
In[11]:= getDownValues[s_]:={}
In[12]:= hasDownValues[x_]:=getDownValues[x]=!={}
In[13]:= ruleListEntries[x_List]:=Union[Union@@ruleListEntries/@x,{x}]
In[14]:= ruleListEntries[x_]:=Select[Union[DependsOn[x][[2]],{x}],hasDownValues]
In[15]:= ruleListEntries[f]
Out[15]= {f}
In[16]:= ruleListEntries[g]
Out[16]= {g}
In[17]:= ruleListEntries[h]
Out[17]= {h,f,g}
In[18]:= ruleListEntries[i]
Out[18]= {i,f,g}
In[19]:= dispatch=getDownValues/@ruleListEntries[i]//Flatten//Union//Dispatch
Out[19]= {HoldPattern[f[x_]]:>x x,HoldPattern[g[x_]]:>x+1,HoldPattern[i[x_]]:>f[g[x]]}
In[20]:= i[x]
Out[20]= (1+x)^2
In[21]:= HoldForm[i[x]]//.dispatch
Out[21]= (x+1) (x+1)
我认为没有办法获取内置符号的DownValues,所以这只是为了将表达式简化为只包含内置函数的点。
答案 1 :(得分:2)
如何构建这样的Dispatch表?
假设您在循环中有一个由n
个顶点组成的图形(网络):
In[1] := rules =
With[{n = 1000},
Table[ToString@i -> ToString@Mod[i + 1, n],
{i, 0, n - 1}]];
您希望通过将这些重写规则应用于初始顶点来遍历图形。您可以使用i /. rules
执行单个步骤,但这是对rules
进行线性搜索,尝试找到Rule
,其中lhs与表达式i
匹配。因此,多次应用这些规则很慢:
In[2] := Nest[# /. rules &, 0, 10000] // AbsoluteTiming
Out[2] = {1.7880482, 0}
Mathematica的Dispatch
允许我们预先计算一个哈希表,将线性查找转换为恒定时间查找:
In[3] := dispatch = Dispatch[rules];
多次应用调度表可以更快地获得相同的答案数量级:
In[4] := Nest[# /. dispatch &, 0, 10000] // AbsoluteTiming
Out[4] = {0.0550031, 0}
在哪种情况下会推荐这种方法?
当:
您正在使用相同的重写规则进行多次重写,
重写规则集包含至少30个具有常量lhs模式的规则,即仅由符号,序列和文字组成。
它是如何运作的?
它只是构建一个哈希表,其中常量模式为键。
是否有其他优化主循环的方法?
最有效的一般方法是用另一种语言重写规则。特别是,ML系列语言(SML,OCaml和F#)具有非常有效的模式匹配编译器和垃圾收集器,因此它们能够比Mathematica的通用重写器更快地重写术语。