优化Mathematica的主循环

时间:2011-03-14 08:04:57

标签: optimization wolfram-mathematica

美好的一天,

关于 Mathematica 中模式匹配和函数的性能的阅读thread我对Timo's idea关于优化表达式评估的印象非常深刻:

  

我偶尔会建造一个   发布所有功能的表格   需要并手动将它应用到我的   开始表达。这提供了一个   速度显着超过正常速度   评价与Mathematica无关   内置函数需要解析   反对我的表达。

如何构建这样的Dispatch表?在哪些情况下会推荐这种方法?它是如何运作的?是否还有其他优化主循环的方法?

2 个答案:

答案 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的通用重写器更快地重写术语。