簡體   English   中英

CLP(FD)的相互排他性

[英]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是有效輸出,因為AB都不是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] ;
...

這不是原始問題的完整解決方案,但應該提供如何以透明方式處理它的想法。


如果您不想使用DCG,這是另一種方法,首先指定除3或4之外的單個數字列表,然后在列表中的任意位置插入3或4(SWI Prolog):

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] ; ... 


在回答對此答案的評論時,您可以創建一個專門應用於CLP(FD)場景的非成員謂詞:

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM