5

我开始学习 Prolog,我想要一个给定整数的程序给P整数A等等。如果没有和的值满足这个方程,应该返回BP = A² + B²ABfalse

例如:如果P = 5,它应该给出A = 1and B = 2(或A = 2and B = 1),因为1² + 2² = 5.

我在想这应该可行:

giveSum(P, A, B) :- integer(A), integer(B), integer(P), P is A*A + B*B.

使用查询:

giveSum(5, A, B).

但是,事实并非如此。我该怎么办?我对 Prolog 很陌生,所以我仍然犯了很多错误。

提前致谢!

4

2 回答 2

6

integer/1是一个非单调谓词。这不是一个允许您在这种情况下应用您期望的推理的关系。举例说明:

?- 整数 (I)。
的。

不存在整数,是吗?至少可以说,让我感到惊讶

代替这种非关系结构,使用 Prolog 系统的CLP(FD) 约束来推理整数。

例如:

?- 5 #= A*A + B*B。
A 在 -2..-1\/1..2 中,
A^2#=_G1025,
_G1025 在 1..4 中,
_G1025+_G1052#=5,
_G1052 在 1..4 中,
B^2#=_G406,
B 在 -2..-1\/1..2

对于具体的解决方案:

?- 5 #= A*A + B*B, 标签([A,B])。
A = -2,
B = -1 ;
A = -2,
B = 1;
A = -1,
B = -2 ;
等等

CLP(FD) 约束是完全纯粹的关系,可以按照您期望的方式使用。有关详细信息,请参阅

我注意到的其他事情:

  • use_underscores_for_readability_as_is_the_convention_in_prolog相反ofMixingTheCasesToMakePredicatesHardToRead
  • 使用声明性名称,避免命令式。例如,为什么要调用它give_sum如果总和已经给出,这个谓词也很有意义。那么,sum_of_squares/3例如,呢?
于 2016-07-20T12:37:37.857 回答
1

为了效率,Prolog 实现者已经选择了——很多很多年前——一些妥协。现在,您的 Prolog 有可能像 CLP(FD) 那样实现高级整数运算。如果是这种情况,mat' 的答案是完美的。但是一些 Prologs(可能是一个幼稚的 ISO Prolog 兼容处理器)可能会抱怨缺少 label/1 和 (#=)/2。因此,传统的 Prolog 解决方案:该技术称为生成和测试

giveSum(P, A, B) :-
  ( integer(P) -> between(1,P,A), between(1,P,B) ; integer(A),integer(B) ),
  P is A*A + B*B.

between/3 它不是内置的 ISO,但比 (#=)/2 和 label/1 更容易编写:)

无论如何,请遵循 mat' 的建议并避免使用“命令式”命名。通常对关系的描述会更好,因为 Prolog 就是这样:一种关系语言。

于 2016-07-20T13:37:40.353 回答