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

dyn*_*eed 2 prolog constraint-programming

我是Prolog的新手,所以请保持温柔.

这是我的规则:

solve(X) :- A = B, A is (7 * (X - 2)), B is (3 * (X + 4)).
Run Code Online (Sandbox Code Playgroud)

显然,这里的正确答案是6.5.如果我把它交给Prolog,它确认:

| ?- solve(6.5).

yes
Run Code Online (Sandbox Code Playgroud)

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

| ?- solve(X).
uncaught exception: error(instantiation_error,(is)/2)
Run Code Online (Sandbox Code Playgroud)

我完全承认,这里发生的一切都是由于我对Prolog的误解.有人可以向我解释我是如何让这个工作或为什么它不起作用?

Wil*_*ess 7

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

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

另一种说法is是"单向",不像=是双向的.这是你的期望.这就是你得到的错误的含义.

求解这样的方程 - 约束 - 是约束求解器的工作.


小智 6

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

这里是Reals的顶级:

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

?- {7 * (X - 2) = 3 * (X + 4)}.
X = 6.5 ;
false.
Run Code Online (Sandbox Code Playgroud)

或者,如果您使用Rational:

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

?- {7 * (X - 2) = 3 * (X + 4)}, R is float(X).
X = 13 rdiv 2,
R = 6.5.
Run Code Online (Sandbox Code Playgroud)

如果你想自己做,那当然会有更多的工作.你必须编写类似的代码

...,
(   ground(X)
->  7 * (X - 2) =:= 3 * (X + 4)
;   X is (3*4 + 2*7) / (7 - 3)
),
...
Run Code Online (Sandbox Code Playgroud)

顺便说一句,你在做什么:A = B, A is ..., B is ....这有点危险,例如:

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

?- 3 - 2 =:=  sin(pi/2).
true.
Run Code Online (Sandbox Code Playgroud)

3 - 2计算结果为1; 然后,sin(pi/2)计算浮点数1.0,这不会与整数1统一.因此,第一个查询失败!

?- 1 = 1.0.
false.
Run Code Online (Sandbox Code Playgroud)

  • 请考虑使用CLP(Q)代替CLP(R):我们不能相信CLP(R)的结果. (2认同)