Wolfram mathematica 数学表函数
我正在运行一个表函数,这将花费太多的时间来完成Wolfram mathematica 数学表函数,wolfram-mathematica,Wolfram Mathematica,我正在运行一个表函数,这将花费太多的时间来完成 我想知道是否有办法检索到目前为止计算的结果。不幸的是,没有。如果您想执行类似于lst=Table[f[I],{I,110000}]的操作,那么如果中止,您仍然可以得到结果 Clear[lst2]; lst2 = {}; (Do[lst2 = {lst2, f[i]}, {i, 1, 10000}]; lst2=Flatten[lst2];) // Timing 对于未定义的f,在我的机器上需要0.173066s,而lst=Table[f[i],{
我想知道是否有办法检索到目前为止计算的结果。不幸的是,没有。如果您想执行类似于
lst=Table[f[I],{I,110000}]
的操作,那么如果中止,您仍然可以得到结果
Clear[lst2];
lst2 = {};
(Do[lst2 = {lst2, f[i]}, {i, 1, 10000}];
lst2=Flatten[lst2];) // Timing
对于未定义的f
,在我的机器上需要0.173066s,而lst=Table[f[i],{i,1,100000}]
大约需要0.06s(即,Table
以不可中断为代价,速度快了3倍)
注意明显的“可中断”解决方案,lst={};
做[AppendTo[lst,f[i]],{i,1,100000}]
大约需要40秒,所以不要这样做:使用链表并在末尾展平,就像在我的第一个示例中一样(但是,如果f[i]
返回一个列表,这将中断,然后需要更加小心)。建议的解决方案
下面是一个版本的表
,它可以中止
,并将保留到目前为止收集的中间结果。这是发布的解决方案的修改版本
它应该能够采用与表
相同的迭代器规范
工作原理
下面是它的工作原理。第一条语句(SetDelayed@……
)将“解析”迭代器,假设它们的形式都是{iteratorSymbol,bounds}
,并将迭代器变量列表分配给变量索引。需要使用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@@上述
将自然生成表单的延迟定义索引:={i,j,k}
。我将这些值分配给指数I,j,k
,以证明在使用此结构时不会对它们进行不必要的评估
下一条语句生成一个收集结果的列表,其中每个结果都分组在一个列表中,列表中包含用于生成结果的索引列表。由于索引
变量是由延迟定义定义的,因此它每次都会重新计算一个新的索引组合。这里使用的另一个关键特性是Do
循环接受与表
相同的迭代器语法(还动态地本地化迭代器变量),同时是一个顺序(常量内存)构造。为了收集中间结果,使用了reaw
和Sow
。由于expr
可以是任何一段代码,特别是也可以使用Sow
,因此需要一个具有唯一名称的自定义标记,以便只获取那些由我们的函数播种的值,而不是它执行的代码。由于Module
自然地生成具有唯一名称的(临时)符号,因此我仅使用Module
生成的变量(没有值)作为标记。这是一种普遍有用的技术
为了能够在用户以交互方式或在代码中发出的Abort[]
情况下收集结果,我们将Do
循环包装在CheckAbort
中。在这种方法中,Abort[]
({}
)上执行的代码在很大程度上是任意的,因为结果的收集无论如何都是由Sow
和eaw
完成的,虽然在更复杂的版本中可能有用,该版本将结果保存到用户提供的某个变量中,然后重新发出中止[]
(该功能当前未实现)
结果,我们进入了一个变量indexedRes
表单的平面列表
{{expr1, {ind11,ind21,...indn1}},...,{exprk, {ind1k,ind2k,...indnk}}
其中,结果与相应的索引组合一起分组。我们需要这些索引组合来从平面列表重建多维结果列表。方法是根据i
-th索引的值重复拆分列表。函数SplitBy
具有此功能,但我们需要提供用于拆分步骤的函数列表。由于子列表{expr,{ind1,…,indn}
中的i
-第个迭代器索引的索引是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]] &}
带有[{i=i},body]
构造的用于在纯函数中注入i
的特定值。将i
的值注入函数
的替代方法确实存在,例如:
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]] &}
或
或
但可能更加模糊(也许除了最后一个)
生成的嵌套列表具有适当的结构,子列表{expr,{ind1,…,indn}
处于-3
级别(从底部开始的第三级)。通过使用Map[First,lst,{-3}]
,我们删除了索引组合,因为嵌套列表已经重建,不再需要它们。剩下的是我们的结果-结果表达式的嵌套列表,其结构与表
生成的类似嵌套列表的结构相对应。最后一条语句包装在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}
但它不会自动编译,而表
会:
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}}
另一种解决方案是将中间计算的结果导出到正在运行的日志文件中,如中所述(请参阅“内存中备份的文件方法”一节)。有了这一点,您将获得新的中间计算结果,并将始终能够调查到目前为止的计算结果
另外,我认为应该按照建议使用监视器
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]] &}
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}
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}}
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}}
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}]
]];
Monitor[Table[Integrate[1/(x^n + 1), x], {n, 20}],
ProgressIndicator[n, {1, 20}]]