我是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的误解。有人可以向我解释我是如何让这个工作或为什么它不能工作?
答案 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
。这很好,因为最初A
和B
没有被实例化,所以你基本上把他们的命运绑在一起 - 如果A
稍后被实例化,那么B
自动也是,或签证-versa。
然后你继续问A is (7 * (X - 2))
。现在,如果您已将X
与6.5
统一起来,则可以对此进行评估 - 然后A
与7 * (6.5 - 2)
或31.5
统一。但请记住,A
已与B
统一,因此B
现在也是31.5
。
现在你说B is (3 * (X + 4))
。因此,X
统一到6.5
,B
与31.5
统一,这与31.5 is (3 * (6.5 + 4))
相同。右边是31.5
,所以这是31.5 is 31.5
,这是真的。
因此,解决solve(6.5)
的问题。
但是,如果你试图解决X
,那么第一个谓词就可以了。但第二个没有。这就像是在问我“这个数字的7倍是我想到的数字的2倍?”除非我告诉你我想的数字你不能给我一个答案。 Prolog也一样。它卡住并报告错误。