将表达式转换为带有扭曲的合取范式

发布于 2024-07-19 08:49:28 字数 815 浏览 9 评论 0原文

我有一个必须与之交互的库,它基本上充当数据源。 检索数据时,我可以将特殊的“过滤表达式”传递给该库,稍后将其转换为 SQL WHERE 部分。 这些表达方式非常有限。 它们必须是合取范式。 喜欢:

(A or B or C) and (D or E or F) and ...

这对于编程来说当然不太舒服。 所以我想制作一个小包装器,它可以解析任意表达式并将它们转换为这种正常形式。 Like:

(A and (B or C) and D) or E

会被翻译成类似的东西:

(A or E) and (B or C or E) and (D or E)

我可以使用 Irony 库将表达式解析为树。 现在我需要对其进行标准化,但我不知道如何...哦,还有一个问题:

  • 最终的表达式可能不包含 NOT 运算符。 但是,我可以通过用逆运算符替换运算符来反转各个项。 所以,这是可以的:

    (不是 A 或不是 B)AND(不是 C 或不是 D)

    但这不是:

    not (A or B) and not (C or D)

  • 我想让表达式尽可能简单,因为它将被转换为几乎相同的 SQL WHERE 语句,因此复杂的语句很可能会降低执行速度。

I've got a library that I have to interface with which acts basically as a data source. When retrieving data, I can pass special "filter expressions" to that library, which later get translated to SQL WHERE part. These expressions are pretty limited. They must be in conjunctive normal form. Like:

(A or B or C) and (D or E or F) and ...

This of course isn't very comfortable for programming. So I want to make a little wrapper which can parse arbitrary expressions and translate them to this normal form. Like:

(A and (B or C) and D) or E

would get translated to something like:

(A or E) and (B or C or E) and (D or E)

I can parse an expression to a tree with the Irony library. Now I need to normalize it, but I don't know how... Oh, also, here's the twist:

  • The final expression may not contain the NOT operator. However, I can inverse the individual terms by replacing the operators with the inverse operators. So, this is OK:

    (not A or not B) AND (not C or not D)

    but this is not:

    not (A or B) and not (C or D)

  • I would like to make the expression as simple as possible, because it will be translated to a practically identical SQL WHERE statement, so a complex statement would most likely slow down execution speed.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

宫墨修音 2024-07-26 08:49:28

我会在树上使用两次迭代,尽管一次迭代可能是可能的。

第一次迭代:通过遍历树并使用德摩根定律来消除 NOT 节点 (维基百科链接)并删除适用的双重否定。

第二次迭代(NOT 现在仅直接位于叶节点之前)
遍历你的树:

Case "AND NODE":
    fine, inspect the children
Case "OR NODE":
    if there is a child which is neither a Leaf nor a NOT node
        apply the distributive law.
        start from parent of current node again
    else
        fine, inspect children

之后你就应该完成了。

I'd use two iterations over the tree, although it's probably possible in one.

First iteration: get rid of your NOT Nodes by walking through the tree and using De Morgan's law (wikipedia link) and remove double negation wherever applicable.

Second iteration (the NOT are now only directly before a leaf node)
Go through your tree:

Case "AND NODE":
    fine, inspect the children
Case "OR NODE":
    if there is a child which is neither a Leaf nor a NOT node
        apply the distributive law.
        start from parent of current node again
    else
        fine, inspect children

After that you should be done.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文