【问题标题】:Set partitioning设置分区
【发布时间】:2016-06-26 08:40:07
【问题描述】:

我正在努力解决这个问题,但我很挣扎。 假设我有一个 S={1,2,3,4,5},一个 L={(1,3,4),(2,3),(4,5),(1,3), (2),(5)} 和另一个具有 L 成本的元组,例如 C={10,20,12,15,4,10}

我想在Prolog中做一个约束程序,以便以最小的成本解决问题。(在这种情况下,它是我将得到的子集的成本总和)

我的问题是我无法理解我将如何进行建模。我知道我应该选择二进制变量 {0,1} 的建模,但我几乎不明白我将如何通过 Prolog 来表达它。

【问题讨论】:

    标签: optimization prolog partitioning constraint-programming


    【解决方案1】:

    有一个简单的方法来做到这一点:您可以使用布尔指标来表示哪些元素构成一个子集。例如,在您的情况下:

    子集(集):- 集 = [[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 ? ; 不

    我把选择一个成本最低的封面作为一个简单的练习。

    【讨论】:

    • 尽管我没有得到 SICStus 和布尔约束求解器的部分,但感谢您的回答,我希望我能做到我想要的
    【解决方案2】:

    也许您的问题实例的显式模型会让事情变得更清晰:

    cover(SetsUsed, Cost) :-
    
        SetsUsed = [A,B,C,D,E,F],       % a Boolean for each set
        SetsUsed #:: 0..1,
    
        A         + D         #= 1,     % use one set with element 1
            B         + E     #= 1,     % use one set with element 2
        A + B     + D         #= 1,     % use one set with element 3
        A     + C             #= 1,     % use one set with element 4
                C         + F #= 1,     % use one set with element 5
    
        Cost #= 10*A + 20*B + 12*C + 15*D + 4*E + 10*F.
    

    你可以解决这个问题,例如在ECLiPSe:

    ?- cover(SetsUsed,Cost), branch_and_bound:minimize(labeling(SetsUsed), Cost).
    
    SetsUsed = [1, 0, 0, 0, 1, 1]
    Cost = 24
    Yes (0.00s cpu)
    

    【讨论】:

    • 对于未知列表,我检查包含列表的每个数字,以便使用该数字设置约束?例如,如果 3 在第 1、第 2 和第 4 个列表中...我检查初始集合,并在找到数字 3 的任何地方存储它以使约束 A+B+D #=1 ???非常非常感谢
    猜你喜欢
    • 1970-01-01
    • 2013-10-22
    • 2023-04-09
    • 2021-12-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-24
    相关资源
    最近更新 更多