Prolog将文本转换为数字并进行算术运算

时间:2014-05-07 01:04:22

标签: prolog

我第一次在prolog工作。 我试图在文本中转换操作。 如, 三+三=六 应该回归真实。 我试过这个。 我在最后一行收到错误,当我尝试添加(ONE,ONE,TWO)时,它返回false而不是true。

numericValue(ONE, 1).
numericValue(TWO, 2).
numericValue(THREE, 3).
numericValue(FOUR, 4).
numericValue(FIVE, 5).
numericValue(SIX, 6).
numericValue(SEVEN, 7).
numericValue(EIGHT, 8).
numericValue(ZERO, 0).
numericValue(NINE, 9).


add(num1,num2,num3):-
    numericValue(num1,a),
    numericValue(num2,b),
    numericValue(num3,c),
    (c =:= a+b -> true ; false).

istBiggerThen(XinEng,YinEng) :-
    numericValue(XinEng, X),
    numericValue(YinEng, Y),
    (  X < Y -> true ;  false).

A  + B = C :- add(A,B,C).

最后一行的错误是

ERROR: /home/name/prolog_examples/crypt.pl:24:
No permission to modify static procedure `(=)/2'

1 个答案:

答案 0 :(得分:2)

l次迭代(小写)与V ariabls(大写):

正如@lurker指出的那样,你的原子和变量已经混淆了。所以你的事实应该是这样的:

text_to_number(one, 1).
text_to_number(two, 2).
text_to_number(three, 3).
%% etc...

虽然你的规则需要使用变量,如下所示:

add(A_Text, B_Text, C_Text) :-
    text_to_number(A_Text, A_Num),
    text_to_number(B_Text, B_Num),
    C_Num is A_Num + B_Num,
    text_to_number(C_Text, C_Num).

bigger_than(A_Text, B_Text) :-
    text_to_number(A_Text, A_Num),
    text_to_number(B_Text, B_Num),
    A_Num > B_Num.

add(ONE, ONE, TWO)结果为假的原因是因为add/3的原始规则只定义了原子num1, num2, num3, a, b, c之间的关系。当您查询add(ONE, ONE, TWO)时,Prolog会尝试将变量与规则头部中的原子统一起来,即add(num1, num2, num3)。因为您有ONE作为查询的第一个和第二个参数,所以这种统一是不可能的,因为ONE = ONE只有num1 \= num2。由于add/3没有其他规则或事实,查询只返回false


使用模式(| Condition | - &gt; true; false):

子句正文中的语句(即:-运算符的右侧)被判断为真或假,因此您几乎不需要使用模式(|Condition| -> true ; false)。例如。如果C_Num is A_Num + B_Num可以与C_NumA_Num的总和统一,则B_Num为真,否则为假,在这种情况下,Prolog将开始追踪跟踪。


使用=:=/2is/2

=:=/2检查其第一个参数与其第二个参数的值是否相等,该参数可以是可以使用is/2计算的算术表达式。查询?- X =:= 2 + 2并且您将获得实例化错误,因为=:=/2无法自由变量与数学表达式进行比较。另一方面,is/2将左侧的变量与右侧表达式的值统一起来:?- X is 2 + 2. X = 4

你对=:=/2的使用会起作用(只要你理顺了变量原子的东西),但你的规则描述了一个低效且迂回的解决方案,原因如下:因为numericValue(Num3,C)先于算术的评估,Prolog将首先将numericValue(Num3,C)与第一个合适的事实统一起来,即。 numericValue(one, 1)然后测试1 =:= A + B。当失败时,Prolog将与下一个事实numericValue(two, 2)统一,然后测试2 =:= A + B,然后测试下一个......直到它最终发生在正确的值上。与我建议的规则相比较:数值A_NumB_NumC_Num is A_Num + B_Num相加,将C_Num与总和统一。然后Prolog将text_to_number(C_Text, C_Num)与具有C_Num的适当值的单一拟合事实统一起来。


定义运算符:

当术语出现在:-的右侧或程序的顶层时,正在定义。但是,您不能简单地重新定义谓词(可以这样做,但需要一些簿记和特殊声明。例如,dynamic/1)。此外,您不希望重新定义+/2=/2等核心术语。但是可以相对轻松地定义自己的谓词。事实上,对谓词定义疯狂是我最喜欢的与Prolog无关的事情之一(尽管我已经注意到在实践中不要使用不必要的运算符,因为它会让你的代码变得晦涩难懂)。

在指令中使用op/3声明运算符。它具有签名op(+Precedence, +Type, :Name)(Cf。,SWI-Prolog documentation):

:- op(200, xfx, user:(++)).
:- op(300, yfx, user:(=::=)).

A ++ B =::= C :- add(A, B, C).

行动中:

?- one ++ two  =::= X.
X = three.