来自建设性否定的一些想法在这里可能会有所帮助。
理论
有一种简单的方法可以进行逻辑切割。特别是对于约束,因为约束通常是否定完成的。因此,如果您有一个约束 C,您通常可以找到具有以下属性的约束 C':
C' <=> ~C
在如下两个子句中强加优先权:
p :- C, q.
p :- r
只需执行以下操作:
p :- C, q.
p :- C', r.
如果您的约束求解器提供了一个具体的否定,例如(#\)/1
您甚至可以为此定义一个运算符:
:- op(1050,xfy,#?).
:- op(1100,xfy,#:).
(A #? B #: C) :- (A, B); (#\ A, C).
然后写下以下内容:
p :- C #? q #: r.
让我们将此策略应用于您的示例:
例子
您的代码当前如下所示:
result(Input, Result) :-
Input #> 10,
Result = decline.
result(Input, Result) :-
Input in 0..20,
Result = offer.
然后执行以下操作:
result(Input, Result) :-
Input #> 10,
Result = decline.
result(Input, Result) :-
Input #=< 10, Input in 0..20,
Result = offer.
这是一个示例运行:
?- result(15, X).
X = decline ;
false.
?- result(8, X).
X = offer.
现在使用(#?)/2
which 例如可以在 SWI-Prolog 中使用,因为那里的 CLP(FD) 库支持具体化。假设我们已经查阅了 CLP(FD) 库,然后定义(#:)/2
如上:
result(Input, Result) :-
Input #> 10
#?
Result = decline
#:
Input in 0..20,
Result = offer.
这是一个示例运行:
?- result(15, X).
X = decline ;
false.
?- result(8, X).
X = offer.
免责声明
(#?)/2
and的后面语法(#:)/2
受到 Java if-then-else 运算符(?)/2
和(:)/2
. 因为我们不能覆盖或扩展定义,所以不可能有更受 Prolog 启发的语法(;)/2
。
有关具体化的更多信息,请参见此处的A.8.4 部分具体化。我们没有做的是具体化我们定义的 CLP(FD) if-then-else 中的合取和析取,因为 then 和 else 部分可能包含其他目标,然后是 CLP(FD) 约束。
再见