Prolog 如何在没有排列的情况下编写findall?
我想写一个程序来评估,在一个特定的行李容量内可以携带哪些物品组合。该计划的重要部分是排除所有可能的排列。程序应该给出每种可能性一次,而不是它们的排列。下面是一个查询示例:Prolog 如何在没有排列的情况下编写findall?,prolog,Prolog,我想写一个程序来评估,在一个特定的行李容量内可以携带哪些物品组合。该计划的重要部分是排除所有可能的排列。程序应该给出每种可能性一次,而不是它们的排列。下面是一个查询示例: ?- place(Possibility, 2). Possibility = [water]; Possibility = [flower]; Possibility = [paper]; Possibility = [meat]; Possibility = [wood]; Possibility = [glass]; P
?- place(Possibility, 2).
Possibility = [water];
Possibility = [flower];
Possibility = [paper];
Possibility = [meat];
Possibility = [wood];
Possibility = [glass];
Possibility = [water, flower];
Possibility = [water, paper];
Possibility = [flower, paper].
到目前为止,我的代码是:
% item(Name, Space)
item(water, 1).
item(flower, 1).
item(paper, 1).
item(meat, 2).
item(wood, 2).
item(glass, 2).
item(stone, 3).
item(gold, 3).
item(metal, 3).
item(platin, 4).
% maximum capacity of bag
maxcapacity(10).
place(Possibility, Capacity) :-
maxcapacity(MaxCapacity),
between(1, MaxCapacity, Capacity),
possibilities(Capacity, [], Possibility).
possibilities(Capacity, Acc, Acc) :-
\+ (space(Possibility, [], 0, Capacity), sort(Possibility, SortedPossibility), \+ member(SortedPossibility, Acc)).
possibilities(Capacity, Acc, PossibilityList) :-
space(Possibility, [], 0, Capacity),
sort(Possibility, SortedPossibility),
not(member(SortedPossibility, Acc)),
Acc1 = [SortedPossibility|Acc],
possibilities(Capacity, Acc1,PossibilityList).
space(Acc, Acc, Space, MaxCapacity) :-
Space =< MaxCapacity,
Acc \= [].
space(Possibility, Acc, Space, MaxCapacity) :-
item(Item, ItemSpace),
not(member(Item, Acc)),
NewSpace is Space + ItemSpace,
NewSpace =< MaxCapacity,
Acc1 = [Item|Acc],
space(Possibility, Acc1, NewSpace, MaxCapacity).
%项(名称、空格)
项目(水,1)。
项目(花卉,1)。
项目(文件,1)。
项目(肉,2)。
项目(木材,2)。
项目(玻璃,2)。
项目(石头,3)。
项目(黄金,3)。
项目(金属,3)。
项目(铂,4)。
%行李最大容量
最大容量(10)。
地点(可能性、容量):-
最大容量(maxcapacity),
介于(1,最大容量,容量),
可能性(容量,[],可能性)。
可能性(容量、Acc、Acc):-
\+(空间(可能性,[],0,容量),排序(可能性,排序可能性),\+成员(排序可能性,Acc))。
可能性(容量、Acc、可能性列表):-
空间(可能性,[],0,容量),
排序(可能性、排序可能性),
非(成员(分类可能性,Acc)),
Acc1=[SortedPossibility | Acc],
可能性(容量、Acc1、可能性列表)。
空间(Acc、Acc、空间、最大容量):-
空间=<最大容量,
Acc\=[]。
空间(可能性、Acc、空间、最大容量):-
项目(项目,项目空间),
非(成员(项目,Acc)),
新闻空间是空间+项目空间,
新闻空间=
我试图通过排序排除排列,但程序仍然给我所有排列,并以某种方式将项目组合放入列表中。该程序应该像上面的示例查询一样工作
我真的很感激任何帮助 您已经用
空格/4
谓词完成了大部分操作,但随后您在可能性/3
中添加了额外的内容,这会“以某种方式将项目组合放入列表”,尽管您不希望这样做
让我们直接看一下space/4
的一个例子:
?- space(Possibility, [], 0, 2).
Possibility = [water] ;
Possibility = [flower, water] ;
Possibility = [paper, water] ;
Possibility = [flower] ;
Possibility = [water, flower] ;
Possibility = [paper, flower] ;
Possibility = [paper] ;
Possibility = [water, paper] ;
Possibility = [flower, paper] ;
Possibility = [meat] ;
Possibility = [wood] ;
Possibility = [glass] ;
false.
请注意,您可以获得容量1的解决方案以及容量2的解决方案。您使用的
maxcapacity/1
和between/3
向我表明,您在这里只需要容量正好为2的解决方案。您可以使用空格/4
谓词更改=您已经完成的大部分操作,但是您可以在可能性/3
中添加额外的内容,这会“以某种方式将项目组合放入列表”,尽管您不希望这样
让我们直接看一下space/4
的一个例子:
?- space(Possibility, [], 0, 2).
Possibility = [water] ;
Possibility = [flower, water] ;
Possibility = [paper, water] ;
Possibility = [flower] ;
Possibility = [water, flower] ;
Possibility = [paper, flower] ;
Possibility = [paper] ;
Possibility = [water, paper] ;
Possibility = [flower, paper] ;
Possibility = [meat] ;
Possibility = [wood] ;
Possibility = [glass] ;
false.
请注意,您可以获得容量1的解决方案以及容量2的解决方案。您使用的maxcapacity/1
和between/3
向我表明,您在这里只需要容量正好为2的解决方案。您可以更改=您的问题是您的程序正在创建可能性列表,而不是可能性。下面的代码找到了一种可能性,然后回溯到下一种可能性
可能性(u,Current,Current)
将当前工作可能性与查询统一,以返回当前可能性作为结果<代码>当前\=[]
用于消除空包的可能性(基于您的预期结果)
回溯后,可能性(容量,[],可能性)
用于查找行李中的初始元素。将选择适合装入袋子的第一个项目,然后我们重复(首先是上面的统一条款,然后是下面的部分装满袋子条款)。一旦袋子里的这件物品用尽了所有的可能,我们回过头来寻找下一件合适的物品
可能性(容量,[Current | Rest],可能性)
基本上以与可能性(容量,[],可能性)
相同的方式运行,但需要进行一次额外检查,以确保我们只按字母顺序获得可能性,从而消除排列。然后,如上所述再次发生
(作为补充,如果你想在一个袋子里储存,比如说两杯水,只需将a@
更改为a@=
)
项(水,1)。
项目(花卉,1)。
项目(文件,1)。
项目(肉,2)。
项目(木材,2)。
项目(玻璃,2)。
项目(石头,3)。
项目(黄金,3)。
项目(金属,3)。
项目(铂,4)。
%行李最大容量
最大容量(10)。
地点(可能性、容量):-
最大容量(maxcapacity),
介于(1,最大容量,容量),
可能性(容量,[],可能性)。
可能性(当前、当前、当前):-
当前\=[]。
可能性(容量,[],可能性):-
项目(A、B),
B=<容量,
新容量是容量-B,
可能性(新产能[A],可能性)。
可能性(容量、[当前|剩余]、可能性):-
项目(A、B),
B=<容量,
新容量是容量-B,
当前,,
可能性(新容量、[A、当前|剩余]、可能性)。
您的问题在于您的程序正在创建可能性列表,而不是可能性。下面的代码找到了一种可能性,然后回溯到下一种可能性
可能性(u,Current,Current)
将当前工作可能性与查询统一,以返回当前可能性作为结果<代码>当前\=[]
用于消除空包的可能性(基于您的预期结果)
回溯后,可能性(容量,[],可能性)
用于查找行李中的初始元素。将选择适合装入袋子的第一个项目,然后我们重复(首先是上面的统一条款,然后是下面的部分装满袋子条款)。一旦袋子里的这件物品用尽了所有的可能,我们回过头来寻找下一件合适的物品
可能性(容量,[Current | Rest],可能性)
基本上以与可能性(容量,[],
?- space(Possibility, [], 0, 2), increasing(Possibility).
Possibility = [flower, water] ;
Possibility = [paper, water] ;
Possibility = [flower, paper] ;
Possibility = [meat] ;
Possibility = [wood] ;
Possibility = [glass] ;
false.
increasing([]).
increasing([_]).
increasing([X,Y|Xs]) :-
X @< Y,
increasing([Y|Xs]).
item(water, 1).
item(flower, 1).
item(paper, 1).
item(meat, 2).
item(wood, 2).
item(glass, 2).
item(stone, 3).
item(gold, 3).
item(metal, 3).
item(platin, 4).
% maximum capacity of bag
maxcapacity(10).
place(Possibility, Capacity) :-
maxcapacity(MaxCapacity),
between(1, MaxCapacity, Capacity),
possibilities(Capacity, [], Possibility).
possibilities(_, Current, Current) :-
Current \= [].
possibilities(Capacity, [], Possibility) :-
item(A, B),
B =< Capacity,
NewCapacity is Capacity - B,
possibilities(NewCapacity, [A], Possibility).
possibilities(Capacity, [Current|Rest], Possibility) :-
item(A, B),
B =< Capacity,
NewCapacity is Capacity - B,
A @< Current,
possibilities(NewCapacity, [A,Current|Rest], Possibility).