[英]Mutual exclusivity in CLP(FD)
我正在使用clp(fd)
编写一个Prolog程序,并且我很难实现我想要的约束之一。
输出是整数列表(长度取决于程序另一部分的输入),其中存在一对互斥的预定义数字对,并且每对中的一个数字必须在输出中。
一个例子:
输出是一个整数列表,每个整数在1到10之间。输出必须包含3或4,但不能同时包含两者。
到目前为止,我有以下,从而限制了它,这样3和4不能同时输出,但它不保证其中之一是在输出中。
mutual2([A], ME1):-
(A in 3 #==> ME1) #/\ (#\ A in 4 #<== ME1).
mutual2([A, B| Tail], ME1):-
(A in 3 #==> ME1) #/\ (#\ A in 4 #<== ME1),
(B in 3 #==> ME1) #/\ (#\ B in 4 #<== ME1),
mutual2([B|Tail], ME1).
编辑:
所以运行:
[A,B] ins 2..6, A #< B, mutual2([1,2,B,A,5],M), label([A,B]).
得到:
A = 2,
B = 3,
M = 1 ;
A = 2,
B = 4,
M = 0 ;
A = 2,
B = 5,
M in 0..1 ;
A = 3,
B = 5,
M = 1 ;
A = 4,
B = 5,
M = 0 ;
但是我不希望A=2, B=5, M in 0..1
是有效输出,因为A
和B
都不是3或4。
我可能会使用CLP(FD)和DCG的组合,因为我们正在处理序列。
这是一个实现,它识别包含正好一个3或一个4的序列:
:- use_module(library(clpfd)).
one_of_3_4 --> no_3_4, [3], no_3_4.
one_of_3_4 --> no_3_4, [4], no_3_4.
no_3_4 --> [].
no_3_4 --> [X], { X in 1..2 \/ 5..9 }.
这产生如下:
2 ?- phrase(one_of_3_4, L), label(L).
L = [3] ;
L = [3, 1] ;
L = [3, 2] ;
L = [3, 5] ;
L = [3, 6] ;
L = [3, 7] ;
L = [3, 8] ;
L = [3, 9] ;
L = [1, 3] ;
L = [2, 3] ;
L = [5, 3] ;
L = [6, 3] ;
L = [7, 3] ;
L = [8, 3] ;
L = [9, 3] ;
...
这不是原始问题的完整解决方案,但应该提供如何以透明方式处理它的想法。
2 ?- one_of_34(L), label(L).
L = [3] ;
L = [4] ;
L = [3, 1] ;
L = [3, 2] ;
L = [3, 5] ;
L = [3, 6] ;
L = [3, 7] ;
L = [3, 8] ;
L = [3, 9] ;
L = [1, 3] ;
L = [2, 3] ;
L = [5, 3] ;
L = [6, 3] ;
L = [7, 3] ;
L = [8, 3] ;
L = [9, 3] ;
L = [4, 1] ;
L = [4, 2] ;
L = [4, 5] ;
L = [4, 6] ;
L = [4, 7] ;
L = [4, 8] ;
L = [4, 9] ;
L = [1, 4] ;
L = [2, 4] ;
L = [5, 4] ;
L = [6, 4] ;
L = [7, 4] ;
L = [8, 4] ;
L = [9, 4] ;
...
然后可以按如下方式调用它:
2 ?- one_of_34(L), label(L). L = [3] ; L = [4] ; L = [3, 1] ; L = [3, 2] ; L = [3, 5] ; L = [3, 6] ; L = [3, 7] ; L = [3, 8] ; L = [3, 9] ; L = [1, 3] ; L = [2, 3] ; L = [5, 3] ; L = [6, 3] ; L = [7, 3] ; L = [8, 3] ; L = [9, 3] ; L = [4, 1] ; L = [4, 2] ; L = [4, 5] ; L = [4, 6] ; L = [4, 7] ; L = [4, 8] ; L = [4, 9] ; L = [1, 4] ; L = [2, 4] ; L = [5, 4] ; L = [6, 4] ; L = [7, 4] ; L = [8, 4] ; L = [9, 4] ; ...
mutual(Output, A, B):-
member(A, Output), not_member(B, Output).
mutual(Output, A, B) :-
member(B, Output), not_member(A, Output).
或者简单地说,你可以缩写not_member/2
使用maplist/2
为:
?- [A,B] ins 2..5, A #< B, mutual([A,B,5],3,4), label([A,B]).
A = 3,
B = 5 ;
A = 2,
B = 3 ;
A = 4,
B = 5 ;
A = 2,
B = 4 ;
false.
使用not_member/2
,这将按预期工作:
mutual(Output, A, B):- member(A, Output), not_member(B, Output). mutual(Output, A, B) :- member(B, Output), not_member(A, Output).
查询会产生所有结果:
?- [A,B] ins 2..5, A #< B, mutual([A,B,5],3,4), label([A,B]). A = 3, B = 5 ; A = 2, B = 3 ; A = 4, B = 5 ; A = 2, B = 4 ; false.
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.