为什么 prolog 允许在其数据库中存在重复的事实和规则?

问题描述 投票:0回答:1

为什么 prolog 允许在其数据库中存在重复的事实和规则?

使向数据库添加事实幂等并不困难。对于规则来说,在两个规则之间建立逻辑相等并不是一件简单的事。

重复的规则和事实可能会导致令人惊讶的结果,而这些结果在逻辑上是不合理的。例如: f(a). f(a). g(X) :- f(X). g(Z) :- f(Z). findall(Y, g(Y), Y).

结果
Y = [a,a,a,a]

从操作上来说,考虑到Prolog的回溯机制,这个结果很容易理解。
但是,这不会给 Prolog 程序的“声明性逻辑”解释带来压力吗?假设 f(a)

两次并不会让它更真实!

从逻辑上来说,接下来的结果应该是Y = [a]

就像在许多 Prolog 实现的统一过程中放弃所谓的“发生检查”一样,允许重复的事实和规则可能是性能方面的考虑。检查重复的事实并不会太困难。我假设,检查重复规则是 NP 完全的,并且将具有指数复杂度的算法。
Prolog 的设计中除了性能之外还有其他原因允许重复的事实和规则吗?我意识到这个问题可以追溯到历史深处,但我相信理解这种设计选择有助于设计更好的 Prolog 程序。

期待社区的见解!

本质上是为了性能。

Prolog 都是关于关系的 - 但没有主键的概念,所以 Prolog 不知道重复项是否是例如有意或需要。

不要忘记:重复可能是程序逻辑的一部分,这取决于开发人员的意图。与自引用相同,这在某些数据结构中可能很有用,这是默认情况下关闭发生检查的合理原因。

由开发人员负责处理重复项。
prolog
1个回答
0
投票
可以在代码中处理重复项,并且有许多内置插件可以提供帮助,例如

一次

排序

一组

不同

重复的删除“破坏”了关系,这是 Prolog 系统本身不做任何尝试的一个很好的理由。 如果程序有: :- dynamic f/1. f(a). f(a). ...这是对基本事实的公然重复。然而,通过部分实例化变量的统一,事情通常更加微妙。

例如,要删除重复的基本事实:

:- dynamic f/1. f(a). f(a). remove_duplicate_fs :- bagof(A, f(A), As), remove_duplicate_fs_(As, []). remove_duplicate_fs_([], _). remove_duplicate_fs_([F|Fs], Prev) :- ( member(M, Prev), F == M -> once(retract(f(F))) ; true ), remove_duplicate_fs_(Fs, [F|Prev]).

swi-prolog 的结果:
?- listing(f/1).
:- dynamic f/1.

f(a).
f(a).

true.

?- remove_duplicate_fs.
true.

?- listing(f/1).
:- dynamic f/1.

f(a).

true.

© www.soinside.com 2019 - 2024. All rights reserved.