【问题标题】:Detecting equivalent expressions检测等效表达式
【发布时间】:2011-07-27 15:45:43
【问题描述】:

我目前正在开发一个 Java 应用程序,我需要实现一个系统来构建 BPF 表达式。我还需要实现检测等效 BPF 表达式的机制。

构建表达式并不难。我可以使用Interpreter 设计模式构建语法树并实现toString 以获取BPF 语法。

但是,检测两个表达式是否等价要困难得多。一个简单的例子如下:

A: src port 1024 and dst port 1024
B: dst port 1024 and src port 1024

为了检测 A 和 B 是等价的,我可能需要在比较它们之前将每个表达式转换为“标准化”形式。对于上面的示例,这很容易,但是,当使用嵌套的 ANDORNOT 操作的组合时,它会变得越来越难。

有谁知道我应该如何最好地解决这个问题?

【问题讨论】:

  • 我认为我们需要在这里更好地定义“等效”。上下文是否重要(由于 DNS,net xx.xx.xx.xx/24 等同于 net xyz)。
  • 检测变量并将它们按某种顺序排列而不更改表达式。意识到 b-a 和 a-b 是不一样的。
  • @Jim Garrison 它应该检测两个表达式在语法上是否等效。它不会做任何 dns 解析,它只会认为你的两个表达式是不同的。

标签: java algorithm design-patterns


【解决方案1】:

比较布尔表达式的一种方法可能是将两者都转换为disjunctive normal form (DNF),然后比较DNF。在这里,变量将是 Berkeley Packet Filter 标记,并且出现在两个表达式中的任何一个中的任何位置的相同标记(例如 port 80)都需要分配相同的变量名称。

http://www.izyt.com/BooleanLogic/applet.php 有一个看起来很有趣的小程序 - 很遗憾,由于浏览器中的 Java 问题,我现在无法尝试。

【讨论】:

  • 转换为 DNF 可能需要指数级时间
【解决方案2】:

我很确定检测等效表达式是一个 np-hard 或 np-complete 问题,即使对于纯布尔表达式也是如此。这意味着要完美地做到这一点,最佳方法基本上是构建所有可能的输入和结果组合的完整表格,然后比较表格。

也许 BPF 表达式在某些方面受到限制会改变这种情况?我不知道,所以我假设不是。

如果您的问题很小,那可能不是问题。作为决策树设计算法的一部分,我完全这样做了。

或者,不要试图做到完美。允许一些假阴性(等效但您不会检测到的情况)。

一种简单的方法可能是执行正常表达式评估的变体,但评估表达式的替代表示而不是结果。对交换运算符施加排序。在评估过程中应用一些明显的简化。用最小的原始运算符集替换丰富的运算符集 - 例如使用 demorgans 来消除 OR 运算符。

这种替代表示形成了一组等效表达式的所有成员的规范表示。它应该是一个等价类,因为您总是为该集合的任何成员找到相同的规范形式。但这只是等价类的集合论/抽象代数意义 - 这并不意味着所有等价表达式都在同一个等价类中。

为了高效的字典查找,您可以使用基于该规范表示的散列或比较。

【讨论】:

  • NP 硬度的优点,但我认为这是最坏的情况,en.wikipedia.org/wiki/Disjunctive_normal_form 给出了最坏的情况,N 是术语的数量,几乎不会超过 100。
  • @thiton - 我记得的方式,析取(或合取)范式很容易从结果(真值)表中导出。如果你有这三种表示中的任何一种,你就可以简单地翻译成其他的。诀窍是从这三种表示中的一种开始 - 但如果您的表达式很简单,那并不是真正的问题。
【解决方案3】:

我肯定会使用语法规范化。也就是说,就像 aix 建议的那样,使用 DNF 转换布尔值并重新排序抽象语法树,使得词法上最小的参数位于左侧。将所有比较标准化为

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-04-23
    • 2016-10-14
    • 1970-01-01
    • 2019-09-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多