为什么我的规则不能求解简单代数方程中的 X?

Why can't my rule solve for X in a simple algebraic equation?

我是 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 的误解。有人可以向我解释我如何使它起作用或为什么它不起作用吗?

在 Prolog 中,is 是算术求值运算符。它在右侧计算表达式的结果,并将其分配给左侧的变量。

要计算的表达式只能包含数字和算术 operators/functions。换句话说,要计算一个表达式,is 必须已经知道其中的所有数字。

另一种说法是 is is "unidirectional",与双向的 = 不同。这是你所期望的。这就是你得到的错误的意思。

求解此类方程式 - 约束 - 是 constraint solver 的工作。

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

因此,例如,如果我尝试将 [3, X, 5][3, 4, 5] 统一,效果很好,而 X = 4.

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

那你接着问A is (7 * (X - 2))。现在,如果您已经将 X6.5 统一,那么可以对其进行评估 - A 然后与 7 * (6.5 - 2)31.5 统一。但是记住 A 已经和 B 统一了,所以 B 现在也是 31.5.

现在你说B is (3 * (X + 4))。因此 X 统一为 6.5B 统一为 31.5 这与 31.5 is (3 * (6.5 + 4)) 相同。右边是 31.5 所以这是 31.5 is 31.5 这是真的。

所以,求解 solve(6.5) 是可行的。

但是,如果您尝试求解 X,那么第一个谓词就可以正常工作。但是第二个没有。就像我问 "What's 7 times the number that is 2 less than the number I'm thinking of?" 除非我告诉你我在想的数字你不能给我答案。 Prolog 也一样。卡住报错

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

这里来自雷亚尔的顶层:

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

?- {7 * (X - 2) = 3 * (X + 4)}.
X = 6.5 ;
false.

或者,如果您使用 Rationals:

?- 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 is ..., B is ...。 这个有点危险,例如:

?- 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.