实际数字不适用于Prolog

时间:2016-07-05 06:50:27

标签: prolog clpfd

我有以下代码:

:-use_module(library(clpfd)).
afn(A,B,C):-
    C #= B*A.

它可以使用整数,但不能使用十进制数字:

43 ?- afn(20, 10, C).
C = 200.

44 ?- afn(20, -10, C).
C = -200.

45 ?- afn(20, -10.5, C).
ERROR: Domain error: `clpfd_expression' expected, found `-10.5'
46 ?- 

我如何在这里使用小数?感谢。

编辑:我发现以下有小数的作品:

afn(A,B,C):-
    C is B * A.

67 ?- afn(20.895, 40.5, C).
C = 846.2475.

'是'是一种正确的方法吗?!

2 个答案:

答案 0 :(得分:3)

CLP(FD)通过整数实现推理。

要将声明性算术扩展为十进制数,基本上有两个选项:

  1. 有理数上使用专用约束求解器。请参阅 CLP(Q)
  2. 缩放所有数字,以便只出现整数并继续使用 CLP(FD)
  3. 我已经看到两种方法都成功应用了。选项(2)有时是优选的,因为CLP(FD)可以更广泛地使用,也因为你可以在有限域上成功地解决它的非线性约束。

    编辑:在您的情况下,合适的查询可能如下所示:

    ?- afn(200, -105, C).
    C = -21000.
    

    最后,您必须再次缩放结果。这样,您可以通过整数模拟小数。

    请注意,使用浮动根本不是一个好的解决方案,因为您无法真正信任结果。因此,只要在Prolog系统中尚未广泛使用更高级的格式,就可以使用有理数或整数。

答案 1 :(得分:1)

你必须要区分

功能(或“模式”)算术。这是您熟悉的其他编程语言之一:您知道哪些参数是输入的,哪些是输出的,您只需计算输入的输出。这就是你从获得的结果(这是标准Prolog的一部分),如果这就是你想要的,那就坚持下去。

?- A=3, B=1.5, C is B * A.
C = 4.5

?- A=3, C=4.5, C is B * A.
instantiation fault                 <<< input B not kown

关系算术。在这里,您要说明必须在所涉及的变量之间保持的等式或不等式。没有输入/输出参数的概念。相反,系统的工作是确保在呈现变量解决方案时保持所有声明的关系。

实现关系算法有许多不同的方法,许多方法只适用于问题的子集(例如只有整数,或只有线性表达式),因此这些功能通常以库的形式提供。

对实数进行一般关系算术的一种可用实现是ECLiPSelibrary(ic)(参见23),它将实数表示为浮点间隔:

?- A=3, C=4.5, C $= B * A.
B = 1.5__1.5                            <<< precise result

?- C $= B * A, C=1, A=10.
B = 0.099999999999999992__0.1           <<< imprecise but accurate result
There are 2 delayed goals.

?- ln(X) $>= sin(X).
X = X{0.36787944117144228 .. 1.0Inf}    <<< partially solved
There are 3 delayed goals.

话虽如此,使用区间运算并正确解释结果并不总是直截了当,这就是为什么@mat建议的解决方法可能有用(适用时)。