wolfram-mathematica - Mathematica 表函数

标签 wolfram-mathematica

我正在运行一个 Table 函数,这将花费太多时间才能完成。

我想知道是否有办法检索到目前为止计算的结果。

最佳答案

建议的解决方案

这是Table的一个版本即 Abort - 能够并将保留到目前为止收集的中间结果。它是发布的解决方案的修改版本here .

ClearAll[abortableTable];
SetAttributes[abortableTable, HoldAll];
abortableTable[expr_, iter__List] :=
  Module[{indices, indexedRes, sowTag},
  SetDelayed @@ 
     Prepend[Thread[Map[Take[#, 1] &, List @@ Hold @@@ Hold[iter]], 
       Hold], indices];
  indexedRes =
     If[# === {}, #, First@#] &@Last@Reap[
        CheckAbort[Do[Sow[{expr, indices}, sowTag], iter], {}], sowTag];
  AbortProtect[
     Map[First,
       SplitBy[indexedRes,
          Table[
            With[{i = i}, Function[Slot[1][[2, i]]]], 
            {i, Length[Hold[iter]] - 1}]], 
       {-3}]]];

它应该能够采用与 Table 相同的迭代器规范。 .

工作原理

这是它的工作原理。第一个语句( SetDelayed @@... )“解析”迭代器,假设它们都是 {iteratorSymbol_,bounds__} 形式的。 ,并将迭代器变量列表分配给变量 indices .与Hold的施工需要防止可能的迭代器变量评估。有很多方法可以做到这一点,我只使用了其中一种。这是它的工作原理:
In[44]:= 
{i, j, k} = {1, 2, 3}; 
Prepend[Thread[Map[Take[#, 1] &, List @@ Hold @@@ 
   Hold[{i, 1, 10}, {j, 1, 5}, {k, 1, 3}]], Hold], indices]

Out[45]= Hold[indices, {i, j, k}] 

使用 SetDelayed @@ the-above然后自然会产生形式 indices:={i,j,k} 的延迟定义.我将值分配给索引 i,j,k证明在使用此构造时不会对它们进行不需要的评估。

下一个语句生成一个收集结果的列表,其中每个结果都分组在一个列表中,其中包含用于生成它的索引列表。自 indices变量由延迟定义定义,它将每次重新评估,以获取新的索引组合。这里使用的另一个重要特征是 Do循环接受与 Table 相同的迭代器语法(并且还动态本地化迭代器变量),同时是一个顺序(恒定内存)构造。收集中间结果,ReapSow被使用。自 expr可以是任何一段代码,特别是也可以使用 Sow ,只有 Reap 才需要一个具有唯一名称的自定义标签。那些值 Sown通过我们的函数,而不是它执行的代码。自 Module自然产生具有唯一名称的(临时)符号,我只是使用了 Module - 生成的没有值的变量,作为标签。这是一种普遍有用的技术。

能够在Abort[]的情况下收集结果由用户交互或在代码中发出,我们将 Do 包裹起来。在 CheckAbort 中循环.在 Abort[] 上执行的代码(这里是 {})在这种方法中很大程度上是任意的,因为无论如何收集结果都是由 Sow 完成的。和 Reap ,尽管在更复杂的版本中可能有用,该版本将结果保存到用户提供的某个变量中,然后重新发出 Abort[] (当前未实现的功能)。

结果,我们进入了一个变量 indexedRes表格的平面列表
{{expr1, {ind11,ind21,...indn1}},...,{exprk, {ind1k,ind2k,...indnk}}

其中结果与相应的索引组合进行分组。我们需要这些索引组合来从平面列表重建多维结果列表。方法是根据i的值对列表进行重复拆分。 -th 索引。函数SplitBy具有此功能,但我们需要提供用于拆分步骤的函数列表。由于索引i - 子列表中的第一个迭代器索引 {expr,{ind1,...,indn}}2,i , 在 i 处进行拆分的函数- 第一步是 #[[2, i]]& ,并且我们需要动态构建此类函数的列表以将其提供给 SplitBy .下面是一个例子:
In[46]:= Table[With[{i = i}, Function[Slot[1][[2, i]]]], {i, 5}]

Out[46]= {#1[[2, 1]] &, #1[[2, 2]] &, #1[[2, 3]] &, #1[[2, 4]] &, #1[[2, 5]] &}
With[{i=i},body]构造用于注入(inject)i的特定值纯函数内部。注入(inject)值 i 的替代方案进入 Function确实存在,例如:
In[75]:= 
Function[Slot[1][[2, i]]] /. Map[List, Thread[HoldPattern[i] -> Range[5]]]

Out[75]= {#1[[2, 1]] &, #1[[2, 2]] &, #1[[2, 3]] &, #1[[2, 4]] &, #1[[2, 5]] &}


In[80]:= Block[{Part}, Function /@ Thread[Slot[1][[2, Range[5]]]]]

Out[80]= {#1[[2, 1]] &, #1[[2, 2]] &, #1[[2, 3]] &, #1[[2, 4]] &, #1[[ 2, 5]] &}


In[86]:= Replace[Table[{2, i}, {i, 5}], {inds__} :> (#[[inds]] &), 1]

Out[86]= {#1[[2, 1]] &, #1[[2, 2]] &, #1[[2, 3]] &, #1[[2, 4]] &, #1[[ 2, 5]] &}

但可能更加晦涩(也许除了最后一个)。

生成的嵌套列表具有适当的结构,带有子列表 {expr,{ind1,...,indn}}处于水平 -3 (从底部算起第三层)。通过使用 Map[First,lst,{-3}] ,我们删除索引组合,因为嵌套列表已经被重建并且不再需要它们。剩下的是我们的结果——结果表达式的嵌套列表,其结构对应于由 Table 生成的类似嵌套列表的结构。 .最后一条语句被包裹在 AbortProtect 中- 以防万一,确保在可能的 Abort[] 之前返回结果火灾。

使用示例

这是我按 Alt+. 的示例( Abort[] ) 在评估命令后不久:
In[133]:= abortableTable[N[(1+1/i)^i],{i,20000}]//Short
Out[133]//Short= {2.,2.25,2.37037,2.44141,<<6496>>,2.71807,2.71807,2.71807}

它几乎和 Table 一样快:
In[132]:= abortableTable[N[(1+1/i)^i,20],{i,10000}]//Short//Timing
Out[132]= {1.515,{2.0000000000000000000,2.2500000000000000000,<<9997>>,2.7181459268252248640}}

In[131]:= Table[N[(1+1/i)^i,20],{i,10000}]//Short//Timing
Out[131]= {1.5,{2.0000000000000000000,2.2500000000000000000,<<9997>>,2.7181459268252248640}}

但它不会自动编译 Table做:
In[134]:= Table[N[(1+1/i)^i],{i,10000}]//Short//Timing
Out[134]= {0.,{2.,2.25,2.37037,2.44141,<<9993>>,2.71815,2.71815,2.71815}}

可以对自动编译进行编码并将其添加到上述解决方案中,我只是没有这样做,因为要做好它需要做很多工作。

编辑

我重新编写了该函数,使某些部分更简洁、更易于理解。还,
在大型列表中,它比第一个版本快约 25%。
ClearAll[abortableTableAlt];
SetAttributes[abortableTableAlt, HoldAll];
abortableTableAlt[expr_, iter : {_Symbol, __} ..] :=
  Module[{indices, indexedRes, sowTag, depth =  Length[Hold[iter]] - 1},
   Hold[iter] /. {sym_Symbol, __} :> sym /. Hold[syms__] :> (indices := {syms});
   indexedRes =  Replace[#, {x_} :> x] &@ Last@Reap[
      CheckAbort[Do[Sow[{expr, indices}, sowTag], iter], Null],sowTag];
   AbortProtect[
      SplitBy[indexedRes, Array[Function[x, #[[2, x]] &], {depth}]][[##,1]] & @@ 
      Table[All, {depth + 1}]
   ]];

关于wolfram-mathematica - Mathematica 表函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6470625/

相关文章:

algorithm - 列出四面体的所有有趣部分

performance - Mathematica 的模式匹配优化不佳?

wolfram-mathematica - 在Mathematica中查找相似但不相同的元素的运行

java - 为什么 MappedByteBuffer 的 array() 方法不起作用?

python - NIST 随机性测试需要 ASCII 0's and 1' 序列,但不接受来自 MATLAB 的任何试验

python - Gauss-Legendre 区间 -x -> 无穷大 : adaptive algorithm to transform weights and nodes efficiently

wolfram-mathematica - 在Mathematica中DropWhile在哪里?

wolfram-mathematica - 粘贴 Mathematica 代码,以便将其分解为单独的输入单元格

wolfram-mathematica - 数学 : Unwanted vertical line in histogram

function - 函数定义中的常量和自变量