【问题标题】:Why this Goldbach's conjecture program does not work in Prolog?为什么这个哥德巴赫猜想程序在 Prolog 中不起作用?
【发布时间】:2018-07-07 19:59:13
【问题描述】:

为什么这个程序在 Prolog 中不起作用?

%  Goldbach's conjecture. 
% Goldbach's conjecture says that every positive even number greater 
% than 2 is the sum of two prime numbers. Example: 28 = 5 + 23.

:- ensure_loaded(p31).

% goldbach(N,L) :- L is the list of the two prime numbers that
%    sum up to the given N (which must be even).
%    (integer,integer) (+,-)

goldbach(4,[2,2]) :- !.
goldbach(N,L) :- N mod 2 =:= 0, N > 4, goldbach(N,L,3).

goldbach(N,[P,Q],P) :- Q is N - P, is_prime(Q), !.
goldbach(N,L,P) :- P < N, next_prime(P,P1), goldbach(N,L,P1).

next_prime(P,P1) :- P1 is P + 2, is_prime(P1), !.
next_prime(P,P1) :- P2 is P + 2, next_prime(P2,P1).

首先,我必须删除代码行:- ensure_loaded(p31)。否则标记一个错误说不存在。

其次,当我使用 ?-goldbach(4,X,Y) 在 SWI-Prolog 屏幕上运行它时。标记了一个错误,上面写着:

错误:参数没有充分实例化

为什么?

有人可以帮我修复程序吗?

谢谢。

【问题讨论】:

  • 您只需要正好两个加数,所以我不会为列表而烦恼。它只是使谓词更加麻烦。 p31 是什么?请注意,is/2 仅用于当第二个参数的所有变量都是已知数值时的算术评估。尝试使用 CLP(FD)。
  • ? ? ?............
  • 让我试试另一个问题,也许这个问题更简单,虽然我假设你从其他地方复制了这段代码,所以你不知道它是如何工作的:你为什么要打电话给goldbach(4, X, Y)?代码注释清楚地表明顶层是goldbach/2。你应该打电话给goldbach(4, L)
  • 您可能认为goldbach(4, X, Y) 会给您XY 中的两个素数,但事实并非如此。 goldbach(4, X) 将在X 的列表中为您提供两个素数。 Prolog 与其他语言完全不同,您需要开始阅读逻辑编程的介绍并积极解决更简单的练习。您正在查看的是一系列复杂练习中的一个已解决的练习,它们之间存在依赖关系。
  • 您的问题是关于为什么该程序不起作用以及是否可以修复它。答案已经给出:您需要调用正确的顶级谓词:goldbach(4, L)。如果您对 Prolog 中编程的特定问题有不同的特定问题,您应该单独发布。如果你只想要这个程序的 3 参数版本,你可以写,my_goldbach(N, X, Y) :- goldbach(N, [X,Y]). 并调用 my_goldbach(4, X, Y).

标签: math error-handling compiler-errors prolog instantiation-error


【解决方案1】:

观察goldbach/2 是被定义的谓词,它使用了一个辅助谓词goldbach/3goldbach/3goldbach/2 在满足N 的某些条件时调用,以计算双联L,使用3 作为goldbach/3 的辅助参数P 的初始值。

事实上,您可以看到goldbach/3 将始终在其第一个和第三个参数实例化的情况下被调用。对第一个参数的要求在goldbach/2的文档中很清楚,标记为+;第三个参数是在goldbach/2 调用它的助手goldbach/3 执行计算时提供的。

goldbach(4, X, Y) 这样的调用失败,因为它试图执行涉及未实例化变量的算术 (Q is N - P),这会导致错误:逻辑变量的算术对 Prolog 没有意义。澄清一下,该程序应该可以正常工作,但您不应该直接调用goldbach/3

就目前而言,谓词is_prime/1 缺失。您删除的 ensure_loaded/1 指令正在寻找将定义此谓词的文件(在此开发中)。

【讨论】:

  • 我应该在代码的哪一部分写is_prime/1? .应该是ensure_loaded/1 而不是ensure_loaded(p31) ?
  • 1.写在哪里都没关系。 2. ensure_loaded/1 是带有 1 个参数的 ensure_loaded 谓词的非正式表示法(请注意,您可以有几个不同的谓词具有相同的名称和不同的数量,这是混淆的核心)。
  • 我添加了 3 行代码行 ensure_loaded/1.is_prime/1.my_goldbach(N, X, Y) :- goldbach(N, [X,Y]). 并在我调用 my_goldbach(4, X, Y). 时正常工作,但由于 my_goldbach(8, X, Y). 而失败,这是为什么呢?
  • 在两个goldbach 谓词之间仍然存在混淆,但这超出了所提出问题的范围,也超出了 cmets 可以合理解决的范围。像 @lurker 一样,我认为最有效的方法是从更简单的示例开始工作,将您的问题隔离在这些示例上,然后提出关于它们的具体问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多