所以我正在写一个背包问题,在我的任务中有一个规格,背包中不能有相同的“重量”物品。
基本上我发送我的物品清单,即“Pantry”,然后是容量,在背包和背包本身内可以有多少重量。
legalKnapsackNoSameRocks(Pantry, Capacity, Knapsack):-
subseq2(Knapsack,Pantry),
weight(Knapsack,W),
W =< Capacity.
然后我制作所有可能组合的子列表
subseq2([],[]).
subseq2([Item | RestX], [Item | RestY]) :-
not(member(arg(2, Item, X), L)),
add_tail(L, arg(2, Item, X), L),
subseq2(RestX,RestY).
subseq2(X, [_ | RestY]) :-
subseq2(X,RestY).
在制作子列表时,我必须检查列表是否包含下一个项目所具有的权重,如果是,那么我不会在列表中添加相同的权重项目。
我想这样做的方法是制作一个新的清单,我在其中添加了物品的“重量”。所以基本上我检查“权重”列表是否包含我想要放入背包的物品的“重量”,如果是,我不会把它放进去。
我也做了一个“附加”谓词
add_tail([],X,[X]).
add_tail([H|T],X,[H|L]):- add_tail(T,X,L).
但它永远不会返回任何东西,它总是错误的。我认为这是因为列表首先是空的?谢谢。
编辑:
权重谓词获取背包并添加所有项目的所有权重并返回总权重。
当我运行程序时,我输入
knapsackOptimizationWithoutSameSizeRocks(
[ rock(smallRock,2,2300),
rock(biggerRock,4,6700),
rock(mediumRock,3,6900),
rock(smallDiamond,2,9200),
rock(smallDiamond,2, 9200),
rock(smallDiamond, 3, 10000)
], 15 ,Knapsack).
完整代码:
rock(smallDiamond,2,9200).
rock(smallRock,2,2300).
rock(biggerRock,4,6700).
rock(mediumRock,3,6900).
rock(smallDiamond,3, 10000).
knapsackOptimizationWithoutSameSizeRocks(Pantry, Capacity, Knapsack) :-
allLegalKnapsacksNoSameRocks(Pantry, Capacity, R),
maximumvalue(R, Knapsack),
value(Knapsack, CALS),
nl,print('value: '), print(CALS),
!.
weight([],0).
weight([rock(_,W,_) | Rest], X) :-
weight(Rest,RestW),
X is W + RestW.
value([],0).
value([rock(_,_,C) | Rest], X) :-
value(Rest,RestC),
X is C + RestC.
subseq2([],[]).
subseq2([Item | RestX], [Item | RestY]) :-
%not(memberchk(arg(2, Item, X), [rock(_, L, _) | Rest])),
%add_tail(L, arg(2, Item, X), L),
%not(memberchk(Item, RestY)),
subseq2(RestX,RestY).
subseq2(X, [_ | RestY]) :-
subseq2(X,RestY).
%add_tail([],X,[X]).
%add_tail([H|T],X,[H|L]):- add_tail(T,X,L).
legalKnapsackNoSameRocks(Pantry, Capacity, Knapsack):-
subseq2(Knapsack,Pantry),
weight(Knapsack,W),
W =< Capacity.
allLegalKnapsacksNoSameRocks(Pantry, Capacity, ListOfLegalKnapsacks) :-
findall(LegalKnapsack,
legalKnapsackNoSameRocks(Pantry, Capacity, LegalKnapsack),
ListOfLegalKnapsacks).
maximumvalue([LEGAL | LEGALS], MAXCALS) :-
value(LEGAL, CALS),
maxCals(LEGALS, CALS, LEGAL, MAXCALS).
maxCals([], MAXCALS, MAXCALLEGAL, MAXCALLEGAL).
maxCals([LEGAL | LEGALS], MAXCALS, MAXCALLEGAL, OUTPUT) :-
value(LEGAL, NEWCALS), NEWCALS > MAXCALS,
maxCals(LEGALS, NEWCALS, LEGAL,OUTPUT).
maxCals([LEGAL | LEGALS], MAXCALS, MAXCALLEGAL, OUTPUT) :-
value(LEGAL, NEWCALS), NEWCALS =< MAXCALS,
maxCals(LEGALS, MAXCALS, MAXCALLEGAL, OUTPUT).
我希望得到像
这样的东西Knapsack = [rock(biggerRock, 4, 6700), rock(smallDiamond, 2, 9200),
rock(smallDiamond, 3, 10000)].
因为这些都是不同的权重,但这个背包组合比这更有价值:
Knapsack = [rock(biggerRock, 4, 6700), rock(mediumRock, 3, 6900),
rock(smallDiamond, 2, 9200)].
如果我可以多次使用相同的权重,那么就会给出
Knapsack = [rock(biggerRock, 4, 6700), rock(mediumRock, 3, 6900),
rock(smallDiamond, 2, 9200), rock(smallDiamond, 2, 9200),
rock(smallDiamond, 3, 10000)].
答案 0 :(得分:1)
您可以这样写legalKnapsackNoSameRocks/3
:
legalKnapsackNoSameRocks(Pantry, Capacity, Knapsack) :-
permutation(Pantry,RandomPantry),
lknsr(RandomPantry,Capacity,[],Knapsack),
weight(Knapsack,W),
W =< Capacity.
lknsr([R|Rs],C,Ls0,Ls) :-
R = rock(_,W,_),
( \+ member(rock(_,W,_),Ls0) ->
Ls1 = [R|Ls0]
; Ls1 = Ls0 ),
lknsr(Rs,C,Ls1,Ls).
lknsr([],_,Ls,Ls).
由于permutation/2
为您提供了列表的所有可能排列,并且findall/3
(在allLegalKnapsacksNoSameRocks/3
中)收集了所有合法组合,maximumvalue/2
可以选择最高的子集值。