Prolog 约束逻辑编程 - 如何在给定整数列表的域变量列表上设置域?
Prolog constraint logic programming - How to set a domain on a List of Domain Variables given a List of Integers?
基本上我想要实现的是:
给定域变量列表,将这些变量设置为与数字列表相关的域。示例:
......
List=[A1,A2,A3],
domain(List,1,5],
setDomain(List,[1,2]),
labeling([],List).
结果:
A1=1, A2=1, A3=1 or
A1=1, A2=1, A3=2 or
A1=1, A2=2, A3=1
等等...
我尝试过的:
setDomain(List,ListIntegers):-
element(X, List, Element),
member(Element,ListIntegers),
main(List):-
List=[A1,A2,A3],
domain(List,1,5],
setDomain(List,[1,2]),
labeling([],List).
但没有成功...
任何人都可以帮助我了解如何完成此操作吗?
在您的解决方案中,您正在使用 labeling/2
但尚未使用 CLP(FD) 定义其参数,因此它不会为您做任何事情。从你的问题或简单的例子来看不是很清楚,但听起来你想要一个给定长度的列表,每个元素都取自由任意元素列表组成的域?
你可以这样做:
member_(List, Element) :- member(Element, List).
domain_list(Length, Domain, List) :-
length(List, Length),
maplist(member_(Domain), List).
这将得到:
6 ?- domain_list(3, [1,3], L).
L = [1, 1, 1] ;
L = [1, 1, 3] ;
L = [1, 3, 1] ;
L = [1, 3, 3] ;
L = [3, 1, 1] ;
L = [3, 1, 3] ;
L = [3, 3, 1] ;
L = [3, 3, 3].
7 ?-
这也适用于任何类型的元素:
7 ?- domain_list(3, [tom, a(b)], L).
L = [tom, tom, tom] ;
L = [tom, tom, a(b)] ;
L = [tom, a(b), tom] ;
L = [tom, a(b), a(b)] ;
L = [a(b), tom, tom] ;
L = [a(b), tom, a(b)] ;
L = [a(b), a(b), tom] ;
L = [a(b), a(b), a(b)].
8 ?-
如果您想使用 CLP(FD),则需要牢记几件事。 CLP(FD)是针对整型域的,CLP(FD)有自己的域指定方式,不是列表形式。
例如,如果您想要一个长度为 N
的列表,其元素位于 [1,2,3,5,6,8]
所描述的域中,您可以将其写为:
length(List, N),
List ins 1..3 \/ 5..6 \/ 8,
label(List).
这会导致,例如:
2 ?- length(List, 3), List ins 1..3 \/ 5..6 \/ 8, label(List).
List = [1, 1, 1] ;
List = [1, 1, 2] ;
List = [1, 1, 3] ;
List = [1, 1, 5] ;
List = [1, 1, 6] ;
List = [1, 1, 8] ;
List = [1, 2, 1] ;
List = [1, 2, 2]
...
使用 ECLiPSe Prolog 你可以写:
:-lib(fd).
applyDomain([],_).
applyDomain([H|T],D):-
var_fd(H,D),
applyDomain(T,D).
domainList(ListDomain,LengthList,ListOutput):-
length(ListOutput,LengthList),
list_to_dom(ListDomain,Domain),
applyDomain(ListOutput,Domain).
查询:
?- domainList([2,3,5,7,8],5,L).
L = [_530{[2, 3, 5, 7, 8]}, _547{[2, 3, 5, 7, 8]}, _564{[2, 3, 5, 7, 8]}, _581{[2, 3, 5, 7, 8]}, _598{[2, 3, 5, 7, 8]}]
Yes (0.00s cpu)
输出意味着列表 L
中的每个变量(在本例中为 _530
、_547
等)具有指定的域 {[2, 3, 5, 7, 8]}
。如果要标记列表,只需添加
labeling(ListOutput).
作为 domainList/3
的最后一行,您将得到:
?- domainList([2, 3, 5, 7, 8], 5, L).
L = [2, 2, 2, 2, 2]
Yes (0.00s cpu, solution 1, maybe more)
L = [2, 2, 2, 2, 3]
Yes (0.00s cpu, solution 2, maybe more)
L = [2, 2, 2, 2, 5]
Yes (0.00s cpu, solution 3, maybe more)
等等...如果您希望所有列表都不同,只需添加
alldifferent(ListOutput),
在 labeling/1
之前,你会得到
?- domainList([2, 3, 5, 7, 8], 5, L).
L = [2, 3, 5, 7, 8]
Yes (0.00s cpu, solution 1, maybe more)
L = [2, 3, 5, 8, 7]
Yes (0.00s cpu, solution 2, maybe more)
L = [2, 3, 7, 5, 8]
Yes (0.00s cpu, solution 3, maybe more)
我一般不会用SWI prolog来解决clpfd
问题,所以不知道SWI中有没有类似的解决方案...
基本上我想要实现的是:
给定域变量列表,将这些变量设置为与数字列表相关的域。示例:
......
List=[A1,A2,A3],
domain(List,1,5],
setDomain(List,[1,2]),
labeling([],List).
结果:
A1=1, A2=1, A3=1 or
A1=1, A2=1, A3=2 or
A1=1, A2=2, A3=1
等等...
我尝试过的:
setDomain(List,ListIntegers):-
element(X, List, Element),
member(Element,ListIntegers),
main(List):-
List=[A1,A2,A3],
domain(List,1,5],
setDomain(List,[1,2]),
labeling([],List).
但没有成功...
任何人都可以帮助我了解如何完成此操作吗?
在您的解决方案中,您正在使用 labeling/2
但尚未使用 CLP(FD) 定义其参数,因此它不会为您做任何事情。从你的问题或简单的例子来看不是很清楚,但听起来你想要一个给定长度的列表,每个元素都取自由任意元素列表组成的域?
你可以这样做:
member_(List, Element) :- member(Element, List).
domain_list(Length, Domain, List) :-
length(List, Length),
maplist(member_(Domain), List).
这将得到:
6 ?- domain_list(3, [1,3], L).
L = [1, 1, 1] ;
L = [1, 1, 3] ;
L = [1, 3, 1] ;
L = [1, 3, 3] ;
L = [3, 1, 1] ;
L = [3, 1, 3] ;
L = [3, 3, 1] ;
L = [3, 3, 3].
7 ?-
这也适用于任何类型的元素:
7 ?- domain_list(3, [tom, a(b)], L).
L = [tom, tom, tom] ;
L = [tom, tom, a(b)] ;
L = [tom, a(b), tom] ;
L = [tom, a(b), a(b)] ;
L = [a(b), tom, tom] ;
L = [a(b), tom, a(b)] ;
L = [a(b), a(b), tom] ;
L = [a(b), a(b), a(b)].
8 ?-
如果您想使用 CLP(FD),则需要牢记几件事。 CLP(FD)是针对整型域的,CLP(FD)有自己的域指定方式,不是列表形式。
例如,如果您想要一个长度为 N
的列表,其元素位于 [1,2,3,5,6,8]
所描述的域中,您可以将其写为:
length(List, N),
List ins 1..3 \/ 5..6 \/ 8,
label(List).
这会导致,例如:
2 ?- length(List, 3), List ins 1..3 \/ 5..6 \/ 8, label(List).
List = [1, 1, 1] ;
List = [1, 1, 2] ;
List = [1, 1, 3] ;
List = [1, 1, 5] ;
List = [1, 1, 6] ;
List = [1, 1, 8] ;
List = [1, 2, 1] ;
List = [1, 2, 2]
...
使用 ECLiPSe Prolog 你可以写:
:-lib(fd).
applyDomain([],_).
applyDomain([H|T],D):-
var_fd(H,D),
applyDomain(T,D).
domainList(ListDomain,LengthList,ListOutput):-
length(ListOutput,LengthList),
list_to_dom(ListDomain,Domain),
applyDomain(ListOutput,Domain).
查询:
?- domainList([2,3,5,7,8],5,L).
L = [_530{[2, 3, 5, 7, 8]}, _547{[2, 3, 5, 7, 8]}, _564{[2, 3, 5, 7, 8]}, _581{[2, 3, 5, 7, 8]}, _598{[2, 3, 5, 7, 8]}]
Yes (0.00s cpu)
输出意味着列表 L
中的每个变量(在本例中为 _530
、_547
等)具有指定的域 {[2, 3, 5, 7, 8]}
。如果要标记列表,只需添加
labeling(ListOutput).
作为 domainList/3
的最后一行,您将得到:
?- domainList([2, 3, 5, 7, 8], 5, L).
L = [2, 2, 2, 2, 2]
Yes (0.00s cpu, solution 1, maybe more)
L = [2, 2, 2, 2, 3]
Yes (0.00s cpu, solution 2, maybe more)
L = [2, 2, 2, 2, 5]
Yes (0.00s cpu, solution 3, maybe more)
等等...如果您希望所有列表都不同,只需添加
alldifferent(ListOutput),
在 labeling/1
之前,你会得到
?- domainList([2, 3, 5, 7, 8], 5, L).
L = [2, 3, 5, 7, 8]
Yes (0.00s cpu, solution 1, maybe more)
L = [2, 3, 5, 8, 7]
Yes (0.00s cpu, solution 2, maybe more)
L = [2, 3, 7, 5, 8]
Yes (0.00s cpu, solution 3, maybe more)
我一般不会用SWI prolog来解决clpfd
问题,所以不知道SWI中有没有类似的解决方案...