为什么我的规则可以用简单的代数方程求解X?

时间:2016-09-22 22:13:13

标签: 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的误解。有人可以向我解释我是如何让这个工作或为什么它不能工作?

3 个答案:

答案 0 :(得分:7)

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

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

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

解决这些方程 - 约束 - 是constraint solver的工作。

答案 1 :(得分:6)

你可以使用一个库,至少在SWI-Prolog中可用:library(clpr)和library(clpq)。

这里是Reals的最高级别:

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

答案 2 :(得分:2)

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

因此,例如,如果我尝试将[3, X, 5][3, 4, 5]统一起来并且X = 4正常工作。

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

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

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

因此,解决solve(6.5)的问题。

但是,如果你试图解决X,那么第一个谓词就可以了。但第二个没有。这就像是在问我“这个数字的7倍是我想到的数字的2倍?”除非我告诉你我想的数字你不能给我一个答案。 Prolog也一样。它卡住并报告错误。