Mathematica的模式匹配效果不佳?

时间:2011-12-15 15:56:36

标签: performance wolfram-mathematica pattern-matching

我最近询问为什么PatternTest引起了大量不必要的评估:PatternTest not optimized? Leonid回答说,对我来说这是一个相当可疑的方法是必要的。我可以接受,虽然我更喜欢更有效的替代方案。

我现在意识到,我相信Leonid已经说过一段时间了,这个问题在 Mathematica 中运行得更深,我感到很困扰。我无法理解为什么这不是或不能更好地优化。

考虑这个例子:

list = RandomReal[9, 20000];
Head /@ list; // Timing
MatchQ[list, {x__Integer, y__}] // Timing
{0., Null}
{1.014, False}

检查列表的头部基本上是即时的,但检查模式需要一秒钟。当然 Mathematica 可以识别出由于列表的第一个元素不是整数,因此模式不能匹配,与PatternTest的情况不同,我无法看到模式中是否存在任何可变性。对此有何解释?


关于打包数组似乎有些混乱,据我所知,这与此问题无关。相反,我关注所有列表中的O(n 2 )时间复杂度,打包或解压缩。

2 个答案:

答案 0 :(得分:8)

MatchQ解压缩这些类型的测试。原因是没有实施任何特殊情况。原则上它可以包含任何内容。

On["Packing"]
MatchQ[list, {x_Integer, y__}] // Timing

MatchQ[list, {x__Integer, y__}] // Timing

改善这一点非常棘手 - 如果你打破模式匹配器就会遇到严重的问题。

编辑1: 确实,解包不是O(n ^ 2)复杂性的原因。但是,它确实表明,对于MatchQ[list, {x__Integer, y__}]部分,代码转到算法的另一部分(需要解压缩列表)。还有一些需要注意的事项:只有当两个模式都是__时才会出现这种复杂性,如果其中任何一个都是_算法具有更好的复杂性。

然后算法会经历所有n * n个潜在的匹配,似乎没有提前救助。大概是因为可能需要构建其他需要这种复杂性的模式 - 问题是上述模式迫使匹配器采用非常通用的算法。

然后我希望MatchQ[list, {Shortest[x__Integer], __}]和朋友,但无济于事。

所以,我的两分钱:要么使用不同的模式(并打开["包装"]以查看它是否转到一般匹配器)或进行预检DeveloperPackedArrayQ[expr] && Head[expr[[1]]]===Integer或一些这样的。

答案 1 :(得分:1)

@the author of the first answer。据我所知,反向生成和读取可用信息,可能是由于检查模式的方式不同。事实上 - 正如他们所说 - 一个特殊的哈希码用于模式匹配。这个散列(基本上是FNV-1循环)使得检查与所涉及的表达类型相关的特定模式(几个xor操作的问题)非常容易。散列算法在表达式内循环,每个子部分与前一个子部分的输出进行xorred。特殊的xor值用于每个原子表达式 - machineInts,machineReals,bigNums,Rationals等。因此,例如,_Integer很容易检查,因为任何整数的散列都是由整数的xor值组成的,所以我们需要做的就是进行逆运算并查看是否匹配 - 即如果我们得到一些特定的价值或类似的东西(对不起,如果我对实际的实施细节含糊不清。它的WIP)。对于一般或不常见的模式,检查可能无法利用此哈希值并需要不同的东西。

@the OP Head[]只是对内部表达式起作用,取表达式的第一个指针的值(表达式实现为指针数组)。这样做就像复制和打印字符串一样简单 - 非常快。在这种情况下甚至不调用模式匹配引擎。