1

我正处于在 Prolog 中编写代码的初始阶段,并且仍在尝试围绕范式进行思考,所以请原谅这个问题的原始性。

我在维基百科上读过

A rule is of the form
Head :- Body.
and is read as "Head is true if Body is true".

这很简单。所以我正在建立一个模拟 1 位加法器功能的知识库。

为此,我正在尝试为以下内容创建规则:

如果存在一个门 X,并且 X 是一个与门,并且 X 有一个端子从它出来,并且该端子有一个信号并且信号为 0 那么门 X 必须也至少有一个输入端有一个信号0。

作为 Prolog 规则,我写了这个来反映我上面的句子:

gate(X) /\ gate_type(X, and) /\ terminal(T, X, out) /\ signal(T, SIG) /\ (SIG is 0) :- (gate(X) /\ gate_type(X, and) /\ terminal_type(R, X, in) /\ signal(R, 0)).

为了测试我的规则,我有一个终端t7,它是与门的终端。

terminal_type(t7, a1, in).
gate_type(a1, and).

当我问 Prolog:signal(t7, 1), signal(t8, 1), signal(t9, X).或类似的问题时,Prolog 先生告诉我

X = 1;
X = 0;

我得到的答案应该只有 X = 1。

4

1 回答 1

2

欢迎来到 Prolog 编程!您从硬件中获得它非常酷,几乎与您所能得到的一样远。

我想我看到了两个问题。

第一个是您的定义忽略了与门的定义特征,即当两个输入均为 1 时,输出将为 1。您将其翻译成 Prolog 看起来有点奇怪,但当然应该考虑到这一点。所以我认为在 Prolog 中你想说的是:

signal(R, 0) :- 
  gate(X), gate_type(X, and), 
  terminal_type(R, X, out),
  terminal_type(R1, X, in), signal(R1, 0).

不过,这还不是全部。你也需要这个:

signal(R, 1) :- 
  gate(X), gate_type(X, and), 
  terminal_type(R, X, out),
  terminal_type(R1, X, in), terminal_type(R2, X, in), R1 \= R2,
  signal(R1, 1), signal(R2, 1).

这可能是正确的,但第二个问题是这signal(t7, 1)不是断言,因此它不会在您的事实数据库中结束。它只是一个光秃秃的结构,因此它不会向您的查询添加任何内容。最简单的解决方案是将其直接添加到您的数据库中:

signal(t7, 1).
signal(t8, 1).

然后进行查询:

signal(t9, X).

或者,你可以assertz/1

assertz(signal(t7, 1)), assertz(signal(t8, 1)), signal(t9, X).

但这有点草率,因为assert这是在回溯时无法消除的副作用。

在实践中,大多数时候您要么通过传递动态查询来将其作为动态查询的一部分,要么将其作为事实数据库的一部分。将两者混合起来很难推理。

如果我是你,我可能会通过将不同事实“类型”的数量减少到更像这样的东西来简化事情:

% gate(Name, Type, Input1, Input2, Output)
gate(a1, and, t7, t8, t9).

然后你可以真正简化谓词:

signal(Out, 0) :-
  gate(_, and, R1, R2, Out),
  ( signal(R1, 0) ; signal(R2, 0)).
signal(Out, 1) :-
  gate(_, and, R1, R2, Out),
  signal(R1, 1),
  signal(R2, 1).
于 2013-03-11T21:27:38.943 回答