使用prolog clpfd无法充分实例化参数

时间:2018-08-13 17:49:54

标签: prolog clpfd

我正在使用CLPFD,但似乎无法摆脱错误:

ERROR: Arguments are not sufficiently instantiated
ERROR: In:
ERROR:   [16] throw(error(instantiation_error,_9234))
ERROR:   [12] clpfd:drep_to_domain(_9270..15,_9266) at /usr/lib/swi-prolog/library/clp/clpfd.pl:3652
ERROR:   [11] clpfd:clpfd_in(_9302,_9308..15) at /usr/lib/swi-prolog/library/clp/clpfd.pl:1608
ERROR:   [10] computeShapeBelow([[circle|...],6|...],[[diamond|...],_9370|...]) 

下面是我的程序,对我来说很明显,来自nth0 / 3的Dim1和Dim2导致Prolog引发此错误。我该如何解决?我找不到使用CLPFD在StackOverflow上应用我在这里看到的解决方案的方法

    :- use_module(library(clpfd)). 

        computeShapeBelow(Shape1,Shape2) :- 
                                nth0(2,Shape1,Location1),
                                nth0(2,Shape2,Location2),
                                nth0(1,Shape1,Dim1),
                                nth0(1,Shape2,Dim2), 
                                nth0(0,Location1,Xcord1),
                                nth0(0,Location2,Xcord2),                                                 
                                nth0(1,Location1,Ycord1),
                                nth0(1,Location2,Ycord2),
                                XlowerLimit1 #= Dim1, 
                                XupperLimit1 #= 20-Dim1,
                                YlowerLimit1 #= Dim1, 
                                YupperLimit1 #= 15-Dim1,
                                XlowerLimit2 #= Dim2, 
                                XupperLimit2 #= 20-Dim2,
                                YlowerLimit2 #= Dim2, 
                                YupperLimit2 #= 15-Dim2,
                                Ycord1 in YlowerLimit1..YupperLimit1, 
                                Ycord2 in YlowerLimit2..YupperLimit2,
                                Xcord1 in XlowerLimit1..XupperLimit1, 
                                Xcord2 in XlowerLimit2..XupperLimit2,                                     
                                Ycord2 #> Ycord1+Dim2+Dim1,                                               
                                labeling([min(Xcord1),
                                     min(Ycord2),
                                     max(Xcord2),  
                                     max(Ycord2)],
                                    [Xcord1,Ycord1,Xcord2,Ycord2]).

修改 listing(computeShapeBelow)产生以下内容。

computeShapeBelow(A, B) :-
    nth0(2, A, C),
    nth0(2, B, D),
    nth0(1, A, E),
    nth0(1, B, J),
    nth0(0, C, Q),
    nth0(0, D, R),
    nth0(1, C, O),
    nth0(1, D, P),
    (   integer(E)
    ->  F=E
    ;   clpfd:clpfd_equal(F, E)
    ),
    (   integer(E)
    ->  G is 20-E
    ;   clpfd:clpfd_equal(G, 20-E)
    ),
    (   integer(E)
    ->  H=E
    ;   clpfd:clpfd_equal(H, E)
    ),
    (   integer(E)
    ->  I is 15-E
    ;   clpfd:clpfd_equal(I, 15-E)
    ),
    (   integer(J)
    ->  K=J
    ;   clpfd:clpfd_equal(K, J)
    ),
    (   integer(J)
    ->  L is 20-J
    ;   clpfd:clpfd_equal(L, 20-J)
    ),
    (   integer(J)
    ->  M=J
    ;   clpfd:clpfd_equal(M, J)
    ),
    (   integer(J)
    ->  N is 15-J
    ;   clpfd:clpfd_equal(N, 15-J)
    ),
    clpfd:clpfd_in(O, H..I),
    clpfd:clpfd_in(P, M..N),
    clpfd:clpfd_in(Q, F..G),
    clpfd:clpfd_in(R, K..L),
    (   integer(P)
    ->  (   integer(O),
        integer(J),
        integer(E)
        ->  P>=O+J+E+1
        ;   S=P,
        clpfd:clpfd_geq(S, O+J+E+1)
        )
    ;   integer(O),
        integer(J),
        integer(E)
    ->  S is O+J+E+1,
        clpfd:clpfd_geq(P, S)
    ;   clpfd:clpfd_geq(P, O+J+E+1)
    ).

1 个答案:

答案 0 :(得分:2)

此错误的原因是您在(in)/2中使用变量作为域边界

作为显示问题的最小示例,请考虑:

?- Var in X..Y.
ERROR: Arguments are not sufficiently instantiated

对于(in)/2,域必须为 ground 。不允许仅使用部分实例化的域。

对此具体问题可能的解决方法是使用诸如(#>)/2等的算术约束,而不是(in)/2。例如:

my_in(Var, Lower, Upper) :-
        Lower #=< Var, Var #=< Upper.

如果您在代码中使用该谓词而不是(in)/2,则问题将消失。我只想弄清楚如何使用谓词。

但是,其他问题将会出现。我认为应该在一个新问题中分别讨论它们。