gpt4 book ai didi

prolog - CLP(FD) 互斥

转载 作者:行者123 更新时间:2023-12-04 12:39:35 27 4
gpt4 key购买 nike

我正在使用 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] ;
...

这不是原始问题的完整解决方案,但应该提供有关如何以透明方式处理它的想法。

如果您不想使用 DCG,这是另一种方法,它首先指定一个除 3 或 4 之外的单个数字列表,然后在列表中的任何位置插入 3 或 4(SWI Prolog):
:- use_module(library(clpfd)).

one_of_3_4(L) :-
length(L1, _),
L1 ins 1..2 \/ 5..9,
( select(3, L, L1)
; select(4, L, L1)
).

这可以被称为如下:
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) 场景的非成员谓词:
not_member(_, []).
not_member(X, [Y|T]) :- X #\= Y, not_member(X, T).

或者简而言之,您可以缩写 not_member/2使用 maplist/2作为:
not_member(X, L) :- maplist(#\=(X), L).

使用 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.

关于prolog - CLP(FD) 互斥,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47414049/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com