Prolog 为什么可以';我的规则不能在一个简单的代数方程中解X吗?

Prolog 为什么可以';我的规则不能在一个简单的代数方程中解X吗?,prolog,constraint-programming,Prolog,Constraint Programming,我不熟悉Prolog,所以请温柔一点 这是我的规则: solve(X) :- A = B, A is (7 * (X - 2)), B is (3 * (X + 4)). 显然,这里的正确答案是6.5。如果我将其交给Prolog,它将确认: | ?- solve(6.5). yes 但是,如果我让Prolog做脏活,它会抛出一个错误: | ?- solve(X). uncaught exception: error(instantiation_error,(is)/2) 我完全承认这里发

我不熟悉Prolog,所以请温柔一点

这是我的规则:

solve(X) :- A = B, A is (7 * (X - 2)), B is (3 * (X + 4)).
显然,这里的正确答案是
6.5
。如果我将其交给Prolog,它将确认:

| ?- solve(6.5).

yes
但是,如果我让Prolog做脏活,它会抛出一个错误:

| ?- solve(X).
uncaught exception: error(instantiation_error,(is)/2)

我完全承认这里发生的一切都是由于我对序言的误解。有人能给我解释一下我该如何使它工作或者为什么它不工作吗?

在序言中,
是一个算术求值操作符。它计算表达式右侧的结果,并将其分配给左侧的变量

要计算的表达式必须仅包含数字和算术运算符/函数。换句话说,要计算表达式,
is
必须已经知道其中的所有数字

另一种说法是,与双向的
=
不同。这正是你所期望的。这就是你所犯错误的意义


解决这样的方程-约束-是一个工程师的工作

Prolog通过统一工作。它试图使结构相同

例如,如果我尝试将
[3,X,5]
[3,4,5]
统一起来,这很好,并且
X=4

在代码中,您首先说的是
A=B
。这很好,因为最初的
A
B
没有实例化,所以基本上是将它们的命运联系在一起-如果
A
后来被实例化,那么
B
也会自动实例化,反之亦然

然后你继续问
A是(7*(X-2))
。现在,如果您已经将
X
6.5
统一,则可以对其进行评估-
A
然后与
7*(6.5-2)
31.5
统一。但是请记住,
A
已经与
B
统一,因此
B
现在也是
31.5

现在你说B是(3*(X+4))
。因此,使用
X
统一到
6.5
B
统一到
31.5
,这与
31.5是(3*(6.5+4))
相同。右侧是
31.5
,因此这是
31.5是31.5
,这是正确的

因此,求解
solve(6.5)
是可行的


但是,如果您尝试求解
X
,那么第一个谓词就可以正常工作。但是第二个没有。这就像我问“比我想的数字少2的7倍数字是多少?”除非我告诉你我想的数字,否则你不能给我答案。Prolog也是如此。它卡住并报告错误。

您可以为此使用库,至少在SWI Prolog中提供:库(clpr)和库(clpq)

以下是Reals的顶层:

?- use_module(library(clpr)).
true.

?- {7 * (X - 2) = 3 * (X + 4)}.
X = 6.5 ;
false.
或者,如果你使用理性:

?- use_module(library(clpq)).
true.

?- {7 * (X - 2) = 3 * (X + 4)}, R is float(X).
X = 13 rdiv 2,
R = 6.5.
如果你想自己做这件事,那当然要做更多的工作。您必须像这样编写代码

...,
(   ground(X)
->  7 * (X - 2) =:= 3 * (X + 4)
;   X is (3*4 + 2*7) / (7 - 3)
),
...
顺便说一句,你在做什么:
A=B,A是…,B是…
。 这有点危险,例如:

?- A = B, A is 3 - 2, B is sin(pi/2).
false.

?- 3 - 2 =:=  sin(pi/2).
true.
3-2
计算为整数1;然后,
sin(pi/2)
计算为浮点数1.0,这与整数1不一致。因此,第一个查询失败

?- 1 = 1.0.
false.
请考虑使用CLP(Q)代替CLP(R):我们不能相信CLP(R)的结果。