【问题标题】:Prolog does not terminate on query with 2 argumentsProlog 不会在使用 2 个参数的查询时终止
【发布时间】:2017-11-12 12:06:36
【问题描述】:

我是 Prolog 的新手,对编程练习有疑问:

我有一个程序,我认为大部分时间都在工作,但是对于特定的查询,我没有得到答案

is_number(0).
is_number(s(N)) :-
  is_number(N).

numberpair(pair(X,Y)) :-
  is_number(X),
  is_number(Y).

?- numberpair(pair(A,B)), A=s(s(0)), B=s(s(s(0))).

所以我知道,Prolog 现在尝试 A 和 B 的所有可能数字 -> [0,s(0),s(s(0)),s(s(s(0))), ... ] 但如果它找到 A 的答案(即s(s(0))),它会在 B 处失败,在下一次调用中,它会尝试 A 的下一个答案(即 s(s(s(0)))),依此类推。 现在的问题是,我希望 Prolog 停止,如果它找到 A 的答案,并且现在只搜索 B 的答案。

谁能给我一个提示,如何解决这个问题?

【问题讨论】:

  • 错字:numberpairD --> numberpair?
  • 啊,是的,对不起……
  • 这没有答案,因为您的查询没有意义。您要求 Prolog 以某种方式神奇地看到查询的未来。它一次只能成功实现一个目标。您不能让它在第三个目标 (B=s(s(s(0)))) 上失败并让它回溯到第一个目标 (numberpair(pair(A,B))),而是在回溯时跳过第二个目标 (A=s(s(0)))。您需要重新定义查询以使其有意义。
  • @lurker:不是。 D 是一个非常广泛的提示如何解决这个问题。
  • @Enigmativity:该查询确实有意义。它写道:当被要求提供所有解决方案时,是否也会找到这个特定的解决方案。换句话说,枚举是公平的还是不公平的。

标签: prolog successor-arithmetics


【解决方案1】:

编辑: 正如 false 指出的那样: 您找不到答案的原因是您的规则 numberpair/1 不会终止。 您找不到答案的原因是 Prolog 以它首先列出的方式枚举您的答案A 的所有可能性,然后是 B 的可能性(请注意,两者都有无限的可能性)。 Prolog 尝试首先为子句 numberpair(pair(A,B)) 找到答案,然后为以下子句 A=s(s(0)) 和 B=s(s(s(0))) .但由于 numberpair 已经不会终止,所以到目前为止它不会“到来”。

如果您更改 clauses 目标的顺序并在 numberpair(pair(A,B)) 之前简单地调用 A=s(s(0)),它将列出所有答案B 的可能性(请注意,这仍然不会终止!)。

?- A=s(s(0)), numberpair(pair(A,B)).

A = s(s(0)),
B = 0 ;
A = s(s(0)),
B = s(0) ;
A = B, B = s(s(0)) ;
A = s(s(0)),
B = s(s(s(0))) .

编辑 2,还提供一个版本,它将以“公平”的方式枚举!

is_number(0).
is_number(s(N)) :-
  is_number(N).

number_number_sum(0,A,A).
number_number_sum(s(A),B,s(C)) :-
    number_number_sum(A,B,C).

numberpair(pair(X,Y)) :-
    is_number(Z),
    number_number_sum(X,Y,Z).

这将为我们提供

?- numberpair(pair(A,B)).
A = B, B = 0 ;
A = 0,
B = s(0) ;
A = s(0),
B = 0 ;
A = 0,
B = s(s(0)) ;
A = B, B = s(0) ;
A = s(s(0)),
B = 0 ;
A = 0,
B = s(s(s(0))) ;
A = s(0),
B = s(s(0)) ;
A = s(s(0)),
B = s(0) ;
A = s(s(s(0))),
B = 0 .

【讨论】:

  • 好吧,我觉得接缝合乎逻辑。
  • » 您找不到答案的原因是您的规则 numberpair/1 不会终止。 « 这不是原因——正如你最后承认的那样。原因是无限的数对集合以非常不公平的方式枚举。所以这里的目标是为 numberpair/1 找到一个公平的枚举
  • 公平的枚举会是这样的吗:A=0, B=0 A=s(0), B=0 A=0, B=s(0) A=s(s( 0)), B=0 A=s(0), B=s(0) A=0, B=s(s(0)) ... 等等 更具体的:我试着移动扔了搜索树通过“广度优先搜索”而不是“深度优先搜索”
  • 不错!请注意,您必须为此付出代价!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-08-19
  • 1970-01-01
  • 2021-11-08
  • 1970-01-01
  • 2014-09-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多