Performance 高效地存储和计算大量布尔表达式

Performance 高效地存储和计算大量布尔表达式,performance,algorithm,data-structures,boolean,scalability,Performance,Algorithm,Data Structures,Boolean,Scalability,我有一大堆(20000)布尔表达式。它们由和,或和非运算符和大量布尔变量A1,A2,A3组成。。。(约1000人)。大多数表达式只包含这些变量中的5个,也许20个 给定一个变量赋值(A1=true,A2=false,A3=false…),我必须找到那些计算结果为false的表达式 同一组表达式将针对多个(10-100)赋值进行求值 为此目的: 我应该如何将表达式存储在磁盘上,以便快速加载和解析它们(我目前将它们作为某种专门的DSL或或多或少规范化(非常慢)的关系数据结构,但我可以改变这一点) 是

我有一大堆(20000)布尔表达式。它们由
运算符和大量布尔变量
A1
A2
A3
组成。。。(约1000人)。大多数表达式只包含这些变量中的5个,也许20个

给定一个变量赋值(
A1=true,A2=false,A3=false…
),我必须找到那些计算结果为
false
的表达式

同一组表达式将针对多个(10-100)赋值进行求值

为此目的:

  • 我应该如何将表达式存储在磁盘上,以便快速加载和解析它们(我目前将它们作为某种专门的DSL或或多或少规范化(非常慢)的关系数据结构,但我可以改变这一点)

  • 是否有一个快速算法/数据结构用于计算我可以使用的表达式

  • JVM上是否存在实现


  • 解决这个问题的SOP方法是将表达式作为字符串存储在RPN(反向波兰表示法)中,然后编写一个简单的堆栈机解析器对其进行计算


    通常,RPN字符串的计算速度几乎与内存中已有的AST(抽象符号树)一样快。而且堆栈机器解析器非常容易编写。

    您可能想看看如何将表达式转换为类似的术语并将其组合起来。然后,可以将表达式双向映射到一组术语,其中任何一个计算为false都意味着整个表达式计算为false。对于每个变量赋值,从一组表达式开始,计算CNF项,直到其中一个计算为false。如果该项为false,则涉及该项的所有表达式也将为false,因此这些表达式也可以从集合中删除

    这种方法是否适合你的情况,不能不看表达式就说出来——有1000个变量和20000个表达式,它们可能没有许多共同的CNF术语


    在Java之外,对于数量多得多的表达式,DNF可能更有用,因为它在GPU上的实现是显而易见的。

    您似乎喜欢Java,但您是否考虑过将这些东西提供给一种具有eval()函数的语言?这可能会将问题简化为在文件中保存表达式并对其求值。请注意,如果您不信任(表达式的源代码),这会带来安全隐患

    我想到了Jython,但可能有几个可以让这项工作做得很短


    如果您与java结过婚,您可能会为布尔代数实现一个递归下降解析器。但这要复杂得多。

    更新:以下网站提供了可能有用的信息

    将表达式列表转换为函数的源代码,当使用变量值调用该函数时,将计算所有函数,并返回哪个表达式的计算结果为false的指示。编译函数,然后为不同的变量值调用它

    我也做过类似的工作,并使用了Python。我必须编写的唯一解析和解释就是将输入布尔运算符“&”、“|”、“~”转换为它们的Python等价物


    对于Python解决方案,您的问题大小似乎很合适。

    您可以构建一个索引,在其中为每个变量记录两组表达式,一组是变量正向出现的表达式,另一组是变量负向出现的表达式。根据变量的值,您可以收集由于该变量而可能变为false的表达式(如果变量设置为false,则出现正值,反之亦然)编辑:这些只是候选项,您仍然需要对它们进行评估,以确定它们是否真的变假


    与仅计算所有表达式相比,这是否有帮助取决于表达式的结构以及有多少表达式计算为false。

    尝试将它们转换为CNF,并使用MiniSat检查表达式的计算结果是否为true或false

    您会多次计算某个特定表达式还是仅计算一次?查看了吗在至于算法。。。请看一看稀疏位集(java.util.Bitset类不是稀疏的,但速度非常快,对于您正在处理的相对较小的数字来说可能还可以)。它们是专门为简化和验证集成电路的布尔逻辑而设计的。@ChrisGerken I更新了问题:同一组表达式将对多个(10-100)赋值求值。这只是NP完全的排序。大多数“随机”问题都是合理的、形式良好的;只有少数人是邪恶的。我解释说,你们的“多根性”问题将来自于善良的家庭。布莱恩特的论文是一篇很好的介绍和必读的文章。关于链接:1000个输入参数的真值表对我来说不是一个好主意。这个问题不是关于生成真值表。该链接包含用于表示和计算布尔表达式的代码。有时你需要提取你需要的东西,因为完整的答案还没有交给你。我有点依附于Java,甚至更依附于JVM,因为任何其他东西都会导致这里的专有技术和部署问题。只要结果很快,我就不怕实现parsera。表达式
    (a&b)|(!a&c)
    对于
    a
    是正数还是负数?给定a、b、c的一组值,您如何收集相应的表达式而不必完全计算它们?@Pete Kirkham该表达式将同时存在于这两个值中,因为
    a
    同时出现正和负两种情况。正数出现在表达式根路径上有偶数个否定的地方,负数出现在奇数的地方。那么,两者同时出现如何确定表达式是否为真呢