当我访问链表时,为什么mathematica内核会崩溃?

时间:2012-12-08 06:52:00

标签: wolfram-mathematica

我正在使用mathematica 7,我正在尝试使用单链表(~50,000个元素)来避免在动态列表中使用AppendTo来提高速度。 在这个测试中,我可以创建一个包含10个元素的列表,如下所示

list1 = Fold[{#1, #2} &, {}, RandomInteger[10^5, 10]]

我尝试使用Part这样访问它(访问随机元素100次)

Timing[list1[[Sequence @@ ConstantArray[1, #], 2]] & /@RandomInteger[{1,10}, 100]]

这适用于小型列表(如上所述)。由于我不理解的原因,当列表包含更多元素(如10 ^ 4)时,这会导致内核死亡。我试过环顾这个网站&在其他地方,但只是无法弄清楚我应该如何使用链表。我甚至试图使用不同的实现,如f[e1,f[e2,f[e3,...f[]...]]],但我不知道一个很好的方式来访问&使用此方案时操纵元素。我想这个问题必须要做{/ {1}},但我不知道如何绕过它。

特别是我希望能够使用

$RecursionLimit

在我的代码中。同样,当列表很小但是最终崩溃内核以获得更大的列表时,这种方法也适用。奇怪的是内核并不总是崩溃,而只是随机地用于大型列表。这听起来类似于here on SE所描述的内容,但我不知道该讨论是否相关。真的,我只需要帮助修改LL元素和&在mathematica中正确使用LL。

提前致谢。

1 个答案:

答案 0 :(得分:3)

我可以确认崩溃,但只有明显更深的Part规范:

n = 5000000;

list1 = Fold[List, {}, RandomInteger[10^5, n]];

Do[
 list1[[Sequence @@ ConstantArray[1, i], 2]] = "token"; Print[i],
 {i, 100000, 200000, 10000}
]
  

100000 110000 120000 130000 140000 150000 160000 170000

因此,在我的系统上,崩溃发生的深度超过170,000。至少在这个深度,只有在分配一个部分而不是仅仅提取一个部分时,它也会发生:

Timing[
 list1[[##, 2]] & @@ ConstantArray[1, #] & /@ RandomInteger[{1, n - 1}, 10]
]
{1.03, {77041, 74008, 29990, 13286, 12762, 48702, 76027, 25009, 31267, 1887}}

建议

作为替代方案,我建议使用Internal` *Bag* functions

n = 5000000;

list2 = Internal`Bag @ RandomInteger[10^5, n];  (* fill our Bag *)

Internal`StuffBag[list2, 27182];  (* add an element to the Bag *)

Internal`BagLength @ list2  (* check the length of our Bag *)
5000001
pos = RandomInteger[{1, n}, 10];  (* pick ten random positions *)

(* assign to those positions values 1 through 10 *)
MapIndexed[
  (Internal`BagPart[list2, #] = #2[[1]]) &,
  pos
];

Internal`BagPart[list2, pos]  (* check the contents of those positions *)
{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
(* convert our Bag into a standard list *)
flat = Internal`BagPart[list2, All];

flat[[pos]]  (* check the contents again *)
{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
Last @ flat  (* check that the element we appended is still there *)
27182