Jes*_*del 8 wolfram-mathematica compilation
如果我想从两个列表中找到所有可能的和list1
和list2
,我用的是Outer[]
函数的规格Plus
为合并算:
In[1]= list1 = {a, b}; list2 = {c, d}; Outer[Plus, list1, list2]
Out[1]= {{a + c, a + d}, {b + c, b + d}}
如果我希望能够处理任意数量的列表,请列出列表,
In[2]= listOfLists={list1, list2};
那么我知道如何找到所有可能的总和的唯一方法是使用Apply[]
函数(有简写@@
)以及Join
:
In[3]= argumentsToPass=Join[{Plus},listOfLists]
Out[3]= {Plus, {a, b}, {c, d}}
In[4]= Outer @@ argumentsToPass
Out[4]= {{a + c, a + d}, {b + c, b + d}}
或者干脆
In[5]= Outer @@ Join[{Plus},listOfLists]
Out[5]= {{a + c, a + d}, {b + c, b + d}}
当我尝试编译时出现问题:
In[6]= Compile[ ..... Outer @@ Join[{Plus},listOfLists] .... ]
Compile::cpapot: "Compilation of Outer@@Join[{Plus},listOfLists]] is not supported for the function argument Outer. The only function arguments supported are Times, Plus, or List. Evaluation will use the uncompiled function. "
问题是,我正在使用支持的功能,即Plus
.问题似乎完全在于Apply[]
功能.因为如果我给外部加一个固定数量的列表,它可以正常工作
In[7]= Compile[{{bob, _Integer, 1}, {joe, _Integer, 1}}, Outer[Plus, bob, joe]]
Out[7]= CompiledFunction[{bob, joe}, Outer[Plus, bob, joe],-CompiledCode-]
但是一旦我使用Apply
,它就会破裂
In[8]= Compile[{{bob, _Integer, 1}, {joe, _Integer, 1}}, Outer @@ Join[{Plus}, {bob, joe}]]
Out[8]= Compile::cpapot: "Compilation of Outer@@Join[{Plus},{bob,joe}] is not supported for the function argument Outer. The only function arguments supported are Times, Plus, or List. Evaluation will use the uncompiled function."
所以我的问题是:有没有办法绕过这个错误,或者,有办法计算从编译函数中任意数量的列表中提取的所有可能的元素总和?
(另外,我不确定"编译"是否是合适的标签.请告知.)
非常感谢.
Leo*_*rin 12
使用它的一种方法是以With
编程方式创建编译函数:
Clear[makeCompiled];
makeCompiled[lnum_Integer] :=
With[{listNames = Table[Unique["list"], {lnum}]},
With[{compileArgs = {#, _Integer, 1} & /@ listNames},
Compile @@ Join[Hold[compileArgs],
Replace[Hold[Outer[Plus, listNames]],
Hold[Outer[Plus, {x__}]] :> Hold[Outer[Plus, x]], {0}]]]];
Run Code Online (Sandbox Code Playgroud)
它可以做得更漂亮,但它的工作原理.例如:
In[22]:= p2 = makeCompiled[2]
Out[22]= CompiledFunction[{list13,list14},Outer[Plus,list13,list14],-CompiledCode-]
In[23]:= p2[{1,2,3},{4,5}]
Out[23]= {{5,6},{6,7},{7,8}}
In[24]:= p3 = makeCompiled[3]
Out[24]= CompiledFunction[{list15,list16,list17},Outer[Plus,list15,list16,list17],-CompiledCode-]
In[25]:= p3[{1,2},{3,4},{5,6}]
Out[25]= {{{9,10},{10,11}},{{10,11},{11,12}}}
Run Code Online (Sandbox Code Playgroud)
HTH
编辑:
您可以将已编译的函数隐藏在另一个函数后面,以便它在运行时创建,而您实际上并未看到它:
In[33]:=
Clear[computeSums]
computeSums[lists : {__?NumberQ} ..] := makeCompiled[Length[{lists}]][lists];
In[35]:= computeSums[{1, 2, 3}, {4, 5}]
Out[35]= {{5, 6}, {6, 7}, {7, 8}}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,您将面临编译的开销,因为您每次都会重新创建编译函数.你可以通过memoization,使用Module
变量进行持久化来优化地控制这个开销,来本地化你的memoized定义:
In[44]:=
Clear[computeSumsMemoized];
Module[{compiled},
compiled[n_] := compiled[n] = makeCompiled[n];
computeSumsMemoized[lists : {__?NumberQ} ..] := compiled[Length[{lists}]][lists]];
In[46]:= computeSumsMemoized[{1, 2, 3}, {4, 5}]
Out[46]= {{5, 6}, {6, 7}, {7, 8}}
Run Code Online (Sandbox Code Playgroud)