Prolog 中的复合布尔表达式

Posted

技术标签:

【中文标题】Prolog 中的复合布尔表达式【英文标题】:Compound boolean expressions in Prolog 【发布时间】:2012-02-15 14:29:05 【问题描述】:

在 Prolog 中,如何实现复合逻辑谓词,如 (A and B) 或 (C and D)?

这似乎是一个简单的问题,但许多平易近人的在线教程对布尔表达式不够详细。我假设你不能只写:

test(A, B, C, D) :- cond(A), cond(B); cond(C), cond(D).

那你会怎么做呢?

【问题讨论】:

如果您尝试运行那段代码,您会发现它完全符合您的要求。 【参考方案1】:

正如其他人所说,您的原始示例

test(A, B, C, D) :- cond(A), cond(B); cond(C), cond(D).

完全有效(假设解析符合您的预期)。你没试过吗?

入门书

逻辑与

foo :- a , b .

逻辑或

foo :- a ; b .

合并

foo :- a , b ; c , d .

以上解析为:

foo :- ( a , b ) ; ( c , d ) .

使用括号表示不同的所需绑定:

foo :- a , ( b ; c ) , d .

更好的是,避免使用; OR 运算符并将备选方案分解为单独的子句。对于人们来说,顺序比分支树结构更容易理解。将交替分解为多个子句可简化测试/调试并提高理解力。因此,更喜欢

foo :- a , b .
foo :- c , d .

结束

foo :- a , b ; c , d .

喜欢

foo :- a , bar , d .

bar :- b .
bar :- c .

结束

foo :- a , ( b ; c ) , d .

可能最重要的是,像这样将事情分解成多个子句可以使以后的维护更容易。结构如下:

foo :- a , b ; c , d .

当您添加另一个案例时,您会怎么做?当它扩展到 50 种替代品时呢?

每个额外的备选方案都会增加通过子句的代码路径数量,从而使测试和理解更加困难。要在测试中获得完整的代码覆盖率,必须单独测试许多替代路径。

具有等价结构

foo :- a , b .
foo :- c , d .

添加备选方案只是添加一个或多个附加子句,每个子句都可以单独测试。

专业程序员首先为那些在几年后需要理解、更改和修复代码的人编写代码(提示:那个人可能就是你自己)。

【讨论】:

【参考方案2】:

连词的一个简单替代方法是使用子语句。对于析取,使用多行。你的例子:

test(A, B, C, D) :- test1(A, B).
test(A, B, C, D) :- test2(C, D).
test1(A, B) :- A, B.
test2(C, D) :- C, D.

(A 或 B)和(C 或 D)呢?

other(A, B, C, D) :- other1(A, B), other2(C, D).
other1(A, B) :- A.
other1(A, B) :- B.
other2(C, D) :- C.
other2(C, D) :- D.

请注意,这只是作为 joel76 答案的替代品而提及。

【讨论】:

【参考方案3】:

test(A, B, C, D) :- (cond(A), cond(B)); (条件(C),条件(D))。

【讨论】:

@Mog:不需要括号,但如果混合 AND 和 OR,它有助于澄清运算符的优先级和绑定。对于很多人来说,像a AND b OR c AND d 这样的表达式并不清楚它是绑定为(a AND b) OR (c AND d) 还是绑定为a AND (b OR c) and d?此外,这是故意的?这是许多编程语言中相当常见的错误来源,因此它有助于明确指出所需的绑定 —少数几个地方之一,恕我直言,多余的括号实际上可以提高信噪比。 当然可以,但在我看来,它不能作为答案接受,它至少应该精确地表明它只是明确的事情并且它相当于 OP 的代码。这就是我投反对票的原因。

以上是关于Prolog 中的复合布尔表达式的主要内容,如果未能解决你的问题,请参考以下文章

语句

Prolog 给定 x 的所有可能表达式

python中循环语句

prolog 一阶逻辑

递归调用中的错误“[Error] 表达式列表被视为初始化程序 [-fpermissive] 中的复合表达式”

C 语言高效编程与代码优化