有一个简单的方法来做到这一点:您可以使用布尔指标来表示哪些元素构成一个子集。例如,在您的情况下:
子集(集):-
集 = [[1,0,1,1,0]-10, % {1,3,4}
[0,1,1,0,0]-20, % {2,3}
[0,0,0,1,1]-12, % {4,5}
[1,0,1,0,0]-15, % {1,3}
[0,1,0,0,0]-4, % {2}
[0,0,0,0,1]-10]。 %{5}
我现在使用 SICStus Prolog 及其Boolean constraint solver 来表达集合封面:
:- 使用模块(库(列表))。
:- 使用模块(库(clpb))。
setcover(封面,费用):-
子集(集),
keys_and_values(Sets, Rows, Costs0),
转置(行,列),
相同长度(行,系数),
地图列表(封面(Coeffs),Cols),
标记(系数),
短语(coeff_is_1(系数,行),封面),
短语(coeff_is_1(Coeffs,Costs0),Costs),
sumlist(成本,成本)。
封面(Coeffs,Col):-
短语(coeff_is_1(Col,Coeffs),Cs),
坐(卡([1],Cs))。
coeff_is_1([], []) --> []。
coeff_is_1([1|Cs], [L|Ls]) --> [L], coeff_is_1(Cs, Ls)。
coeff_is_1([0|Cs], [_|Ls]) --> coeff_is_1(Cs, Ls)。
对于每个子集,一个布尔变量用于表示该子集是否是封面的一部分。基数约束确保每个元素只被覆盖一次。
示例查询及其结果:
| ?- setcover(封面,成本)。
封面 = [[0,0,0,1,1],[1,0,1,0,0],[0,1,0,0,0]],
成本 = 31 ? ;
封面 = [[1,0,1,1,0],[0,1,0,0,0],[0,0,0,0,1]],
成本 = 24 ? ;
不
我把选择一个成本最低的封面作为一个简单的练习。